代码:
// 调试器.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <windows.h>
#include <list>
#include <algorithm> //使用STL中的算法需要包含此头文件
#include "调试器.h"
#include "Disasm/Decode2Asm.h"
#include <fstream>
using namespace std;
typedef struct Singlesteprecovery
{
BYTE m_RecoveryByte;//恢复字节
DWORD m_RecoveryAddress;//要恢复得地址
char szFlags[4];//标志位
}Singlesteprecovery;
DEBUG_EVENT g_DebugEvent;
Singlesteprecovery g_Singlesteprecovery[100] = {0};
int g_nCount = 0;
HANDLE g_hProcessHandle = NULL;
DWORD g_dwOEP = 0;
char g_szFlags[32] = { 0 };//全局符号
int g_nInedx = 0;//全局索引
int g_nUCount = 0;//U指令的计数器
DWORD g_dwUEIP = 0;//U指令时算出来的EIP
BOOL GetOEP(char* Path);
BOOL MyBP(DEBUG_EVENT& DebugEvent, DWORD pAddress, BYTE bCode, const char* szFlags);
BOOL MyBL();
BOOL MySetByte(DEBUG_EVENT& DebugEvent, DWORD pAddress, BYTE bCode);
void LoadDll(DEBUG_EVENT& DebugEvent);
void MyEXCEPTION_DEBUG_EVENT(DEBUG_EVENT& DebugEvent);
int main()
{
char szPaht[] = "calc.exe";
STARTUPINFO si = {};
PROCESS_INFORMATION pi = {};
BOOL bRet = CreateProcess(NULL,
(LPSTR)szPaht,
NULL,
NULL,
FALSE,
DEBUG_ONLY_THIS_PROCESS,
NULL,
NULL,
&si,
&pi);
if (bRet == FALSE)
{
return 0;
}
int nn = 0;
while (WaitForDebugEvent(&g_DebugEvent, INFINITE))
{
int a = 0;
switch (g_DebugEvent.dwDebugEventCode)
{
case EXCEPTION_DEBUG_EVENT:
MyEXCEPTION_DEBUG_EVENT(g_DebugEvent);
break;
case CREATE_THREAD_DEBUG_EVENT:
//printf("CREATE_THREAD_DEBUG_EVENT\r\n");
break;
case CREATE_PROCESS_DEBUG_EVENT:
g_hProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, g_DebugEvent.dwProcessId);
bRet = GetOEP(szPaht);//G到入口点
MyBP(g_DebugEvent, g_dwOEP, 0xCC, "g");
//printf("CREATE_PROCESS_DEBUG_EVENT\r\n");
break;
case EXIT_THREAD_DEBUG_EVENT:
//printf("EXIT_THREAD_DEBUG_EVENT\r\n");
break;
case EXIT_PROCESS_DEBUG_EVENT:
// printf("EXIT_PROCESS_DEBUG_EVENT\r\n");
break;
case LOAD_DLL_DEBUG_EVENT:
// LoadDll(g_DebugEvent);
break;
case UNLOAD_DLL_DEBUG_EVENT:
//printf("UNLOAD_DLL_DEBUG_EVENT\r\n");
break;
case OUTPUT_DEBUG_STRING_EVENT:
// printf("OUTPUT_DEBUG_STRING_EVENT\r\n");
break;
default:
//printf("default\r\n");
break;
}
//提交处理结果
bRet=ContinueDebugEvent(g_DebugEvent.dwProcessId, g_DebugEvent.dwThreadId, DBG_CONTINUE);
if (bRet == FALSE)
{
return 0;
}
}
return 0;
}
int MyStrlen(char* str)
{
int nLen = 0;
char* r = str;
while (*r != 0)
{
if (*r != ':' && *r != ' ')
{
nLen++;
}
r++;
}
return nLen;
}
BOOL GetOEP(char* Path)
{
DWORD dw3C = 0;
DWORD dwOEP = 0;
DWORD dwImageBase = 0;
fstream f;
f.open(Path, ios::in || ios::binary);
if (!f.is_open())
{
return FALSE;
}
f.seekp(0x3c,ios::beg);
f.read((char*)&dw3C, sizeof(DWORD));
f.seekp(dw3C + 0x18 + 0x10, ios::beg);//dwOEP
f.read((char*)&dwOEP, sizeof(DWORD));
f.seekp(dw3C + 0x18 + 0x1c, ios::beg);
f.read((char*)&dwImageBase, sizeof(DWORD));
f.close();
dwOEP += dwImageBase;
g_dwOEP = dwOEP;
return TRUE;
}
void DelAry(Singlesteprecovery* Singlesteprecovery, int Num)
{
for (int i = Num; i < g_nCount - 1; i++)
{
Singlesteprecovery[i] = Singlesteprecovery[i + 1];
}
g_nCount--;
}
BOOL OutCommand(DWORD Address,char*strOpcode, char*strAsmCode)
{
printf("- ");
char szLine[32] = { 0 };
cin.getline(szLine, 32);
char cBit1 = *szLine;
char szBit2[4] = { 0 };
char szAddress[32] = { 0 };
memcpy(szBit2, szLine, 2);
if (cBit1 == 'g' || cBit1 == 'G')
{
//g 0x?????????
if (strlen(szAddress) < 4)
{
return FALSE;
}
else
{
memcpy(szAddress, szLine + 4, 32 - 4);
DWORD dwAddress = strtol(szAddress, NULL, 16);
MyBP(g_DebugEvent, dwAddress, 0xCC, "g");
return FALSE;
}
}
else if (cBit1 == 't' || cBit1 == 'T')
{
CONTEXT ctx;
ctx.ContextFlags= CONTEXT_ALL;
HANDLE hThread = OpenThread(PROCESS_ALL_ACCESS, FALSE, g_DebugEvent.dwThreadId);
BOOL bRet = GetThreadContext(hThread, &ctx);
ctx.EFlags |= 0x100;
SetThreadContext(hThread, &ctx);
memset(g_szFlags, 0, 32);
strcpy(g_szFlags, "t");
return FALSE;
}
else if (cBit1 == 'p' || cBit1 == 'P')
{
//判断是不是CALL不是CALL则调用普通t步入的逻辑 是CALL则当前EIP+当前指令长度下断点即可
char szBuff[32] = { 0 };
memcpy(szBuff, strAsmCode, 4);
if (!strcmp(szBuff, "call"))
{
int nLen=MyStrlen(strOpcode)/2;
DWORD dwAddress = Address + nLen;
MyBP(g_DebugEvent, dwAddress, 0xcc, "g");
return FALSE;
}
else
{
CONTEXT ctx;
ctx.ContextFlags = CONTEXT_ALL;
HANDLE hThread = OpenThread(PROCESS_ALL_ACCESS, FALSE, g_DebugEvent.dwThreadId);
BOOL bRet = GetThreadContext(hThread, &ctx);
ctx.EFlags |= 0x100;
SetThreadContext(hThread, &ctx);
memset(g_szFlags, 0, 32);
strcpy(g_szFlags, "t");
CloseHandle(hThread);
return FALSE;
}
}
else if (cBit1 == 'r' || cBit1 == 'R')
{
CONTEXT ctx;
HANDLE hThread;
char szBuff[256] = { 0 };
ctx.ContextFlags = CONTEXT_ALL;
hThread = OpenThread(PROCESS_ALL_ACCESS, FALSE, g_DebugEvent.dwThreadId);
BOOL bRet = GetThreadContext(hThread, &ctx);
if (bRet == FALSE)
{
return TRUE;
}
sprintf(szBuff, "Eax=%x\r\n Ecx=%x\r\n Edx=%x\r\n Ebx=%x\r\n Esp=%x\r\n Ebp=%x\r\n Esi=%x\r\n Edi=%x\r\n" ,
ctx.Eax, ctx.Ecx, ctx.Edx, ctx.Ebx, ctx.Esp, ctx.Ebp, ctx.Esi, ctx.Edi);
printf(szBuff);
return TRUE;
}
else if (cBit1 == 'U' || cBit1 == 'u')
{
CONTEXT ctx;
BYTE strCode[100] = { 0 };
HANDLE hThread = NULL;
int nLen = 0;
if (g_dwUEIP == 0)
{
ctx.ContextFlags = CONTEXT_ALL;
hThread = OpenThread(PROCESS_ALL_ACCESS, FALSE, g_DebugEvent.dwThreadId);
BOOL bRet = GetThreadContext(hThread, &ctx);
g_dwUEIP = ctx.Eip;
bRet = ReadProcessMemory(g_hProcessHandle, (LPCVOID)g_dwUEIP,
strCode, sizeof(strCode), NULL);
if (bRet == FALSE)
{
return FALSE;
}
}
else
{
BOOL bRet = ReadProcessMemory(g_hProcessHandle, (LPCVOID)g_dwUEIP,
strCode, sizeof(strCode), NULL);
if (bRet == FALSE)
{
return FALSE;
}
}
for (int i = 0; i < 10; i++)
{
char szOpcode[64] = { 0 };
char szAsmCode[64] = { 0 };
UINT uLen = 16;
Decode2AsmOpcode(strCode+ nLen, szAsmCode,
szOpcode, &uLen, (UINT)g_dwUEIP);
char szBuff[256] = { 0 };
sprintf(szBuff, "地址:0x%x 机器码:%s 汇编:%s", g_dwUEIP, szOpcode, szAsmCode);
printf("%s\r\n", szBuff);
nLen +=MyStrlen(szOpcode)/2;
g_dwUEIP += MyStrlen(szOpcode) / 2;
}
if (hThread != NULL)
{
CloseHandle(hThread);
}
return TRUE;
}
else if (!strcmp(szBit2, "bp") || !strcmp(szBit2, "BP"))
{
//bp 0x????????
memcpy(szAddress, szLine + 5, 32 - 5);
DWORD dwAddress = strtol(szAddress, NULL, 16);
MyBP(g_DebugEvent, dwAddress, 0xCC, "bp");
return TRUE;
}
else if (!strcmp(szBit2, "bl") || !strcmp(szBit2, "BL"))
{
//bl 显示
MyBL();
return TRUE;
}
else if (!strcmp(szBit2, "bc") || !strcmp(szBit2, "BC"))
{
//bc ? 删除第几个
memcpy(szAddress, szLine + 3, 32 - 3);
DWORD dwAddress = strtol(szAddress, NULL, 16);
BOOL bRet = MySetByte(g_DebugEvent, g_Singlesteprecovery[dwAddress].m_RecoveryAddress, g_Singlesteprecovery[dwAddress].m_RecoveryByte);
if (bRet == FALSE)
{
printf("删除失败\r\n");
return TRUE;
}
else
{
printf("删除成功\r\n");
return TRUE;
}
DelAry(g_Singlesteprecovery, dwAddress);
return TRUE;
}
else
{
printf("不认识该指令\r\n");
return TRUE;
}
}
BOOL MyBL()
{
printf("===================================================================================\r\n");
for (int i = 0; i < g_nCount; i++)
{
if (!strcmp(g_Singlesteprecovery[i].szFlags, "bp") || !strcmp(g_Singlesteprecovery[i].szFlags, "DP"))
{
printf("ID:%x-Base:%x\r\n", i, g_Singlesteprecovery[i].m_RecoveryAddress);
}
}
printf("===================================================================================\r\n");
return TRUE;
}
BOOL MyBP(DEBUG_EVENT& DebugEvent, DWORD pAddress, BYTE bCode, const char* szFlags)
{
//恢复原本字节
DWORD flOldProtect = 0;
BOOL bRet = VirtualProtectEx(g_hProcessHandle, (LPVOID)pAddress, sizeof(bCode), PAGE_READWRITE, &flOldProtect);
if (bRet == FALSE)
{
printf("VirtualProtectEx失败\r\n");
return FALSE;
}
//先保存一下原本字节
memset(g_Singlesteprecovery[g_nCount].szFlags, 0, 4);
strcpy(g_Singlesteprecovery[g_nCount].szFlags, szFlags);
g_Singlesteprecovery[g_nCount].m_RecoveryAddress = pAddress;
bRet = ReadProcessMemory(g_hProcessHandle, (LPVOID)pAddress, &g_Singlesteprecovery[g_nCount].m_RecoveryByte, sizeof(BYTE), NULL);
if (bRet == FALSE)
{
return FALSE;
}
g_nCount++;
bRet = WriteProcessMemory(g_hProcessHandle, (LPVOID)pAddress, &bCode, sizeof(bCode), NULL);
if (bRet == FALSE)
{
return FALSE;
}
bRet = VirtualProtectEx(g_hProcessHandle, (LPVOID)pAddress, sizeof(bCode), flOldProtect, &flOldProtect);
if (bRet == FALSE)
{
return FALSE;
}
printf("指令成功\r\n");
return TRUE;
}
BOOL MySetByte(DEBUG_EVENT& DebugEvent, DWORD pAddress, BYTE bCode)
{
DWORD flOldProtect = 0;
BOOL bRet = VirtualProtectEx(g_hProcessHandle, (LPVOID)pAddress, sizeof(bCode), PAGE_READWRITE, &flOldProtect);
if (bRet == FALSE)
{
return FALSE;
}
bRet = WriteProcessMemory(g_hProcessHandle, (LPVOID)pAddress, &bCode, sizeof(bCode), NULL);
if (bRet == FALSE)
{
return FALSE;
}
bRet = VirtualProtectEx(g_hProcessHandle, (LPVOID)pAddress, sizeof(bCode), flOldProtect, &flOldProtect);
if (bRet == FALSE)
{
return FALSE;
}
return TRUE;
}
//异常处理函数
void MyEXCEPTION_DEBUG_EVENT(DEBUG_EVENT& DebugEvent)
{
CONTEXT ctx;
HANDLE hThread = NULL;
char strAsmCode[256] = { 0 };//汇编指令
char strOpcode[256] = { 0 };//机器码
int nIndex = -1;
DWORD dwAddress = 0;
//判断是什么异常
//printf("断点异常:%x\r\n",DebugEvent.u.Exception.ExceptionRecord.ExceptionCode);
if (DebugEvent.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT)
{
//断点异常0x8000003
for (int i = 0; i < g_nCount; i++)
{
if (g_Singlesteprecovery[i].m_RecoveryAddress == (DWORD)DebugEvent.u.Exception.ExceptionRecord.ExceptionAddress)
{
nIndex = i;
break;
}
}
if (nIndex == -1)
{
return;
}
BOOL bRet = MySetByte(DebugEvent, g_Singlesteprecovery[nIndex].m_RecoveryAddress, g_Singlesteprecovery[nIndex].m_RecoveryByte);
if (bRet == FALSE)
{
goto DeleteData;
}
BYTE strCode[16] = { 0 };
bRet = ReadProcessMemory(g_hProcessHandle, (LPVOID)g_Singlesteprecovery[nIndex].m_RecoveryAddress,
strCode, sizeof(strCode), NULL);
if (bRet == FALSE)
{
goto DeleteData;
}
UINT uLen = 16;
Decode2AsmOpcode(strCode, strAsmCode,
strOpcode, &uLen, g_Singlesteprecovery[nIndex].m_RecoveryAddress);
char szBuff[256] = { 0 };
sprintf(szBuff, "地址:0x%x 机器码:%s 汇编:%s", g_Singlesteprecovery[nIndex].m_RecoveryAddress, strOpcode, strAsmCode);
printf("%s\r\n", szBuff);
dwAddress = g_Singlesteprecovery[nIndex].m_RecoveryAddress;
ctx.ContextFlags = CONTEXT_ALL;
hThread = OpenThread(PROCESS_ALL_ACCESS, FALSE, DebugEvent.dwThreadId);
bRet = GetThreadContext(hThread, &ctx);
if (bRet == FALSE)
{
goto DeleteData;
}
if (!strcmp(g_Singlesteprecovery[nIndex].szFlags, "g") || !strcmp(g_Singlesteprecovery[nIndex].szFlags, "G"))
{
//G指令不需要恢复
DelAry(g_Singlesteprecovery, nIndex);
}
else if (!strcmp(g_Singlesteprecovery[nIndex].szFlags, "bp") || !strcmp(g_Singlesteprecovery[nIndex].szFlags, "BP"))
{
//设置单步位
ctx.EFlags |= 0x100;//把Eflags第八位变成1 单步位设置为1
ctx.Eip--;
SetThreadContext(hThread, &ctx);
CloseHandle(hThread);
memset(g_szFlags, 0, 32);
strcpy(g_szFlags, "bp");
g_nInedx = nIndex;
return;
}
ctx.Eip--;
SetThreadContext(hThread, &ctx);
}
else if (DebugEvent.u.Exception.ExceptionRecord.ExceptionCode == STATUS_SINGLE_STEP)
{
//单步异常0x8000004
if (!strcmp(g_szFlags, "bp") || !strcmp(g_szFlags, "BP"))
{
BOOL bRet = MySetByte(DebugEvent, g_Singlesteprecovery[g_nInedx].m_RecoveryAddress, 0xCC);
if (bRet == FALSE)
{
goto DeleteData;;
}
}
else if (!strcmp(g_szFlags, "t") || !strcmp(g_szFlags, "T"))
{
BYTE strCode[16] = { 0 };
BOOL bRet = ReadProcessMemory(g_hProcessHandle, (LPVOID)DebugEvent.u.Exception.ExceptionRecord.ExceptionAddress,
strCode, sizeof(strCode), NULL);
if (bRet == FALSE)
{
goto DeleteData;
}
UINT uLen = 16;
Decode2AsmOpcode(strCode, strAsmCode,
strOpcode, &uLen, (UINT)DebugEvent.u.Exception.ExceptionRecord.ExceptionAddress);
char szBuff[256] = { 0 };
sprintf(szBuff, "地址:0x%x 机器码:%s 汇编:%s", DebugEvent.u.Exception.ExceptionRecord.ExceptionAddress, strOpcode, strAsmCode);
printf("%s\r\n", szBuff);
dwAddress = (DWORD)DebugEvent.u.Exception.ExceptionRecord.ExceptionAddress;
}
}
DeleteData:
while (1)
{
BOOL bRet = OutCommand(dwAddress, strOpcode, strAsmCode);
if (bRet == FALSE)
{
g_dwUEIP = 0;
break;
}
}
if (hThread != NULL)
{
CloseHandle(hThread);
}
return;
}
//加载DLL
void LoadDll(DEBUG_EVENT& DebugEvent)
{
DWORD dwStrAddress = 0;
if (g_hProcessHandle == NULL)
{
return;
}
BOOL bRet = ReadProcessMemory(g_hProcessHandle, DebugEvent.u.LoadDll.lpImageName, &dwStrAddress, sizeof(DWORD), NULL);
if (bRet == FALSE)
{
return;
}
if (DebugEvent.u.LoadDll.fUnicode)
{
wchar_t wszDllName[MAX_PATH] = { 0 };
ReadProcessMemory(g_hProcessHandle, (LPVOID)dwStrAddress, wszDllName, MAX_PATH, NULL);
printf("%ws\r\n", wszDllName);
printf("%x\r\n", DebugEvent.u.LoadDll.lpBaseOfDll);
}
else
{
char szDllName[MAX_PATH] = { 0 };
ReadProcessMemory(g_hProcessHandle, (LPVOID)dwStrAddress, szDllName, MAX_PATH, NULL);
printf("%ws\r\n", szDllName);
printf("%x\r\n", DebugEvent.u.LoadDll.lpBaseOfDll);
}
}