//网上找的一段代码改了改,调了调,只能当测试用哦...
#include <windows.h>
#include <strsafe.h>
#include <stddef.h>
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#define new new( _CLIENT_BLOCK, __FILE__, __LINE__)
// 检测内存泄漏
// _CrtDumpMemoryLeaks();//一般放main返回处
#pragma comment(lib,"strsafe")
//B8 00000000 mov eax, &szDllPath
//50 push eax
//B9 00000000 mov ecx, &LoadLibrary
//FFD1 call ecx
//CC int3
//结构必须字节对齐!
#pragma pack(1)
typedef struct _INJECT_CODE
{
BYTE byMOV_EAX;
DWORD dwMOV_EAX_VALUE;
BYTE byPUSH_EAX;
BYTE byMOV_ECX;
DWORD dwMOV_ECX_VALUE;
WORD wCALL_ECX;
BYTE byINT3;
CHAR szDllPath[MAX_PATH];
}INJECT_CODE,*PINJECT_CODE;
#pragma pack()
//代码注入函数
BOOL InjectDebuggeeCode(HANDLE hProcess,LPVOID lpBaseAddress,PCHAR szDllPath)
{
BOOL fSuccess = FALSE;
INJECT_CODE ic = {0};
ic.byMOV_EAX = 0xB8;
ic.dwMOV_EAX_VALUE = (DWORD)lpBaseAddress + offsetof(INJECT_CODE,szDllPath);
ic.byPUSH_EAX = 0x50;
ic.byMOV_ECX = 0xB9;
ic.dwMOV_ECX_VALUE = (DWORD)&LoadLibrary;
ic.wCALL_ECX = 0xD1FF;
ic.byINT3 = 0xCC;
StringCbCopy(ic.szDllPath,MAX_PATH,szDllPath);
fSuccess = WriteProcessMemory(hProcess,lpBaseAddress,&ic,sizeof(ic),NULL);
if(!fSuccess)printf("Error:%d,Inject Debuggee Code Failed.",GetLastError());
fSuccess = FlushInstructionCache(hProcess,lpBaseAddress,sizeof(ic));
if(!fSuccess)printf("Error:%d,Flush Debuggee Code Failed.",GetLastError());
return fSuccess;
}
int main(int argc,char **argv)
{
BOOL fSuccess = FALSE;
DWORD dwProcessId = 0;
LPVOID lpBaseAddress = NULL;
HANDLE hThread = NULL;
HANDLE hProcess = NULL;
DEBUG_EVENT dbgEvent = {0};
CONTEXT ctxOld = {CONTEXT_FULL};
CONTEXT ctxNew = {CONTEXT_FULL};
INJECT_CODE ic = {0};
STARTUPINFO si = {sizeof(si)};
PROCESS_INFORMATION pi = {0};
//Debug_Attach 为0时测试调试打开子进程注入dll方式,为 1 时没测试根据配置dwProcessId的值附加注入dll到被调进程
#define Debug_Attach 0
#if Debug_Attach
dwProcessId = 12656; //被附加时的进程ID,每次进行测试时自己修改
#else
//对子进程时行注入,输入子进程的全路径
CHAR * pProcess = "D:\\Desktop\\DbgView\\Dbgview.exe";
#endif
//被注入的dll,,正常的dll都行
CHAR * pDll= "D:\\Desktop\\EnumDirFile.dll";
#if Debug_Attach
//1.通过DebugActiveProcess将目标进程附加到调试器上
fSuccess = DebugActiveProcess(dwProcessId);
if(!fSuccess){printf("Debug Process [%d] Failed.",dwProcessId);return 0;}
#else
fSuccess = CreateProcessA(NULL, pProcess, NULL, NULL, FALSE, DEBUG_ONLY_THIS_PROCESS, NULL, NULL, &si, &pi);
if(!fSuccess){printf("CreateProcessA [%s] Failed.",pProcess);return 0;}
#endif
//2.本程序退出时,防止被调试进程也一并退出
fSuccess = DebugSetProcessKillOnExit(FALSE);
if(!fSuccess){printf("DebugSetProcessKillOnExit ProcessID [%d] Failed.",dwProcessId);return 0;}
//3.建立调试循环体,一旦接收到通知,调试信息便会被填充到DEBUG_EVENT结构中
while(WaitForDebugEvent(&dbgEvent,INFINITE))
{
switch(dbgEvent.dwDebugEventCode)
{
case CREATE_PROCESS_DEBUG_EVENT :
hProcess = dbgEvent.u.CreateProcessInfo.hProcess;
hThread = dbgEvent.u.CreateProcessInfo.hThread;
//分配内存,填充注入指令
lpBaseAddress = VirtualAllocEx(hProcess,
NULL,
sizeof(INJECT_CODE),
MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE);
if(NULL == lpBaseAddress)
{
printf("Error:%d,Can not alloc enough memory",GetLastError());
return 0;
}
//将加载DLL指令写入到目标进程中
fSuccess = InjectDebuggeeCode(hProcess,lpBaseAddress, pDll);
if(!fSuccess) return 0;
//获取当前线程上下文
fSuccess = GetThreadContext(hThread,&ctxOld);
if(!fSuccess){printf("GetThreadContext return false ProcessID [%d] Failed.",dwProcessId);return 0;}
ctxNew = ctxOld;
ctxNew.Eip = (DWORD)lpBaseAddress;
printf("Old Eip = 0x%08X\n",ctxOld.Eip);
printf("New Eip = 0x%08X\n",ctxNew.Eip);
//4.设置新的线程上下文
fSuccess = SetThreadContext(hThread,&ctxNew);
if(!fSuccess){printf("GetThreadContext return false ProcessID [%d] Failed.",dwProcessId);return 0;}
break;
case EXCEPTION_DEBUG_EVENT :
if(dbgEvent.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT)
{
fSuccess = GetThreadContext(hThread,&ctxNew);
if(!fSuccess){printf("GetThreadContext return false ProcessID [%d] Failed.",dwProcessId);return 0;}
//第一次捕获断点则跳过不执行!查阅MSDN中DebugActiveProcess的最后一段话
//After all of this is done, the system resumes all threads in the process.
//When the first thread in the process resumes, it executes a breakpoint instruction
//that causes an EXCEPTION_DEBUG_EVENT debugging event to be sent to the debugger.
//All future debugging events are sent to the debugger by using the normal mechanism and rules.
if(ctxNew.Eip != (DWORD)lpBaseAddress + 0x0e) break;
printf("Second Exception Eip = 0x%08X/n",ctxNew.Eip);
//释放内存
VirtualFreeEx(hProcess,
lpBaseAddress,
sizeof(INJECT_CODE),
MEM_RELEASE);
//5.设置原先的线程上下文
fSuccess = SetThreadContext(hThread,&ctxOld);
if(!fSuccess){printf("SetThreadContext return false ProcessID [%d] Failed.",dwProcessId);return 0;}
//执行原EIP指向的指令
fSuccess = ContinueDebugEvent(dbgEvent.dwProcessId,dbgEvent.dwThreadId,DBG_CONTINUE);
if(!fSuccess){printf("ContinueDebugEvent return false ProcessID [%d] Failed.",dwProcessId);return 0;}
return 0; //退出调试程序!
}
break;
}
fSuccess = ContinueDebugEvent(dbgEvent.dwProcessId,dbgEvent.dwThreadId,DBG_EXCEPTION_NOT_HANDLED);
if(!fSuccess){printf("ContinueDebugEvent return false ProcessID [%d] Failed.",dwProcessId);return 0;}
}
}