1. 程式人生 > >逆向新手踩坑指南之爬爬山能鍛煉身體

逆向新手踩坑指南之爬爬山能鍛煉身體

博客 相加 html 堆棧 裏的 搜索引擎 打開 bsp 左右

逆向新手踩坑指南之爬爬山能鍛煉身體

首先坐下,打開電腦,平復一下心情,開始逆向分析。

對了,開始之前,首先推薦一下本站大神的逆向工程系統教程:【傳送門】

好了,正文開始。軟件運行一下是這樣的:

技術分享圖片

直接IDA打開,字符串窗口(shift+F12):

技術分享圖片

what a f********ck???!!!這是啥?說好的字符串呢?說好的各種函數呢?

想了想忘了一件事情,先查查有沒有殼:

技術分享圖片

看到了剛才的小坑,順便在看看有沒有什麽加密方式:

技術分享圖片

沒有,很好,直接upx脫殼,然後再次進入IDA【其實根據剛才IDA的提示也能看出來是upx的殼】:

技術分享圖片

這次看到了字符串,然後根據關鍵字符串交叉引用後來到函數:

技術分享圖片

直接F5:

技術分享圖片

圈一裏面是什麽暫時不想管,直接從18行開始基本比較明顯了,一個是屏幕輸出函數printf,一個是從屏幕獲得輸入,圈二IDA本身分析得也很明顯,就是判斷長度的,字符串限制為19。22行跟進去以後是這樣的 :

技術分享圖片

這TM是啥?!?!?!不過結合26行,31行,37行能看到類似於a=a+b一樣的東西,是從dword_41A138[]裏面取值,然後直接加到dword_423D78這個變量裏面。

從29行和35行能判斷這個輸入的字符串一定是L或者R【根據ASCII碼】,既然22行不懂,就直接先動態走一走:

輸入19個字符串後:

技術分享圖片

在堆棧段看到了自己的輸入,然後跟進411C4F這個函數:

技術分享圖片

跟進去看得有點頭暈….但是看到函數的返回值eax裏面是13,換成十進制就是19,也就是這個函數是用來判斷輸入長度的【從IDA的整體流程也能推測出來】,繼續跟:

技術分享圖片

進入411C88這個函數:

技術分享圖片

這裏是一個重點,函數在這裏一直在41195C和411992之間循環,並且,在411987這一步直接和4做了異或,直接導致將我們輸入的字符串所有偶數位做了異或。從這一點判斷,這個函數應該是IDA偽代碼的第22行,對字符串進行了處理 :

技術分享圖片

處理方法就是偶數位和4做異或,根據IDA的判斷,異或後的值只能是L或者R。於是再次輸入的時候就知道該輸入些什麽了。經過反推,奇數位只能是L或者R,偶數位只能是V(代表R)或者H(代表L)。字符串輸入什麽變得清晰了。

直接讓程序執行完,然後手動改棧裏面的值,再返回:

技術分享圖片

從這裏開始的一大長串我沒有仔細分析,太多了,看得心煩,跟了幾次以後發現總是在這裏[411D97]跳轉,方便起見直接這裏下了斷點,也在[411D9C]這裏下了斷點,之所以這樣,是想隨時關註著各個寄存器的變化和堆棧的變化 :

技術分享圖片

然後結合IDA的整個流程:

技術分享圖片

能大概推測出這裏應該就是根據輸入的字符串判斷是在圈一還是圈二。

處理完畢以後就能直接出結果了:

技術分享圖片

還是我太天真,將輸入提交以後發現並不正確。然後思路基本就卡到這裏了,連續一兩天沒有進展,心裏憋屈得不得了。後來再次看題目的時候發現題目是mountain climbing。英文翻譯是爬山,爬山,爬山,山呢?!!!於是我的思路就有變成了找山…

繼續回到IDA來看吧,因為已經沒什麽可以看的了。這次就變成了分析前面所有沒分析過的函數,首先就是dword_41A138[]裏面是什麽?

技術分享圖片

