x64dbg - 第十一章 | 反匯編練習(二) 下
前置作業
這篇延續上兩篇文章,所以請先行觀看x64dbg - 第九章 | 反匯編練習(二) 上和x64dbg - 第十章 | 反匯編練習(二) 中
- 重點:
00401340
,該函數是計算序列號的地方。 - 重點:比較的時候是使用
ebp
和eax
比較,而ebp
為程式計算出來的eax
為使用者輸入的。1
2
30040138D | 55 | push ebp | ebp:"5075"
0040138E | 50 | push eax | eax:"12345678"
0040138F | FF15 04404000 | call dword ptr ds:[<&lstrcmpA>] |
任務目標
- 找出計算序列號的邏輯。
實際分析
開啟
TraceMe.exe
在命令區塊輸入
bp 00401340
,並按Enter
(狀態:已於 00401340 設置中斷點!)F9
執行程式輸入用戶名
abcdefg
和序列號12345678
,並按下Check
斷點在
00401340 | 55 | push ebp |
F8
一步一步過,並持續觀察第一段分析
1
2
3
4
5
6
7
8
9
1000401340 | 55 | push ebp |
00401341 | 8B6C24 0C | mov ebp,dword ptr ss:[esp+C] |
00401345 | 56 | push esi |
00401346 | 57 | push edi |
00401347 | 8B7C24 18 | mov edi,dword ptr ss:[esp+18] |
0040134B | B9 03000000 | mov ecx,3 |
00401350 | 33F6 | xor esi,esi |
00401352 | 33C0 | xor eax,eax |
00401354 | 3BF9 | cmp edi,ecx |
00401356 | 7E 21 | jle traceme.401379 |該段分析是表示輸入的用戶名長度與3做比較
註:所以一開始才會有用戶名長度必須大於四個
F8
繼續步過,並持續觀察第二段分析
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29// 反匯編視窗:主要計算序列號的核心
00401358 | 53 | push ebx |
00401359 | 83F8 07 | cmp eax,7 |
0040135C | 7E 02 | jle traceme.401360 |
0040135E | 33C0 | xor eax,eax |
00401360 | 33D2 | xor edx,edx | edx:"abcdefg"
00401362 | 33DB | xor ebx,ebx |
00401364 | 8A1429 | mov dl,byte ptr ds:[ecx+ebp] |
00401367 | 8A98 30504000 | mov bl,byte ptr ds:[eax+405030] |
0040136D | 0FAFD3 | imul edx,ebx | edx:"abcdefg"
00401370 | 03F2 | add esi,edx | edx:"abcdefg"
00401372 | 41 | inc ecx |
00401373 | 40 | inc eax |
00401374 | 3BCF | cmp ecx,edi |
00401376 | 7C E1 | jl traceme.401359 |
// 暫存器視窗:以下為尚未進入計算核心的一個暫存器狀態
EAX : 00000000
EBX : 00000007
ECX : 00000003
EDX : 0018F6D8 "abcdefg"
EBP : 0018F6D8 "abcdefg"
ESP : 0018F66C
ESI : 00000000
EDI : 00000007
EIP : 00401359 traceme.00401359
// 資料視窗:`00405030`記憶體的值
00405030 0C 0A 13 09 0C 0B 0A 08 D0 F2 C1 D0 BA C5 B4 ED \f\n\t\f\v\n序列号错mov dl,byte ptr ds:[ecx+ebp]
表示抓取用戶名第ecx
偏移量的值- 所以
EDX
會是00000064
- 所以
mov bl,byte ptr ds:[eax+405030]
表示抓取00405030
的第eax
偏移量的值- 所以
EBX
會是0000000C
- 所以
imul edx,ebx
表示兩值相乘00000064
乘0000000C
等於000004B0
- 所以
EDX
會是000004B0
add esi,edx
表示兩值相加- 所以
ESI
會是000004B0
- 所以
inc ecx
表示ECX++
- 所以
ECX
會是00000004
- 所以
inc eax
表示EAX++
- 所以
EAX
會是00000001
- 所以
cmp ecx,edi
表示兩值比較- 因為不同,所以
SF = 1、OF = 0
- 因為不同,所以
jl traceme.401359
表示若低於則跳轉00000004
<00000007
所以跳轉到00401359
1 | // 暫存器視窗:第一次計算後狀態 |
- 上面已經針對每一行指令去做說明,經過運算過後最終會得到
ebp
的序列號 - 至於會迴圈幾次取決於輸入的用戶名長度
分析總結
- 根據輸入的用戶名,從第四個字元開始做序列號的計算
- 序列號的計算是透過
00405030
記憶體中0C 0A 13 09 0C 0B 0A 08 \f\n\t\f
值來做乘法、相加的計算
額外補充
[ ]
包起來的記憶體位址,表示會取該位址裡面的值- 例:
mov edi,dword ptr ss:[0018F6D8]
,會將0018F6D8
裡面的值存到EDI
裡面
- 例:
mov dl,byte ptr ds:[ecx+ebp]
如何知道他是修改EDX
暫存器的?mov bl,byte ptr ds:[eax+405030]
如何知道他是修改EBX
暫存器的?- 請參考下圖;
dl
表示8-bit
的EDX
- 請參考下圖;
bl
表示8-bit
的EBX
- 請參考下圖;
- C/C++資料長度
- BYTE = 8 BIT
- CHAR = 1 BYTE
- INT = 4 BYTE
- DOUBLE = 8 BYTE
- LONG = 4 BYTE
- SHORT = 2 BYTE
- WORD = 2 BYTE
- DWORD = 4 BYTE = 32 BIT
mov dl,byte ptr ds:[ecx+ebp]
為何只有儲存64
進EDX
?ds
表示什麼?mov bl,byte ptr ds:[eax+405030]
為何只有儲存0C
進EBX
?ds
表示什麼?byte
定義了儲存的容器大小,所以假設ecx:00000003
、ebp:0018F6D8
相加後0x18F6DB
,而0x18F6DB
中的值為64
- 請參考下圖;
ds
表示資料區段暫存器
經驗分享
- 計算記憶位址的四則運算,可以用
x64dbg
提供的計算機做運算00000003+0018F6D8
或是00000064*0000000C
- 每次在看會異動暫存器的指令時,往往無法第一時間知道來源暫存器和會被異動的暫存器哪個;其實只要注意暫存器視窗的標示即可。
- 請參考下圖,當滑鼠點擊到
mov dl,byte ptr ds:[ecx+ebp]
,然後注意右邊的暫存器視窗。ECX
、EBP
有綠色底線,表示來源EDX
有紅色底線,表示會被異動的暫存器
- 請參考下圖,當滑鼠點擊到
imul edx,ebx
,然後注意右邊的暫存器視窗。EBX
有綠色底線,表示來源EDX
有咖啡色底線,表示儲存的暫存器
註:以上參考了
x64dbg
x64dbg’s documentation!
CSDN billvsme的专栏 的 OllyDbg 使用笔记 (二)