程序:

運行程序

彈出一個對話框,點擊 OK

來到主界面,點擊 Help -> Register Now

這是輸入注冊碼的地方
按關閉程序的按鈕

會提示剩下 30 天的使用時間
用 Resscope 載入程序
在 Dialog 下找到程序要退出時的那個對話框

在 100 處找到該對話框
103 為 lpTemplateName 對話框模板
逆向:
用 OD 載入程序

右鍵 -> 查找 -> 所有命令

64 為 100 的十六進制

找到很多 push 0x64 的指令
右鍵 -> 在每個命令上設置斷點

跑一下程序

程序停在該斷點處,此時程序還沒運行起來,而且那個對話框是在程序被關閉的時候彈出的
按 F9 繼續運行

程序運行起來后,直接關閉程序

此時停在該斷點處,該處就是要彈出對話框的地方,可以把其它斷點都去掉了

這個 call 指令就是顯示模態對話框的指令
往上拉一點

這里有個 je 跳轉指令,如果執行跳轉的話,將跳過那個 call 指令
je 指令上面的 cmp 指令把 eax 和 1 進行比較,如果 eax 等於 1,就能執行跳轉
而 eax 的值是 call 指令調用的函數返回的值

在 call 指令下一個斷點,跑一下程序
按退出程序的按鈕之后,停在了 call 斷點處

按 F7 步入

按 F8 往下走

在這里調用了一個 API 函數 RegOpenKeyEx,這個 API 函數用於打開一個注冊表的鍵,注冊表鍵值不區分大小寫
該函數如果調用成功,則返回0(ERROR_SUCCESS)。否則,返回值為文件 WINERROR.h 中定義的一個非零的錯誤代碼
按 F8 接着往下走

這條指令把 API 函數 RegQueryValueEx 的地址傳給 esi
按 F8 接着往下走

這里有個 call esi,就是調用 RegQueryValueEx 函數
RegQueryValueEx 用於檢索一個已打開的注冊表句柄中,指定的注冊表鍵的類型和設置值
函數調用成功的話返回 0,如果失敗返回錯誤代碼
函數原型:
LONG WINAPI RegQueryValueEx(
HKEY hKey, // 一個已打開項的句柄,或者指定一個標准項名
LPCTSTR lpValueName, // 要查詢注冊表鍵值的名字字符串,注冊表鍵的名字,以空字符結束
LPDWORD lpReserved, // 未用,設為零
LPDWORD lpType, // 用於裝載取回數據類型的一個變量
LPBYTE lpData, // 用於裝載指定值的一個緩沖區
LPDWORD lpcbData // 用於裝載lpData緩沖區長度的一個變量,一旦返回,它會設為實際裝載到緩沖區的字節數
);
RegQueryValueEx 會把找到的鍵的值存放到數據緩沖區

它的參數按反依次對應
該函數要拿到 RegName3 鍵的值,把結果存到 edx 的地址中
edx 對應 lpData,ecx 對應 lpcbData

edx、ecx 分別為這兩個地址

調用完該函數后,該函數返回 2,也就是調用失敗,因為在注冊表中找不到 RegName3
按 F8 接着往下走

走到一個跳轉已實現的跳轉指令

如果該跳轉指令實現跳轉的話就會跳到函數的末尾
如果該跳轉指令不實現跳轉,接着往下走

就會再一次調用 RegQueryValueEx 函數,這次是要查找 RegCode3 鍵的值
會存放到 edx 的地址中

按 F8 接着往下走

這個跳轉指令也是跳轉到函數的末尾
讓其不跳轉

這兩句把這兩個地址傳給 edx 和 ecx,而這兩個地址剛才都傳給 edx 過,用來存放 RegName3 和 RegCode3 的結果

分別將 ecx 和 edx 入棧,然后通過 call 調用一個函數來驗證他們
按 F7 步入
該函數有兩個返回值

一個為 1,一個為 0
按 F8 往下走

有個已實現的跳轉

如果跳轉將跳過返回值為 1 的 retn
不讓其跳轉,接着往下走

接下來的三條跳轉指令都是跟第一條語句一樣的跳法,看來返回值為 1 才是我們想要的
讓這三條語句不跳,繼續往下走

這是最后一個跳轉指令,讓它不跳
接着往下走

函數返回了 1
接着往下走,一路默認

走到 retn 指令,此時 eax 的值還是為 1

eax 的值為 1,cmp 指令把 eax 的值 和 1 比較,如果相等,je 就執行跳轉
跳轉就跳過了調用對話框的那個 call 指令
