Like Share Discussion Bookmark Smile

J.J. Huang   2019-09-05   x64dbg   瀏覽次數:

x64dbg - 第三十一章 | 反匯編練習(二十)

目標程式

檔案下載:KeygenMe.exe
解壓密碼:morosedog


任務目標

  • 分析註冊碼算法

分析程式

  • 執行KeygenMe.exe

  • 輸入morosedog123456789

  • 點擊Check

  • 彈出Error detected! Remove debugger from Hard Drive (檢測到錯誤! 從硬盤驅動器中刪除調試器)

  • 點擊確定關閉視窗

  • 點擊About

  • 彈出It's quite simple : (self)keygen me. Good luck !!!!!

  • 點擊確定關閉視窗

檢驗顯示是使用MASM32 / TASM32編寫。


額外補充


搜尋思路

  • GetDlgItemTextA,對其設定中斷點

實際分析

  • 開啟KeygenMe.exe

  • 命令輸入bp GetDlgItemTextA,對其設定中斷點

  • 觀看中斷點視窗,可以看到已經下好中斷點

    1
    2
    3
    類型 位址       模組/標籤/異常                     狀態  反組譯         命 摘要
    軟體
    77086B36 <user32.dll.GetDlgItemTextA> 已啟用 mov edi,edi 0
  • F9執行程式

  • 輸入用戶名morosedog和序列號123456789,並按下Check

  • 斷點在77086B36 < | 8BFF | mov edi,edi |

    • 可見斷點記憶體位址為77086B36
  • F9執行程式,使用Alt + F9執行到使用者代碼(U),找到Call的位置。

  • 向上觀察

    1
    2
    3
    4
    5
    6
    004012B1   | 6A 1A                 | push 1A                                  |
    004012B3 | 68 38304000 | push <keygenme.sub_403038> | 403038:"morosedog"
    004012B8 | 6A 6A | push 6A |
    004012BA | FF75 08 | push dword ptr ss:[ebp+8] |
    004012BD | E8 08010000 | call <JMP.&GetDlgItemTextA> |
    004012C2 | 83F8 00 | cmp eax,0 |
  • F9繼續執行

  • 又斷點在77086B36 < | 8BFF | mov edi,edi |

    • 這是因為有兩個輸入框
  • F9執行程式,使用Alt + F9執行到使用者代碼(U),找到Call的位置。

  • 向上觀察

    1
    2
    3
    4
    5
    6
    004012C7   | 6A 1A                 | push 1A                                  |
    004012C9 | 68 38314000 | push keygenme.403138 | 403138:"123456789"
    004012CE | 6A 6B | push 6B |
    004012D0 | FF75 08 | push dword ptr ss:[ebp+8] |
    004012D3 | E8 F2000000 | call <JMP.&GetDlgItemTextA> |
    004012D8 | 83F8 00 | cmp eax,0 |
  • 在反匯編視窗右鍵點選分析->分析模組

    • x64dbg會有效幫助模組的分析及標記
  • F8一步一步過,並持續觀察、分析

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    004012F6   | 68 38304000           | push <keygenme.sub_403038>               | 403038:"morosedog"
    004012FB | E8 30010000 | call <JMP.&lstrlen> |
    00401300 | 33F6 | xor esi,esi | esi:sub_4011E2
    00401302 | 8BC8 | mov ecx,eax |
    00401304 | B8 01000000 | mov eax,1 |
    00401309 | 8B15 38304000 | mov edx,dword ptr ds:[<sub_403038>] | 00403038:"morosedog"
    0040130F | 8A90 37304000 | mov dl,byte ptr ds:[eax+403037] | eax+403037:L"g"
    00401315 | 81E2 FF000000 | and edx,FF |
    0040131B | 8BDA | mov ebx,edx |
    0040131D | 0FAFDA | imul ebx,edx |
    00401320 | 03F3 | add esi,ebx | esi:sub_4011E2
    00401322 | 8BDA | mov ebx,edx |
    00401324 | D1FB | sar ebx,1 |
    00401326 | 83C3 03 | add ebx,3 |
    00401329 | 0FAFDA | imul ebx,edx |
    0040132C | 2BDA | sub ebx,edx |
    0040132E | 03F3 | add esi,ebx | esi:sub_4011E2
    00401330 | 03F6 | add esi,esi | esi:sub_4011E2
    00401332 | 40 | inc eax |
    00401333 | 49 | dec ecx |
    00401334 | 75 D3 | jne keygenme.401309 |
  • 00401300 ~ 00401334 為註冊碼的計算指令

  • esi 儲存每次循環結果

  • ecx 為輸入的morosedog長度 (用於迴圈次數)

  • 以下為第一次的循環分析

  • mov edx,dword ptr ds:[<sub_403038>] 將輸入的morosedog存入edx

  • mov dl,byte ptr ds:[eax+403037]morosedog根據迴圈每個字的第一個字存入dl

  • and edx,FF 將高24位清為零

    • 當前edx6F726F6D = 0110 1111 0111 0010 0110 1111 0110 1101
    • 然後根據and``FF這表示 0000 0000 0000 0000 0000 0000 1111 1111 做相乘
    • 結果會是0000 0000 0000 0000 0000 0000 0110 1101 = 0000006D
  • imul ebx,edx 表示兩數相乘

    • 當前ebx = 0000006D,當前edx = 0000006D 相乘結果 ebx = 00002E69
  • add esi,ebx 表示兩數相加

    • 當前esi = 00000000ebx = 00002E69 (解釋為每次迴圈結果 相加 ebx)
  • mov ebx,edxedx 存放於 ebx

  • sar ebx,1 表示將向右移一位,代表除二

    • 當前ebx = 0000006D = 0000 0000 0000 0000 0000 0000 0110 1101
    • 向右移位 = 000000036 = 0000 0000 0000 0000 0000 0000 0011 0110
  • add ebx,3 表示加三

  • imul ebx,edx 表示兩數相乘

    • 當前ebx = 00000039,當前edx = 0000006D 相乘結果 ebx = 00001845
  • sub ebx,edx 表示減去

    • 當前ebx = 00001845,當前edx = 0000006D 減去結果 ebx = 000017D8
  • add esi,ebx 表示兩數相加

    • 當前esi = 00002E69,當前ebx = 000017D8 相加結果 esi = 00004641
  • add esi,esi 表示兩數相加 (自己加自己,表示自己乘二)

    • 結果 esi = 00008C82
  • inc eax 表示加一 (類似i++)

  • dec ecx 表示減一 (類似i–)

  • 根據上面的分析,最終可以得到esi的值就是註冊碼

  • 註冊機程式碼

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    #include <stdio.h>

    main() {
    int i, result = 0;
    char a[] = "morosedog";

    for (i = 0; i < 9; i++) {

    result += a[i] * a[i] + (a[i] / 2 + 3) * a[i] - a[i];
    result *= 2;

    }

    printf("$d\n", result);

    }
  • 將結果轉16進制與esi比對及結果


註:以上參考了
x64dbg
x64dbg’s documentation!
CSDN billvsme的专栏OllyDbg 使用笔记 (十七)