学破解第113天,《CM区mcyaas坛友的简单易语言程序》分析
前言:
从小学到大专(计算机网络技术专业),玩过去的,所以学习成绩惨不忍睹,什么证书也没考,直到找不到工作才后悔,不知道怎么办才好。
2017年12月16日,通过19元注册码注册论坛账号,开始做伸手党,潜水一年多,上来就是找软件。(拿论坛高大上的软件出去装X)
2018年8月某一天,报名了华中科技大学网络教育本科(计算机科学与技术专业)2018级秋季。(开始提升学历)
2019年6月17日,不愿再做小菜鸟一枚,开始零基础学习破解。(感谢小糊涂虫大哥在我刚开始学习脱壳时,录制视频解答我的问题)
2020年7月7日,感谢H大对我的鼓励,拥有了第一篇获得优秀的文章。(接下来希望学习逆向,逆天改命)
坛友们,年轻就是资本,和我一起逆天改命吧,我的学习过程全部记录及学习资源:https://www.52pojie.cn/thread-1208234-1-1.html
本文视频讲解地址:https://www.52pojie.cn/thread-1215697-1-1.html
立帖为证!--------记录学习的点点滴滴
0x1获取CM信息
1.看标题,菜鸟第一个CM,嗯,和我一样的菜鸟,我想应该能对付,就拿它学习一番。
2.观察界面,易语言程序,没学过易语言,心里有点慌,没学过易语言,只学了点C++,再看成功居然不弹窗口了,说明messageBOX断点不能用了,更慌了。
3.但是我最近学了一天的windows程序设计,了解了窗口程序的运行机制,我觉得还是可以试试的。
4.接下来就带和我一样的小菜鸟们试试几种常见的易语言破解方式。
0x2记事本破解
1.为什么会想到用记事本破解呢?因为论坛好多新手发的CM,都能通过记事本搜索到“编辑框1”这个字符串。
2.按照经验,把文件后缀名改为.txt,打开后搜索字符串,唯一比较像key的就是123456,为什么呢,因为字符串没加密,肯定会在ASCII码可表示范围内,也就是我们能从键盘上输入的字符,只有123456最可疑了。
3.验证key:输入123456,果然进度条跑满了。
0x3搜索字符串破解
1.易语言会生成大量的字符串,会给一些新手朋友们一种易语言搜索不到有用的字符串的错觉。
2.以这个程序为例,可以直接拖到顶部看见字符串“123456”,那么就可以回车过去F2下断点,以它为突破口。
3.跑一遍,整个流程都出来了
004010B8 |. E8 09010000 call CM_by_AA.004011C6 ; 获取输入的字符串
004010BD |. 83C4 10 add esp,0x10
004010C0 |. 8945 FC mov [local.1],eax ; 取出eax,也就是我输入的111111
004010C3 |. 68 701C4800 push CM_by_AA.00481C70 ; 123456
004010C8 |. FF75 FC push [local.1] ; 入栈
004010CB |. E8 34FFFFFF call CM_by_AA.00401004 ; 比较字符串是否相等
004010D0 |. 83C4 08 add esp,0x8 ; 销毁局部变量
004010D3 |. 83F8 00 cmp eax,0x0 ; 相等返回0,小于,这里所以返回-1
004010D6 |. B8 00000000 mov eax,0x0 ; 将eax置0
004010DB |. 0f94c0 sete al ; ZF为0,这里设置false
004010DE |. 8945 F8 mov [local.2],eax
004010E1 |. 8B5D FC mov ebx,[local.1] ; 将字符串的值还给ebx
004010E4 |. 85DB test ebx,ebx
004010E6 |. 74 09 je short CM_by_AA.004010F1 ; 这里不为0,不跳转
004010E8 |. 53 push ebx
004010E9 |. E8 D2000000 call CM_by_AA.004011C0 ; 这里可能是个释放堆上内存的函数
004010EE |. 83C4 04 add esp,0x4
004010F1 |> 837D F8 00 cmp [local.2],0x0
004010F5 |. 0F84 22000000 je CM_by_AA.0040111D ; 这里不跳走,即可爆破
004010FB |. 6A 00 push 0x0
004010FD |. 68 64000000 push 0x64 ; 进度条跑满,默认为0
00401102 |. 6A FF push -0x1
00401104 |. 6A 0D push 0xD
00401106 |. 68 0A000116 push 0x1601000A
0040110B |. 68 01000152 push 0x52010001
00401110 |. E8 A5000000 call CM_by_AA.004011BA ; 显示进度条
00401115 |. 83C4 18 add esp,0x18
00401118 |. E9 1D000000 jmp CM_by_AA.0040113A
0040111D |> 6A 00 push 0x0
0040111F |. 68 00000000 push 0x0 ; 这里为0,所以执行后,进度不变,还是0
00401124 |. 6A FF push -0x1
00401126 |. 6A 0D push 0xD
00401128 |. 68 0A000116 push 0x1601000A
0040112D |. 68 01000152 push 0x52010001
00401132 |. E8 83000000 call CM_by_AA.004011BA ; 显示进度条
0x4通过401000破解
1.首先搜索401000处,找到00401004F2下断
00401000 . 33C0 xor eax,eax
00401002 . C3 retn
00401003 90 nop
00401004 /$ 8B5424 04 mov edx,dword ptr ss:[esp+0x4]
00401008 |. 8B4C24 08 mov ecx,dword ptr ss:[esp+0x8]
0040100C |. 85D2 test edx,edx
0040100E |. 75 0D jnz short CM_by_AA.0040101D
00401010 |. 33C0 xor eax,eax
00401012 |. 85C9 test ecx,ecx ; CM_by_AA.00481C70
00401014 |. 74 06 je short CM_by_AA.0040101C
00401016 |. 8039 00 cmp byte ptr ds:[ecx],0x0
00401019 |. 74 01 je short CM_by_AA.0040101C
2.然后随便输入111111,断在了这里,F8跟着走一遍,大概意思就懂了
00401004 /$ 8B5424 04 mov edx,dword ptr ss:[esp+0x4] ; 111111
00401008 |. 8B4C24 08 mov ecx,dword ptr ss:[esp+0x8] ; 123456
0040100C |. 85D2 test edx,edx ; 111111
0040100E |. 75 0D jnz short CM_by_AA.0040101D ; 输入的字符串不为空就会跳
0040101D |> \85C9 test ecx,ecx ; 123456
0040101F |. 75 09 jnz short CM_by_AA.0040102A ; 密文123456不为空也跳
0040102A |> \F7C2 03000000 test edx,0x3 ; 数据对齐,我也不懂,反正32位系统肯定是4字节*8对齐的,所以这里运算结果肯定为0
00401030 |. 75 37 jnz short CM_by_AA.00401069 ; 运算结果不为0才跳转
00401032 |> 8B02 /mov eax,dword ptr ds:[edx] ; 然后进行循环比较
00401034 |. 3A01 |cmp al,byte ptr ds:[ecx]
00401036 |. 75 2B |jnz short CM_by_AA.00401063
00401038 |. 0AC0 |or al,al
0040103A |. 74 24 |je short CM_by_AA.00401060
0040103C |. 3A61 01 |cmp ah,byte ptr ds:[ecx+0x1]
0040103F |. 75 22 |jnz short CM_by_AA.00401063
00401041 |. 0AE4 |or ah,ah
00401043 |. 74 1B |je short CM_by_AA.00401060
00401045 |. C1E8 10 |shr eax,0x10
00401048 |. 3A41 02 |cmp al,byte ptr ds:[ecx+0x2]
0040104B |. 75 16 |jnz short CM_by_AA.00401063
0040104D |. 0AC0 |or al,al
0040104F |. 74 0F |je short CM_by_AA.00401060
00401051 |. 3A61 03 |cmp ah,byte ptr ds:[ecx+0x3]
00401054 |. 75 0D |jnz short CM_by_AA.00401063
00401056 |. 83C1 04 |add ecx,0x4
00401059 |. 83C2 04 |add edx,0x4
0040105C |. 0AE4 |or ah,ah
0040105E |.^ 75 D2 \jnz short CM_by_AA.00401032
00401060 |> 33C0 xor eax,eax
00401062 |. C3 retn
3.所以爆破思路很简单,就是进这个函数后直接跳转到00401063这一行即可。
00401063 |> 1BC0 sbb eax,eax
00401065 |. |D1E0 shl eax,1
00401067 |. |40 inc eax ; eax从0到1
00401068 |. |C3 retn
0x5通过消息断点破解
1.首先我们要明白什么是消息,消息,就是指Windows发出的一个通知,告诉应用程序某个事情发生了。例如,单击鼠标、改变窗口尺寸、按下键盘上的一个键都会使Windows发送一个消息给应用程序。
2.例如这个程序鼠标左键单机事件就是一个事件,windows通过回调函数,调用WndProc,然后在这个函数里,我们就可以对我们需要的消息进行处理了。
//处理消息
switch (uMsg)
{
case WM_LBUTTONDOWN://按下鼠标左键
MessageBox(hwnd, TEXT("你好啊!"), TEXT("小菜鸟一枚"), MB_OK);
return -1;//消息处理完后返回
}
详细的windows程序代码见:https://www.52pojie.cn/thread-1213978-1-1.html
3.所以我们可以通过消息断点找到处理输入字符串的地方,WM_LBUTTONDOWN是一个宏定义,为16进制常量,这个程序我们需要找到比较字符串的函数,所以应捕获使用鼠标左键单击松开后的消息,也就是WM_LBUTTONUP事件。
4.有了思路,接下来就可以实战了,OD直接运行程序,点击w,显示当前窗口信息,选择“提交”按钮,右键设置消息断点,如图所示!
5.然后消息类型选择202 WM_LBUTTONUP事件,接下来还是输入111111,单击后,断在系统领空,F2在401000处下断点,运行过去,然后F8向下走,可以看到一系列相关的windows API函数。
00471DCF |. 50 push eax ; |Buffer = 00000006
00471DD0 |. FF76 1C push dword ptr ds:[esi+0x1C] ; |hWnd = 0012077E (class='Edit',parent=00160782)
00471DD3 |. FF15 34054800 call dword ptr ds:[<&USER32.GetWindowTex>; \GetWindowTextA
00471DD9 |. 8B4C24 08 mov ecx,dword ptr ss:[esp+0x8] ; 111111
00471DDD |. 6A FF push -0x1
00471DDF |. E8 8A2B0000 call CM_by_AA.0047496E
00471DE4 |. EB 0C jmp short CM_by_AA.00471DF2
00471DE6 |> 8B01 mov eax,dword ptr ds:[ecx]
00471DE8 |. FF7424 08 push dword ptr ss:[esp+0x8]
00471DEC |. FF90 88000000 call dword ptr ds:[eax+0x88]
00471DF2 |> 5E pop esi ; 00A25258
00471DF3 \. C2 0400 retn 0x4
上面这段代码调用GetWindowTextA获取输入的字符串,00471DDF这个call里面是计算输入的字符串长度,也就是windows API对应的lstrlenA函数。。
004010BD |. 83C4 10 add esp,0x10
004010C0 |. 8945 FC mov [local.1],eax ; 取出eax,也就是我输入的111111
004010C3 |. 68 701C4800 push CM_by_AA.00481C70 ; 123456
004010C8 |. FF75 FC push [local.1] ; 入栈
004010CB |. E8 34FFFFFF call CM_by_AA.00401004 ; 比较字符串是否相等
一路单步最后就来到了这里,FF75 FC也就是我们常说的易语言按钮事件,因为它有固定的偏移量push dword ptr ss:[ebp-0x4],所以这里就可以作为按钮事件的特征码,下一步就是比较了。
0x5总结
1.通过0x3分析的时候,可能有些朋友们想到了通过直接复制那个push和call不就可以在启动的时候,就让进度条显示满(push窗口法),大家可以试试行不行。
2.通过搜索相关资料,终于明白了test edx,3和test edx,1分别是判断地址是否为4的倍数,2的倍数,数据对齐用,32位系统必然是4字节对齐。
3.上面我都只写了寻找爆破点,实际分析的过程中,密文123456其实都看得到,所以没提追码这回事,跑一遍就能看到密文。
4.我个人理解是因为上面那个push是寄存器间接寻址,指令是固定的,所以可作为易语言按钮事件特征码。
参考资料:
https://baike.baidu.com/item/windows%E6%B6%88%E6%81%AF%E5%A4%84%E7%90%86%E6%9C%BA%E5%88%B6/9420571?fr=aladdin
https://bbs.pediy.com/thread-190300.htm
《加密解密第四版》P31-33-消息断点
windows程序设计(珍藏版)
CM程序地址:https://www.52pojie.cn/thread-1213547-1-1.html
PS:虽然我现在还是零基础的小菜鸟一枚,也许逆天改命我会失败,但也有着成功的可能,只要还有希望,就决不放弃!
善于总结,善于发现,找到分析问题的思路和解决问题的办法。