西湖论剑CTF
这个比赛只做了一道题,看了很久确实也没做出来。没有想到程序的执行逻辑可以在32位和64位的不同执行环境下进行切换。
Dual personality
总体来讲该程序
第一次 从
32-> 64 赋值key -> 32
第二次 从
32-> 64 循环左移 -> 32
第三次 从
32 -> 64 进行了两次加密,一次就是基本的逻辑运算,另一次是异或。-> 32
- 将exe程序送进ida,发现main函数无法被正常反编译。
sub_401120
函数会把下面的二进制修改为 EA D0 11 40 00 33 00
—–jmp far 33:004011D0h
往后面跳转之后程序就变成了执行64位语句了。所以需要把相应的二进制dump下来放到64位ida中进行分析。
这里不要被这个
jmp far ptr loc_4014FE+2
给欺骗了,这个语句没有被正确解析。这句话会远跳转到33:4011D0这个地址。远跳转有一个隐形的操作,他会将代码段寄存器CS设置为跳转到的这个段对应的段选择子,这里执行完了远跳转之后CS的值会变为0x33,
- 把4011d0h地址处的二进制dump出来用ida64分析之后。
注意 gs:qword_60 中 qword_60 是指
60 00 00 00
而不是 0x00000060地址处的内容,否则人家会写成gs:[qword_60]
- 其实
407000h
处存放的是原本call sub_401120
下面一句的地址004013E8
。当返回32位执行模式之后,刚好回到下面的语句。
这里有一个加密的过程。
- 在加密完成之后,有一个
call fword ptr
其实和jmp far
是一样的道理切换到 64位模式下执行。
这次跳转的地址为 00401200
, 跟之前的操作是一样的, 同样是dump下来放到ida中分析。
注意这里面的 0x40705c
– 在第一次跳转到64模式下执行的过程中,将 BeingDebugged
的标志位放到了这个地址里面。
__ROL8__
是一个循环左移的操作 其中retaddr[1]
指向的实际上是用户输入
。
执行完成之后返回到32位执行环境中。
- 第三次跳转到64位环境里面
同样dump 0x401290的字节码,使用64位IDA分析,这个函数主要修改了0x407000保存的返回值,然后对0x407014开始 的数组中的常量进行处理,得到新的值。
注意的是 407050h 存放的是0x401467
注意:前两次切换到64位模式后,函数结束就重新切换到32位模式了,但是这次出来后仍然为64位模式,因此main函数之后的代码也都是64位的指令
此时
407000h
中存放的实际上是0x004014C5
- 后面就是常见的比较字符串的操作了。
参考资料
win PEB 中BeingDebugged标志位获取—https://blog.csdn.net/Simon798/article/details/100702034
ret 和 retf 的区别 – https://zhuanlan.zhihu.com/p/372398363