一个go语言crackme分析
by anhkgg
2019年2月23日
先看看
直接运行看看,尝试输入,看看结果。
一个console的程序,有提示信息,入手点应该很明显,找字符串,或者printf
,scanf
之类的函数。
查个壳,是tElock 1.0 (private) -> tE! *
,没脱过,常规脱壳方法尝试弄不掉,百度一番看到挺多经验分享的,但都是0.9x
版本的分析,不适用于本版本,那就放弃脱壳了(求脱壳大佬分享技巧)。
OD加载后直接运行,通过字符串搜索去查找,并未找到提示信息“口令解码失败”。
尝试再命令窗口输入bp printf
,然后F9,OD断下,此时参数如下,OD并没有解析出中文字符,用工具查看一番,发现是UTF-8编码。
所以前面OD解析“口令解码失败”编码问题,搜索不到。再次尝试进入内存(M)
窗口,Ctrl+B
后在HEX
输入字符的UTF-8
编码,然后搜索,果然找到了。
另外找到一篇讨论OD
编码问题的文章,有兴趣的可以看看:https://bbs.pediy.com/thread-181118.htm
不过此处也没什么用了,因为bp printf
也能找到关键代码。
在输入uid
和口令之后,在printf
断下,查看此时调用堆栈。
调用堆栈
地址 堆栈 函数过程 / 参数 调用来自 结构
1104BE80 00461BBD <jiubugao.printf> jiubugao.00461BB8
1104BE84 1104C160 format = ""
1104BE88 110101B0
1104BEA4 004635DD jiubugao.00461AD0 jiubugao.004635D8
1104BEC4 00462FA1 jiubugao.004635A0 jiubugao.00462F9C
1104BEF8 0047BA5A 包含jiubugao.00462FA1 jiubugao.0047BA58
1104BF28 0047BAF5 jiubugao.0047B9F0 jiubugao.0047BAF0
1104BF4C 0048C220 <jiubugao.printf> jiubugao.0048C21B
1104BF50 1104BF9C format = "?J"
1104BF54 00000001
1104BFCC 0042609A 包含jiubugao.0048C220 jiubugao.00426098
此时做了一番思考,作为console
程序,整个代码都在main
中完成,可能大概代码结构如下:
int main() {
printf("【春节】解题领红包之三\n");
printf("请输入您的吾爱破解uid:);
scanf("%s", &uid);
printf("请输入您的口令:);
scanf("%s", &code);
if(check(uid, code)) {
printf("口令解码失败");
} else {
//
}
}
那么通过调用栈回溯到mian
,真个代码结构就会很清楚了,算法分析也应该会更简单。
在OD
中回溯直到0048C220
看到结构类似上面猜测的代码,然后dump出来,通过IDA
查看确认了一下,应该没错了。
分析算法
开始分析算法,通过OD
调试确认,前面一部分都是输入输出相关代码,直接跳过。
直到看到下面几个特征,明显看出是hash算法相关特征了,一番搜索之后确认之后是sha1
。
调试结果和py计算结果一致,将输入的uid
通过sha1
算法得到一个hash值。
看到这个特别的返回值方式,以及字符串中这种xxx.go
的字符,我才意识到这是一个go
语言写的程序。
继续检查输入的口令长度,小于0x10
则输出"口令解码失败"。
输入长于0x10
的口令之后,重新开始,然后看下一个函数。看到这个ABCD...+/
特征,很明显就是base64
编码,第一个反应是把口令编码。
结果发现并不是我想的那样,结果如下。
看到输出"口令解码失败"意识到这可能是base64
解码函数,生成一个base64
编码字符输入尝试一下。
>>> base64.b64encode('1234567890')
'MTIzNDU2Nzg5MA=='
果然,调试中看到解码正确。
继续往下走,到48BC80
,输入刚才解码的口令以及uid
的hash
,先直接F8跳过。
程序异常提示出一些信息,可以看出这个在AesDecrypt
的时候出错。
所以意识到48BC80
是AES
解密算法。那么输入的口令结构应该是这样的才能解密成功。
输入口令=Base64Encode(AesCrypt(口令,sha1(uid)))
找了一段aes
加密的python
代码,构造一个口令,如下:
python aes.py
kJgRdtADqzjDKXiHHr770g== 11111111
在口令出输入kJgRdtADqzjDKXiHHr770g==
之后,再次尝试,果然解密成功。
继续往下,看到判断解密的口令长度是不是0x1A
,如果不是则错误。
所以加密前口令长度应该0x1A
,先修改标志让OD正常继续执行,到402000
,三个参数,解密后口令,HappyNewYearFrom52PoJie.CnLine Islands Standa
,以及口令长度,很明显是一个字符串比较函数。
结合长度限制0x1A
,那么口令应该是HappyNewYearFrom52PoJie.Cn
,用python加密后输入尝试一下。
python aes.py
9D7boJcaCbENFCpf6YRBmJFZjPsPyUot8sHdR5YTChw= HappyNewYearFrom52PoJie.Cn
果然成功。
彩蛋
最后已经完成了,我用IDA
打开了原始程序看一看,没想到看到了这个。
IDA
完全支持go
语言IDL
符号解析,然后最开始PEID
查的啥壳啊,完全是忽悠人的。
所以如果刚开我就用IDA
来分析这个代码,是不是更快呢!
第一次分析go
的坑,以后会长记性了。