欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

攻防世界 crypto入门WP

程序员文章站 2022-03-05 12:41:17
...

攻防世界 crypto入门WP

前言

下学期要求密码和Re,现在这俩几乎是空白,趁着暑假的功夫,最近也能闲下来,就学一学crypto,其实真正接触发现挺有意思的,各种密码的加密千奇百怪,层出不穷,也是需要慢慢积累经验,花了一天时间把攻防世界的密码入门全做了,这里简单说一下自己做的时候的思路,顺便练习python…python实在没学好,自己太辣鸡了。。。一些特别基础的就带过来,就写一些自己还没那么熟悉的

正文

混合编码

JiM3NjsmIzEyMjsmIzY5OyYjMTIwOyYjNzk7JiM4MzsmIzU2OyYjMTIwOyYjNzc7JiM2ODsmIzY5OyYjMTE4OyYjNzc7JiM4NDsmIzY1OyYjNTI7JiM3NjsmIzEyMjsmIzEwNzsmIzUzOyYjNzY7JiMxMjI7JiM2OTsmIzEyMDsmIzc3OyYjODM7JiM1NjsmIzEyMDsmIzc3OyYjNjg7JiMxMDc7JiMxMTg7JiM3NzsmIzg0OyYjNjU7JiMxMjA7JiM3NjsmIzEyMjsmIzY5OyYjMTIwOyYjNzg7JiMxMDU7JiM1NjsmIzEyMDsmIzc3OyYjODQ7JiM2OTsmIzExODsmIzc5OyYjODQ7JiM5OTsmIzExODsmIzc3OyYjODQ7JiM2OTsmIzUwOyYjNzY7JiMxMjI7JiM2OTsmIzEyMDsmIzc4OyYjMTA1OyYjNTY7JiM1MzsmIzc4OyYjMTIxOyYjNTY7JiM1MzsmIzc5OyYjODM7JiM1NjsmIzEyMDsmIzc3OyYjNjg7JiM5OTsmIzExODsmIzc5OyYjODQ7JiM5OTsmIzExODsmIzc3OyYjODQ7JiM2OTsmIzExOTsmIzc2OyYjMTIyOyYjNjk7JiMxMTk7JiM3NzsmIzY3OyYjNTY7JiMxMjA7JiM3NzsmIzY4OyYjNjU7JiMxMTg7JiM3NzsmIzg0OyYjNjU7JiMxMjA7JiM3NjsmIzEyMjsmIzY5OyYjMTE5OyYjNzc7JiMxMDU7JiM1NjsmIzEyMDsmIzc3OyYjNjg7JiM2OTsmIzExODsmIzc3OyYjODQ7JiM2OTsmIzExOTsmIzc2OyYjMTIyOyYjMTA3OyYjNTM7JiM3NjsmIzEyMjsmIzY5OyYjMTE5OyYjNzc7JiM4MzsmIzU2OyYjMTIwOyYjNzc7JiM4NDsmIzEwNzsmIzExODsmIzc3OyYjODQ7JiM2OTsmIzEyMDsmIzc2OyYjMTIyOyYjNjk7JiMxMjA7JiM3ODsmIzY3OyYjNTY7JiMxMjA7JiM3NzsmIzY4OyYjMTAzOyYjMTE4OyYjNzc7JiM4NDsmIzY1OyYjMTE5Ow==

密码的题很多就是给你个txt,好评,上来给你一串字符,判断为base64,那么先base64decode一下,得到:

LzExOS8xMDEvMTA4Lzk5LzExMS8xMDkvMTAxLzExNi8xMTEvOTcvMTE2LzExNi85Ny85OS8xMDcvOTcvMTEwLzEwMC8xMDAvMTAxLzEwMi8xMDEvMTEwLzk5LzEwMS8xMTkvMTExLzExNC8xMDgvMTAw

解密之后还是base64,在这里说一下base编码的特征

  • base64:

    (1)在base64中的可打印字符包括字母A-Z、a-z、数字0-9,+ / =。

    (2)永远是4的倍数,不足四的用=补齐。

  • base32:

    base32中只有大写字母(A-Z)和数字234567

  • base16:

    base16中只有数字0-9以及大写字母ABCDEF

