電氣網(wǎng)站模板免費(fèi)推廣的網(wǎng)站有哪些
當(dāng)讀者需要獲取到特定進(jìn)程內(nèi)的寄存器信息時(shí),則需要在上述代碼中進(jìn)行完善,首先需要編寫CREATE_PROCESS_DEBUG_EVENT
事件,程序被首次加載進(jìn)入內(nèi)存時(shí)會(huì)被觸發(fā)此事件,在該事件內(nèi)首先我們通過(guò)lpStartAddress
屬性獲取到當(dāng)前程序的入口地址,并通過(guò)SuspendThread
暫停程序的運(yùn)行,當(dāng)被暫停后則我沒就可以通過(guò)ReadProcessMemory
讀取當(dāng)前位置的一個(gè)字節(jié)機(jī)器碼,目的是保存以便于后期的恢復(fù),接著通過(guò)WriteProcessMemory
向?qū)Χ?code>(void*)dwAddr地址寫出一個(gè)0xCC
斷點(diǎn),該斷點(diǎn)則是int3
停機(jī)指令,最后ResumeThread
恢復(fù)這個(gè)線程的運(yùn)行,此時(shí)程序中因存在斷點(diǎn),則會(huì)觸發(fā)一個(gè)EXCEPTION_DEBUG_EVENT
異常事件。
case CREATE_PROCESS_DEBUG_EVENT:
{// 獲取入口地址 0x0 可以增加偏移到入口后任意位置DWORD dwAddr = 0x0 + (DWORD)de.u.CreateProcessInfo.lpStartAddress;// 暫停線程SuspendThread(de.u.CreateProcessInfo.hThread);// 讀取入口地址處的字節(jié)碼ReadProcessMemory(de.u.CreateProcessInfo.hProcess, (const void*)dwAddr, &bCode, sizeof(BYTE), &dwNum);// 在入口地址處寫入 0xCC 即寫入 INT 3 暫停進(jìn)程執(zhí)行WriteProcessMemory(de.u.CreateProcessInfo.hProcess, (void*)dwAddr, &bCC, sizeof(BYTE), &dwNum);// 恢復(fù)線程ResumeThread(de.u.CreateProcessInfo.hThread);break;
}
當(dāng)異常斷點(diǎn)被觸發(fā)后,則下一步就會(huì)觸發(fā)兩次異常,第一次異常我們可以使用break
直接跳過(guò),因?yàn)榇藬帱c(diǎn)通常為系統(tǒng)斷點(diǎn),而第二次斷點(diǎn)則是我們自己設(shè)置的int3斷點(diǎn),此時(shí)需要將該請(qǐng)求發(fā)送至OnException
異常處理函數(shù)對(duì)其進(jìn)行處理,在傳遞時(shí)需要給與&de
調(diào)試事件,以及&bCode
原始的機(jī)器碼;
case EXCEPTION_DEBUG_EVENT:
{switch (dwCC_Count){// 第0次是系統(tǒng)斷點(diǎn),這里我們直接跳過(guò)case 0:dwCC_Count++; break;// 第1次斷點(diǎn),我們讓他執(zhí)行下面的函數(shù)case 1:OnException(&de, &bCode); dwCC_Count++; break;}
}
異常事件會(huì)被流轉(zhuǎn)到OnException(DEBUG_EVENT* pDebug, BYTE* bCode)
函數(shù)內(nèi),在本函數(shù)內(nèi)我們首先通過(guò)使用OpenProcess/OpenThread
兩個(gè)函數(shù)得到當(dāng)前進(jìn)程的句柄信息,接著使用SuspendThread(hThread)
暫時(shí)暫停進(jìn)程內(nèi)線程的執(zhí)行,通過(guò)調(diào)用ReadProcessMemory
得到線程上下文異常產(chǎn)生的首地址,當(dāng)?shù)玫绞椎刂泛?#xff0c;則可以調(diào)用GetThreadContext(hThread, &context)
得到當(dāng)前線程的上下文,一旦上下文被獲取到則讀者即可通過(guò)context.
的方式得到當(dāng)前程序的所有寄存器信息,為了讓程序正常執(zhí)行當(dāng)讀取結(jié)束后,通過(guò)WriteProcessMemory
我們將原始機(jī)器碼寫回到內(nèi)存中,并SetThreadContext
設(shè)置當(dāng)前上下文,最后使用ResumeThread
運(yùn)行該線程;
void OnException(DEBUG_EVENT* pDebug, BYTE* bCode)
{CONTEXT context;DWORD dwNum;BYTE bTmp;HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pDebug->dwProcessId);HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, pDebug->dwThreadId);// 暫停指定的線程SuspendThread(hThread);// 讀取出異常首地址ReadProcessMemory(hProcess, pDebug->u.Exception.ExceptionRecord.ExceptionAddress, &bTmp, sizeof(BYTE), &dwNum);context.ContextFlags = CONTEXT_FULL;GetThreadContext(hThread, &context);printf("\n");printf("EAX = 0x%08X | EBX = 0x%08X | ECX = 0x%08X | EDX = 0x%08X \n",context.Eax, context.Ebx, context.Ecx, context.Edx);printf("EBP = 0x%08X | ESP = 0x%08X | ESI = 0x%08X | EDI = 0x%08X \n\n",context.Ebp, context.Esp, context.Esi, context.Edi);printf("EIP = 0x%08X | EFLAGS = 0x%08X\n\n", context.Eip, context.EFlags);// 將剛才的CC斷點(diǎn)取消,也就是回寫原始指令集WriteProcessMemory(hProcess, pDebug->u.Exception.ExceptionRecord.ExceptionAddress, bCode, sizeof(BYTE), &dwNum);context.Eip--;// 設(shè)置線程上下文SetThreadContext(hThread, &context);// printf("進(jìn)程句柄: 0x%08X \n", pDebug->u.CreateProcessInfo.hProcess);// printf("主線程句柄: 0x%08X \n", pDebug->u.CreateProcessInfo.hThread);printf("虛擬入口點(diǎn): 0x%08X \n", pDebug->u.CreateProcessInfo.lpBaseOfImage);// 恢復(fù)線程執(zhí)行ResumeThread(hThread);CloseHandle(hThread);CloseHandle(hProcess);
}
當(dāng)這段程序被運(yùn)行后,讀者可看到如下圖所示的輸出信息,該進(jìn)程中當(dāng)前寄存器的狀態(tài)基本上都可以被獲取到;
本文作者: 王瑞
本文鏈接: https://www.lyshark.com/post/94ad4ba.html
版權(quán)聲明: 本博客所有文章除特別聲明外,均采用 BY-NC-SA 許可協(xié)議。轉(zhuǎn)載請(qǐng)注明出處!