從字面上理解rand()就是隨機數函數,每次都產生不一樣的隨機數,然後根據這個去進行加數字的運算,這TM能算出來啥?!

然而事實告訴我還是我太天真了(原諒我大學不是計算機專業,沒好好學過C….)。

c語言裏面有一個產生隨機數的函數,rand()。但是在學習過程中發現這是偽機的,雖然叫隨機,但是每一次結果都一樣(下面圖片來自隨便一個搜索引擎,隨便一搜一大把的講解):

技術分享圖片

於是思路一下子清晰了,srand()是一個固定的值(IDA裏面對沒有定義的數字後面會有一個u,undefined),那麽rand()產生的數字也是固定的!!!根據代碼描述,基本可以斷定那個dword_41A138[]就是山了,數組下標是這樣的101,201,202,301,302,303…寫成這樣也許更直觀:

技術分享圖片

從IDA裏的27行到41行看:

技術分享圖片

76(十進制ASCII碼)是L,82(十進制ASCII碼)是R,對應上面那張圖就是從101到201是L,從101到202是R。L和R就代表了如何下山。沒錯,你沒有看錯,就是下山,不是爬山。

問題來了,根據等差數列進行算數,一共由210個數字堆成山,一共20層,走法多了去了,這TM誰知道哪條路是對的…正在一籌莫展的時候想起了這一句話:

技術分享圖片

要找最大的數,那麽也簡單,從下山開始,只選擇最大的那個數。後來發現也不行,比如201是比202大,但是303比所有101,201,202加起來都要大,如果選了201,那麽永遠走不到303。這怎麽辦?

只能遍歷了。

問題又來了,怎麽遍歷?!!我想到了二叉樹遍歷,雖然C語言忘得差不多了,但是還依稀記得一點數據結構。當我自信滿滿得去操作一番搜索引擎的時候又進到了一個坑裏,二叉樹遍歷的代碼是這樣的(來自用搜索引擎搜索二叉樹遍歷後返回的一大把博客中隨便一個網絡博客):

技術分享圖片一共316行,相信我,這不是我想要的,首先以我近乎於只穿著內褲的C語言功底讀懂316行代碼還需要很多時間,其次還要搞明白並熟練使用結構體變量。而且,經過耐心的學習以後發現二叉樹遍歷不能滿足我的需求,因為二叉樹遍歷無法實現從E到D:

技術分享圖片

於是我的這道題目再次陷入深坑….

這裏卡了一天半左右,沒有任何思路,後來無聊,想了想一共有多少條路?我能不能手工遍歷(我是一個天真善良吃苦耐勞的八道杠優秀代表)。從上往下數第二層有2條,走到第三層有4層,第四層有8條…不會算了,在紙上畫到第五層的時候我已經有點崩潰了,又耐心思考了一個小時左右,耐著性子畫到了六層,終於讓我這個暈乎乎的腦袋看到了規律,2的幾次方。從山頂到第二層有2條路,到第三層有4條路,是2的平方。第四層是2的3次方。因為每一個節點對應下一層的節點只有兩個選擇。我打開windows鍵,在運行處輸入calc以後用科學計算器算了算2的19次方:

技術分享圖片

這是逼著我用程序來解這道題(此時心裏有一萬句臟話想說出口)。

既然用程序,問題就又來了,我如何表現每一種走法呢?這裏我又卡住了,盯著自己在紙上畫的所謂的山看了好久也沒有想出來用什麽辦法來表現每一條路徑。看看作者的源程序:

技術分享圖片

作者用了兩個數字來寫,i就是第幾層,j就是在i層的第幾個數。可是我表現不了從302到403啊,等等,302,403兩個數層數和尾標都是差1,在看看整個山的分布:

技術分享圖片

