前言
非常感谢子昂师傅分享的wp,从中学习到了一种逆向的思路。
关于此题,我主要打算讲三点:
1.脱壳
2.关键函数该怎么找
3.golang编写的程序的一些特点
分析
【查壳】
- 64位程序加了UPX壳,我是头一次遇见的,没什么好的工具管用,只能x64gdb手脱。
- 可是这个程序有些奇怪,一开始断下来的位置并不属于用户态
- 这点与32位程序加了UPX后的不同。尝试使用ESP定律脱壳,在x64dbg中选择的是硬件访问8字节
- 最后成功来到
- 这个应该就是OEP了吧?我不太确定,原因有两点:
1 .可以肯定的一点就是他不是C/C++、E语言、VB、Delph、Borland的OEP,但是Golang的OEP我没见过。
2 .即使是OEP,脱壳下来不一定就能运行。 - 但是这些对我的分析影响都不大,因为从这个位置脱下来IDA能够大部分的函数,至少从心理上给了我很大的安慰 ( ̄▽ ̄)~*
- 接下来就是从键盘接受用户的输入了,发现直接下断strcmp、scanf函数程序都不会断下,而直接退出了。那想想跟字符串有关的函数还有strlen,试一试。哎,能断下来了!接着返回到用户态,咋RAX存的不是字符串的长度呢???并且此时,栈中都还没看到输入的字符。怀着疑惑,继续单步,跳出了好几个call才出现输入的数据
- 此时rax,rcx都存着字符串的长度
- 找到字符串存放的位置和字符串存放的内存位置
- 既然已取得字符串的长度,那么接下来的操作应该会有比较长度的过程,先下个内存单字节断点,果然在后面断了下来,此时正处在关键函数中
- 输入的字符串长度小于16就会失败,在IDA中可以看到正确流程的算法。在此之前,得让IDA将数据转为代码,再建立函数才能够看到。
- 到这里就很简单了,检验的算法就是异或而已。在IDA中把byte_541AC0的数据dump下来,然后在x64dbg中把data数据dump下来,逐个异或不就完事了吗?然而结果却是个乱码,仔细对比x64dbg和IDA中的数据,发现byte_541AC0不一样。这是由脱壳导致的,脱壳后没修复,故而某些地方的数据会出错!
脚本
key=[0xA0,0x1B,0x86,0x5C,0xCA,0xCA,0xEF,0x2A,0x8F,0xDF,0x19,0xA7,0x06,0x51,0xA9,0x5A]
d=[0xE8,0x7E,0xB7,0x6D,0xA5,0x95,0x98,0x1A,0xFD,0xEE,0x7D,0xF8,0x34,0x62,0x9A,0x69]
f=''
for i in range(16):
f+=chr(key[i]^d[i])
print f
- 将结果输入源程序,得到正确得答案
特点
- IDA一开始没能识别出来代码,是因为IDA默认以0x00作为数据和代码的分隔符,这也是普遍编程语言生成的EXE的特点,而Golang生成的EXE,会在数据和代码中间填充0xCC,所以IDA没法识别部分连的紧密的数据和函数。而Golang生成的程序也是由汇编代码对应的机器码组成的,所以IDA能够分析其程序。