推荐在了解了相应章节的内容后再来练习,你会觉得顿时悟了
记录一下自己的解题过程
2,3,4题目附件来源:https://book.nu1l.com/tasks/#/pages/reverse/5.4
[第五章 CTF之RE章]Hello, RE
附件
ida拖入直接查看字符串,发现flag
[第五章 CTF之RE章]BabyAlgorithm
步骤:
- 无壳,64位ida载入,112行的if可知,v10是加密后的数组
上面的一长串(我转换成了16进制)
- sub_400874函数
sub_40067A()和sub_400753()两个函数都是加密算法
sub_40067A(),就是流密钥的生成
sub_400753(),是加密
书上的p274有标识这是RC4加密的代码段
sub_400646函数的作用是两数交换,等价于书上写的swap(s[i],s[j])
具体的关于RC4加密的算法可以参考这篇文章
知道上述的知识后,可知本题的密钥是‘Nu1Lctf233’
,加密后的密文是[0xc6,0x21,0xca,0xbf,0x51,0x43,0x37,0x31,0x75,0xe4,0x8e,0xc0,0x54,0x6f,0x8f,0xee,0xf8,0x5a,0xa2,0xc1,0xeb,0xa5,0x34,0x6d,0x71,0x55,0x8,0x7,0xb2,0xa8,0x2f,0xf4,0x51,0x8e,0xc,0xcc,0x33,0x53,0x31,0x0,0x40,0xd6,0xca,0xec,0xd4 ]
密文转换成字符型看一下Æ!Ê¿QC71uäŽÀToîøZ¢Áë¥4mqU²¨/ôQŽ Ì3S1
import base64
a=[0xc6,0x21,0xca,0xbf,0x51,0x43,0x37,0x31,0x75,0xe4,0x8e,0xc0,0x54,0x6f,0x8f,0xee,0xf8,0x5a,0xa2,0xc1,0xeb,0xa5,0x34,0x6d,0x71,0x55,0x8,0x7,0xb2,0xa8,0x2f,0xf4,0x51,0x8e,0xc,0xcc,0x33,0x53,0x31,0x0,0x40,0xd6,0xca,0xec,0xd4]
s=""
for i in a:
s+=chr(i)
print(s)
print(str(base64.b64encode(s.encode('utf-8')), 'utf-8'))
发现是乱码,看不懂,我在这儿懵了好久,找了RC4加密的脚本,查了资料后才知道这边要给它进行‘utf-8’编码,然后得到真正的密文w4Yhw4rCv1FDNzF1w6TCjsOAVG/Cj8Ouw7hawqLDgcOrwqU0bXFVCAfCssKoL8O0UcKODMOMM1MxAEDDlsOKw6zDlA==
贴一下百度后整理好的解密脚本,看完脚本,应该能更好的理解RC4加密
import base64
def rc4_main(key = "init_key", message = "init_message"):
print("RC4解密主函数调用成功")
print('\n')
s_box = rc4_init_sbox(key)
crypt = rc4_excrypt(message, s_box)
return crypt
def rc4_init_sbox(key):
s_box = list(range(256))
print("原来的 s 盒:%s" % s_box)
print('\n')
j = 0
for i in range(256):
j = (j + s_box[i] + ord(key[i % len(key)])) % 256
s_box[i], s_box[j] = s_box[j], s_box[i]
print("混乱后的 s 盒:%s"% s_box)
print('\n')
return s_box
def rc4_excrypt(plain, box):
print("调用解密程序成功。")
print('\n')
plain = base64.b64decode(plain.encode('utf-8'))
plain = bytes.decode(plain)
res = []
i = j = 0
for s in plain:
i = (i + 1) % 256
j = (j + box[i]) % 256
box[i], box[j] = box[j], box[i]
t = (box[i] + box[j]) % 256
k = box[t]
res.append(chr(ord(s) ^ k))
print("res用于解密字符串,解密后是:%res" %res)
print('\n')
cipher = "".join(res)
print("解密后的字符串是:%s" %cipher)
print('\n')
print("解密后的输出(没经过任何编码):")
print('\n')
return cipher
a=[0xc6,0x21,0xca,0xbf,0x51,0x43,0x37,0x31,0x75,0xe4,0x8e,0xc0,0x54,0x6f,0x8f,0xee,0xf8,0x5a,0xa2,0xc1,0xeb,0xa5,0x34,0x6d,0x71,0x55,0x8,0x7,0xb2,0xa8,0x2f,0xf4,0x51,0x8e,0xc,0xcc,0x33,0x53,0x31,0x0,0x40,0xd6,0xca,0xec,0xd4]
s=""
for i in a:
s+=chr(i)
s=str(base64.b64encode(s.encode('utf-8')), 'utf-8')
rc4_main("Nu1Lctf233", s)
[第五章 CTF之RE章]BabyConst
附件,密码a031
步骤:
-
无壳,64位ida载入
首先让我们输入一个长度为48的字符串,之后每四位一组,进行了加密,最后每四位一组去与unk_603080处的数据进行比较,每次是16位一比较 -
看一下unk_603080处的数据
这样看不方便,于是我切换到了16进制文本状态,正好12行,每次比较一行数据
-
看一下加密函数sub_40085B
熟悉md5加密的一看就知道这是在初始化MD缓存器,具体的看这篇介绍md5加密的文章
在sub_4008A7()和sub_4009F5()两个加密函数里都用到了下图的加密方法
书上的p274标识了这种算法是md5,
-
加上之前的特征值,确定了这边是将我们输入的数据每4位一划分进行了12次的md5加密,加密后的结果就是刚刚上方截图的每行16位一共12行的数据
-
利用在线网站撞库破解一下md5
拼接一下就是flag
n1book{U5in9__c0n5ts_7o_1d3nt1fy_mD5__41gor1thm}
[第五章 CTF之RE章]BabyLib
步骤:
- 无壳儿,64位ida载入,通过检索字符串,发现了跟flag有关的信息,找到了关键代码段
一开始给了我们几个大长串的数据,65537
找个数据比较引人注目,之前做过多次RSA解密,找个数据都是公钥(E),这里又出现的了找个数据让人怀疑它是RSA加密,直接上RSA解密脚本
import gmpy2
import binascii
p = 9842210544704105105386460208892325341518023212707647450607909247791133264519200579173177912467785842558060968492186761162106356089009194470097546296829163
q = 12972360952153818155692381381571252126631475184728971905301445264084096070607651598626783223094292740492828654265391639843199875189333033337169565006624907
e = 65537
c = 110694010334901653238216140152683772418101197298114114481381418739511015861349388028360214495059500357527716613334520805339266807313669925649167175211788624655809951516502907329949137499677877779584898365309802983718066683849944838484002656376845311375573423677826690834875095904482448693671735053088583663382
n = p * q
d = gmpy2.invert(e, (p-1) * (q-1))
m = gmpy2.powmod(c, d, n)
print(binascii.unhexlify(hex(m)[2:]).decode(encoding="utf-8"))
n1book{1d3nt1fy_GMp_l1br4ry}