日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux vc 调试方法,VC实现【API钩取】【调试法】附加调试器

發布時間:2024/3/7 linux 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux vc 调试方法,VC实现【API钩取】【调试法】附加调试器 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

最近在學習逆向核心,在論壇也發了幾篇帖子說說自己的經驗,幫助自己鞏固知識,也方便了大家。

如果帖子中有什么疏漏甚至不對的地方,請大牛們指出,我會積極改正的!

廢話不多說,還是我【Miss丿小沫】,上教程!

-----------------------------------------------------------------------------------------------------

我在DLL注入里面也提到了API鉤取這一概念,涉及的知識點比較多,也上了難度,我準備細致的介紹,講解。

我能力有限,如果有錯誤的地方,歡迎大家指正!

-----------------------------------------------------------------------------------------------------

鉤取(Hook)是一種截取信息(比如SetWindowsHook()獲取鍵盤記錄),更改程序執行流,添加新功能(DLL注入)的技術。

列一下流程:

①:使用反匯編器(IDA)或者調試器(OD)了解程序的結構和工作原理

②:開發Hook代碼

③:靈活操作可執行文件和進程內存,執行Hook

其中,鉤取API的技術就叫做API鉤取,它將鉤取API,改變程序執行流,達到某些我們想要的目的。

