160個crackme(6)
這是160個crackme的第六道,比較簡單;
一·逆向的軟體及目的:
當我們點選About-Help的時候,就知道了這道crackme是讓我們輸入正確的Nome(我覺得作者是將name打錯了…)和Codice,然後OK鍵和Cancella鍵會消失,顯示出後面的圖示:
二·開始工作:
分析:首先我們發現這個歐卡鍵是被灰度的,不可用,所以猜測應該是先輸入正確的註冊碼後,Cancella鍵消失,然後ok鍵可以用,然後再輸入正確的註冊碼後Ok鍵消失,圖示顯示出來。
正式開始逆向:
- PEID查殼:
沒有殼,是Delphi寫的。
- 因為IDE對Delphi編寫的軟體我覺得沒有DeDe分析的好,所以我喜歡用DeDe檢視一下事件:
一共有10個事件,根據名字我們發現前四個事件應該是關鍵的,我們在OD中將這幾個事件的開始地址00442C78,00442D64,00442E04,00442EA8下斷點並寫上註釋。
NomeChange事件:當我還在輸入的時候就斷在了00442E04的位置,然而我們並沒有點選任何按鈕,說明軟體在輸入的時候就開始判斷對不對了。然後我們F8單步繼續走(注意觀察堆疊和暫存器的變化),當我們走到00442E57的時候,我們發現將我們輸入的name放到暫存器EAX裡了,而下面剛好有一個call,這個call很有可能是驗證name的函式,所以F7單步進入,然後看到這裡:
說明輸入的name必須大於5個字元,然後下面就是關鍵演算法:
00442A93到00442AAC就是判斷name的演算法,翻譯成python就是:
eax=1 name=input(“name”) a=name b=len(a) ebx=b for i in range(0,b-1): ecx=ord(a[i]) esi=ord(a[i+1]) ecx=ecx*esi ecx=ecx*eax ebx=ebx+ecx eax=eax+1 print(hex(ebx))
然後通過name用上面演算法算出來的一個值減去通過codice用另一個演算法算出來的值,如果等於0x29A,那麼cancella鍵就會消失
CodeChange事件:當我們輸入codie時,程式斷下來了,然後F8繼續執行,同樣觀察堆疊和暫存器,在00442EE3的地址處,codice放入EAX中,所以進入下面的call,剛好是codice的演算法。
判斷codice的演算法:
可以看出輸入的codice必須是數字,然轉換為python程式碼就是:
for i in codie:
ecx=10*eax+int(i)
eax=ecx
print(hex(eax))
其實就是將codie字串轉換為unicode編碼
codeclik事件:點選cancella鍵時,在00442EA8斷了下來,然後00442EE7位置的call進入,這裡就是讓cancella鍵消失的關鍵函數了:
取name的第五位a[4],然後除以0x7取餘數後加0x2的值的階乘儲存下來,然後減去name計算出來的值如果等於0x7A69,就消去cancella鍵。
所以消去cancella鍵的註冊機可以這樣寫:
name=input("輸入name:")
eax=ord(name[4])%0x7+0x2 #對應0x0442B35
ebx=1
for i in range(1,eax+1): #call 0x042A20
ebx=ebx*i
eax=0
for i in name:
eax=eax+ord(i)*ebx #對應0x0442B54
ebx=eax-0x7a69 #反推密碼 對應0x0442B65
key=ebx
print(u"cancella鍵消失的密碼:%d"%key)
okclik事件:用上面同樣的方法,找到時ok鍵消失的演算法的位置00442BF9:
密碼從後往前獲取密碼一位的平方乘以(下標+1),除以0x19,餘數加0x41,替換掉原來的密碼位置,然後和name比較一不一樣,如果一樣就將ok鍵消失掉。
所以用python寫註冊機可以這樣寫:
先輸入codice然後再根據codice反算出name:
codice=input("輸入codice:")
a=codice
ecx=len(a)
eax=0
x=0
key=" "
for i in range(0,ecx):
x=ord(a[i])*ord(a[i]) #對應0x0442C0E
if(x>0xffff): #對應0x0442C10
x=0xffff
eax=x*(i+1)%0x19+0x41 #對應0x0442C1B和0x0442C1D
if(eax>0xff):
eax=0xff
key=key+chr(eax) #對應0x0442C21
print("OK鍵消失的name:%s"%key)
總結:將使ok鍵消失的程式碼和cancella消失的程式碼分開寫,也就是讓cancella的程式碼是通過name算出codice,讓ok鍵消失的程式碼是通過codice去算name,這樣要簡單一點!