调试器打开子进程和附加子进程注入DLL

//网上找的一段代码改了改,调了调,只能当测试用哦...
#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;}	
	}

}


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值