继续base64decode得到

/119/101/108/99/111/109/101/116/111/97/116/116/97/99/107/97/110/100/100/101/102/101/110/99/101/119/111/114/108/100

很明显的ascii码

主要为了练习练习py,每个题都写了exp

#coding=utf-8
import base64
cipher_ascii = '119/101/108/99/111/109/101/116/111/97/116/116/97/99/107/97/110/100/100/101/102/101/110/99/101/119/111/114/108/100'
cipher_ascii = cipher_ascii.replace('/',',')
cipher_list = list(map(int,cipher_ascii.split(',')))
lst = []
for num in cipher_list:
    lst.append(chr(num))
plain = "".join(lst)
print('cyberpeace{'+plain+'}')
#cyberpeace{welcometoattackanddefenceworld}

幂数加密

考点是云影密码

此密码运用了1248代码

原理很简单,有了1,2,4,8这四个简单的数字,你可以以加法表示出0-9任何一个数字,例如0=28,7=124,9=18。 这样,再用1-26来表示A-Z,就可以用作密码了。 为了不至于混乱,我个人引入了第五个数字0,来用作间隔,以避免翻译错误,所以还可以称“01248密码”。 题目:12401011801180212011401804 第一步,分割,即124 1 118 118 212 114 18 4 第二步,基本翻译,例如124可以表示7,也可以表示16(但不可能是34,因为不会超过26),所以可以放在一边,翻译其他没有异议的, 可得:124 a s s w o 18 d 第三步,推测得出明文。可以推测后面的18表示r,前面的为p最合适。 明文:password(密码)

cipher8842101220480224404014224202480122

因此根据云影密码的原理,写个脚本:

#coding=utf-8
num_str = '8842101220480224404014224202480122'
num = num_str.replace('0',',')
num_list = num.split(',')
print(num_list)

lst = []
asc2 = 0
for i in range(len(num_list)):
    for j in num_list[i]:
        asc2 += int(j)
    lst.append(asc2)
    asc2 = 0

flag = ''
for i in lst:
    flag+=chr(i+96)
print('cyberpeace{'+flag.upper()+'}')
#cyberpeace{WELLDONE}

Railfence

给的提示很直白,连我这个小新手都知道是栅栏密码,给的**是5,这里说明一下栅栏密码加密方式:

即把将要传递的信息中的字母交替排成上下两行,再将下面一行字母排在上面一行的后边,从而形成一段密码。栅栏密码是一种置换密码。

例如密文:TEOGSDYUTAENNHLNETAMSHVAED

解密过程:先将密文分为两行

​ **T E O G S D Y U T A E N N
  H L N E T A M S H V A E D ****

再按上下上下的顺序组合成一句话

THE LONGEST DAY MUST HAVE AN END.

  • 进阶

    密文为:

PFEE SESN RETM MFHA IRWE OOIG MEEN NRMA ENET SHAS DCNS IIAA IEER BRNK FBLE LODI

去掉空格:PFEESESNRETMMFHAIRWEOOIGMEENNRMAENETSHASDCNSIIAAIEERBRNKFBLELODI

共64个字符,以8个字符为一栏,排列成8*8的方阵(凯撒方阵):

P F E E S E S N   R E T M M F H A   I R W E O O I G   M E E N N R M A   E N E T S H A S   D C N S I I A A   I E E R B R N K   F B L E L O D I

从上向下竖着读:PRIMEDIFFERENCEBETWEENELEMENTSRESMONSIBLEFORHIROSHIMAANDNAGASAKI

插入空格:PRIME DIFFERENCE BETWEEN ELEMENTS RESMONSIBLE FOR HIROSHIMA AND NAGASAKI

但是在这里,发现用栅栏密码怎么也得不到看着靠谱的flag,才知道这是W型栅栏密码 举个简单例子

    #同样一个字符串:123456789
	key=3
	1----5----9  #让数字以W型组织,同样是三组,但每组的数量不一定相同
	-2--4-6--8
	--3----7--
	#加密密文:159246837

