170531 逆向-CrackMe之007
1625-5 王子昂 總結《2017年5月31日》 【連續第242天總結】
A.CrackMe(7)
B.這次挑戰一下2星的程式
拖入PEiD,無殼,Delphi編寫的。
跟昨天的是同一個作者,同樣分多關、隱藏按鈕的套路
不過這次OK是直接顯示的,雖然也有Cancella
這次比昨天的難,反而有文字字串了,直接搜尋就能找到相應位置
不過有好用的Dede幹嘛不用呢,還能方便地直接標出API的名字
拖入Dede,一共有三個事件,分別響應cancella、register和again
again還不知道是啥,按照昨天的順序,先跟cancella試試吧
找到事件,往下翻幾步就看到了熟悉的test ax,ax和jz 這裡大概就是關鍵跳轉了,爆破之
彈出了兩個框,“GREAT!"和”LAMER“
前者很明顯是恭喜的意思,但是LAMER我百度了一下,除了最多的是一個服裝品牌,百度翻譯說是蹩腳的、差勁的意思
嗯?而且成功以後只有彈窗,沒有任何變化
雖然很奇怪,但是上上下下都翻了幾遍也沒看到別的路徑了只好先這樣
同樣,找到register的地址,判斷方法相同,爆破後register按鈕消失,出現了"...again"按鈕
此時Name的框變成了灰色無法輸入狀態,看樣子兩次的Name是不允許改變的啊
同樣,在Dede中找到again事件的地址,爆破,全部消失露出了Logo。
值得一提的是,因為register存在內層的一個關鍵call,我剛開始爆破內部call的時候,後面嘗試點選again居然也直接通過了
後面才發現again事件和register事件程式碼完全一樣,呼叫的是同一個函式(call)
演算法:
先是cancella
跟進去有兩次關鍵跳轉,跟昨天相似
最外部通過test ax,ax來判斷是否為0;然後第二層再一個test
跟到關鍵call裡面以後,進行了一番非常複雜的計算。但是核心的只有長度比較和字串ASCII比較
只要取兩個字元相同的、長度都大於4的字串即可
輸入後反應與爆破相同
然後看register
跟進去,在關鍵call中耐著性子讀每行程式碼
首先是一個複雜的雙層巢狀迴圈,對每個字元,都與整個字串的所有ASCII碼相乘一遍,然後再乘以一個數,最後全部累加起來。這個數在多次執行的情況下都是0,那麼最終求和就全是0了。
求和結果與0做異或運算,應該是取反的效果
修正:與一個小夥伴討論,又去查找了一下,該段程式碼應為abs絕對值函式的優化彙編
若為正數,dx為0,xor 0和sub 0的結果都不變
若為負數,dx為-1,xor -1為取反,sub -1為+1,即求該負數的補碼,即求相反數
綜上是為絕對值函式
(原始碼為mov eax,ebx
cdq
xoreax,edx
subeax,edx)
感覺在bx作為累加和恆為正的前提下,dx一定為0,則做異或運算和作差的結果應該就是取反吧
再除以0xA2C2A,保留餘數
然後拿出code轉換成整型的值,用除以0x59的商+除以0x50的餘數+1,與之前的數比較,相等則通過
之前說了Name的最終求和為0,最後的餘數也為0。而Code的結果有一個+1,除非是造成溢位才有可能得到0。然而作為32位除法的商和餘數,似乎無法使得結果出現FFFFFFFF。那麼就需要找出之前一直為0的數是怎麼回事了
向上跟蹤,發現這個數的路徑是ds:[0x445830]→eax→edi,跟到0x445830的地址,附近全是空的,壓根不在資料儲存附近
有點懵逼了,上下再看看程式碼,突然發現之前還有一處出現了mov ds:[0x445830],eax的語句。這不就是我夢寐以求的來源嗎,趕緊看看附近:喔,原來它只在對Code轉化成整型卻為0時才會觸發。此時會彈出一個錯誤視窗“YOU MUST INSERT A VALID LONG INTEGER VALUE IN THE CODE EDITOR...",然後會將Code的ASCII送入一個call中,算出值送入0x445830的記憶體區
那還等什麼,輸一個字母再跟進去唄:首先長度要大於5,然後取每個字元的ASCII除以0x11,餘數+1後乘上前一個字元的ASCII,進行一個(長度-1)的迴圈。加上0x37B的固定數,除以0x7148的餘數再取絕對值,即為之前演算法用到的數了。
總結一下,在這個演算法中,一個Name需要搭配兩次Code,分別為字母A和數字N;最終需要滿足f3[ f1(Name) , f2(A) ]=f4(N)的關係
again和register是一樣的演算法,將之前得到的數再輸入一遍即可
之後看了一下之前參考的52破解論壇的CrackMe系列的writeup,發現他沒有找到0x445830的位置,就卡著了╮(╯_╰)╭
不過後面跟帖裡有人給出了正解,跟我想的差不多
C.明日計劃
CrackMe(8)