關于API的概念就不贅述了,(百度百科:http://baike.baidu.com/link?url= ... 9n63O8bV7We25xVyz-7)

API封裝在DLL中,程序運行時就會加載各種DLL(kernel32.dll,ntdll.dll等),上節DLL注入中就可以看出來了

-----------------------------------------------------------------------------------------------------

1.jpg (68.02 KB, 下載次數: 0)

2016-7-15 14:24 上傳

以notepad為例,要打開一個文件,notepad會發生如下調用:

1.jpg (21.08 KB, 下載次數: 0)

2016-7-15 14:26 上傳

程序正常調用API:

1.jpg (28.71 KB, 下載次數: 0)

2016-7-15 14:28 上傳

當我們HookAPI后:

1.jpg (55.36 KB, 下載次數: 0)

2016-7-15 14:30 上傳

利用上節的知識,將hook.dll注入目標進程后,hook.dll將鉤取目標API,并執行我們自己的代碼,改變程序執行流,這樣,每當程序調用目標API后,都會經由我們自己的代碼

下面給出一張技術圖表:

1.jpg (85.31 KB, 下載次數: 0)

2016-7-15 14:33 上傳

①:【方法】API鉤取一般都采用動態方法

②:【位置】指出API鉤取時操作哪部分

<1>:IAT 將其內部的API函數地址修改為Hook函數地址,實施起來簡單,但無法鉤取不在IAT而在程序中動態加載的DLL中的API。(關于IAT的詳細講解,大家可以參考驛站的【PE文件格式解析】)

<2>:代碼 *.dll映射到內存是,從中查找目標API地址,并直接修改代碼,應用廣泛。

<3>:EAT 并不常用,不在贅述

③:【技術】從表中也可以看出,API鉤取可分為兩種方法:調試法和注入法(代碼注入和DLL注入)

調試法:

調試通過向目標進程附加調試器鉤取API,調試器擁有被調試進程的所有權限

注入法:

DLL注入:

(詳細見我上一章【VC實現DLL注入】)在Dll中創建Hook代碼和設置代碼,并在DllMain()中調用,注入的同時也就完成了Hook

代碼注入:

(我準備再開一章專講代碼注入)

④:【API】列舉了幾個各自技術要用到的API

-----------------------------------------------------------------------------------------------------

大致了解完枯燥的理論后,開始實例講解!

利用【調試法】向notepad附加調試器,嘗試鉤取WriteFile()API

在這之前,我們有必要了解一下調試器。

調試器工作原理:

被調試進程注冊后,每當被調試進程發生調試事件(DebugEvent)時,OS就會暫停進程執行,并匯報給調試器,當調試器處理完相關事件后,使被調試程序繼續執行。

一張圖說明調試器的異常處理(EXCEPTION):

1.jpg (61.63 KB, 下載次數: 0)

2016-7-15 15:01 上傳

列舉調試事件(DebugEvent)(共9個):

EXCEPTION_DEBUG_EVENT

CREATE_THREAD_DEBUG_EVENT

CREATE_PROCESS_DEBUG_EVENT

EXIT_THREAD_DEBUG_EVENT

EXIT_PROCESS_DEBUG_EVENT

LOAD_DLL_DEBUG_EVENT

UNLOAD_DLL_DEBUG_EVENT

OUTPUT_DEBUG_STRING_EVENT

RIP_EVENT

我們主要關注EXCEPTION_DEBUG_EVENT,列舉出與其相關的異常事件列表:

EXCEPTION_ACCESS_VIOLATION

EXCEPTION_ARRAY_BOUNDS_EXCEEDED

EXCEPTION_BREAKPOINT

EXCEPTION_DATATYPE_MISALIGNMENT

EXCEPTION_FLT_DENORMAL_OPERAND

EXCEPTION_FLT_DIVIDE_BY_ZERO

EXCEPTION_FLT_INEXACT_RESULT

EXCEPTION_FLT_INVALID_OPERATION

EXCEPTION_FLT_OVERFLOW

EXCEPTION_FLT_STACK_CHECK

EXCEPTION_FLT_UNDERDLOW

EXCEPTION_ILLEGAL_INSTRUCTION

EXCEPTION_IN_PAGE_ERROR

EXCEPTION_INT_DIVIDE_BY_ZERO

EXCEPTION_INT_OVERFLOW

EXCEPTION_INVALID_DISPOSITION

EXCEPTION_PRIV_INSTRUCTION

EXCEPTION_SINGLE_STEP

EXCEPTION_STACK_OVERFLOW

(FUCK!我想罵人!剛寫好的帖子渣B瀏覽器崩潰了,結果一堆都沒了。。從頭開始吧。。。)

我們只關心EXCEPTION_BREAKPOINT這個事件,因為要用int3下斷點(斷點的IA-32指令是0xCC。),通過這個事件反饋給調試器。

-----------------------------------------------------------------------------------------------------

下面講解一下整個調試流程:

①:對目標進程附加調試器,開始調試

②:下斷點,將目標API函數的起始地址第一個字節設置為0xCC

③:程序調用目標API,斷下,反饋信息給調試器

④:執行我們自己的代碼

⑤:恢復0xCC,使API正常執行

⑥:再次下斷,將目標API函數的起始地址第一個字節設置為0xCC

這就是基本的流程了

-----------------------------------------------------------------------------------------------------

OK,開始真正的實戰,

我們對notepad進行API鉤取,在其保存文件時,將文本中所有小寫字母替換成大寫字母。

第一步:

先來用OD分析一下notepad.exe的執行流

(這利用的是XP的notepad.exe,WIN7的貌似有保護,我OD調試后立即崩潰)

notepad.zip

(33.41 KB, 下載次數: 16)

2016-7-15 16:38 上傳

點擊文件名下載附件

下載積分: 驛站幣 -1

(大家要掌握一定的OD基礎)

好,OD附加notepad.exe

1.jpg (331.11 KB, 下載次數: 0)

2016-7-15 15:33 上傳

我們的目標是WriteFile()API,

OD代碼區右鍵->Search For->name in all modules

查找WriteFile()

雙擊 export WriteFile()進入代碼區

1.jpg (116.54 KB, 下載次數: 0)

2016-7-15 16:32 上傳

在 752b75d5 處F2下斷,F9運行

回到notepad.exe,輸入我們的內容,然后保存

1.jpg (28.18 KB, 下載次數: 0)

2016-7-15 16:40 上傳

程序斷在了752b75d5,

查看棧

1.jpg (40.35 KB, 下載次數: 0)

2016-7-15 18:56 上傳

緩沖區地址是2D9968,存放在ESP + 8處

1.jpg (80.64 KB, 下載次數: 0)

2016-7-15 18:57 上傳

在Dump中查看,發現就是我們的文本

我們用調試方法來APIHook,在WriteFile()起始地址設置int3后,此時被調試者的EIP(存儲著CPU下一條指令)是多少呢?

EIP = 752b75d5 + 1 = 752b75d6,我們在WriteFile()起始地址設置int3后,EIP值+1,等遇到Breatpoint異常后,會反饋給調試器處理,等我們處理完之后,EIP會恢復WriteFile()起始值,

但這里還有一個問題,如果執行流只返回到WriteFile()起始地址,再次遇到int3還是會返回異常,就進入了無限死循環!為此,我們還應該恢復0xCC處的原始值,以保證API得正常執行。

-----------------------------------------------------------------------------------------------------

好,這一系列問題分析完之后,就可以動手寫代碼啦!

界面還是上次DLL注入的界面,只是多加了一個APIHook按鈕。

1.jpg (6.59 KB, 下載次數: 0)

2016-7-15 19:09 上傳

void CCodeInjectDlg::OnBnClickedButtonApihook()

{

CString str;

//獲取進程PID

GetDlgItemText(IDC_EDIT_PID,str);

dwPID = FindPID(str);

//附加調試器

if(!DebugActiveProcess(dwPID))

{

AfxMessageBox(_T("附加調試器失敗!"),MB_ICONSTOP | MB_OK);

return ;

}

//進入調試器循環

DebugLoop();

}復制代碼

這段代碼很簡單,就是獲取進程ID,附加調試器,進入循環,處理來自進程的各種消息

下面著重講解一下,DebugLoop()

剛剛講到OnBnClickedButtonApihook()這個函數,這次我們修改一下這個函數

void CCodeInjectDlg::OnBnClickedButtonApihook()

{

HANDLE hThread = CreateThread(NULL,0,ThreadProc,(LPVOID)this,0,NULL);

CloseHandle(hThread);

}復制代碼

把主要代碼(DebugLoop)放在了ThreadProc()里面,因為DebugLoop()這個循環會阻塞主程序。

ThreadProc()函數:

DWORD WINAPI ThreadProc(LPVOID lpDlg)

{

CCodeInjectDlg* pDlg = (CCodeInjectDlg*)lpDlg;

CString str;

//獲取進程PID

pDlg->GetDlgItemText(IDC_EDIT_PID,str);

pDlg->dwPID = pDlg->FindPID(str);

//附加調試器

if(!DebugActiveProcess(pDlg->dwPID))

{

AfxMessageBox(_T("附加調試器失敗!"),MB_ICONSTOP | MB_OK);

return 0;

}

//進入調試器循環

pDlg->DebugLoop();

return 0;

}復制代碼

----------------------------------------------------------------------------------

下面來看一下DebugLoop()函數:

void CCodeInjectDlg::DebugLoop()

{

DEBUG_EVENT DE;

//等待調試事件

while(WaitForDebugEvent(&DE,INFINITE))

{

switch(DE.dwDebugEventCode)

{

//附加到調試進程

case CREATE_PROCESS_DEBUG_EVENT:

CreateProcessDebugEvent(&DE);

break;

//返回異常

case EXCEPTION_DEBUG_EVENT:

ExceptionDebugEvent(&DE);

break;

//進程退出

case EXIT_PROCESS_DEBUG_EVENT:

return ;

}

ContinueDebugEvent(DE.dwProcessId,DE.dwThreadId,DBG_CONTINUE);

}

}復制代碼

WaitForDebugEvent()就是暫停進程,等待被調試者反饋的調試事件了。

DEBUG_EVENT結構:

typedef struct _DEBUG_EVENT {

DWORD dwDebugEventCode;

DWORD dwProcessId;

DWORD dwThreadId;

union {

EXCEPTION_DEBUG_INFO? ?? ?Exception;

CREATE_THREAD_DEBUG_INFO??CreateThread;

CREATE_PROCESS_DEBUG_INFO CreateProcessInfo;

EXIT_THREAD_DEBUG_INFO? ? ExitThread;

EXIT_PROCESS_DEBUG_INFO? ?ExitProcess;

LOAD_DLL_DEBUG_INFO? ?? ? LoadDll;

UNLOAD_DLL_DEBUG_INFO? ???UnloadDll;

OUTPUT_DEBUG_STRING_INFO??DebugString;

RIP_INFO? ?? ?? ?? ?? ?? ?RipInfo;

} u;

} DEBUG_EVENT, *LPDEBUG_EVENT;

當程序接收到被調試者反饋的調試事件后就將調試事件設置為DEBUG_EVENT的第一個參數dwDebugEventCode

前面也說過了,共有9種調試事件,dwDebugEventCode就是這9種中的一種,根據事件的種類,也會相應設置DEBUG_EVENT.u中的結構體成員

ContinueDebugEvent()就是使暫停的進程繼續執行。

----------------------------------------------------------------------------------

當調試器附加到進程上后,調試事件為CREATE_PROCESS_DEBUG_EVENT,并調用CreateProcessDebugEvent(&DE)函數,該函數的作用就是獲取信息(WriteFile()起始地址首字節指令),并下int3斷點

當我們保存文件時,就會觸發斷點,調試事件為EXCEPTION_DEBUG_EVENT,并調用ExceptionDebugEvent(&DE)函數,該函數就取消int3斷點,改變代碼的執行流,替換小寫字母為大寫字母,并且再次下int3斷點

----------------------------------------------------------------------------------

CreateProcessDebugEvent(&DE)函數:

void CCodeInjectDlg::CreateProcessDebugEvent(LPDEBUG_EVENT lpDE)

{

BYTE bInt3 = 0xCC;

//獲取WriteFile()函數地址

lpThread = (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("kernel32.dll"),_T("WriteFile"));

//下斷點,更改WriteFile()起始地址為0xCC,并備份原內容

memcpy(&CPDbg_Info,&lpDE->u.CreateProcessInfo,sizeof(CREATE_PROCESS_DEBUG_INFO));

ReadProcessMemory(CPDbg_Info.hProcess,lpThread,&bOriByte,sizeof(BYTE),NULL);

WriteProcessMemory(CPDbg_Info.hProcess,lpThread,&bInt3,sizeof(BYTE),NULL);

}復制代碼

獲取WriteFile()起始地址(DLL注入章節中已經講解了)

CREATE_PROCESS_DEBUG_INFO結構體:

typedef struct _CREATE_PROCESS_DEBUG_INFO {

HANDLE? ?? ?? ?? ?? ???hFile;

HANDLE? ?? ?? ?? ?? ???hProcess;

HANDLE? ?? ?? ?? ?? ???hThread;

LPVOID? ?? ?? ?? ?? ???lpBaseOfImage;

DWORD? ?? ?? ?? ?? ?? ?dwDebugInfoFileOffset;

DWORD? ?? ?? ?? ?? ?? ?nDebugInfoSize;

LPVOID? ?? ?? ?? ?? ???lpThreadLocalBase;

LPTHREAD_START_ROUTINE lpStartAddress;

LPVOID? ?? ?? ?? ?? ???lpImageName;

WORD? ?? ?? ?? ?? ?? ? fUnicode;

} CREATE_PROCESS_DEBUG_INFO, *LPCREATE_PROCESS_DEBUG_INFO;

結構體里面存儲著關于進程的信息

ReadProcessMemory()用來獲取WriteFile()起始地址首字節指令,用來取消斷點是恢復

WriteProcessMemory()就是下int3斷點的

----------------------------------------------------------------------------------

ExceptionDebugEvent(&DE)函數:

void CCodeInjectDlg::ExceptionDebugEvent(LPDEBUG_EVENT lpDE)

{

PEXCEPTION_RECORD per = &lpDE->u.Exception.ExceptionRecord;

CONTEXT cText;

DWORD dwBuf_Num = 0,dwBuf_Buf = 0;

PBYTE pbBuf = NULL;

BYTE bInt3 = 0xCC;

//斷點int3,并且當前地址為WriteFile()

if(per->ExceptionCode == EXCEPTION_BREAKPOINT && per->ExceptionAddress == lpThread)

{

//恢復0xCC

WriteProcessMemory(CPDbg_Info.hProcess,lpThread,&bOriByte,sizeof(BYTE),NULL);

//獲取線程上下文

cText.ContextFlags = CONTEXT_CONTROL;

GetThreadContext(CPDbg_Info.hThread,&cText);

//獲取WriteFile()第2、3參數

ReadProcessMemory(CPDbg_Info.hProcess,(LPVOID)(cText.Esp + 0x8),&dwBuf_Buf,sizeof(DWORD),NULL);

ReadProcessMemory(CPDbg_Info.hProcess,(LPVOID)(cText.Esp + 0xC),&dwBuf_Num,sizeof(DWORD),NULL);

//分配臨時緩沖區

pbBuf = (PBYTE)malloc(dwBuf_Buf + 1);

memset(pbBuf,0,dwBuf_Buf + 1);

//復制WriteFile()緩沖區到臨時緩沖區

ReadProcessMemory(CPDbg_Info.hProcess,(LPVOID)dwBuf_Buf,pbBuf,dwBuf_Num,NULL);

//小寫轉大寫(ASCII)

for(int i = 0;i < dwBuf_Num;i ++)

{

//判斷是否是小寫字母

if(pbBuf[i] >= 0x61 && pbBuf[i] <= 0x7A)

{

pbBuf[i] -= 0x20;

}

}

//變換后緩沖區寫到WriteFile()緩沖區

WriteProcessMemory(CPDbg_Info.hProcess,(LPVOID)dwBuf_Buf,pbBuf,dwBuf_Num,NULL);

//釋放緩沖區

free(pbBuf);

//修改線程上下文

cText.Eip = (DWORD)lpThread;

SetThreadContext(CPDbg_Info.hThread,&cText);

//繼續運行被調試進程

ContinueDebugEvent(lpDE->dwProcessId,lpDE->dwThreadId,DBG_CONTINUE);

Sleep(0);

//再次寫入int3斷點

WriteProcessMemory(CPDbg_Info.hProcess,lpThread,&bInt3,sizeof(BYTE),NULL);

}

}復制代碼

PEXCEPTION_RECORD里面儲存著異常信息,我們判斷該異常是不是斷點并且是斷在WriteFile()處的

首先我們用開始保存的原始信息恢復0xCC斷點

CONTEXT線程上下文里面存儲著有關線程的信息(CPU中各寄存器的值)

typedef struct _CONTEXT {

DWORD ContextFlags;

DWORD Dr0;

DWORD Dr1;

DWORD Dr2;

DWORD Dr3;

DWORD Dr6;

DWORD Dr7;

FLOATING_SAVE_AREA FloatSave;

DWORD SegGs;

DWORD SegFs;

DWORD SegEs;

DWORD SegDs;

DWORD Edi;

DWORD Esi;

DWORD Ebx;

DWORD Edx;

DWORD Ecx;

DWORD Eax;

DWORD Ebp;

DWORD Eip;

DWORD SegCs;

DWORD EFlags;

DWORD Esp;

DWORD SegSs;

} CONTEXT;

(具體分析見前面OD分析部分)

下面用WriteProcessMemory()獲取WriteFile()的兩個參數,第一個參數(ESP + 0x8)里面保存著緩沖區的地址,第二個參數(ESP + 0xC)就是緩沖區大小

接下來就是復制WriteFile()緩沖區數據到臨時緩沖區,并轉換大小寫后,回寫到WriteFile()緩沖區,并且將EIP值修改為WriteFile()起始地址,保證API正常運行,ContinueDebugEvent()使進程繼續執行,

Sleep(0)呢,會釋放當前線程的剩余時間片。。BALABALABALA。。。。如果沒有Sleep(0)的話,有時會發生崩潰

最后再次寫入int3斷點,以保證下次保存時再次鉤取API

----------------------------------------------------------------------------------

好了,主要代碼就結束了,不知道當大家看到自己寫出來的API HOOK有沒有一點小激動呢?

我是【Miss丿小沫】,下次定會帶來更好的講解!

總結

以上是生活随笔為你收集整理的linux vc 调试方法,VC实现【API钩取】【调试法】附加调试器的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 精品国产18久久久久久二百 | 久操精品 | 国产精品久久久一区二区 | 男女激情四射网站 | 91久久精品无码一区二区 | 日韩三级网 | 99re免费视频 | 精品少妇一区二区三区密爱 | 91精品国产一区二区在线观看 | 免费超爽大片黄 | 黄色av日韩 | 爽妇网国产精品 | 亚洲精品激情视频 | 神马影院午夜伦理 | 亚洲综合狠狠 | 国产精品一区二区三区四 | 欧美有码视频 | 亚洲情人网| 成人免费视频国产免费麻豆 | aaaaa级少妇高潮大片免费看 | 日韩欧美第一页 | 公侵犯人妻中文字慕一区二区 | 亚洲精品二三区 | 欧洲精品久久久久毛片完整版 | 亚洲在线资源 | 哪里可以免费看av | 香蕉视频在线免费看 | 亚洲女人网| xxxx999| 香蕉一区二区 | 久久黄色一级 | 国产三级三级三级三级三级 | 天堂视频在线观看免费 | 人妻少妇一区二区 | 国产区一区二区三区 | 少妇视频在线 | 成人国产精品一区二区 | 久草免费在线观看视频 | 成人妇女淫片aaaa视频 | 新91视频在线观看 | 久久精品久久久 | 中文字幕黑人 | jizjiz中国少妇高潮水多 | 久久久久爱 | 国产毛片一区二区三区 | 天天射天天射 | 少妇高潮21p| 国产高清一区在线观看 | 麻豆tv在线| 国产av一区二区三区精品 | 色涩网站 | 成人福利免费视频 | 日本一区二区人妻 | 手机在线免费av | 亚洲黄a| 色噜噜日韩精品欧美一区二区 | 欧美久久综合 | av免费网站| 九九综合视频 | 波多野结衣导航 | 天天躁日日躁狠狠躁av麻豆 | 美女扒开内裤让男人桶 | 97超碰自拍 | 久久一道本 | 久久人妻免费视频 | 国产精品麻豆成人av电影艾秋 | 国产一区二区三区视频 | 色网站在线免费观看 | av一区二区免费 | 久久精品人人做人人爽 | 99爱视频在线 | av先锋影音 | 动漫涩涩免费网站在线看 | 国产又黄又爽 | 97自拍视频在线 | 国产精品国产精品国产专区不片 | 中文字幕免费高清在线观看 | 久久丫精品 | 国产成人传媒 | 日本在线视频一区二区三区 | 快播91| 黑丝啪啪| 竹菊影视一区二区三区 | 国产欧美高清 | 久草资源站 | 久久久久亚洲av成人人电影 | 天堂网视频 | 91中文字幕在线观看 | av福利在线免费观看 | 黄色精品视频在线观看 | 中国女人性猛交 | 污视频在线观看免费 | 日韩毛片网站 | 91精品福利视频 | 美女又爽又黄又免费 | 久久亚洲一区二区三区四区 | 无码人妻精品一区二区三区在线 | 国产影音先锋 | 国产精品丝袜黑色高跟鞋 |