009 和 008 相比,多出來了一個輸入 Name 的輸入框。git
分別輸入 name 和 key,能夠看到錯誤提示:github
能夠看到,程序沒有殼,和 008 同樣仍是使用 VB 編寫的。函數
使用 OD 載入程序,搜索字符串測試
雙擊跟進程序,向上查找,和 008 同樣spa
能夠看到有一個比較的函數,一個 test 語句加一個跳轉指令,還有正確提示的字符串。3d
咱們在比較函數處下斷點,運行程序,程序斷在了斷點處。
繼續運行程序,能夠看到 比較函數運行完,EAX 寄存器的值爲 0code
咱們將 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; }