原文來自:https://bbs.ichunqiu.com/thread-43041-1-1.html
0×00 序言:
1.自從上次筆者調戲完盜取文件密碼大黑客后,這激發了筆者的創作熱情,就給大家帶來程序逆向系列,當然有一些地方還是有所欠缺,請大家在私聊中指出我文中的錯誤,我會加以改正。
2.本篇教程每篇文章都會在附件中給出一個程序逆向例子,所用到的知識都會在該篇文章中體現,有興趣的同學可以自己實踐實踐
3.為什么要學習逆向破解?
a.你可以漢化一些軟件給予大家使用
b.你可以進行病毒分析
c.外掛輔助的研究
d.程序的破解
4.這套系列筆者所用的工具已經被筆者整理為工具包,鏈接地址: https://bbs.ichunqiu.com/thread-43019-1-1.html
5.破解的環境要求由於一些程序的編寫者不期望自己的程序被破解(其實誰也不期望),所以就采取了一些比較極端的方法,比如:格式化您的重要資料 ……
所以,程序破解的時候需要用到虛擬機,虛擬機推薦使用vmware
下載鏈接: https://pan.baidu.com/s/19eBzCzPrSs4xnkwrcWNV_Q
密碼: 9954
虛擬機安裝教程: https://jingyan.baidu.com/article/25648fc1c467eb9191fd00d6.html
系統鏡像下載地址:
只需要把您需要用到的鏡像的下載鏈接放到迅雷里即可
——————————————————————————————————————————————————————————————————
0×01首先認識一下OD(Ollydbg)
打開OD界面,呈現出下圖的窗口分布,這里筆者對OD界面的幾個窗口進行了一下標識。
1.菜單窗口:
從左往右依次去說這些按鈕的作用以及快捷鍵:
(1) 打開新的可執行文件[快捷鍵F3]
(2) 重新載入程序[快捷鍵Ctrl+F2]
(3) 關閉程序 [快捷鍵Alt+F2]
(4) 運行程序[快捷鍵F9]
(5) 暫停執行程序 [快捷鍵F12]
(6) 單步步入[快捷鍵F7]
(7) 單步步過[快捷鍵F8]
(8) 跟蹤步入[快捷鍵Ctrl+F11]
(9) 跟蹤步過[快捷鍵Ctrl+F12]
(10) 執行到返回[快捷鍵Ctrl+F9]
(11) 轉到反匯編窗中口的地址(轉到表達式)[快捷鍵Ctrl+G]
(12) 顯示記錄窗口[快捷鍵Alt+L]
(13) 顯示模塊窗口[快捷鍵Alt+E]
(14) 顯示內存窗口[快捷鍵Alt+M]
(15) 顯示線程窗口
(16) 顯示窗口
(17) 顯示句柄窗口
(18) 顯示CPU窗口[快捷鍵Alt+C]
(19) 顯示補丁窗口[快捷鍵Ctrl+P]
(20) 顯示調用堆棧窗口[快捷鍵Alt+K]
(21) 顯示斷點窗口[快捷鍵Alt+B]
(22) 顯示參考窗口[快捷鍵Alt+R]
(23) 顯示Run 跟蹤窗口
(24) 顯示源碼窗口
(25) 調試選項(快捷鍵Alt+O)
(26) 界面選項
(27) 幫助
2.反匯編窗口:
為了演示方便筆者決定用C語言寫個簡單的Hello World!程序
代碼如下:
將編譯好的文件拖入OD
這里筆者對反匯編窗口進行了一下划分和標注:
這里面地址即為程序的內存地址,hex即為hex數據,反匯編就是程序的匯編代碼,注釋即為od分析出來的,雙擊即可編輯,信息窗口能對操作進行更加詳細的查看。
3.寄存器窗口:
這里就簡單介紹幾個通用寄存器
ESP:指向堆棧棧頂
EBP:大部分用來定位局部變量和參數
其余的就各自拆開來用
這里面不低寄存器做更加深入的講解,有興趣的同學可以看看王爽的《匯編語言(第3版) 》。
另外, 點擊標簽寄存器 (FPU) 可以切換顯示寄存器的方式
4.數據窗口:
數據窗口主要的即為程序或者內存的數據,右鍵可以切換顯示方式
5.堆棧窗口:
主要存放線程的臨時數據,可以用於動態調試.
6.命令行窗口:
主要就是執行一些下斷命令
比如:bp+API函數名稱
——————————————————————————————————————————————————
0×02 一些常用的操作
為了方便演示下面的操作,筆者寫了一段代碼來檢測explorer.exe進程的程序
代碼如下:
#include <windows.h>
#include <tlhelp32.h>
#include <stdio.h>
int main()
{
char* procressName = “explorer.exe”;
char pName[MAX_PATH];
strcpy(pName, procressName);
CharLowerBuff(pName, MAX_PATH);
PROCESSENTRY32 currentProcess;
currentProcess.dwSize = sizeof(currentProcess);
HANDLE hProcess = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcess == INVALID_HANDLE_VALUE)
{
printf(“函數CreateToolhelp32Snapshot調用失敗!\n”);
return FALSE;
}
BOOL bMore = Process32First(hProcess, ¤tProcess);
while (bMore)
{
CharLowerBuff(currentProcess.szExeFile, MAX_PATH);
if (strcmp(currentProcess.szExeFile, pName) == 0)
{
CloseHandle(hProcess);
printf(“發現explorer.exe”);
system(“pause”);
exit(0);
}
bMore = Process32Next(hProcess, ¤tProcess);
}
printf(“沒有發現explorer.exe\n”);
CloseHandle(hProcess);
printf(“Cracke Success!”);
getchar();
return 0;
}
編譯完成后運行
打開OD
1. OD載入程序的兩種方法
(1) 拖拽exe文件載入,這個很簡單直接把exe文件拖拽到OD窗口中就行
(2) 進程附加,前提是你需要先運行所要附加的exe
a. 首先運行需要附加的exe
b.點擊 文件->附加,找到需要附加的進程,選中后點擊附加
2. 字符串搜索方法
在反匯編窗口上點擊右鍵->中文搜索引擎[根據需要你可以選取相應的篩選選項(1.搜索ASCII,2.搜索UNICODE,3.智能搜索)]
PS: ASCII 又叫ANSI 簡寫為A
UNICODE又叫WideChar 簡寫為W
程序API里面的A/W就是指的這兩種編碼
用剛剛那個檢測explorer進程的exe為例子:
ASCII搜索:
UNICODE搜索:
智能搜索:
在這里面筆者推薦在搜索字符串的時候使用智能搜索
3. 下斷點以及刪除斷點:
(1).快捷鍵下斷點(F2):用鼠標選中需要下段的代碼,按一下F2
(2) 用鼠標選中代碼右鍵 -> 斷點 -> 切換
(3)命令行下斷點:
a. 先找到需要下段的內存地址:
b. 在命令行窗口輸入bp 內存地址
本程序中需要下段的內存地址為: 00B510EC輸入命令: bp 00B510EC,回車
(4)刪除斷點
a.查看 –> 斷點 然后就進入到顯示斷點窗口(快捷鍵 Alt+B)
b.用鼠標點擊需要刪除的斷點右鍵刪除即可
(PS:這里面斷點的使用並不全面,這是做了一個簡單的介紹而已)
4.保存文件
就以這個檢測Explorer.exe的程序為例子
我們需要將程序改為直接輸出Cracke Success!
首先搜索字符串找到Cracke Success!
雙擊字符串跟蹤
往上翻一翻字符串會發現”沒有發現explorer.exe\n”這段ASCII,用鼠標選中ASCII所在的代碼,如圖所示
這里面用白色圓形所傳出來的是一段跳轉,我們需要跟蹤一下
(這里的紅線代表的是跳轉實現,而白線則是不實現。)
發現是從je short Checking.00B510EC跳轉過來
這里面普及一下匯編的條件跳轉指令:
jmp :無條件跳轉 (jump)
je/jz :結果為0跳轉 (jump zero)
jnz/jne: 結果不為0跳轉 (jump not zero)
js:結果為負跳轉 (Jump if sign)
jns:結果為正跳轉(Jump if not sign)
jb:小於則跳轉(Jump below)
jnb:大於或等於則跳轉(Jump not below)
回到這個程序中,程序的意思就是調用CreateToolhelp32Snapshot函數去創造一個當前進程快照,利用ProcessFirst和 ProcessNext這兩個API函數去遍歷進程快照的進程並且與Explorer.exe做cmp,如果結果為真就不跳轉,輸出“
發現explorer.exe”,如果結果為假就跳轉“沒有發現explorer.exe Cracke Success!”
所以這其中的關鍵就在於遍歷查找部分
用鼠標選中后,雙擊編輯
將條件跳轉的je改為無條件跳轉的jmp
右鍵 -> 復制到可執行文件 –> 所有修改
點擊全部復制
右鍵后,找到保存文件
我們將其重命名為Cracker-Checking Explorer.exe
保存在桌面上
運行一下
這個檢測進程就被我們繞過了
——————————————————————————————————————————————————
0×03 常用匯編指令掃盲
1.通用數據傳送指令
MOV(Move)傳送
例如 mov a,b 就是把b的值傳給a
PUSH(Push onto the stack)進棧
POP(Pop from the stack)出棧
注:push和pop由於堆棧平衡原理
有push就必須要有pop
XCHG(Exchange)交換
2.標志寄存器傳送指令
PUSHF(push the flags) 標志進棧
POPF(pop the flags) 標志出棧
3.條件跳轉(一般配合cmp使用)
JMP(jump) 無條件跳轉
JZ/JE(Jump if zero,or equal) 結果為零(或相等)則跳轉 注:檢測Z位
JNZ/JNE(Jump if not zero,or not equal) 結果不為零(或不相等)則跳轉 注:檢測Z位
JS(Jump if sign) 結果為負則跳轉 注:檢測S位
JNS(Jump if not sign) 結果為正則跳轉 注:檢測S位
JB(Jump Below):小於則跳轉 注:檢測C位
JNB(Jump Not Below ):大於或等於則跳轉 注:檢測C位
那這些C位,Z位,S位在哪里看呢?
在0×01認識OD中在寄存器窗口中認識了標志寄存器,如圖:
這里用jnz去舉例,jnz的判斷檢查Z位,當Z位是0的時候就不跳轉,在Z為是1的時候就跳轉
4.子程序
CALL 調用指令
RET 返回指令
5.LOOP 循環指令
6.算數指令
ADD 加法指令
SUB 減法指令
SUBR 減法指令
MUL 乘法指令
DIV 除法指令
DIVR ;除法指令
7.nop 空指令
0×04 總結
本篇文章介紹了OD 的基礎使用,以及一些基礎操作
介紹了一些常用的匯編指令,如果有哪些常用的匯編指令沒有補充到位的以及文章中出現瑕疵的地方歡迎在評論區中指出,我會及時審改的
閱讀原文可下載附件,附件中有本篇文章的例子以及一個演示例子。