一、Pwn
1、three | solved
这题看到程序输入3字节后有个call指令,可以执行命令:
所以填入机器码,利用mov指令跳转到ecx寄存器(rcx正好有我们后面的输入的bss的地址),就可跳到bss地址执行我们的静态ropchain,直接getshell~
1 | #coding=utf8 |
这次的pwn题太难了,只有1题可以做,心塞塞~
二、Re
1、xx
这题一共3关,ida分析程序先:
这里一波操作看不懂没关系,我们x64debug下就会发现,是将输入的前4字节作为后面xxtea算法的key的前4字节,后面3字节都是’\x00\x00\x00\x00’,根据输入是完整格式flag{xxxxxxxxxxxx},而key是取了输入的前4字节,所以可以动态调试,可以提取出key就是flag\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
key处理好了后,就进行xxtea的加密,这里没有魔改代码,所以可以直接上脚本解密。
第二关是置换这个简单,知道了密文就可还原回去:
第三关是迭代异或:
这里静态分析可能有点辛苦(ACM底子差哎,我直接跟汇编动态调试出来了算法)
这里可以写个脚本直接异或回去,脚本10分钟,手撕5分钟,比赛时直接照着汇编结果手撕计算了,这里肯定可以写个脚本逆向一下。
接着有个cmp的比较,所以我们知道密文:
下面一步步反解回去:
1、提取出密文,x64动态调试时,直接内存提取或者ida直接小端序提取:
1 | data = [0xCE,0xBC,0x40,0x6B,0x7C,0x3A,0x95,0xC0,0xEF,0x9B,0x20,0x20,0x91,0xF7,0x02,0x35,0x23,0x18,0x02,0xC8,0xE7,0x56,0x56,0xFA] |
2、迭代异或解密:
1 | #coding=utf8 |
3、置换解密:
1 | store = [0xCE,0xBC,0x40,0xA5,0xB2,0xF4,0xe7,0xb2,0x9d,0xA9,0x12,0x12,0xc8,0xAE,0x5B,0x10,0x6,0x3d,0x1d,0xd7,0xf8,0xdc,0xdc,0x70] |
4、xxtea解密,这里将miwen转成字节流即change:
1 | change = '\xbc\xa5\xce\x40\xf4\xb2\xb2\xe7\xa9\x12\x9d\x12\xae\x10\xc8\x5b\x3d\xd7\x06\x1d\xdc\x70\xf8\xdc' |
这是完整的exp:
1 | #coding=utf8 |
2.easyRE
一开始被坑了,base64一直解密出来一个网站,发现找不到flag,后来想到第一个输入的hint是找flag头,于是一个个找,发现了真正的主逻辑:
先通过flag字符和table前四个数异或解出key,这里把table和key字符异或就可出了:
1 | flag = "" |
3、childRE
直接分析主逻辑:
分析逻辑可以知道,这题有3关,第一关对输入进行了一个排序算法,这个好逆,第二关是把排完序的字符串进行了一个C++的函数名扩展修饰,就是那个系统调用UnDecorateSymbolName函数,使得31位的输入变成了62位,这一步我们可以通过自己写一个反解程序,通过修饰后的程序名得到修饰前的程序名,最后是一个简单的check,可以直接爆破得到我们修饰后的程序名,下面一步步反解:
1、先提取出数据并爆破得到我们的62位函数名密文:
1 | a = "55565653255552225565565555243466334653663544426565555525555222" |
2、接着写VS2019写一个系统调用的反解程序:
1 |
|
我们运行下得到未修饰的程序名,是个31位的字符串,即我们的输入排序后的字符串:
1 | ip = "?My_Aut0_PWN@R0Pxx@@AAEPADPAE@Z" |
3、排序算法逆向:
这里直接用一个小技巧,x64动态看内存,输入0到u的有序字符,调用完毕后,看内存提取出排完序的顺序,接着再写个脚本将密文对号入座即可,打比赛时,直接手撕:
这里还是写个脚本跑一波:
1 | kk = "0123456789abcdefghijklmnopqrstu" |
最后是完整的exp:
1 | import md5 |
4、calc
这题作者自己实现了一个大数运算,有3次输入,每次输入一个大整数,既可得到flag,然后通过调试和分析可以得到搞出关键性的check,前面的计算没有用到,白分析了哎,直接看分析出来的关键性check
1 | ((input1 + input2) * (input1 + input2) * (input1 + input2) - 3 * input1 * input2 * input2 - 3 * input2 * input1 * input1 == ((4 + input3) * (4 + input3) * (4 + input3) - (input3 * input3) * 12 - 48 * input3 - 22)) |
我们用x1,x2和x3表示3个输入,然后化简得到(x1+x2)^3-3x1x2x3-3x2x1^2==(4+x3)^3-12x3^2-48*x3-22将3次幂拆分成2次幂,然后再化简约去同类项可得:x1^3 + x2^3 +(-x3)^3 = 42,这里一开始用z3跑,用symp都跑不出来,申请写了3个for循环爆破,但是都出不了,后面上网谷歌,找到一篇文章:https://zhuanlan.zhihu.com/p/81655767
所以直接得到3个数:x1= 80435758145817515x2=12602123297335631x3= 80538738812075974输入程序最后拿到flag:flag{951e27be2b2f10b7fa22a6dc8f4682bd}