Crackme中的游戏-----贪吃蛇
某日,闲来无聊,从C盘浏览到F盘,又从F盘浏览到C盘。无意中翻出个CrackMe。反正无事,就当复习好了。不看不知道,一看还真不错,不只是单调的函数拉,贪吃蛇的小游戏一定玩过吧?注册的过程就是个贪吃蛇游戏。(本文适合和我一样入门级的朋友,所以注释得很罗嗦,高手莫笑。)
废话不多说~,FI检查,无壳。OllyDbg载入。这种CrackMe就是很适合我们菜鸟,无壳无花样。下断,到下面地址:
00401092 >>pushad //从这里开始,取得我们添入的信息,开始处理。
00401093 .>push 7F
00401095 .>push Snake.00401E00
0040109A .>push 3E8
0040109F .>push dword ptr ds:[401F00]
004010A5 .>call dword ptr ds:[<&USER32.Get> ; \GetDlgItemTextA
004010AB .>test eax,eax ;下面一小段是判断是否输入姓名和注册码的,我们跳过一些代码
004010AD .>jnz short Snake.004010CB
…………
00401103 >>call Snake.004012AA ; 这个CALL对输入的注册码进行形式上判断
00401108 .>test al,al ; 跟进很容易知道注册码只能是0-9,A-F
0040110A .>jnz short Snake.00401128 ;注册码不合要求,不跳出错
0040110C .>push 30
0040110E .>push Snake.00401400 ; |Title = "Error"
00401113 .>push Snake.00401464 ; |Text = "There is something wrong with your Serial..."
00401118 .>push dword ptr ds:[401F00] ; |hOwner = 000B01A8 ('Snake ',class='#32770')
0040111E .>call dword ptr ds:[<&USER32.Mes>; \MessageBoxA
00401124 .>popad
00401125 .>xor eax,eax
00401127 .>retn
00401128 >>call Snake.00401173 ; 这个CALL是将401B00到401BFF清零,在这区域两边添加16个FF,作为边界
0040112D .>call Snake.0040119B ;对名字进行处理的关键call
00401132 .>call Snake.0040120C ;对注册码进行处理的关键call
00401137 .>test al,al
00401139 .>jnz short Snake.00401157 ; 跳则成功,不跳OVER。爆破这里OK,不过我们的目的是找算法。
我们先跟进对注册名处理的CALL:
0040119B /$>push eax
0040119C |.>push ecx
0040119D |.>push edx
0040119E |.>push esi
0040119F |.>push edi
004011A0 |.>xor ecx,ecx
004011A2 |.>mov esi,Snake.00401E00 ; 这是保存注册名的地址
004011A7 |.>mov edi,Snake.00401B00 ;记的前面1个CALL清零的区域不?这就是这区域的开始地址,也就是我们贪吃蛇的游戏范围
004011AC |.>push esi
004011AD |.>mov dl,0
004011AF |>>/mov al,byte ptr ds:[esi] ;[esi]保存的注册名
004011B1 |.>|inc esi
004011B2 |.>|add dl,al
004011B4 |.>|test al,al ; 对名字各位求和,取低8位,记为S,即求和后与0x000000FF作与运算
004011B6 |.>\jnz short Snake.004011AF
004011B8 |.>pop esi
循环1:这个循环作用是产生名字长度个“CC”标志
004011B9 |>>/movzx eax,byte ptr ds:[esi] ; 取名字的1位
004011BC |.>|xor al,dl ; 记T=Name[n] XOR S;
004011BE |>>|/sub dl,al ; S=(S-T)AND 000000FF(注意是低8位运算,始终只取低8位,所以我们算的时候要与0x000000FF作与运算
004011C0 |.>||or byte ptr ds:[edi+eax],0CC ; [401b00+T]=CC;
004011C4 |.>||jnz short Snake.004011CA ;??上一步结果不可能为0
004011C6 |.>||dec dl
004011C8 |.>|\jmp short Snake.004011BE
004011CA |>>|inc ecx ;记数器,注册名长度为几,ecx+几次
004011CB |.>|inc esi
004011CC |.>|cmp byte ptr ds:[esi],0 ; 注册名是否取完
004011CF |.>\jnz short Snake.004011B9
上面这循环,在401B00-401BFF这段地址产生CC标志,即我们这游戏中蛇要吃的果子,其实,只要多看下就知道这段程序有问题,我在文末还会说明下。
循环2:这个循环是找个位置放‘DD’标志
004011D1 |.>mov dword ptr ds:[401F04],ecx ; 名字长度
004011D7 |.>xor dl,al ; S=S XOR T;
004011D9 |>>/sub al,dl ; T=(T-S) AND 0x000000FF;
004011DB |.>|cmp byte ptr ds:[edi+eax],0CC ; 比较是不是已经放了CC标志了
004011DF |.>|jnz short Snake.004011E5 ; 不是就存放DD标志
004011E1 |.>|dec dl ; 是CC标志就再找位置
004011E3 |.>\jmp short Snake.004011D9 ;
004011E5 |>>mov byte ptr ds:[edi+eax],0DD ; [401B00+T]=DD
004011E9 |.>mov al,dl ; T=S;
这个小循环是找个没存放CC标志的位置放DD标志,后面我们可以知道,DD是最后1个果子
循环3:找个位置放99标志,从下面可知,99是蛇头
004011EB |>>/cmp byte ptr ds:[edi+eax],0CC ;
004011EF |.>|je short Snake.004011F7 ; 寻找1个既没存放CC,也没存放DD标志的位置
004011F1 |.>|cmp byte ptr ds:[edi+eax],0DD ;
004011F5 |.>|jnz short Snake.004011FB ;
004011F7 |>>|dec al
004011F9 |.>\jmp short Snake.004011EB
004011FB |>>lea eax,dword ptr ds:[edi+eax]
004011FE |.>mov byte ptr ds:[eax],99 ; [401BDD+T]=99;
00401201 |.>mov dword ptr ds:[401700],eax
00401206 |.>pop edi
00401207 |.>pop esi
00401208 |.>pop edx
00401209 |.>pop ecx
0040120A |.>pop eax
0040120B \.>retn
从上面的分析可以知道,对注册名的处理结果是在401B00至401BFF的空间中产生数量与注册名长度相等的’CC’标志以及1个’DD’标志和1个’99’标志.
下面我们再跟进对注册码进行处理的CALL:
0040120C /$>pushad ; 游戏开始,准备好吃果子了。
0040120D |.>mov esi,Snake.00401D00 ; 注册码地址
00401212 |.>mov edi,Snake.00401700 ; "99"标志的地址
00401217 |>>/movzx eax,byte ptr ds:[esi] ; 取注册码的1位 记作PASS[n]
0040121A |.>|test al,al ;
0040121C |.>|je short Snake.00401260
0040121E |.>|sub al,30 ;这几句ASCII码变成0-15的数字
00401220 |.>|cmp al,0A ;
00401222 |.>|jb short Snake.00401226 ; PASS[n]<10在401226处理
00401224 |.>|sub al,7 ; 若是字母,就-7,结果是A=10,B=11…F=15
00401226 |>>|mov ecx,eax ;
00401228 |.>|and al,3 ; 即PASS[n] MOD 4
0040122A |.>|shr cl,2 ; PASS[n]/4,是整数相除,ECX即下面的K
0040122D |.>|mov edx,10 ;edx是每次蛇移动的距离
00401232 |.>|test al,al ;看PASS[n] MOD 4是否为0
[招生]科锐逆向工程师培训(2025年3月11日实地,远程教学同时开班, 第52期)!