記錄一下,以免難以查找
期間走了很多彎路,想直接看破解部分的,請跳到13小節,以下:
1
od載入,斷在C語言運行時的入口
2 稍微向下拉一點,就到了Window窗口程序的入口 WinMain,即下圖的 0059173B
3 F7單步進入,005BE120處的Call是進入AfxWinMain
4 再往下一點, 005C7480處就是進入CWinApp.InitInstance()了
上圖 005C7472處的call是進入CWinApp.InitApplication()
以上的邏輯是程序進入 start->_WinMain -> WinMain-> CWinApp.InitInstance ()。 然後並沒有任何卵用,因爲都不是跟這個程序相關的,這是MFC的框架部分,進入CWinApp.InitInstance()後就被易語言的核心庫接管了,在這裏追了好幾天,對比了MFC的Dialog,SDI,MDI類型的程序,始終不一樣,都快放棄了,結果發現這個程序目錄裏會釋放出krnl這種東西,百度了一下才發現這是易語言……被自己蠢哭了。以下再跟下去,可以發現釋放各種核心庫和支持庫,校驗庫md5的代碼,這裏就不展開了,初始化流程是這樣,點了一個按鈕之後,怎麼知道這個按鈕對應的處理函數在哪裏呢?這裏就要祭出神器了,有大神分析過易語言消息分發的機制,http://bbs.pediy.com/showthread.php?t=195626,
易語言派發事件的特徵碼FF55FC5F5E
5 直接在Od Ctrl+B, 確定後,來到易語言分派消息的地方
00519F7D
6 F2 下斷,然後F7單步進入,我們就來到了點擊 登錄後 處理登錄的代碼了,
看到那個 ASC字符串麼,說明我們來對了,因爲沒有勾選那個協議的話,要彈個框,要求先勾選那個協議。往下拉一點,有個判斷 登錄成功 的字符串,說明登錄網絡操作的代碼應該在前面,於是我們在前面一個call處下斷,0047B0EA。這裏我作爲一個新手,犯了個自以爲是的錯誤,看到判斷
登錄成功 的地方,按照慣性思維,把判斷後的jmp代碼nop掉不就行了麼,nop掉之後運行,崩掉了。教程上邊都是這樣寫的啊?怎麼不對呢,教程是教程,實際應用中哪會這麼簡單,師傅領進門,修行靠個人啊。實際上這裏登錄成功和登錄失敗服務器返回的內容和格式都是不一樣的,這點後面細說。
7 F7單步進入,這裏就是拼接url,網絡驗證,解析服務器返回的內容了,這裏是重點,我們的破解也在這裏。向下大概翻閱一下,翻到ret,大概瀏覽一下這個函數,估計一下函數完成的內容。前半部分各種獲取隨機數,HardDiskCode,拼接url,然後網絡操作,接下來判斷服務器返回的內容,前半部分略過不提,接下來需要壓入30個參數的函數,就是網絡操作了,00404655處的call就是網絡操作,有興趣可以跟進入看看,不過這裏我們沒必要,因爲我跟進入讀完了發現跟我們的目的沒有任何關係,摔……
8 完了之後又開始釋放調用之前分配的各種參數,說優化不好也確實是這樣,很少見到過需要30個參數的函數,call前一堆Alloc,call後一堆Free,這種風格在代碼裏大量出現。剛剛我們網絡操作的call後 我們單步一下看看是什麼情況,F7單步到00404743處的代碼後
9 寄存器eax裏出現了服務器返回的內容
10 然後接下來的代碼就不貼圖了,主要邏輯是
判斷返回的內容中是否有 !DOCTYPE ,如果有說明服務器出錯了,
判斷返回值是否爲空,空說明服務器連接失敗,
判斷返回內容左邊4個字是否是登錄成功 ,
如果是,開始解析內容
解析內容的方法是將返回的內容 使用\r\n分割,分割的代碼在這裏。
11 因爲需要了解分割的內容格式是什麼樣的,繼續往下讀代碼。接下來兩段是判斷分割後的內容,分割後應該是返回一個數組,數組分爲3部分,第一部分是int值表示第二部分有幾個int,第二部分是多個int值,表示第三部分有多少,第二部分的多個int值乘積結果就是第三部分的個數,第三部分就是多個指針,指向分割後的字符串。判斷的代碼在下面:
12 看00404910那個地方,分割後的結果有9個字符串啊,這下明白了我們爲什麼不能直接nop掉前面判斷登錄成功登錄失敗的代碼了吧,因爲根本沒用,登錄成功後還有一些其他的操作需要用到這裏的數據。再往下就是將分割後的字符串保存到傳入這個函數的參數arg1中,arg1應該是個對象,接下來分別將9個參數存入對應的位置,
00404991 arg1+1c處存放第一個
004049EF arg1+0x8處存放第二個等等,其中第1個和第4個參數是字符串,其他的都是int值。然後這個函數就完了……然後我們就開始我們的破解之路啦,以上都是胡亂分析,接下來纔是真正的破解。
13 然後也並不知道這9個參數分別是什麼,只知道第一個參數是“登錄成功”不管它,先試一下,先構造一個返回值 登錄成功\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8,先跑一下,看看是什麼結果。
od重新載入,斷點下載00404739處,F9運行
14 來到斷點處後,點EAX右鍵,數據窗口跟隨,
15 可以看到這裏就是服務器返回的內容,雙擊02EC6E38處,也即是圖上D3的那個位置,我們要修改這裏的數據,複製一下代碼B5C7C2BCB3C9B9A60D0A310D0A320D0A330D0A340D0A350D0A360D0A370D0A3800
粘貼到
Hex + 00處,粘貼之前取消保持大小處的勾,修改02EC6E34處即圖上0d處的值爲21,爲什麼要複製上面的代碼呢,因爲0D0A就是\r\n,B5C7C2BCB3C9B9A60就是“登錄成功”的GBK編碼了,31就是1,32就是2,33就是3,38就是8,方便我們判斷下面不同的字段是什麼意思,修改完成後,上圖02EC6E30處010000表示第二部分1個字節,02EC6E30處21表示第三部分33個字節,第三部分就是我們粘貼進去的代碼啦
16 然後F9運行,然後看到什麼了,神奇的登錄成功,點擊確定後我們就進入主界面啦,從圖上我們可以看出來,9個字段分別是什麼意思,當然4個和第6個還是不知道是什麼意思,字段2是上次登錄ip,字段3是上次登錄時間的Stamp,字段5是在線時長的秒數,字段7是歷史購票數,字段8是賬號到期時間的Stamp,我把用戶名抹掉了……
19 這只是在內存中運行,我們要怎麼破解呢,根據上面的跟蹤,我們只要把下圖中eax固定爲我們的值就可以了
20 首先我們先在程序裏邊找個地方存放我們的返回內容
Od-插件-中文搜索引擎-搜索asc,找出代碼中所有需要字符串的地方
21 我們看0056B9D0處那裏應該是個說明性的文字,一般不會用到,我們就把我們的字符串放在這裏,這裏調用的是0xA8D44C處的字符串,在OD的數據窗口ctrl+G跳轉到0xA8D44C,看到內容是0x00A8DBDC, 因爲是小端序,內容在內存中是DCDBA800,順序是反的
22 再ctrl+G跳轉到0x00A8DBDC ,就可以看到字符串了
23 點擊00A8DBDC處即圖上D3的位置,粘貼下面的代碼到OD的窗口
010000003B000000B5C7C2BCB3C9B9A60D0A310D0A322E322E322E320D0A313435303530373837300D0A340D0A3535350D0A360D0A300D0A3134363135303738373000
這裏我解釋一下上邊的數據,
01000000表示第二部分1個int
3B000000表示第三部分3B個字節,即59
下面是第三部分
B5C7C2BCB3C9B9A60D0A登錄成功
310D0A字段1,不知道含義
322E322E322E320D0A字段2,上次登錄ip,內容是2.2.2.2
313435303530373837300D0A字段3 上次登錄時間,內容是1450507870,表示2015年12月19日 14:51:10
340D0A 字段4,這個其實是用戶等級的意思
3535350D0A字段5,在線時長,內容是555秒
360D0A 字段6,未知
300D0A 字段7 歷史購票總數,內容是0
3134363135303738373000字段8,賬號過期時間,內容是1461507870,表示2016年04月24日 22:24:30
24 然後再來到我們上面的要賦值的EAX處,修改成下圖的代碼,這樣不管服務器返回什麼,最後都是我們填寫的內容了
任意處點 右鍵 複製到可執行文件 ,在彈出的框裏 複製-全選,然後點保存文件。我們就破解好了,好了麼?還沒有,雙擊破解後的exe,竟然檢測到修改了文件,媽蛋,繼續OD載入,插件-中文搜索-搜索ASC 找到 “檢測到您的……”字符串,點擊就來到檢測文件修改的代碼處了。
25 004037B9處,eax裏保存了判斷md5的結果,0爲相等,1爲不等。全部nop掉
然後保存即可。
最後附上一張圖: