攻防世界LostKey
LostKey
检测参数,一共要4个参数
对每一个参数字符串clone一个进程进行处理
第一个参数是一个函数,每个字符串的都单独用一个函数处理
第二个参数是一个地址-0x1000 * (i + 1) + 0x100000 + dword_80EA3AC
剩下的重要的就是arg,把参数字符串和一个地址放进去
看clone的操作
这里对syscall的反编译不太好,动态调一下可以知道a1和a2是传进来的enc函数,a3是上面计算的地址,-0x1c得到v8,是sys_clone子进程的栈,a5是传进来的arg,包括一个数组和参数字符串
子进程创建之后会执行a1函数,也就是enc
enc函数里注意到修改了返回地址
sub_8079A50
函数分析一下发现其实是syscall,0x1A是sys_ptrace
,ptrace了自己,一方面反调,另一方面还有返回值,enc里面调用了两次sys_ptrace
第一次会返回0,第二次因为已经被ptrace了,会返回-1,所以两个分支都会进入,enc剩下的部分就是打印一个没用的字符串,然后返回,进入被修改的返回地址
动态调试手动改进程的栈还有手动进入enc函数,看一下栈的内容
第一个是call的返回地址,从0x000
开始看,第一个是arg参数,包括一个数组和参数字符串,后面的内容和计算出来的地址一样,主要看被改的返回地址
发现是一个ROP链,执行过来
参数字符串被放到了ebp里面,继续调后面的ROP
从字符串里取4个字符到eax
把4个字节异或0x466C7578
再与0x210D191E
比较,检测是否为flag
,决定后面ROP链的调用,结果相等进入sub_804A240
,结果失败进入sub_804A1E0
sub_804A1E0
使进程结束
比较成功再取四个字符,异或0x78756C46
与0x4B1D383D
,检测是否为{Th3
,比较失败进程退出,比较成功继续后续调用,后面的调用跟参数字符串无关了,主要是把参数字符串复制到一个地方
分析enc2
函数里面基本相似,修改了4个全局变量,然后把返回地址改到ROP链里面去
还是一样ebp指向参数字符串,这里做传参操作,然后调用函数sub_80714B0
从这里可以猜到要求第二段flag长度为16(实际上不是),剩余的操作应该是一个字符串复制,没有明显的根据结果返回到不同的函数
这里把ebp当参数,调用sub_8062D90,ebp是参数字符串
这个函数返回值是字符串的长度
这里如果前面返回结果小于等于1会把esp-0x1c,重新进入之前的ROP链,循环,正常情况会继续调用后面的ROP
这里从字符串里取一个字符,取反,高低4位交换,再取下一个字符,异或前一个处理后的字符,后面有rsp+8,实际上循环,该操作进行字符串长度-1次,如下
1 |
|
上面操作结束后会到sub_804A300
,这里是把最后一个字符异操作后异或0x41
1 |
|
4字节一比较,不相等置位cl
后面一直都是4字节一比较
实际不为0的长度是0x19
最后根据cl的值判断进入哪个分支,sub_804A1E0
错误分支,后面的不用再分析,已经可以解密出第二段flag _key_1s_in_th3_secret_com
1 |
|
接下来是第三段enc3
传参给后面的函数
三个参数分别是字符串,数字6,还有一个缓冲区
这里很明显的初始化了md5最开始没看出来看题目源码才知道是md5
计算前6个字符的md5
这里是16字节的比较,比较的数据在栈里面,每次pop到esi
也就是6个字符的md5需要是7b4d6ff46ac46c3f628acc930d937d81
,爆破得到第三段flag
p4rtme
第四段,enc4
分析方法与前三段类似,把字符串分三次进行加密操作,最后进行比较
1 |
|
实际上就是tea加密,这里用到的密钥就是在enc1、enc2、enc3里面被改的4个dword
1 |
|
tea解密得到最后一段flag nt_of_your_t00l_sh3d...}
这道题比较有意思的地方在与用clone创建子进程设置进程的栈,通过ROP链来检测flag,最后通过共享内存的方式使主进程能够打印完整flag,还有就是ptrace的反调试,容易误认为其只会进入一个分支执行,但实际两个分支全部执行才能得到完整的key