因此直接在线W型栅栏密码,**是5,直接出flag了。

这里mark一个网站:http://www.atoolbox.net/Tool.php

easy_RSA

RSA、DES这样的应该是密码学题目的常态,因此原理还是得弄清楚,RSA是基于数学难题的,这点上学期的课没有白听,大致地说,RSA算法基于一个十分简单的数论事实:将两个大质数相乘十分容易,但是想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加***。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qhMG25Qn-1593442175638)(C:\Users\86189\AppData\Roaming\Typora\typora-user-images\image-20200629183902255.png)]

题目描述是

在一次RSA**对生成中,假设p=473398607161,q=4511491,e=17 求解出d

因此在这里我们的目的是先求出r=(p-1)*(q-1),然后找到e*d % r ==1这个d就是所求,在这里使用gmpy2.invert求逆元

d = gmpy2.invert(e,n) # 求逆元,de = 1 mod n

贴下exp:

#coding=utf-8
import gmpy2

p=473398607161
q=4511491
e=17
phin = (p-1)*(q-1)

d = gmpy2.invert(e,phin)
d = str(d)
print('cyberpeace{'+d+'}')  #RSA私钥即为d
#cyberpeace{125631357777427553}

easychallenge

这题的考点主要就是给了一个pyc文件,也就是类似java的class文件,只需要将其反编译即可得到py文件,发现就是一个编码,三重编码得到密文,因此只需要对应写好解码,在依次解码即可得到flag

mark反编译pyc网站: https://tool.lu/pyc/

贴出exp:

#!/usr/bin/env python
# encoding: utf-8
import base64


def encode1(ans):
    s = ''
    for i in ans:
        x = ord(i) ^ 36
        x = x + 25
        s += chr(x)

    return s

def decode1(ans):
    s = ''
    for i in ans:
        x = ord(i)
        x = x - 25
        x = x ^ 36
        s+= chr(x)
    return s

def encode2(ans):
    s = ''
    for i in ans:
        x = ord(i) + 36
        x = x ^ 36
        s += chr(x)

    return s

def decode2(ans):
    s = ''
    for i in ans:
        x = ord(i)
        x = x ^ 36
        x = x - 36
        s += chr(x)
    return s


def encode3(ans):
    return base64.b32encode(ans)

def decode3(ans):
    return base64.b32decode(ans)

final = 'UC7KOWVXWVNKNIC2XCXKHKK2W5NLBKNOUOSK3LNNVWW3E==='
#if encode3(encode2(encode1(flag))) == final:
print(decode1(decode2(decode3(final).decode('ISO-8859-1'))))
#cyberpeace{interestinghhhhh}

值得注意到是,这里编码还只能是ISO-8859-1,因为如果是其他的,python会用\xx来表示,这样一直会报错,经过多次尝试编码是ISO-8859-1时,才能够正确解码。

轮转机加密

题目描述是

2:  < KPBELNACZDTRXMJQOYHGVSFUWI <
3:  < BDMAIZVRNSJUWFHTEQGYXPLOCK <
4:  < RPLNDVHGFCUKTEBSXQYIZMJWAO <
5:  < IHFRLABEUOTSGJVDKCPMNZQWXY <
6:  < AMKGHIWPNYCJBFZDRUSLOQXVET <
7:  < GWTHSPYBXIZULVKMRAFDCEONJQ <
8:  < NOZUTWDCVRJLXKISEFAPMYGHBQ <
9:  < XPLTDSRFHENYVUBMCQWAOIKZGJ <
10: < UDNAJFBOWTGVRSCZQKELMXYIHP <
11: < MNBVCXZQWERTPOIUYALSKDJFHG <
12: < LVNCMXZPQOWEIURYTASBKJDFHG <
13: < JZQAWSXCDERFVBGTYHNUMKILOP <

**为:2,3,7,5,13,12,9,1,8,10,4,11,6
密文为:NFQKSEVOQOFNP

给的提示就是轮转机加密,这种加密还挺有意思,并且它要结合具体语义的,即在最后是选取有语义的一条为明文,结合题目来说

 通过所给顺序排序 : 2,3,7,5,13,12,9,1,8,10,4,11,6
 将排序后的第一个字符串移位,使得N在字符串首部
 第二个字符串移位,使得F在字符串首部
 依次按照下列所给提示排序
 NFQKSEVOQOFNP

