程序:
運行程序
彈出一個對話框,點擊 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 指令