|
本帖最后由 Follow丶Me 于 2018-10-9 13:41 编辑
10.1国庆宅在家里,没事干就调戏了扫雷。
这是在Windows 7下的32位扫雷程序,有空在看看64位。
首先理清逆向思路:
1.载入OD,下消息断点201 (后来发现此路不通....)
2.后来枚举所有函数,发现了Rand这个有趣的东东,然后OD中 bp rand
3.最后游戏结束的时候发现对话框,可以直接给 DialogBoxParamW下断
上面是我自己的开始的思路,当然有大神提供思路的,请留言,十分感谢。
第一步,当然是载入OD,bp rand
接着程序会断这里
之后OD会不停的断在这,我们在堆栈窗口找到上层CALL的调用地址,再搜索哪些地方调用了当前的CALL,每个调用的地方都F2
就会得出有8个地方调用了,把那个一直调用rand的断点的去掉,还有把bp rand那个断也去掉
去掉之后再点击格子,此时回到OD如当前图片的断点,去这个CALL的头部从上往下分析。
经过分析,得知当前CALL是一个“布雷函数”
[Asm] 纯文本查看 复制代码
mov edi,edi ;布雷函数
push ebp
mov ebp,esp
push ecx
push ecx
push ebx
push esi
push edi
mov esi,ecx
call MineSweeper.0034D816 ;全局变量到EAX
push dword ptr ds:[esi+0x2C] ;push 5BB9B276 == push eax
mov dword ptr ss:[ebp-0x08],eax ;mov ecx, eax
call MineSweeper.0034D821 ;这个参数也就是eax 即为随机序列种子
push 0x00000010
call MineSweeper.0034DCA7 ;申请4个DWORD大小的空间(malloc)
pop ecx ;变相的平衡堆栈 ecx = eax = 0x5BB9B276
test eax,eax
je MineSweeper.003400F1
push 0x00000010 ;初始化函数第一个参数0x10
mov ecx,eax ;ecx = 01FD6948 即为第一次申请的空间首地址
call MineSweeper.0033F959 ;上面四个参数初始化为:0x0 0x0 0x10 0x0
mov dword ptr ss:[ebp-0x04],eax ;ecx = eax 即为01FD6948
jmp MineSweeper.003400F5
and dword ptr ss:[ebp-0x04],0x00000
mov eax,dword ptr ds:[esi+0x08] ;获取扫雷的行 rows
imul eax,dword ptr ds:[esi+0x0C] ;获取扫雷的列 eax = rows * columns -> 9+9 = 0x51
xor edi,edi ;i=0 edi置零
test eax,eax
jle MineSweeper.0034014B
mov ecx,dword ptr ds:[esi+0x0C] ;ecx = columns.....[esi]=3DC248
mov eax,edi ;eax = i
cdq
idiv ecx ;此时ecx为columns i/dwColumn=eax行号....edx列号
xor ecx,ecx ;ecx置零
sub edx,dword ptr ss:[ebp+0x08] ;sub 0,0 鼠标点击的列号
sub eax,dword ptr ss:[ebp+0x0C] ;sub 0,0 鼠标点击的行号
test edx,edx ;列号!!!
setnl cl ;根据列号是否正负,取绝对值
lea ecx,dword ptr ds:[ecx+ecx-0x01]
imul ecx,edx
cmp ecx,0x01
jnle MineSweeper.00340136 ;第一个差值绝对值<=1,判断第二个差值
xor ecx,ecx ;ecx置零
test eax,eax ;行号!!!
setnl cl ;根据行号是否正负,取绝对值
lea ecx,dword ptr ds:[ecx+ecx-0x01]
imul ecx,eax
cmp ecx,0x01
jle MineSweeper.0034013F ;第二个差值绝对值>=1
mov ecx,dword ptr ss:[ebp-0x04]
push edi
call MineSweeper.00355A51
mov eax,dword ptr ds:[esi+0x08] ;行数
imul eax,dword ptr ds:[esi+0x0C] ;列数 -> 行数 * 列数 = 0x51
inc edi ;i++
cmp edi,eax ;判断是否布满81个格子
jl MineSweeper.00340102 ;没有布满就继续
push 0x00000010
call MineSweeper.0034DCA7 ;第二次4个DWORD大小的申请空间
pop ecx ;变相平衡堆栈 ecx = 0x10
test eax,eax
je MineSweeper.00340165 ;可能是申请失败时的操作
push dword ptr ds:[esi+0x04] ;雷数入栈
mov ecx,eax ;ecx为第二次申请的首地址
call MineSweeper.0033F959 ;第二次申请空间初始化 0x0,0x0,0xA,0x0
mov edi,eax ;edi 为第二次申请的首地址
jmp MineSweeper.00340196 ;无条件跳
xor edi,edi
jmp MineSweeper.00340196
mov eax,dword ptr ss:[ebp-0x04] ;eax = 第一次申请的首地址
mov eax,dword ptr ds:[eax] ;eax = 0x4D = 77
test eax,eax
jbe MineSweeper.0034019D ;判断雷是否布完了
dec eax
push eax ;循环从0x4D 开始减一 入栈
push 0x00000000
call MineSweeper.0034D7F3 ;rand函数 随机数是:0-0x4C之间 即0-76之间
mov ebx,eax ;ebx = 雷的随机数
mov eax,dword ptr ss:[ebp-0x04] ;第一个申请的首地址
mov eax,dword ptr ds:[eax+0x0C] ;eax = 0436F980
push dword ptr ds:[eax+ebx*4] ;找到随机布局中放雷的位置
mov ecx,edi ;ecx = 第二个申请的首地址
call MineSweeper.00355A51 ;将数据保存到第二个申请空间里
mov ecx,dword ptr ss:[ebp-0x04] ;ecx第一个申请的首地址
push ebx
call MineSweeper.0034EC9E
mov eax,dword ptr ds:[edi] ;eax的值是存放布雷数
cmp eax,dword ptr ds:[esi+0x04] ;判断雷数
jne MineSweeper.00340169 ;雷数=第二次申请空间的第一个属性值
xor ecx,ecx
cmp dword ptr ds:[edi],ecx
jbe MineSweeper.003401C4
mov eax,dword ptr ds:[edi+0x0C] ;获取存雷数组的地址
mov eax,dword ptr ds:[eax+ecx*4] ;取第i(ecx)个雷的位置数
mov ebx,dword ptr ds:[esi+0x0C] ;扫雷初始化数据中第四个属性是列数
cdq
idiv ebx ;雷的位置数 / 列数 = 真实布雷的地址(EAX行号,EDX列号)
mov ebx,dword ptr ds:[esi+0x44] ;[esi+0x44]地址表
mov ebx,dword ptr ds:[ebx+0x0C] ;[[esi+0x44]+0xc] 第二层地址表
inc ecx ;i++
mov edx,dword ptr ds:[ebx+edx*4]
mov edx,dword ptr ds:[edx+0x0C] ;根据雷所在列号取第edx(列号)个地址
mov byte ptr ds:[eax+edx],0x01 ;为雷时,填充0x1
cmp ecx,dword ptr ds:[edi] ;判断是否布完了
jc MineSweeper.003401A3 ;布雷完毕
push 0x00000001
mov ecx,edi
call MineSweeper.0033FC96 ;free
mov ecx,dword ptr ss:[ebp-0x04]
pop edi
pop esi
pop ebx
test ecx,ecx
je MineSweeper.003401DE
push 0x00000001
call MineSweeper.0033FC96 ;free
push dword ptr ss:[ebp-0x08]
call MineSweeper.0034D821
leave
retn 0x0008
这还没完,在堆栈窗口找到向上2层的CALL那个才是左键点击的CALL
[Asm] 纯文本查看 复制代码
mov edi,edi ;左键单击函数
push ebp
mov ebp,esp
mov eax,dword ptr ds:[MineSweeper.003A68B4] ;这玩意就是基址
push ebx
push esi
mov esi,dword ptr ss:[ebp+0x08]
push edi
mov byte ptr ds:[eax+0x000000C5],0x01
push dword ptr ds:[esi+0x1C] ;这个是y 坐标
mov edi,ecx
push dword ptr ds:[esi+0x18] ;这个是x 坐标
mov ecx,dword ptr ds:[MineSweeper.003A68B4] ;this 指针
xor bl,bl
call MineSweeper.00341418 ;判断单击的是不是雷,传X,Y坐标
test eax,eax ;比较返回值
jnle MineSweeper.00346FF1
mov dword ptr ds:[edi+0x0000009C],esi
inc bl
jmp MineSweeper.00346FF9
push eax
mov ecx,edi
call MineSweeper.00346BCD ;后续CALL
mov byte ptr ds:[edi+0x000000AC],0x01
pop edi
pop esi
mov al,bl
pop ebx
pop ebp
etn 0x0004
再分析一下这个CALL里面“主要”做了什么:call MineSweeper.00341418 --> 判断单击的是不是雷,传X,Y坐标
[Asm] 纯文本查看 复制代码
mov edi,edi
push ebp
mov ebp,esp
ecx,dword ptr ds:[ecx+0x10] ;this指针偏移+0x10(第5个属性地址)
pop ebp
jmp MineSweeper.00340C50 ;无条件跳
mov edi,edi
push ebp
mov ebp,esp
push ecx ;this->第5个属性地址
push ebx
mov ebx,dword ptr ss:[ebp+0x08] ;x坐标
push esi ;[esi+0x1C] = 存放x,y坐标的地址
mov esi,ecx ;此时esi=ecx=this指针->第5个属性地址
mov eax,dword ptr ds:[esi+0x40] ;this->某个对象
mov eax,dword ptr ds:[eax+0x0C] ;某个对象->属性
mov eax,dword ptr ds:[eax+ebx*4] ;ebx = x坐标
mov eax,dword ptr ds:[eax+0x0C] ;这个eax指向的地址就是存储[color=#666]所有列状态的地址表[/color]
push edi
mov edi,dword ptr ss:[ebp+0x0C] ;y 坐标
mov eax,dword ptr ds:[eax+edi*4] ;edi = y坐标
xor ecx,ecx
mov dword ptr ss:[ebp-0x04],ecx
cmp eax,0x09 ;未点击
je MineSweeper.00340C95
cmp eax,0x0B ;问号
je MineSweeper.00340C95
mov eax,dword ptr ds:[MineSweeper.003A68B4]
cmp byte ptr ds:[eax+0x18],cl
je MineSweeper.00340CE5
push ecx
push ecx
push ecx
call MineSweeper.003505E9
xor ecx,ecx
jmp MineSweeper.00340CE5
cmp dword ptr ds:[esi+0x18],ecx ;this->第七属性
jne MineSweeper.00340CBA ;判断是否第一次鼠标点击
push edi
push ebx
mov ecx,esi
call MineSweeper.003400BB ;布雷CALL
push 0x00000000
push edi
push ebx
push 0x00000000
push edi
push ebx
mov ecx,esi
call MineSweeper.00340A42
mov dword ptr ds:[esi+0x24],ebx
mov dword ptr ds:[esi+0x28],edi
jmp MineSweeper.00340CDD
mov eax,dword ptr ds:[esi+0x44]
mov eax,dword ptr ds:[eax+0x0C]
mov eax,dword ptr ds:[eax+ebx*4] ;这个ecx里面就是存储[color=#666]所有列有雷的地址表 [/color]
mov eax,dword ptr ds:[eax+0x0C]
cmp byte ptr ds:[edi+eax],cl ;判断是否为雷 [edi+eax]->edi=行 eax=地址偏移 cl=0(cl值不变)
je MineSweeper.00340CD0 ;不为雷跳转
最后分析得出:
真实基址 = 扫雷起始地址 + 0x868B4(RVA)
格子数据 = [[[[[[[真实基址] + 0x10] + 0x40] + 0x0C] + 4 * X坐标] + 0x0C]+ 4 * Y坐标]
取值范围:1~8数字 9未开 10旗 11问号 12空
雷数据 = [[[[[[[真实基址] + 0x10] + 0x44] + 0x0C] + 4 * X坐标] + 0x0C] + Y坐标]
esi = [[真实基址] + 0x10]
[esi + 0x04] = 雷数
[esi + 0x08] = 行数
[esi + 0x0C] = 列数
[esi + 0x18] = 鼠标左键单机次数
第一次单机时:
列号:[esi + 0x24]
行号:[esi + 0x28]
这就是鼠标左键CALL分析了,至于右键CALL提供思路:在第一块数据方格中下硬件写入断点
然后回溯跟踪 直到返回2次后,就是我们要找的CALL
OK...............................分析到这就结束了。
具体实现核心代码:
附上超级难度下秒杀图:
下载完成后把后缀名改一下,另外我用的是VS2015写的。
Projects003.7z
(950.37 KB, 下载次数: 21)
Projects002.7z
(1 MB, 下载次数: 26)
Projects001.7z
(1 MB, 下载次数: 26)
|
评分
-
参与人数 35 | 威望 +1 |
HB +93 |
THX +19 |
收起
理由
|
longge188
| |
|
+ 1 |
[吾爱汇编论坛52HB.COM]-吃水不忘打井人,给个评分懂感恩! |
虚心学习
| |
+ 1 |
|
[吾爱汇编论坛52HB.COM]-软件反汇编逆向分析,软件安全必不可少! |
temp
| |
+ 1 |
|
|
李卓吾
| |
+ 1 |
|
|
消逝的过去
| |
|
+ 1 |
|
冷亦飞
| |
+ 1 |
|
|
沉默的承诺
| |
+ 1 |
|
|
三月十六
| |
+ 1 |
|
|
芜湖哈
| |
+ 1 |
|
|
l278785481
| |
+ 1 |
|
|
车太震
| |
+ 1 |
+ 1 |
[吾爱汇编论坛52HB.COM]-感谢楼主热心分享,小小评分不成敬意! |
在天一方
| |
+ 2 |
|
[吾爱汇编论坛52HB.COM]-学破解防破解,知进攻懂防守! |
fjgh
| |
+ 2 |
+ 1 |
[吾爱汇编论坛52HB.COM]-学破解防破解,知进攻懂防守! |
liugu0hai
| |
+ 1 |
+ 1 |
[吾爱汇编论坛52HB.COM]-软件反汇编逆向分析,软件安全必不可少! |
口水鸡
| |
+ 1 |
|
[吾爱汇编论坛52HB.COM]-软件反汇编逆向分析,软件安全必不可少! |
hetao8003200
| |
|
+ 1 |
|
zxjzzh
| |
+ 2 |
|
[吾爱汇编论坛52HB.COM]-学破解防破解,知进攻懂防守! |
XiaoWeiSec
| |
+ 1 |
|
[吾爱汇编论坛52HB.COM]-吃水不忘打井人,给个评分懂感恩! |
kll545012
| |
+ 1 |
|
[吾爱汇编论坛52HB.COM]-软件反汇编逆向分析,软件安全必不可少! |
成丰羽
| |
+ 1 |
|
[吾爱汇编论坛52HB.COM]-感谢楼主热心分享,小小评分不成敬意! |
越宝
| |
|
+ 1 |
|
beijita520
| |
+ 1 |
|
|
2473262754
| |
+ 1 |
+ 1 |
|
baky1223
| |
+ 1 |
+ 1 |
[吾爱汇编论坛52HB.COM]-吃水不忘打井人,给个评分懂感恩! |
bnjzzheng
| |
|
+ 1 |
[吾爱汇编论坛52HB.COM]-吃水不忘打井人,给个评分懂感恩! |
zhangz
| |
+ 1 |
+ 1 |
|
w18665346
| |
+ 1 |
+ 1 |
[快捷评语] - 评分=感恩!简单却充满爱!感谢您的作品! |
liumeng
| |
+ 1 |
|
[快捷评语] - 评分=感恩!简单却充满爱!感谢您的作品! |
千江月8
| |
+ 1 |
+ 1 |
学习了很多 |
warhome
| |
+ 1 |
+ 1 |
[快捷评语] - 吃水不忘打井人,给个评分懂感恩! |
wangxp
| |
+ 1 |
+ 1 |
[快捷评语] - 评分=感恩!简单却充满爱!感谢您的作品! |
Oneness神
| |
+ 2 |
+ 1 |
[快捷评语] - 评分=感恩!简单却充满爱!感谢您的作品! |
耶稣
| |
+ 6 |
+ 1 |
[快捷评语] - 2018,狗年发发发,狗年旺旺旺! |
李沉舟
| |
+ 6 |
+ 1 |
[快捷评语] - 2018,狗年发发发,狗年旺旺旺! |
Shark恒
| + 1 |
+ 50 |
+ 1 |
[快捷评语] - 评分=感恩!简单却充满爱!感谢您的作品! |
查看全部评分
|