009 和 008 相比,多出來了一個輸入 Name 的輸入框。git
分別輸入 name 和 key,能夠看到錯誤提示:github
能夠看到,程序沒有殼,和 008 同樣仍是使用 VB 編寫的。函數
使用 OD 載入程序,搜索字符串
測試
雙擊跟進程序,向上查找,和 008 同樣
spa
能夠看到有一個比較的函數,一個 test 語句加一個跳轉指令,還有正確提示的字符串。3d
咱們在比較函數處下斷點,運行程序,程序斷在了斷點處。
繼續運行程序,能夠看到 比較函數運行完,EAX 寄存器的值爲 0
code
咱們將 EAX 寄存器的值修改成 1,運行程序
blog
能夠看到,程序出現正確提示,能夠推測該比較函數就是關鍵點。
再次運行到該函數,查看參數。
進程
在這裏有一個關於 VB 的知識點,不知道的話這個程序很難分析出來。
VB 的變量都相似於一個結構體。變量的前 8 個字節,存放的是該變量的數據類型信息。第 9 個字節開始存放的是該變量的真正地址。也就是說「首地址+8」纔是該變量的真正地址。ip
分別查看兩個參數
第一個參數
第二個參數
能夠看出來,第一個參數是咱們輸入的 key。通過測試,發現第二個參數就是正確的 key。
那麼這個 key 是哪裏來的呢?咱們向上找。
發現了一個循環
這個循環其實很簡單:
循環結束,程序又對循環獲得的值進行了加工
程序先把獲得的值,和 0x499602D2 進行相乘
而後依次使用"-"替換掉了計算結果的第4位和第9位,最後獲得的值就是真正的 Key。
#include <stdio.h> #include <string.h> int Key() { char szName[20] = { 0 }; char szKey[30] = { 0 }; int NameLen = 0; __int64 Result = 0; printf("請輸入用戶名:"); scanf_s("%s", szName, 20); NameLen = strlen(szName); for (int i = 0; i < NameLen; i++) { Result += szName[i]; } Result *= 1234567890; sprintf(szKey, "%I64d", Result); szKey[3] = '-'; szKey[8] = '-'; printf("%s", szKey); return 0; } int main(int argc, char* argv[]) { Key(); return 0; }