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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

逆向工程核心原理读书笔记-API钩取之记事本小写转大写

發(fā)布時間:2024/4/11 编程问答 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 逆向工程核心原理读书笔记-API钩取之记事本小写转大写 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

我們通過一個示例來練習鉤取Notepad.exe的WriteFile,保存文件時將小寫字母全部轉(zhuǎn)換為大寫字母。下面我們先測試一下代碼。
運行notepad.exe并查看PID。


在命令行窗口中輸入命令與參數(shù)。


輸入一串小寫字母之后選擇保存。


再次打開文件,之前的小寫字母全部變成了大寫字母。


我們來分析一下源代碼,看看是怎么實現(xiàn)的。
首先看一下main函數(shù)。main函數(shù)通過DebugActiveProcess將調(diào)試器附加到該運行的進程上,然后進入DebugLoop處理來自被調(diào)試者的調(diào)試事件。

[cpp]?view plaincopy
  • int?main(int?argc,?char*?argv[])??
  • {??
  • ????DWORD?dwPID;??
  • ??
  • ????if(?argc?!=?2?)??
  • ????{??
  • ????????printf("\nUSAGE?:?hookdbg.exe?<pid>\n");??
  • ????????return?1;??
  • ????}??
  • ??
  • ????//?Attach?Process??
  • ????dwPID?=?atoi(argv[1]);??
  • ????if(?!DebugActiveProcess(dwPID)?)??
  • ????{??
  • ????????printf("DebugActiveProcess(%d)?failed!!!\n"??
  • ???????????????"Error?Code?=?%d\n",?dwPID,?GetLastError());??
  • ????????return?1;??
  • ????}??
  • ??
  • ????//?debugger?loops??
  • ????DebugLoop();??
  • ??
  • ????return?0;??
  • }??
  • 接下來是DebugLoop。它從被調(diào)試者處接收事件并處理,然后使被調(diào)試者繼續(xù)運行。ContinueDebugEvent是一個使被調(diào)試者繼續(xù)運行的函數(shù)。 [cpp]?view plaincopy
  • void?DebugLoop()??
  • {??
  • ????DEBUG_EVENT?de;??
  • ????DWORD?dwContinueStatus;??
  • ??
  • ????//?Waiting?for?the?event?occurred?by?debuggee??
  • ????while(?WaitForDebugEvent(&de,?INFINITE)?)??
  • ????{??
  • ????????dwContinueStatus?=?DBG_CONTINUE;??
  • ??
  • ????????//?Debuggee?process?generates?or?attaches?event??
  • ????????if(?CREATE_PROCESS_DEBUG_EVENT?==?de.dwDebugEventCode?)??
  • ????????{??
  • ????????????OnCreateProcessDebugEvent(&de);??
  • ????????}??
  • ????????//?Exception?event??
  • ????????else?if(?EXCEPTION_DEBUG_EVENT?==?de.dwDebugEventCode?)??
  • ????????{??
  • ????????????if(?OnExceptionDebugEvent(&de)?)??
  • ????????????????continue;??
  • ????????}??
  • ????????//?Debuggee?process?terminates?event??
  • ????????else?if(?EXIT_PROCESS_DEBUG_EVENT?==?de.dwDebugEventCode?)??
  • ????????{??
  • ????????????//?debuggee?stop?->?debugger?stop??
  • ????????????break;??
  • ????????}??
  • ??
  • ????????//?Run?the?debuggee?again??
  • ????????ContinueDebugEvent(de.dwProcessId,?de.dwThreadId,?dwContinueStatus);??
  • ????}??
  • }??
  • DebugLoop處理3種調(diào)試事件,分別是EXIT_PROCESS_DEBUG_EVENT、CREATE_PROCESS_DEBUG_EVENT、EXCEPTION_DEBUG_EVENT。
    1.被調(diào)試進程終止時會觸發(fā)EXIT_PROCESS_DEBUG_EVENT。這里在發(fā)生該事件時,調(diào)試器與被調(diào)試者將一起終止。
    2.OnCreateProcessDebugEvent是CREATE_PROCESS_DEBUG_EVENT事件句柄,被調(diào)試進程啟動(或者附加)時即調(diào)用執(zhí)行該函數(shù)。下面看一下它的核心部分。

    [cpp]?view plaincopy
  • BOOL?OnCreateProcessDebugEvent(LPDEBUG_EVENT?pde)??
  • {??
  • ????//?get?WriteFile()?API?address??
  • ????g_pfWriteFile?=?GetProcAddress(GetModuleHandleA("kernel32.dll"),?"WriteFile");??
  • ??
  • ????//?API?Hook?-?WriteFile()??
  • ????//?change?first?byte?to?0xCC(INT?3)???
  • ????memcpy(&g_cpdi,?&pde->u.CreateProcessInfo,?sizeof(CREATE_PROCESS_DEBUG_INFO));??
  • ????ReadProcessMemory(g_cpdi.hProcess,?g_pfWriteFile,???
  • ??????????????????????&g_chOrgByte,?sizeof(BYTE),?NULL);??
  • ????WriteProcessMemory(g_cpdi.hProcess,?g_pfWriteFile,???
  • ???????????????????????&g_chINT3,?sizeof(BYTE),?NULL);??
  • ??
  • ????return?TRUE;??
  • }??
  • 首先獲取WriteFile的起始地址,它獲取的不是被調(diào)試進程的內(nèi)存地址,而是調(diào)試進行的內(nèi)存地址。對于Windows XP的DLL而言,它們在所有進程中都會加載到相同的地址(虛擬內(nèi)存)。由于調(diào)試器擁有被調(diào)試進程的句柄(帶有調(diào)試權限),所以可以使用ReadProcessMemory和WriteProcessMemory對被調(diào)試進程的內(nèi)存空間自由進行讀寫操作。
    3.OnExceptionDebugEvent是EXCEPTION_DEBUG_EVENT事件句柄,它處理被調(diào)試者的INT3指令。下面看一下它的核心部分。

    [cpp]?view plaincopy
  • BOOL?OnExceptionDebugEvent(LPDEBUG_EVENT?pde)??
  • {??
  • ????CONTEXT?ctx;??
  • ????PBYTE?lpBuffer?=?NULL;??
  • ????DWORD?dwNumOfBytesToWrite,?dwAddrOfBuffer,?i;??
  • ????PEXCEPTION_RECORD?per?=?&pde->u.Exception.ExceptionRecord;??
  • ??
  • ????//?BreakPoint?exception?(INT?3)???
  • ????if(?EXCEPTION_BREAKPOINT?==?per->ExceptionCode?)??
  • ????{??
  • ????????//?BP?at?WriteFile()?API??
  • ????????if(?g_pfWriteFile?==?per->ExceptionAddress?)??
  • ????????{??
  • ????????????//?#1.?Unhook??
  • ????????????//?restore?0xCC?to?original?byte???
  • ????????????WriteProcessMemory(g_cpdi.hProcess,?g_pfWriteFile,???
  • ???????????????????????????????&g_chOrgByte,?sizeof(BYTE),?NULL);??
  • ????????????//?#2.?Get?Thread?Context???
  • ????????????ctx.ContextFlags?=?CONTEXT_CONTROL;??
  • ????????????GetThreadContext(g_cpdi.hThread,?&ctx);??
  • ????????????//?#3.?Get?WriteFile()?param?2,?3??
  • ????????????//???param?2?:?ESP?+?0x8??
  • ????????????//???param?3?:?ESP?+?0xC??
  • ????????????ReadProcessMemory(g_cpdi.hProcess,?(LPVOID)(ctx.Esp?+?0x8),???
  • ??????????????????????????????&dwAddrOfBuffer,?sizeof(DWORD),?NULL);??
  • ????????????ReadProcessMemory(g_cpdi.hProcess,?(LPVOID)(ctx.Esp?+?0xC),???
  • ??????????????????????????????&dwNumOfBytesToWrite,?sizeof(DWORD),?NULL);??
  • ????????????//?#4.?Allocates?temp?buf??
  • ????????????lpBuffer?=?(PBYTE)malloc(dwNumOfBytesToWrite+1);??
  • ????????????memset(lpBuffer,?0,?dwNumOfBytesToWrite+1);??
  • ????????????//?#5.?Copy?WriteFile()?buf?to?temp?buf??
  • ????????????ReadProcessMemory(g_cpdi.hProcess,?(LPVOID)dwAddrOfBuffer,???
  • ??????????????????????????????lpBuffer,?dwNumOfBytesToWrite,?NULL);??
  • ????????????printf("\n###?original?string?###\n%s\n",?lpBuffer);??
  • ????????????//?#6.?Lower?case?letters?->?Upper?case?letters??
  • ????????????for(?i?=?0;?i?<?dwNumOfBytesToWrite;?i++?)??
  • ????????????{??
  • ????????????????if(?0x61?<=?lpBuffer[i]?&&?lpBuffer[i]?<=?0x7A?)??
  • ????????????????????lpBuffer[i]?-=?0x20;??
  • ????????????}??
  • ??
  • ????????????printf("\n###?converted?string?###\n%s\n",?lpBuffer);??
  • ??
  • ????????????//?#7.?Copy?to?WriteFile()?buf??
  • ????????????WriteProcessMemory(g_cpdi.hProcess,?(LPVOID)dwAddrOfBuffer,???
  • ???????????????????????????????lpBuffer,?dwNumOfBytesToWrite,?NULL);??
  • ??????????????
  • ????????????//?#8.?release?temp?buf??
  • ????????????free(lpBuffer);??
  • ??
  • ????????????//?#9.?Change?EIP?to?WriteFile()?address??
  • ????????????ctx.Eip?=?(DWORD)g_pfWriteFile;??
  • ????????????SetThreadContext(g_cpdi.hThread,?&ctx);??
  • ??
  • ????????????//?#10.?Run?Debuggee?process??
  • ????????????ContinueDebugEvent(pde->dwProcessId,?pde->dwThreadId,?DBG_CONTINUE);??
  • ????????????Sleep(0);??
  • ??
  • ????????????//?#11.?API?Hook??
  • ????????????WriteProcessMemory(g_cpdi.hProcess,?g_pfWriteFile,???
  • ???????????????????????????????&g_chINT3,?sizeof(BYTE),?NULL);??
  • ??
  • ????????????return?TRUE;??
  • ????????}??
  • ????}??
  • ??
  • ????return?FALSE;??
  • }??
  • 首先脫鉤,因為在將小寫字母轉(zhuǎn)換為大寫字母之后需要正常調(diào)用WriteFile。接著獲取線程的上下文,獲取WriteFile的第二個參數(shù)和第三個參數(shù)的值。調(diào)用WriteFile時,我們要在傳遞過來的參數(shù)中知道param2(緩沖區(qū)地址)和param3(緩沖區(qū)大小)這兩個參數(shù)。函數(shù)參數(shù)存儲在棧中,通過CONTEXT.Esp成員可以獲得它們的值。然后把小寫字母轉(zhuǎn)換為大寫字母之后覆寫WriteFile緩沖區(qū),把線程上下文的EIP修改為WriteFile起始地址。因為在WriteFile的起始地址處設置了斷點,被調(diào)試者內(nèi)部調(diào)用WriteFile時,會在起始地址處遇到INT3指令。執(zhí)行該指令時,EIP的值會增加一個字節(jié),所以EIP的當前地址為WriteFile+1。修改好CONTEXT.Eip成員后,調(diào)用SetThreadContext。現(xiàn)在運行調(diào)試進程。如果沒有Sleep(0)語句,Notepad.exe在調(diào)用WriteFile的過程中我們的程序會嘗試將WriteFile的首字節(jié)修改為0xCC,這可能導致內(nèi)存訪問異常。最后設置鉤子,方便下次鉤取操作。
    完整的代碼如下。 [cpp]?view plaincopy
  • #include?"windows.h"??
  • #include?"stdio.h"??
  • ??
  • LPVOID?g_pfWriteFile?=?NULL;??
  • CREATE_PROCESS_DEBUG_INFO?g_cpdi;??
  • BYTE?g_chINT3?=?0xCC,?g_chOrgByte?=?0;??
  • ??
  • BOOL?OnCreateProcessDebugEvent(LPDEBUG_EVENT?pde)??
  • {??
  • ????//?get?WriteFile()?API?address??
  • ????g_pfWriteFile?=?GetProcAddress(GetModuleHandleA("kernel32.dll"),?"WriteFile");??
  • ??
  • ????//?API?Hook?-?WriteFile()??
  • ????//?change?first?byte?to?0xCC(INT?3)???
  • ????memcpy(&g_cpdi,?&pde->u.CreateProcessInfo,?sizeof(CREATE_PROCESS_DEBUG_INFO));??
  • ????ReadProcessMemory(g_cpdi.hProcess,?g_pfWriteFile,???
  • ??????????????????????&g_chOrgByte,?sizeof(BYTE),?NULL);??
  • ????WriteProcessMemory(g_cpdi.hProcess,?g_pfWriteFile,???
  • ???????????????????????&g_chINT3,?sizeof(BYTE),?NULL);??
  • ??
  • ????return?TRUE;??
  • }??
  • ??
  • BOOL?OnExceptionDebugEvent(LPDEBUG_EVENT?pde)??
  • {??
  • ????CONTEXT?ctx;??
  • ????PBYTE?lpBuffer?=?NULL;??
  • ????DWORD?dwNumOfBytesToWrite,?dwAddrOfBuffer,?i;??
  • ????PEXCEPTION_RECORD?per?=?&pde->u.Exception.ExceptionRecord;??
  • ??
  • ????//?BreakPoint?exception?(INT?3)???
  • ????if(?EXCEPTION_BREAKPOINT?==?per->ExceptionCode?)??
  • ????{??
  • ????????//?BP?at?WriteFile()?API??
  • ????????if(?g_pfWriteFile?==?per->ExceptionAddress?)??
  • ????????{??
  • ????????????//?#1.?Unhook??
  • ????????????//?restore?0xCC?to?original?byte???
  • ????????????WriteProcessMemory(g_cpdi.hProcess,?g_pfWriteFile,???
  • ???????????????????????????????&g_chOrgByte,?sizeof(BYTE),?NULL);??
  • ????????????//?#2.?Get?Thread?Context???
  • ????????????ctx.ContextFlags?=?CONTEXT_CONTROL;??
  • ????????????GetThreadContext(g_cpdi.hThread,?&ctx);??
  • ????????????//?#3.?Get?WriteFile()?param?2,?3??
  • ????????????//???param?2?:?ESP?+?0x8??
  • ????????????//???param?3?:?ESP?+?0xC??
  • ????????????ReadProcessMemory(g_cpdi.hProcess,?(LPVOID)(ctx.Esp?+?0x8),???
  • ??????????????????????????????&dwAddrOfBuffer,?sizeof(DWORD),?NULL);??
  • ????????????ReadProcessMemory(g_cpdi.hProcess,?(LPVOID)(ctx.Esp?+?0xC),???
  • ??????????????????????????????&dwNumOfBytesToWrite,?sizeof(DWORD),?NULL);??
  • ????????????//?#4.?Allocates?temp?buf??
  • ????????????lpBuffer?=?(PBYTE)malloc(dwNumOfBytesToWrite+1);??
  • ????????????memset(lpBuffer,?0,?dwNumOfBytesToWrite+1);??
  • ????????????//?#5.?Copy?WriteFile()?buf?to?temp?buf??
  • ????????????ReadProcessMemory(g_cpdi.hProcess,?(LPVOID)dwAddrOfBuffer,???
  • ??????????????????????????????lpBuffer,?dwNumOfBytesToWrite,?NULL);??
  • ????????????printf("\n###?original?string?###\n%s\n",?lpBuffer);??
  • ????????????//?#6.?Lower?case?letters?->?Upper?case?letters??
  • ????????????for(?i?=?0;?i?<?dwNumOfBytesToWrite;?i++?)??
  • ????????????{??
  • ????????????????if(?0x61?<=?lpBuffer[i]?&&?lpBuffer[i]?<=?0x7A?)??
  • ????????????????????lpBuffer[i]?-=?0x20;??
  • ????????????}??
  • ??
  • ????????????printf("\n###?converted?string?###\n%s\n",?lpBuffer);??
  • ??
  • ????????????//?#7.?Copy?to?WriteFile()?buf??
  • ????????????WriteProcessMemory(g_cpdi.hProcess,?(LPVOID)dwAddrOfBuffer,???
  • ???????????????????????????????lpBuffer,?dwNumOfBytesToWrite,?NULL);??
  • ??????????????
  • ????????????//?#8.?release?temp?buf??
  • ????????????free(lpBuffer);??
  • ??
  • ????????????//?#9.?Change?EIP?to?WriteFile()?address??
  • ????????????ctx.Eip?=?(DWORD)g_pfWriteFile;??
  • ????????????SetThreadContext(g_cpdi.hThread,?&ctx);??
  • ??
  • ????????????//?#10.?Run?Debuggee?process??
  • ????????????ContinueDebugEvent(pde->dwProcessId,?pde->dwThreadId,?DBG_CONTINUE);??
  • ????????????Sleep(0);??
  • ??
  • ????????????//?#11.?API?Hook??
  • ????????????WriteProcessMemory(g_cpdi.hProcess,?g_pfWriteFile,???
  • ???????????????????????????????&g_chINT3,?sizeof(BYTE),?NULL);??
  • ??
  • ????????????return?TRUE;??
  • ????????}??
  • ????}??
  • ??
  • ????return?FALSE;??
  • }??
  • ??
  • void?DebugLoop()??
  • {??
  • ????DEBUG_EVENT?de;??
  • ????DWORD?dwContinueStatus;??
  • ??
  • ????//?Waiting?for?the?event?occurred?by?debuggee??
  • ????while(?WaitForDebugEvent(&de,?INFINITE)?)??
  • ????{??
  • ????????dwContinueStatus?=?DBG_CONTINUE;??
  • ??
  • ????????//?Debuggee?process?generates?or?attaches?event??
  • ????????if(?CREATE_PROCESS_DEBUG_EVENT?==?de.dwDebugEventCode?)??
  • ????????{??
  • ????????????OnCreateProcessDebugEvent(&de);??
  • ????????}??
  • ????????//?Exception?event??
  • ????????else?if(?EXCEPTION_DEBUG_EVENT?==?de.dwDebugEventCode?)??
  • ????????{??
  • ????????????if(?OnExceptionDebugEvent(&de)?)??
  • ????????????????continue;??
  • ????????}??
  • ????????//?Debuggee?process?terminates?event??
  • ????????else?if(?EXIT_PROCESS_DEBUG_EVENT?==?de.dwDebugEventCode?)??
  • ????????{??
  • ????????????//?debuggee?stop?->?debugger?stop??
  • ????????????break;??
  • ????????}??
  • ??
  • ????????//?Run?the?debuggee?again??
  • ????????ContinueDebugEvent(de.dwProcessId,?de.dwThreadId,?dwContinueStatus);??
  • ????}??
  • }??
  • ??
  • int?main(int?argc,?char*?argv[])??
  • {??
  • ????DWORD?dwPID;??
  • ??
  • ????if(?argc?!=?2?)??
  • ????{??
  • ????????printf("\nUSAGE?:?hookdbg.exe?<pid>\n");??
  • ????????return?1;??
  • ????}??
  • ??
  • ????//?Attach?Process??
  • ????dwPID?=?atoi(argv[1]);??
  • ????if(?!DebugActiveProcess(dwPID)?)??
  • ????{??
  • ????????printf("DebugActiveProcess(%d)?failed!!!\n"??
  • ???????????????"Error?Code?=?%d\n",?dwPID,?GetLastError());??
  • ????????return?1;??
  • ????}??
  • ??
  • ????//?debugger?loops??
  • ????DebugLoop();??
  • ??
  • ????return?0;??
  • }??
  • 總結(jié)

    以上是生活随笔為你收集整理的逆向工程核心原理读书笔记-API钩取之记事本小写转大写的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。