也就是先按数字把每行字符串排好序,在按照**把每行的字符串给换一下,二次排完后再找列中有具体语义的。

贴出exp:

#coding=utf-8
"""
**为:2,3,7,5,13,12,9,1,8,10,4,11,6
密文为:NFQKSEVOQOFNP
"""
key = "2,3,7,5,13,12,9,1,8,10,4,11,6"
cipher_text = "NFQKSEVOQOFNP"

file = open("C:\\Users\\86189\\Desktop\\1.txt",encoding='utf-8')
cipher_str = []
for line in file:
    cipher_str.append(line.strip())

key_index = key.split(',')
cipher_nowstr = []
for index in key_index:
    cipher_nowstr.append(cipher_str[int(index) - 1])

table = 0
cipher_last = []
for c in cipher_text:
    str = cipher_nowstr[table]
    num = str.index(c)
    cipher_last.append(str[num:]+str[:num])
    table+=1
flag = ''
for str in cipher_last:
    flag += str[-9] #倒数第九列有具体语义
print('flag{'+flag.lower()+'}')
#fireinthehole

easyRSA

这个题恐怕是耗费我时间最多的一题,一直在配置python环境,头大。。。这里是推荐使用CTF-RSA-TOOLS,但是导入的很多包都没有,因此开始漫长入坑路,终于在我的vps下配置好了,那我们开始看题。

题目给了一个公钥的pem文件还有一个flag.enc,但是flag.enc是无法打开的,当我们知道公钥和密文后是能够根据公钥来**密文的内容从而获得明文的。

分析公钥和私钥产生

  1. 随机选择两个不同大质数 p 和 q,计算 N=p×q
  2. 根据欧拉函数,求得 r=φ(N)=(p−1)(q−1)
  3. 选择一个小于 r 的整数 e,使 e 和 r 互质。并求得 e 关于 r 的模反元素,命名为 dd,有 ede^d≡1(modr)
  4. 将 p 和 q 的记录销毁

此时,(N,e)(N,e) 是公钥,(N,d)(N,d) 是私钥

消息加密

首先需要将消息 m 以一个双方约定好的格式转化为一个小于 N,且与 N 互质的整数 n。如果消息太长,可以将消息分为几段,这也就是我们所说的块加密,后对于每一部分利用如下公式加密:

nen^e≡ c (modN)

消息解密

利用** d 进行解密。

cdc^d≡n(modN)

我们可以知道,RSA公钥主要有两个信息:模数(modulus)和指数(exponent),也就是我们所说的N和e。只要有了这两个信息,我们便可以生成公钥,然后使用rsa库对数据进行加密

kali中有openssl能够对pem文件提取出其模数n和指数e

openssl rsa -pubin -text -modulus -in warmup -in pubkey.pem

当得到模数n时,通过对它的因数分解分别能得到p和q,当得到这俩数之后和e之后,便可以通过这五个数来构造RSA私钥对密文进行解密了,这里可以直接使用RSA_TOOLS

python2 solve.py -k ../pubkey.pem --decrypt ../flag.enc  # -k指定公钥  --decrypt 指定解密文件

攻防世界 crypto入门WP

或者也可以通过脚本来解密:

攻防世界 crypto入门WP

先通过openssl得到了模数和指数,在分解模数n得到p和q

#coding=utf-8
import gmpy2
import rsa

q = 275127860351348928173285174381581152299
p = 319576316814478949870590164193048041239
n = 87924348264132406875276140514499937145050893665602592992418171647042491658461
e = 65537
d = int(gmpy2.invert(e,(p-1)*(q-1)))
pri_key = rsa.PrivateKey(n,e,d,p,q)
f = open('C:\\Users\\86189\\Desktop\\547de1d50b95473184cd5bf59b019ae8\\flag.enc','rb')
print(rsa.decrypt(f.read(),pri_key))
#b'PCTF{256b_i5_m3dium}\n'