找到了一個規律,每條路都是只能差1,比如這條路:101,201,302,403,503,604…這條路裏,層數差1是固定的,可以用循環實現,問題是如何實現1,1,2,3,3,4這個路數。要麽加0,要麽加1。要麽加0,要麽加1。要麽加0,要麽加1。默念無數遍以後得到了這樣一個數列01101,我嘞個王母娘娘,臣妾終於做到了~!!!這TM不就是二進制麽,0代表往左走一步,1代表往右走一步。(偉大的二進制~!偉大的十六進制~!)如果有6層,那麽01101換算成十進制就是13,一共有32條路,00000也算一條路的話(十進制的0),11111就是最後一條路,十進制就是31,0到31一共32個數字,Nice,完美實現了所有路徑的表示,此時,半天又過去了…於是代碼實現就容易得多了,先定一個小目標,實現6層的山,用Python:

技術分享圖片

已然實現了所有路徑的表示方法,Nice!!!

下面面臨著怎麽把山裏的數字給扒出來,從作者的定義方式來看,定義的數組的長度在2000多,否則下標放不下,簡單,直接對照偽代碼寫出來C代碼,然後自己跑一邊就行,於是有了這段C代碼:

技術分享圖片

由於強迫癥的限制,我就不想在windows上跑,沒環境,不想裝,偉大的linux幹啥都行,為啥非要在windows上吊死,於是在我的kali上跑完以後是這樣的(自己又給自己挖了一個坑):

技術分享圖片

好了,數字找到了,也能按照自己的意願去進行遍歷了,剩下的就是融合C和Python在一起,用Python實現腳本計算(別問我為啥不用C)。

問題TMD又來了,我要如何把210個數字移到Python裏,這裏,我選擇了裸奔的方式:手工輸入!(C語言如何實現文件讀寫不會!不想學!)210個數字寫到Python的字典裏,比如:

技術分享圖片

實現遍歷的方法在前面已經寫出來,還剩下如何根據路徑把對應的數字進行相加,給一段關鍵代碼:

技術分享圖片

原理就是根據路徑尋找字典裏對應的點的值,然後相加,每條路徑都產生一個值,不斷的比較,只取最大的那個就行。

一陣開心地等待過後有了結果,然後根據最開始的對字符串進行處理的方式逆回去,提交答案以後又給了我當頭一棒,我是有多天真!!!為什麽不對?後來我把Python跑出來的結果用題目的exe跑了一遍,發現得到的數字不一樣…..郁悶。為啥不一樣?同樣是rand函數,固定srand。痛定思痛過後反思到了也許是不同的平臺就不一樣,然而我還是不想在電腦上裝VC。

那怎麽辦?

讓程序自己吐出來這個數組!

然後重新用OD運行這個exe,不過這次用F8走,為的是找到數組生成過程中產生的數字,於是我來到了這裏:

技術分享圖片

圖裏面這個不斷的跳轉就是在生成我們需要的這個數組,我們在411C29這個地方下斷點,並且每次查看對應地址的內容:

技術分享圖片

這就是我們需要的數組,總不能再跟210次,再寫210個字典裏的值吧?於是經過再次使用搜索引擎的技能,學會了條件斷點記錄到日誌,這樣,能把每次經過411C22這個點時的edx的值記錄在案!!!!

順便一說,在Python裏的文件讀寫,我還是會一點的…..

記錄的日誌大概是這個樣子的:

技術分享圖片

經過這次的改變,我的Python腳本再次跑了起來,得到如下結果:

技術分享圖片

然後根據那一連串的1001去反推回L和R,再反推回V和H,於是這次用我的字符串跑exe以後,exe跑出來的結果和我的Python一樣了。然後提交分數,FFFFF********KKKKKKKK!!!!!!還不對!!!為啥?我都找到最大的路了,得到最大的分數了!

然後,我笑了,腦子高興糊塗了,我提交了我的路徑,正確!

七天過去了,做逆向真是打發時間的好幫手~

相信聰明的你已經看到了我所有犯過的錯誤,並且已經知道了我寫的是哪裏的writeup…..

exe鏈接: https://pan.baidu.com/s/1o8LxYA2 密碼: jisg

逆向新手踩坑指南之爬爬山能鍛煉身體