-
-
[原创]reversing.kr第15题PEPassword
-
发表于: 2019-2-18 11:17 3752
-
1,original.exe程序没有加壳,直接运行发现密码是加密了的。直接用ida和od进行分析

通过分析发觉就是将下面两处的数据异或后放到对应的地址处输出,并没有发现什么秘密。

do { v5 = *(&v20 + v4) ^ *(&v7 + v4); *(&v7 + v4) = v5; *(&v34 + v4++) = v5; } while ( v4 < 13 );
2.运行password check,程序没有相应的按钮,不知道程序的目的是什么,进行查壳,是SMT壳

选择单步跟踪的方法进行分析,由于第一个call会跑飞,所以我们进入到第一个call进行分析.
程序运行的时候会先对自己进行解密操作,然后回出现相应的调用函数。然后一直单步运行,就会发现相应的关键函数

GetMessageA用来从消息框获取输入的数据,
TranslateMessage 函数将虚拟键消息转换成字符消息。该字符消息又被发送给对应线程(调用TranslateMessage的线程)的消息队列,当线程再次调用GetMessage函数或PeekMessage函数获取消息的时候被读取。
DispatchMessageA
通常消息从GetMessage函数获得或者TranslateMessage函数传递的。消息被分发到回调函数(过程函数),作用是消息传递给操作系统,然后操作系统去调用我们的回调函数,也就是说我们在窗体的过程函数中处理消息。
je明显是相等就会进入循环,所以我们要对判断的地址进行判定。这里可以下内存写入断点,看看什么时候对地址进行了写入操作。这里使用ida的交叉引用来寻找所有可能会对数据的操作。跳转到0x4091a8位置处,查看这里的数据。

跳转到0x4091a8位置处,往上面几个位置处下断点,然后运行程序

可以看到我们的输入,传入esi然后在0x409197调用函数0x4091d8,然后将eax和0xE98F842A比较,所以0x4091d8就是关键call.
里面是比较复杂的操作,每个字符进行0xffff次操作,长度未知,所以逆变换很难

这里选择对0x4091a6处进行直接爆破。然后继续运行程序,执行到用户代码处。
接下来运行程序,程序会报错,所以下面就要逐步的运行程序,对程序进行判断。
函数0x409200处出现的pushad操作,这然后对0x401000处进行异或操作,显然是解密操作

调用两次复杂函数,然后将值存入ebx,最后用ebx对eax进行变换,
由于我们有原函数origin.exe,拖入OD中找到401000处的机器码,于是可以得到eax序列的值,问题在于ebx是多少
,
这里ebx的穷举空间有0xffffffff,虽然有点大但还可以接受 ,拿eax的原始值和第一次变换值就可以穷举出ebx了
。
参考代码
ori = 0xb7aac296 tar = 0x5a5a7e05 def ror(a, n): for i in range(n): p = a & 1 a = p*0x100000000 + a >> 1 return a def de(key): p = ori ^ key q = ror(p, (key & 0xff00) >> 8) if(q == tar): print("Correct! The password is ", hex(p)) f = open("F:\ctf\\reversing.kr\\PEPassword\\ebx.txt", 'w') f.write(hex(p)) f.close return True else: return False for i in range(0xffffffff): de(i) if(i%0x10000==0):#LOG print(hex(i))
本文参考链接:
c92K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3f1#2x3Y4m8G2K9X3W2W2i4K6u0W2j5$3&6Q4x3V1k6@1K9s2u0W2j5h3c8Q4x3X3b7$3y4e0l9^5x3o6u0Q4x3X3b7I4i4K6u0V1x3g2)9J5k6h3S2@1L8h3H3`.
do { v5 = *(&v20 + v4) ^ *(&v7 + v4); *(&v7 + v4) = v5; *(&v34 + v4++) = v5; } while ( v4 < 13 );
2.运行password check,程序没有相应的按钮,不知道程序的目的是什么,进行查壳,是SMT壳

选择单步跟踪的方法进行分析,由于第一个call会跑飞,所以我们进入到第一个call进行分析.
程序运行的时候会先对自己进行解密操作,然后回出现相应的调用函数。然后一直单步运行,就会发现相应的关键函数

GetMessageA用来从消息框获取输入的数据,
TranslateMessage 函数将虚拟键消息转换成字符消息。该字符消息又被发送给对应线程(调用TranslateMessage的线程)的消息队列,当线程再次调用GetMessage函数或PeekMessage函数获取消息的时候被读取。
DispatchMessageA
通常消息从GetMessage函数获得或者TranslateMessage函数传递的。消息被分发到回调函数(过程函数),作用是消息传递给操作系统,然后操作系统去调用我们的回调函数,也就是说我们在窗体的过程函数中处理消息。
je明显是相等就会进入循环,所以我们要对判断的地址进行判定。这里可以下内存写入断点,看看什么时候对地址进行了写入操作。这里使用ida的交叉引用来寻找所有可能会对数据的操作。跳转到0x4091a8位置处,查看这里的数据。

跳转到0x4091a8位置处,往上面几个位置处下断点,然后运行程序

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
赞赏
他的文章
- [原创]angr/pyvex模块学习 9205
- [原创] Valgrind VEX IR 9730
- [原创]内存映射文件-进程间共享数据 11991
- [求助]C#反编译字符串出现乱码如何解决 4368
- [原创]windows dll注入/Api钩取技术简单总结 57674
赞赏
雪币:
留言: