【文章标题】: 新手练习 - 使 winmine (踩地雷) 不会爆炸
【文章作者】: riijj
【软件名称】: windows 的 winmine (踩地雷游戏)
【加壳方式】: 无壳
【使用工具】: OD
【操作平台】: winxp / win2000
【文章简介】: 给新手练习,启发对控制程序流程的兴趣,没有技术含量,老手们勿看
Part 1. 序
平日大家学习的知识,主要针对软件的保护 (例如壳) 和防止被破解。今天换一换口味,一起破坏 windows 自带的小游戏 – 踩地雷
这是一个简单的程序,只有一个 exe,没有壳。我们的目标是使这个 winmine 变成不会爆炸的,即使我们 click 中了地雷,也可以继续进行游戏,直至把地图完成为止
要完成这个任务,或许我们想 : 平日针对注册名字和序号的破解,见多了,但是今次要分析 winmine 的流程,了解它的结构,并且作出最正确的修改。
Part 2. OD 加载
从它的原理开始思考,假设它有一个数据结构,我们 click 在地图上,它便会检查是否中了地雷,如果中了,便立即完结了。
我们明显可以中断的地点,包括 : 按下鼠标消息, 游戏的计时消息
还有一个地方,就是绘画地雷 icon 的 function。每一场新游戏的开始,也会进行一些绘画工作。当我们中了地雷,它也需要把地雷绘画出来的。我们想,这个地方经常被呼叫。
01003E1A |. 8B45 14 MOV EAX,DWORD PTR SS:[EBP+14]
01003E1D |> 5D POP EBP
01003E1E \. C2 1000 RETN 10
01003E21 > $ 6A 70 PUSH 70 // <- 在这里
01003E23 . 68 90130001 PUSH winmine.01001390
01003E28 . E8 DF010000 CALL winmine.0100400C
01003E2D . 33DB XOR EBX,EBX
设断点
bp SetTimer
F9 运行,程序出现了。
现在,我们开始一个新游戏,当我们在地图点 click 第一次的时候,游戏开始计时,它便呼叫 SetTimer,我们将会停在那里。
开新游戏,随意按一个格子。
77E1C41F 90 NOP
77E1C420 90 NOP
77E1C421 > B8 0B120000 MOV EAX,120B // <- 在这里
77E1C426 8D5424 04 LEA EDX,DWORD PTR SS:[ESP+4]
77E1C42A CD 2E INT 2E
77E1C42C C2 1000 RETN 10
单步或 alt + F9 返回 winmine 的领空,便会到达
01003830 |. FF05 9C570001 INC DWORD PTR DS:[100579C]
01003836 |. E8 7AF0FFFF CALL winmine.010028B5
0100383B |. 6A 00 PUSH 0 ; /Timerproc = NULL
0100383D |. 68 E8030000 PUSH 3E8 ; |Timeout = 1000. ms
01003842 |. 53 PUSH EBX ; |TimerID
01003843 |. FF35 245B0001 PUSH DWORD PTR DS:[1005B24] ; |hWnd = 000B0132 ('Minesweeper',class='Minesweeper')
01003849 |. 891D 64510001 MOV DWORD PTR DS:[1005164],EBX ; |
0100384F |. FF15 B4100001 CALL DWORD PTR DS:[<&USER32.SetTimer>] ; \SetTimer
01003855 |. 85C0 TEST EAX,EAX // <- 在这里
01003857 |. 75 07 JNZ SHORT winmine.01003860
01003859 |. 6A 04 PUSH 4 ; /Arg1 = 00000004
0100385B |. E8 F0000000 CALL winmine.01003950 ; \winmine.01003950
01003860 |> A1 18510001 MOV EAX,DWORD PTR DS:[1005118]
01003865 |. 8B0D 1C510001 MOV ECX,DWORD PTR DS:[100511C]
0100386B |> 841D 00500001 TEST BYTE PTR DS:[1005000],BL
01003871 |. 5B POP EBX
01003872 |. 75 10 JNZ SHORT winmine.01003884
这时候,我们下断绘图 api,
bp BitBlt
F9 运行,中断在 BitBlt
77F42CB7 8D5424 04 LEA EDX,DWORD PTR SS:[ESP+4]
77F42CBB CD 2E INT 2E
77F42CBD C2 0400 RETN 4
77F42CC0 > 55 PUSH EBP
77F42CC1 8BEC MOV EBP,ESP
77F42CC3 8B4D 28 MOV ECX,DWORD PTR SS:[EBP+28]
77F42CC6 8B45 28 MOV EAX,DWORD PTR SS:[EBP+28]
alt+F9 返回到
01002647 |. FF35 245B0001 PUSH DWORD PTR DS:[1005B24] ; /hWnd = 0010013A ('Minesweeper',class='Minesweeper')
0100264D |. FF15 2C110001 CALL DWORD PTR DS:[<&USER32.GetDC>] ; \GetDC
01002653 |. 8B4C24 0C MOV ECX,DWORD PTR SS:[ESP+C]
01002657 |. 68 2000CC00 PUSH 0CC0020 ; /ROP = SRCCOPY
0100265C |. 8BF0 MOV ESI,EAX ; |
0100265E |. 8B4424 0C MOV EAX,DWORD PTR SS:[ESP+C] ; |
01002662 |. 8BD1 MOV EDX,ECX ; |
01002664 |. 6A 00 PUSH 0 ; |YSrc = 0
01002666 |. C1E2 05 SHL EDX,5 ; |
01002669 |. 0FBE9402 40530>MOVSX EDX,BYTE PTR DS:[EDX+EAX+1005340] ; |
01002671 |. 6A 00 PUSH 0 ; |XSrc = 0
01002673 |. 83E2 1F AND EDX,1F ; |
01002676 |. FF3495 205A000>PUSH DWORD PTR DS:[EDX*4+1005A20] ; |hSrcDC
0100267D |. C1E1 04 SHL ECX,4 ; |
01002680 |. 6A 10 PUSH 10 ; |Height = 10 (16.)
01002682 |. 6A 10 PUSH 10 ; |Width = 10 (16.)
01002684 |. 83C1 27 ADD ECX,27 ; |
01002687 |. C1E0 04 SHL EAX,4 ; |
0100268A |. 51 PUSH ECX ; |YDest
0100268B |. 83E8 04 SUB EAX,4 ; |
0100268E |. 50 PUSH EAX ; |XDest
0100268F |. 56 PUSH ESI ; |hDestDC
01002690 |. FF15 5C100001 CALL DWORD PTR DS:[<&GDI32.BitBlt>] ; \BitBlt
01002696 |. 56 PUSH ESI ; /hDC = 03010285
01002697 |. FF35 245B0001 PUSH DWORD PTR DS:[1005B24] ; |hWnd = 0010013A ('Minesweeper',class='Minesweeper')
0100269D |. FF15 28110001 CALL DWORD PTR DS:[<&USER32.ReleaseDC>] ; \ReleaseDC
这里有典型的复制 bitmap 函数,我们单步到 retn 离开
01003008 /$ 55 PUSH EBP
01003009 |. 8BEC MOV EBP,ESP
0100300B |. 53 PUSH EBX
0100300C |. 8B5D 08 MOV EBX,DWORD PTR SS:[EBP+8]
0100300F |. 56 PUSH ESI
01003010 |. 57 PUSH EDI
01003011 |. 8B7D 0C MOV EDI,DWORD PTR SS:[EBP+C]
01003014 |. 8BF7 MOV ESI,EDI
01003016 |. C1E6 05 SHL ESI,5
01003019 |. 03F3 ADD ESI,EBX
0100301B |. 0FBE86 4053000>MOVSX EAX,BYTE PTR DS:[ESI+1005340]
01003022 |. A8 40 TEST AL,40
01003024 |. 75 57 JNZ SHORT winmine.0100307D
01003026 |. 83E0 1F AND EAX,1F
01003029 |. 83F8 10 CMP EAX,10
0100302C |. 74 4F JE SHORT winmine.0100307D
0100302E |. 83F8 0E CMP EAX,0E
01003031 |. 74 4A JE SHORT winmine.0100307D
01003033 |. FF05 A4570001 INC DWORD PTR DS:[10057A4]
01003039 |. 57 PUSH EDI
0100303A |. 53 PUSH EBX
0100303B |. E8 FBFEFFFF CALL winmine.01002F3B
01003040 |. 8945 0C MOV DWORD PTR SS:[EBP+C],EAX
01003043 |. 57 PUSH EDI
01003044 |. 0C 40 OR AL,40
01003046 |. 53 PUSH EBX
01003047 |. 8886 40530001 MOV BYTE PTR DS:[ESI+1005340],AL
0100304D |. E8 F4F5FFFF CALL winmine.01002646 // 绘图呼叫
01003052 |. 837D 0C 00 CMP DWORD PTR SS:[EBP+C],0 // <- 来到这里
01003056 |. 75 25 JNZ SHORT winmine.0100307D
01003058 |. A1 98570001 MOV EAX,DWORD PTR DS:[1005798]
0100305D |. 891C85 A051000>MOV DWORD PTR DS:[EAX*4+10051A0],EBX
01003064 |. 893C85 C057000>MOV DWORD PTR DS:[EAX*4+10057C0],EDI
0100306B |. 40 INC EAX
0100306C |. 83F8 64 CMP EAX,64
0100306F |. A3 98570001 MOV DWORD PTR DS:[1005798],EAX
01003074 |. 75 07 JNZ SHORT winmine.0100307D
01003076 |. 8325 98570001 >AND DWORD PTR DS:[1005798],0
0100307D |> 5F POP EDI
0100307E |. 5E POP ESI
0100307F |. 5B POP EBX
01003080 |. 5D POP EBP
01003081 \. C2 0800 RETN 8
我们想知道这个地区是不是一个子函数,所以在 OD 点选 01003008 这行 (这部份函数的第一行指令),然后 Ctrl +R ,搜索 winmine 所有对这里的呼叫
搜索得到 9 个结果,被不同地方呼叫,很明显这里只是一个子函数。我们要了解整体流程,还要往上走
F8 单步离开
01003084 /$ 55 PUSH EBP
01003085 |. 8BEC MOV EBP,ESP
01003087 |. 53 PUSH EBX
01003088 |. FF75 0C PUSH DWORD PTR SS:[EBP+C] ; /Arg2
0100308B |. 33DB XOR EBX,EBX ; |
0100308D |. FF75 08 PUSH DWORD PTR SS:[EBP+8] ; |Arg1
01003090 |. 43 INC EBX ; |
01003091 |. 891D 98570001 MOV DWORD PTR DS:[1005798],EBX ; |
01003097 |. E8 6CFFFFFF CALL winmine.01003008 ; \winmine.01003008
0100309C |. 391D 98570001 CMP DWORD PTR DS:[1005798],EBX
010030A2 |. 74 70 JE SHORT winmine.01003114
010030A4 |. 56 PUSH ESI
010030A5 |. 57 PUSH EDI
010030A6 |> 8B349D C057000>/MOV ESI,DWORD PTR DS:[EBX*4+10057C0]
010030AD |. 8B3C9D A051000>|MOV EDI,DWORD PTR DS:[EBX*4+10051A0]
010030B4 |. 4E |DEC ESI
010030B5 |. 8D47 FF |LEA EAX,DWORD PTR DS:[EDI-1]
010030B8 |. 56 |PUSH ESI ; /Arg2
010030B9 |. 50 |PUSH EAX ; |Arg1
010030BA |. E8 49FFFFFF |CALL winmine.01003008 ; \winmine.01003008
010030BF |. 56 |PUSH ESI ; /Arg2
010030C0 |. 57 |PUSH EDI ; |Arg1
010030C1 |. E8 42FFFFFF |CALL winmine.01003008 ; \winmine.01003008
010030C6 |. 8D47 01 |LEA EAX,DWORD PTR DS:[EDI+1]
010030C9 |. 56 |PUSH ESI ; /Arg2
010030CA |. 50 |PUSH EAX ; |Arg1
010030CB |. 8945 0C |MOV DWORD PTR SS:[EBP+C],EAX ; |
010030CE |. E8 35FFFFFF |CALL winmine.01003008 ; \winmine.01003008
我们看见很多 winmine.01003008 的呼叫 (刚才的绘图函数),我们估计,这里是 winmine 分析那个地图的地区,被一起打开了,需要显示空白地面出来。
那些参数 Arg1 和 Arg2,不用说,它就是 winmine 地图的 X-Y 坐标。
我们继续向前走,离开这里,返回到
0100356A |. EB 44 JMP SHORT winmine.010035B0
0100356C |> FF7424 18 PUSH DWORD PTR SS:[ESP+18] ; /Arg2
01003570 |. C1E0 05 SHL EAX,5 ; |
01003573 |. 8D8408 4053000>LEA EAX,DWORD PTR DS:[EAX+ECX+1005340] ; |
0100357A |. C602 0F MOV BYTE PTR DS:[EDX],0F ; |
0100357D |. 8008 80 OR BYTE PTR DS:[EAX],80 ; |
01003580 |. 56 PUSH ESI ; |Arg1
01003581 |. E8 FEFAFFFF CALL winmine.01003084 ; \winmine.01003084
01003586 |. EB 28 JMP SHORT winmine.010035B0
01003588 |> 6A 4C PUSH 4C
0100358A |. 50 PUSH EAX
0100358B |. 56 PUSH ESI
0100358C |. E8 1AF9FFFF CALL winmine.01002EAB
01003591 |. 6A 00 PUSH 0
01003593 |. EB 16 JMP SHORT winmine.010035AB
01003595 |> 50 PUSH EAX ; /Arg2
01003596 |. 56 PUSH ESI ; |Arg1
01003597 |. E8 E8FAFFFF CALL winmine.01003084 ; \winmine.01003084
0100359C |. A1 A4570001 MOV EAX,DWORD PTR DS:[10057A4] // 在这里
010035A1 |. 3B05 A0570001 CMP EAX,DWORD PTR DS:[10057A0]
010035A7 |. 75 07 JNZ SHORT winmine.010035B0
010035A9 |. 6A 01 PUSH 1
010035AB |> E8 CCFEFFFF CALL winmine.0100347C
010035B0 |> 5F POP EDI
010035B1 |. 5E POP ESI
010035B2 |. 5D POP EBP
010035B3 |. 5B POP EBX
010035B4 \. C2 0800 RETN 8
这个地方,比较长一点,我们向上看看,开始位置是 01003512 。我们 Ctr+R 搜索一下,发现只有一处呼叫,很明显这里是高层的流程部份。
我们尝试把 BitBlt 断点清除,在 01003512 下断,F9 让程序运行。
winmine 正常显示了,刚才被按的地方打开了,现在我们再随意按一个格子。
01003512 /$ 8B4424 08 MOV EAX,DWORD PTR SS:[ESP+8] // 果然断在这里
01003516 |. 53 PUSH EBX
01003517 |. 55 PUSH EBP
01003518 |. 56 PUSH ESI
01003519 |. 8B7424 10 MOV ESI,DWORD PTR SS:[ESP+10]
0100351D |. 8BC8 MOV ECX,EAX
0100351F |. C1E1 05 SHL ECX,5
01003522 |. 8D9431 4053000>LEA EDX,DWORD PTR DS:[ECX+ESI+1005340]
01003529 |. F602 80 TEST BYTE PTR DS:[EDX],80
0100352C |. 57 PUSH EDI
0100352D |. 74 66 JE SHORT winmine.01003595
0100352F |. 833D A4570001 >CMP DWORD PTR DS:[10057A4],0
01003536 |. 75 50 JNZ SHORT winmine.01003588
01003538 |. 8B2D 38530001 MOV EBP,DWORD PTR DS:[1005338]
0100353E |. 33C0 XOR EAX,EAX
01003540 |. 40 INC EAX
01003541 |. 3BE8 CMP EBP,EAX
01003543 |. 7E 6B JLE SHORT winmine.010035B0
这个地方,是 winmine 被玩家按下时的处理程序。这里或许包含了检查 "中地雷" 的跳转。我们现在 F8 单步分析。
01003512 /$ 8B4424 08 MOV EAX,DWORD PTR SS:[ESP+8] // 开始跟踪
01003516 |. 53 PUSH EBX
01003517 |. 55 PUSH EBP
01003518 |. 56 PUSH ESI
01003519 |. 8B7424 10 MOV ESI,DWORD PTR SS:[ESP+10]
0100351D |. 8BC8 MOV ECX,EAX
0100351F |. C1E1 05 SHL ECX,5
01003522 |. 8D9431 4053000>LEA EDX,DWORD PTR DS:[ECX+ESI+1005340]
01003529 |. F602 80 TEST BYTE PTR DS:[EDX],80
0100352C |. 57 PUSH EDI
0100352D |. 74 66 JE SHORT winmine.01003595 // 跳了
0100352F |. 833D A4570001 >CMP DWORD PTR DS:[10057A4],0
01003536 |. 75 50 JNZ SHORT winmine.01003588
01003538 |. 8B2D 38530001 MOV EBP,DWORD PTR DS:[1005338]
0100353E |. 33C0 XOR EAX,EAX
01003540 |. 40 INC EAX
01003541 |. 3BE8 CMP EBP,EAX
01003543 |. 7E 6B JLE SHORT winmine.010035B0
01003545 |. 8B1D 34530001 MOV EBX,DWORD PTR DS:[1005334]
0100354B |. BF 60530001 MOV EDI,winmine.01005360
01003550 |> 33C9 /XOR ECX,ECX
01003552 |. 41 |INC ECX
01003553 |. 3BD9 |CMP EBX,ECX
01003555 |. 7E 0B |JLE SHORT winmine.01003562
01003557 |> F6040F 80 |/TEST BYTE PTR DS:[EDI+ECX],80
0100355B |. 74 0F ||JE SHORT winmine.0100356C
0100355D |. 41 ||INC ECX
0100355E |. 3BCB ||CMP ECX,EBX
01003560 |.^7C F5 |\JL SHORT winmine.01003557
01003562 |> 40 |INC EAX
01003563 |. 83C7 20 |ADD EDI,20
01003566 |. 3BC5 |CMP EAX,EBP
01003568 |.^7C E6 \JL SHORT winmine.01003550
0100356A |. EB 44 JMP SHORT winmine.010035B0
0100356C |> FF7424 18 PUSH DWORD PTR SS:[ESP+18] ; /Arg2
01003570 |. C1E0 05 SHL EAX,5 ; |
01003573 |. 8D8408 4053000>LEA EAX,DWORD PTR DS:[EAX+ECX+1005340] ; |
0100357A |. C602 0F MOV BYTE PTR DS:[EDX],0F ; |
0100357D |. 8008 80 OR BYTE PTR DS:[EAX],80 ; |
01003580 |. 56 PUSH ESI ; |Arg1
01003581 |. E8 FEFAFFFF CALL winmine.01003084 ; \winmine.01003084
01003586 |. EB 28 JMP SHORT winmine.010035B0
01003588 |> 6A 4C PUSH 4C
0100358A |. 50 PUSH EAX
0100358B |. 56 PUSH ESI
0100358C |. E8 1AF9FFFF CALL winmine.01002EAB
01003591 |. 6A 00 PUSH 0
01003593 |. EB 16 JMP SHORT winmine.010035AB
01003595 |> 50 PUSH EAX ; /Arg2 // 到达了这里
01003596 |. 56 PUSH ESI ; |Arg1
01003597 |. E8 E8FAFFFF CALL winmine.01003084 ; \winmine.01003084 // 绘图
0100359C |. A1 A4570001 MOV EAX,DWORD PTR DS:[10057A4]
010035A1 |. 3B05 A0570001 CMP EAX,DWORD PTR DS:[10057A0]
010035A7 |. 75 07 JNZ SHORT winmine.010035B0 // 跳过
010035A9 |. 6A 01 PUSH 1
010035AB |> E8 CCFEFFFF CALL winmine.0100347C
010035B0 |> 5F POP EDI // 到这里
010035B1 |. 5E POP ESI
010035B2 |. 5D POP EBP
010035B3 |. 5B POP EBX
010035B4 \. C2 0800 RETN 8
从上面看,有两个可疑的跳转,
第一个是 0100352D,下面包含了很多代码,我们估计它是踏中地雷时的处理部份。
第二个是 010035A7,这个暂时不清楚,或许是一些后期工作。如果不跳,只呼叫一个地方 CALL winmine.0100347C ,我们现在先从这个入手,试试修改这个简单的跳转,看看 CALL winmine.0100347C 有甚么特别。
F9 运行,再任意按一个格子,断在 01003512
单步到 010035A7,把 OD 中 ZF 旗标修改为 1,使它不跳
F9 运行
奇怪的事发生了 ! winmine 显示输入玩家名称,因为 winmine 误认我们完成游戏了,时间是破纪录的快。
这个情况,表示了如果我们成功把游戏的地图解开,最后便会来到 010035A7,呼叫 CALL winmine.0100347C 完成游戏。
我们想,这个是成功的呼叫,那么就是说,如果我们踏中了地雷,并且它跳过了这里,直接离开此区的话,我们便要阻止那一个跳转。
我们重新开始游戏,只在 01003512 设断点,一直按下 winmine 格子,直至我们踏中了地雷
01003512 /$ 8B4424 08 MOV EAX,DWORD PTR SS:[ESP+8]
01003516 |. 53 PUSH EBX
01003517 |. 55 PUSH EBP
01003518 |. 56 PUSH ESI
01003519 |. 8B7424 10 MOV ESI,DWORD PTR SS:[ESP+10]
0100351D |. 8BC8 MOV ECX,EAX
0100351F |. C1E1 05 SHL ECX,5
01003522 |. 8D9431 4053000>LEA EDX,DWORD PTR DS:[ECX+ESI+1005340] // 分析后,发现这里是 winmine 地图的数据结构所在
01003529 |. F602 80 TEST BYTE PTR DS:[EDX],80
0100352C |. 57 PUSH EDI
0100352D |. 74 66 JE SHORT winmine.01003595 // 检查了是否踏中地雷
0100352F |. 833D A4570001 >CMP DWORD PTR DS:[10057A4],0 // 踏中了,来到这里
01003536 |. 75 50 JNZ SHORT winmine.01003588
我们看了一下 LEA EDX,DWORD PTR DS:[ECX+ESI+1005340] ,在 dump 中看到一段有规律的资料,很明显这些就是 winmine 地图的真正资料。
我们踏中了地雷, 0100352D 不跳,到达下面。我们开始 F8 跟踪,看看有甚么发现
0100352F |. 833D A4570001 >CMP DWORD PTR DS:[10057A4],0
01003536 |. 75 50 JNZ SHORT winmine.01003588 // <- 跳了
01003538 |. 8B2D 38530001 MOV EBP,DWORD PTR DS:[1005338]
0100353E |. 33C0 XOR EAX,EAX
...
01003586 |. EB 28 JMP SHORT winmine.010035B0
01003588 |> 6A 4C PUSH 4C // <- 到了这里
0100358A |. 50 PUSH EAX
0100358B |. 56 PUSH ESI
0100358C |. E8 1AF9FFFF CALL winmine.01002EAB
01003591 |. 6A 00 PUSH 0
01003593 |. EB 16 JMP SHORT winmine.010035AB // 强行跳了
01003595 |> 50 PUSH EAX ; /Arg2
01003596 |. 56 PUSH ESI ; |Arg1
01003597 |. E8 E8FAFFFF CALL winmine.01003084 ; \winmine.01003084
0100359C |. A1 A4570001 MOV EAX,DWORD PTR DS:[10057A4]
010035A1 |. 3B05 A0570001 CMP EAX,DWORD PTR DS:[10057A0]
010035A7 |. 75 07 JNZ SHORT winmine.010035B0
010035A9 |. 6A 01 PUSH 1
010035AB |> E8 CCFEFFFF CALL winmine.0100347C // 来到这里,很值得注意,因为上一次成功游戏,也是到这里
010035B0 |> 5F POP EDI
010035B1 |. 5E POP ESI
010035B2 |. 5D POP EBP
010035B3 |. 5B POP EBX
010035B4 \. C2 0800 RETN 8
很奇怪,最后我们再次到达 010035AB 的 CALL winmine.0100347C,我们上一次成功了游戏,不是也到了这里吗 ? 看清楚一点,今次的参数,
是 push 了 0,上一次是 push 1
意思是, CALL winmine.0100347C 这个呼叫,如果传入了 1,代表游戏成功,如果是 0 代表你踏中地雷。
到了现在的阶段,我们可以任意修改它了。
按照我们当初的目标,是使它在踏中了地雷时不会爆炸。
我们知道,一般的点按 (不是完成游戏,也没有踏中地雷),是会跳过 010035AB,直接来到 010035B0 的。我们现在只需要把踏中地雷的跳转修改,指向这里便行了。
01003586 |. EB 28 JMP SHORT winmine.010035B0
01003588 |> 6A 4C PUSH 4C // <- 到了这里
0100358A |. 50 PUSH EAX
0100358B |. 56 PUSH ESI
0100358C |. E8 1AF9FFFF CALL winmine.01002EAB
01003591 |. 6A 00 PUSH 0 // <- 改这里
01003593 |. EB 16 JMP SHORT winmine.010035AB // 强行跳了 <-- 改这里
我们把 01003591 nop 了,再把 01003593 的 jmp 改成 JMP 010035B0
清除其它断点,重新开始游戏, F9 运行
现在任意打开格子
果然,即使踏中了地雷,它是显示了,但不会爆炸 :-)
Part 3. 总结
近年软件安全的发展,走到了一个很复杂的地步,双方都花了大量 "气力",不论破解或保护,都很费精神,花的体力巨大。我们对于一些简单的破解所带来的趣味,是很怀念的。这篇文章希望给新手们一次比较有趣的学习,只懂得使用简单 OD,不懂脱壳或算法的兄弟,也可以参与。
2007 年 5 月9 日
转载请保持内容完整
[课程]Linux pwn 探索篇!