首页
社区
课程
招聘
[分享]一段注入代码到目标进程并自加载一个dll的代码
发表于: 2009-12-25 15:02 12455

[分享]一段注入代码到目标进程并自加载一个dll的代码

2009-12-25 15:02
12455

#include "stdafx.h"
#include <winnt.h>

#pragma warning(disable:4102)

typedef HMODULE (WINAPI *LOADLIBRARYA)(LPCSTR lpLibFileName);
typedef FARPROC (WINAPI *GETPROCADDRESS)(HMODULE hModule, LPCSTR pszProcName);
typedef DWORD (WINAPI *GETLASTERROR)();
typedef LPVOID (WINAPI *VIRTUALALLOC)(LPVOID lpAddress, DWORD dwSize, DWORD flAllocationType, DWORD flProtect);
typedef BOOL (WINAPI *VIRTUALFREE)(LPVOID lpAddress, DWORD dwSize, DWORD dwFreeType);
typedef BOOL (WINAPI *FREELIBRARY)(HMODULE hModule);
typedef void (WINAPI *OUTPUTDEBUGSTRINGA)(LPCSTR lpOutputString);
typedef VOID (WINAPI *SLEEP)(DWORD dwMilliseconds);


typedef void (WINAPI *MYCOPYMEMORY)(LPVOID lpDst, LPCVOID lpSrc, DWORD dwLength);

typedef BOOL (WINAPI *PDLLMAIN)(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);



#define THUNK_BEGIN_TAG \
	__asm _emit 't' \
	__asm _emit 'h' \
	__asm _emit 'u' \
	__asm _emit 'n' \
	__asm _emit 'k' \
	__asm _emit '_' \
	__asm _emit 'b' \
	__asm _emit 'e' \
	__asm _emit 'g' \
	__asm _emit 'i' \
	__asm _emit 'n' 

#define THUNK_BEGIN_STR "thunk_begin"

#define THUNK_END_TAG \
	__asm _emit 't' \
	__asm _emit 'h' \
	__asm _emit 'u' \
	__asm _emit 'n' \
	__asm _emit 'k' \
	__asm _emit '_' \
	__asm _emit 'e' \
	__asm _emit 'n' \
	__asm _emit 'd' 

#define THUNK_END_STR "thunk_end"

#define CODE_BEGIN_TAG \
	__asm _emit 'c' \
	__asm _emit 'o' \
	__asm _emit 'd' \
	__asm _emit 'e' \
	__asm _emit '_' \
	__asm _emit 'b' \
	__asm _emit 'e' \
	__asm _emit 'g' \
	__asm _emit 'i' \
	__asm _emit 'n' 

#define CODE_BEGIN_STR "code_begin"

#pragma check_stack(off)
#pragma pack(push, 8)

__declspec(naked) void TestCode()
{
	// 临时变量
	DWORD offsetLabel;

	HMODULE hKernel32;
	
	LOADLIBRARYA pLoadLibraryA;
	GETPROCADDRESS pGetProcAddress;
	FREELIBRARY pFreeLibrary;
	//VIRTUALALLOC pVirtualAlloc;
	MYCOPYMEMORY pCopyMemory;
	OUTPUTDEBUGSTRINGA pOutputDbgStringA;
	SLEEP pSleep;

	// 起始标志
	THUNK_BEGIN_TAG

	__asm
	{
//// module 
//_RO_dwKernel32Base:
//		INT 3
//		INT 3
//		INT 3
//		INT 3

// api地址空间 使用的时候外部程序填写
_RO_LoadLibraryA: 
		INT 3
		INT 3
		INT 3
		INT 3

_RO_GetProcAddress:
		INT 3
		INT 3
		INT 3
		INT 3

_RO_FreeLibrary:
		INT 3
		INT 3
		INT 3
		INT 3

// string 
_RO_szKernel32:				// db "kernel32.dll",0 13
		_emit 'K'
		_emit 'e'
		_emit 'r'
		_emit 'n'
		_emit 'e'
		_emit 'l'
		_emit '3'
		_emit '2'
		_emit '.'
		_emit 'd'
		_emit 'l'
		_emit 'l'
		_emit '\0'

_RO_szOutputDebugStringA:	// db "OutputDebugStringA",0  19
		_emit 'O'
		_emit 'u'
		_emit 't'
		_emit 'p'
		_emit 'u'
		_emit 't'
		_emit 'D'
		_emit 'e'
		_emit 'b'
		_emit 'u'
		_emit 'g'
		_emit 'S'
		_emit 't'
		_emit 'r'
		_emit 'i'
		_emit 'n'
		_emit 'g'
		_emit 'A'
		_emit '\0'

_RO_szSleep:				// db "Sleep",0 6
		_emit 'S'
		_emit 'l'
		_emit 'e'
		_emit 'e'
		_emit 'p'
		_emit '\0'


		CODE_BEGIN_TAG

// 		INT 3	// 调试
// 		INT 3
// 		INT 3
// 		INT 3
// 		INT 3
// 		INT 3
// 		INT 3
// 		INT 3
// 主函数
_MAINCODE_BEGIN:
		PUSHAD
		PUSHFD
		MOV EBP, ESP						// 给VC构造BP FRAME 
		SUB ESP, 1024						// 临时变量

		// 取得偏移量
		CALL _GET_EIP
_GET_EIP:         
		POP EAX								// 获取当前的EIP, 也就是GET_EIP 处的va !!!
		SUB EAX, OFFSET _GET_EIP			// 计算标号实际地址跟编译生成地址的偏移,用offsetLabel 保存
		MOV offsetLabel, EAX      
		MOV EBX, EAX						// offserLabel

		// 初始化临时变量
		MOV EAX, OFFSET _RO_LoadLibraryA	// LoadLibraryA
		ADD EAX, EBX
		MOV EAX, DWORD PTR [EAX]
		MOV pLoadLibraryA, eax

		MOV EAX, OFFSET _RO_GetProcAddress	// GetProcess
		ADD EAX, EBX
		MOV EAX, DWORD PTR [EAX]
		MOV pGetProcAddress, eax
			
		MOV EAX, OFFSET _RO_FreeLibrary		// FreeLibrary
		ADD EAX, EBX
		MOV EAX, DWORD PTR [EAX]
		MOV pFreeLibrary, eax

		MOV EAX, OFFSET _PROC_MemCpy		// CopyMemory
		ADD EAX, EBX
		MOV pCopyMemory, EAX;

		MOV EAX, OFFSET _RO_szKernel32		// hKernel32
		ADD EAX, EBX
		PUSH EAX
		CALL DWORD PTR[pLoadLibraryA]
		MOV hKernel32, EAX

		// 做测试
		MOV EAX, _RO_szOutputDebugStringA
		ADD EAX, EBX
		MOV ESI, hKernel32
		CALL _PROC_GetProcAddress
		MOV pOutputDbgStringA, EAX

		MOV EAX, _RO_szSleep
		ADD EAX, EBX
		MOV ESI, hKernel32
		CALL _PROC_GetProcAddress
		MOV pSleep, EAX

_TEST:
		MOV EAX, _RO_szOutputDebugStringA
		ADD EAX, EBX
		PUSH EAX
		CALL DWORD PTR[pOutputDbgStringA]

		PUSH 0x3E8
		CALL DWORD PTR[pSleep]
		JMP _TEST

_MAINCODE_END:
		XOR EAX, EAX						// 函数返回值
		MOV ESP, EBP
		POPFD
		POPAD
		RETN 4								// 线程函数有一个参数
	}

// 子函数
	__asm
	{
// 取函数地址 eax=函数名 esi=模块地址
_PROC_GetProcAddress:
		PUSH EDX
		PUSH EAX
		PUSH ESI
		MOV EDX, OFFSET _RO_GetProcAddress
		ADD EDX, offsetLabel
		CALL [EDX]
		POP EDX
		RETN
	}

	__asm
	{
// 简单的memcpy 函数
_PROC_MemCpy:   
		PUSH EBP
		MOV EBP,ESP
		PUSH ECX
		PUSH EAX
		PUSH ESI
		PUSH EDI
		MOV EDI,DWORD PTR SS:[EBP+08h]		// dst
		MOV ESI,DWORD PTR SS:[EBP+0Ch]		// src
		MOV ECX,DWORD PTR SS:[EBP+10h]		// len
		TEST ECX, ECX
		JZ __CopyEnd						// copy 0字节的.textbss 要出错所以修改 by ranbo
		XOR EAX,EAX

__cpy:
		LODS BYTE PTR DS:[ESI]
		STOS BYTE PTR ES:[EDI]
		LOOP __cpy

__CopyEnd:
		POP EDI
		POP ESI
		POP EAX
		POP ECX
		MOV ESP,EBP
		POP EBP
		RET 0CH
	}

	THUNK_END_TAG
}

#pragma check_stack(off)
// 注入一个进程 并load一个dll的代码
__declspec(naked) void LoadLibraryCode()
{
	DWORD offsetLabel;
	HMODULE hKernel32;
	
	// 函数指针
	LOADLIBRARYA pLoadLibraryA;
	GETPROCADDRESS pGetProcAddress;
	FREELIBRARY pFreeLibrary;
	VIRTUALALLOC pVirtualAlloc;
	MYCOPYMEMORY pCopyMemory;
	OUTPUTDEBUGSTRINGA pOutputDbgStringA;
	SLEEP pSleep;

	// loadlibrary时候用的临时变量
	PBYTE pbyLibrary;				// dll内存数据

	// 起始标志
	THUNK_BEGIN_TAG

	__asm
	{
//// 需要load的 dll 内存 指针 外部初始化时候申请内存并填写这个指针 
_RO_pbyLibrary:
		INT 3
		INT 3
		INT 3
		INT 3

// api地址空间 使用的时候外部程序填写
_RO_LoadLibraryA: 
		INT 3
		INT 3
		INT 3
		INT 3

_RO_GetProcAddress:
		INT 3
		INT 3
		INT 3
		INT 3

_RO_FreeLibrary:
		INT 3
		INT 3
		INT 3
		INT 3

// string 
_RO_szKernel32:				// db "kernel32.dll",0 13
		_emit 'K'
		_emit 'e'
		_emit 'r'
		_emit 'n'
		_emit 'e'
		_emit 'l'
		_emit '3'
		_emit '2'
		_emit '.'
		_emit 'd'
		_emit 'l'
		_emit 'l'
		_emit '\0'

_RO_szVirtualAlloc:
		_emit 'V'
		_emit 'i'
		_emit 'r'
		_emit 't'
		_emit 'u'
		_emit 'a'
		_emit 'l'
		_emit 'A'
		_emit 'l'
		_emit 'l'
		_emit 'o'
		_emit 'c'
		_emit '\0'

_RO_szOutputDebugStringA:	// db "OutputDebugStringA",0  19
		_emit 'O'
		_emit 'u'
		_emit 't'
		_emit 'p'
		_emit 'u'
		_emit 't'
		_emit 'D'
		_emit 'e'
		_emit 'b'
		_emit 'u'
		_emit 'g'
		_emit 'S'
		_emit 't'
		_emit 'r'
		_emit 'i'
		_emit 'n'
		_emit 'g'
		_emit 'A'
		_emit '\0'

_RO_szSleep:				// db "Sleep",0 6
		_emit 'S'
		_emit 'l'
		_emit 'e'
		_emit 'e'
		_emit 'p'
		_emit '\0'


		CODE_BEGIN_TAG

// 		INT 3	// 调试
// 		INT 3
// 		INT 3
// 		INT 3
// 		INT 3
// 		INT 3
// 		INT 3
// 		INT 3
// 主函数
_MAINCODE_BEGIN:
		PUSHAD
		PUSHFD
		MOV EBP, ESP						// 给VC构造BP FRAME 
		SUB ESP, 2048						// 临时变量

		// 取得偏移量
		CALL _GET_EIP
_GET_EIP:         
		POP EAX								// 获取当前的EIP, 也就是GET_EIP 处的va !!!
		SUB EAX, OFFSET _GET_EIP			// 计算标号实际地址跟编译生成地址的偏移,用offsetLabel 保存
		MOV offsetLabel, EAX      
		MOV EBX, EAX						// offserLabel

		// 初始化临时变量
		// lib操作的几个api必须最先初始化 然后handler 之后才能开始调用函数
		MOV EAX, OFFSET _RO_pbyLibrary
		ADD EAX, EBX
		MOV EAX, DWORD PTR[EAX]
		MOV pbyLibrary, EAX

		MOV EAX, OFFSET _RO_LoadLibraryA	// LoadLibraryA
		ADD EAX, EBX
		MOV EAX, DWORD PTR [EAX]
		MOV pLoadLibraryA, eax

		MOV EAX, OFFSET _RO_GetProcAddress	// GetProcess
		ADD EAX, EBX
		MOV EAX, DWORD PTR [EAX]
		MOV pGetProcAddress, eax
			
		MOV EAX, OFFSET _RO_FreeLibrary		// FreeLibrary
		ADD EAX, EBX
		MOV EAX, DWORD PTR [EAX]
		MOV pFreeLibrary, eax

		// handler 
		MOV EAX, OFFSET _RO_szKernel32		// hKernel32
		ADD EAX, EBX
		PUSH EAX
		CALL DWORD PTR[pLoadLibraryA]
		MOV hKernel32, EAX


		// 做测试用的几个API 用GetProcess得到
		MOV EAX, OFFSET	_RO_szVirtualAlloc	// VirtualAlloc
		ADD EAX, EBX
		MOV ESI, hKernel32
		CALL _PROC_GetProcAddress
		MOV pVirtualAlloc, eax

		MOV EAX, _RO_szOutputDebugStringA
		ADD EAX, EBX
		MOV ESI, hKernel32
		CALL _PROC_GetProcAddress
		MOV pOutputDbgStringA, EAX

		MOV EAX, _RO_szSleep
		ADD EAX, EBX
		MOV ESI, hKernel32
		CALL _PROC_GetProcAddress
		MOV pSleep, EAX

		// 自定义函数初始化
		MOV EAX, OFFSET _PROC_MemCpy		// CopyMemory
		ADD EAX, EBX
		MOV pCopyMemory, EAX;


// _TEST:
// 		MOV EAX, _RO_szOutputDebugStringA
// 		ADD EAX, EBX
// 		PUSH EAX
// 		CALL DWORD PTR[pOutputDbgStringA]
// 
// 		PUSH 0x3E8
// 		CALL DWORD PTR[pSleep]
// 		JMP _TEST

	}

	//-------------------------------------------------------------
	// C++代码 加载dll
	// 
	// 1. 申请内存 copy header section 到内存中
	PIMAGE_DOS_HEADER		pOrgDosHead;
	PIMAGE_NT_HEADERS		pOrgNtHead;
	PIMAGE_SECTION_HEADER	pOrgSecHead;

	PBYTE					pMemoryImage;

	pOrgDosHead = (PIMAGE_DOS_HEADER)pbyLibrary;
	pOrgNtHead = (PIMAGE_NT_HEADERS)(pbyLibrary + pOrgDosHead->e_lfanew);
	pOrgSecHead = IMAGE_FIRST_SECTION(pOrgNtHead);

	pMemoryImage = (PBYTE)pVirtualAlloc(NULL,
		pOrgNtHead->OptionalHeader.SizeOfImage,
		MEM_RESERVE | MEM_COMMIT,
		PAGE_EXECUTE_READWRITE);

	if (!pMemoryImage)
	{
		//__asm int 3;
		goto _MAINCODE_END;
	}

	// copy header
	pCopyMemory(pMemoryImage, pbyLibrary, pOrgNtHead->OptionalHeader.SizeOfHeaders);

	// copy section
	for(int i=0; i< pOrgNtHead->FileHeader.NumberOfSections; i++, pOrgSecHead++)
	{
		pCopyMemory(
			pMemoryImage + pOrgSecHead->VirtualAddress,
			pbyLibrary + pOrgSecHead->PointerToRawData,
			pOrgSecHead->SizeOfRawData
			);
	}

	// 2. 填充导入表
	// 指向copy之后的东东
	PIMAGE_DOS_HEADER		pDosHead;
	PIMAGE_NT_HEADERS		pNtHead;
	PIMAGE_SECTION_HEADER	pSecHead;
	PIMAGE_OPTIONAL_HEADER	pOptHead;
	PIMAGE_BASE_RELOCATION	pBaseReloc;

	pDosHead = (PIMAGE_DOS_HEADER)pMemoryImage;
	pNtHead = (PIMAGE_NT_HEADERS)(pMemoryImage + pDosHead->e_lfanew);
	pSecHead = IMAGE_FIRST_SECTION(pNtHead);
	pOptHead = &pNtHead->OptionalHeader;


	if(pOptHead->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size != 0)
	{
		PIMAGE_IMPORT_DESCRIPTOR pid;
		pid=(IMAGE_IMPORT_DESCRIPTOR *)
			(pMemoryImage + pOptHead->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);

		// For all imported DLLs
		while(pid->FirstThunk && pid->Name)
		{
			DWORD	*pdwThunkRef;
			DWORD	*pdwFuncRef;
			char	*pszDllName;
			HMODULE	hDll;

			pszDllName=(char *) (pMemoryImage + pid->Name);
			hDll = pLoadLibraryA(pszDllName);
			
			if(hDll==NULL) 
			{
				pOutputDbgStringA(pszDllName);
				//__asm int 3;
				goto _MAINCODE_END;
			}

			if(pid->OriginalFirstThunk)
			{
				pdwThunkRef = (DWORD *)(pMemoryImage + pid->OriginalFirstThunk);
				pdwFuncRef = (DWORD *)(pMemoryImage + pid->FirstThunk);
			}
			else
			{
				pdwThunkRef = (DWORD *)(pMemoryImage + pid->FirstThunk);
				pdwFuncRef = (DWORD *)(pMemoryImage + pid->FirstThunk);
			}

			for( ; *pdwThunkRef; pdwThunkRef++, pdwFuncRef++)
			{
				DWORD	dwAddr;

				if(IMAGE_SNAP_BY_ORDINAL(*pdwThunkRef))
				{
					// win 98 需要单独处理
					dwAddr = (DWORD)pGetProcAddress(hDll, (LPCSTR)IMAGE_ORDINAL(*pdwThunkRef));
				}
				else
				{
					PIMAGE_IMPORT_BY_NAME	pName;
					pName = (PIMAGE_IMPORT_BY_NAME)(pMemoryImage + (*pdwThunkRef));
					dwAddr = (DWORD)pGetProcAddress(hDll, (LPCSTR)&pName->Name);
				}

				*pdwFuncRef = dwAddr;
			}

			pid++;
		}
	}


	//__asm int 3;
	// 3. 重定位
	DWORD delta;
	delta=(DWORD)pMemoryImage - (DWORD)pOptHead->ImageBase;

 	if((delta!=0) && (pOptHead->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size!=0)) 
 	{
 		pBaseReloc = (PIMAGE_BASE_RELOCATION)(pMemoryImage 
			+ pOptHead->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
 
 
 		while(pBaseReloc->VirtualAddress != 0)
		{
			// 结构
			// WORD	offset:12;
			// WORD	type:4;

			int		i;
			PWORD	pwItem = (PWORD)((DWORD)pBaseReloc + IMAGE_SIZEOF_BASE_RELOCATION);
			int		nItems = 
				(pBaseReloc->SizeOfBlock - IMAGE_SIZEOF_BASE_RELOCATION) / sizeof(WORD);
 
 			for(i=0; i<nItems; i++, pwItem++) 
			{
				DWORD	dwType, dwOffset;
				DWORD   *pBlock;

				dwType = (*pwItem) >> 12;
				dwOffset = (*pwItem) & 0xFFF;
				pBlock = (DWORD *)(pMemoryImage + pBaseReloc->VirtualAddress + dwOffset);

				// 不能使用switch 
				// switch表在函数体之外 而且是绝对地址 引用跳转会出错
				if(dwType == IMAGE_REL_BASED_ABSOLUTE)
				{
				}
				else if(dwType == IMAGE_REL_BASED_HIGH)
				{
 					*((WORD *)pBlock) += HIWORD(delta);
				}
				else if(dwType == IMAGE_REL_BASED_LOW)
				{
					*((WORD *)pBlock) += LOWORD(delta);
				}
 				else if(dwType == IMAGE_REL_BASED_HIGHLOW)
				{
 					*((DWORD *)pBlock) += delta;
				}
				else if(dwType == IMAGE_REL_BASED_HIGHADJ)
				{
					DWORD adjust;
 					adjust=((*((WORD *)pBlock)) << 16) | (*(pwItem+1));
 					adjust += delta;
 					adjust += 0x00008000;
 					*((WORD *)pBlock) = HIWORD(adjust);
 					pwItem++;	// 这种被占用了 加一次
 				}
 				else
				{
					//__asm int 3;
 					goto _MAINCODE_END;
 				}
  			}

			pBaseReloc = (PIMAGE_BASE_RELOCATION)
				((PBYTE)pBaseReloc + pBaseReloc->SizeOfBlock);
 		}
 	}

	//__asm int 3;

	// 4. 运行dllmain
	PDLLMAIN pDllMain;
	pDllMain=(PDLLMAIN)(pMemoryImage + pOptHead->AddressOfEntryPoint);
	pDllMain((HMODULE) pMemoryImage, DLL_PROCESS_ATTACH, NULL);


	__asm{
_MAINCODE_END:
		//__asm int 3;
		MOV ESP, EBP
		POPFD
		POPAD
		XOR EAX, EAX						// 函数返回值
		RETN 4								// 线程函数有一个参数
	}

// 子函数
	__asm
	{
// 取函数地址 eax=函数名 esi=模块地址
_PROC_GetProcAddress:
		PUSH EDX
		PUSH EAX
		PUSH ESI
		MOV EDX, OFFSET _RO_GetProcAddress
		ADD EDX, offsetLabel
		CALL [EDX]
		POP EDX
		RETN
	}

	__asm
	{
// 简单的memcpy 函数
_PROC_MemCpy:   
		PUSH EBP
		MOV EBP,ESP
		PUSH ECX
		PUSH EAX
		PUSH ESI
		PUSH EDI
		MOV EDI,DWORD PTR SS:[EBP+08h]		// dst
		MOV ESI,DWORD PTR SS:[EBP+0Ch]		// src
		MOV ECX,DWORD PTR SS:[EBP+10h]		// len
		TEST ECX, ECX
		JZ __CopyEnd						// copy 0字节的.textbss 要出错所以修改 by ranbo
		XOR EAX,EAX

__cpy:
		LODS BYTE PTR DS:[ESI]
		STOS BYTE PTR ES:[EDI]
		LOOP __cpy

__CopyEnd:
		POP EDI
		POP ESI
		POP EAX
		POP ECX
		MOV ESP,EBP
		POP EBP
		RET 0CH
	}

	THUNK_END_TAG
}

#pragma pack(pop)
#pragma check_stack 

// 内部申请的内存 外边要delete掉
PBYTE GetTestCode(UINT& cbCodeSize, UINT& cbFuncOffset)
{
	LPCSTR pcszThunkBegin = THUNK_BEGIN_STR;
	LPCSTR pcszThunkEnd = THUNK_END_STR;
	LPCSTR pcszCodeBegin = CODE_BEGIN_STR;

	UINT cbMemSize = 0;			// 整段需要copy的代码长度
	UINT cbCodeOffset = 0;		// mem开始距离 maincode起始的偏移 需要用这个作为线程起始地址
	PBYTE pbyCode = NULL;		// 原生代码开始地址
	PBYTE pbyMem = NULL;

	pbyCode = (PBYTE)&TestCode;
	if (0 != memcmp(pbyCode, pcszThunkBegin, strlen(pcszThunkBegin)))
	{
		OutputDebugStringA("pbyCode error thunk begin tag not find!\n");
		return NULL;
	}

	pbyCode += strlen(pcszThunkBegin);

	// 计算需要copy的size
	pbyMem = pbyCode;
	while(memcmp(pbyMem, pcszThunkEnd, strlen(pcszThunkEnd)))
	{
		pbyMem ++;
	}
	cbMemSize = (UINT)(pbyMem - pbyCode);

	// 计算函数起始地址离mem的偏移量
	pbyMem = pbyCode;
	while(memcmp(pbyMem, pcszCodeBegin, strlen(pcszCodeBegin)))
	{
		pbyMem ++;
	}
	cbCodeOffset = (UINT)(pbyMem - pbyCode + strlen(pcszCodeBegin));

	// 生成本地代码 并初始化
	pbyMem = new BYTE[cbMemSize];
	if (!pbyMem)
	{
		return NULL;
	}

	memcpy(pbyMem, pbyCode, cbMemSize);

	// 初始化三个API _RO_LoadLibraryA, _RO_GetProcAddress, _RO_FreeLibrary
	*(LOADLIBRARYA *)pbyMem = &::LoadLibraryA;
	*(GETPROCADDRESS *)(pbyMem + 4) = &::GetProcAddress;
	*(FREELIBRARY *)(pbyMem + 8) = &::FreeLibrary;

	// 填写返回值
	cbCodeSize = cbMemSize;
	cbFuncOffset = cbCodeOffset;
	return pbyMem;
}

void FreeLocalCode(PBYTE pbyCodeMem)
{
	if (pbyCodeMem)
	{
		delete[] pbyCodeMem;
	}
}

BOOL InjectTestCode(HANDLE hProcess)
{
	BOOL fSucceeded = FALSE;

	PBYTE pbyInjCode = NULL;
	UINT cbCodeSize = 0;
	UINT cbCodeOffset = 0;

	PBYTE pbyCodeRemote = NULL;
	DWORD dwOldProtect = 0;
	DWORD dwNumBytesXferred = 0;
	HANDLE hThread = NULL;
	DWORD dwThreadId = 0;

	// 初始化inject code
	pbyInjCode = GetTestCode(cbCodeSize, cbCodeOffset);
	if(!pbyInjCode)
	{
		goto finish;
	}


	// 在目标进程申请地址,写入代码并启动远程线程
	pbyCodeRemote = (PBYTE)VirtualAllocEx(hProcess, NULL, cbCodeSize,
										   MEM_COMMIT | MEM_TOP_DOWN,
                                           PAGE_EXECUTE_READWRITE);
	if(!pbyCodeRemote)
	{
		goto finish;
	}

	if (!VirtualProtectEx(hProcess, pbyCodeRemote, cbCodeSize,
						PAGE_EXECUTE_READWRITE, &dwOldProtect)) 
	{
		goto finish;
	}

	if (!WriteProcessMemory(hProcess, pbyCodeRemote,
						pbyInjCode, cbCodeSize, &dwNumBytesXferred)) 
	{
		goto finish;
	}

	 if ((hThread = CreateRemoteThread(hProcess, NULL, 65536, 
						(LPTHREAD_START_ROUTINE)(pbyCodeRemote+cbCodeOffset),
						NULL, 0, &dwThreadId)) == NULL)
	 {
		goto finish;
	}

	fSucceeded = TRUE;
finish:
	if(pbyInjCode)
	{
		FreeLocalCode(pbyInjCode);
	}

	GetLastError();
	return fSucceeded;
}

//-----------------------------------------------------------------------
// 测试注入代码到目标进程并load一个dll
//

BOOL InjectLoadLibCode(HANDLE hProcess, LPCTSTR pszLibName)
{
	BOOL fSucceeded = FALSE;
	LPCSTR pcszThunkBegin = THUNK_BEGIN_STR;
	LPCSTR pcszThunkEnd = THUNK_END_STR;
	LPCSTR pcszCodeBegin = CODE_BEGIN_STR;

	UINT cbThunkSize = 0;			// 整段需要copy的代码长度
	UINT cbCodeOffset = 0;		// mem开始距离 maincode起始的偏移 需要用这个作为线程起始地址
	PBYTE pbyCode = NULL;		// 原生代码开始地址
	PBYTE pbyThunk = NULL;

	PBYTE pbyImage = NULL;
	DWORD cbFileSize=0, cbReadSize=0;
	HANDLE hLibFile = INVALID_HANDLE_VALUE;

	// 读取文件
	hLibFile = CreateFile(pszLibName, 
		GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
	if(hLibFile == INVALID_HANDLE_VALUE)
	{
		goto finish;
	}

	cbFileSize = GetFileSize(hLibFile, NULL);
	pbyImage = new BYTE[cbFileSize];

	if (!ReadFile(hLibFile, pbyImage, cbFileSize, &cbReadSize, NULL) 
		|| cbReadSize!=cbFileSize)
	{
		goto finish;
	}


	// 构建取代码
	pbyCode = (PBYTE)&LoadLibraryCode;
	if (0 != memcmp(pbyCode, pcszThunkBegin, strlen(pcszThunkBegin)))
	{
		OutputDebugStringA("pbyCode error thunk begin tag not find!\n");
		return NULL;
	}

	pbyCode += strlen(pcszThunkBegin);

	// 计算需要copy的size
	pbyThunk = pbyCode;
	while(memcmp(pbyThunk, pcszThunkEnd, strlen(pcszThunkEnd)))
	{
		pbyThunk ++;
	}
	cbThunkSize = (UINT)(pbyThunk - pbyCode);

	// 计算函数起始地址离mem的偏移量
	pbyThunk = pbyCode;
	while(memcmp(pbyThunk, pcszCodeBegin, strlen(pcszCodeBegin)))
	{
		pbyThunk ++;
	}
	cbCodeOffset = (UINT)(pbyThunk - pbyCode + strlen(pcszCodeBegin));

	// 生成本地代码 并初始化
	pbyThunk = new BYTE[cbThunkSize];
	if (!pbyThunk)
	{
		goto finish;
	}

	memcpy(pbyThunk, pbyCode, cbThunkSize);

	// 初始化三个API _RO_LoadLibraryA, _RO_GetProcAddress, _RO_FreeLibrary
	*(LOADLIBRARYA *)(pbyThunk + 0x04) = &::LoadLibraryA;
	*(GETPROCADDRESS *)(pbyThunk + 0x08) = &::GetProcAddress;
	*(FREELIBRARY *)(pbyThunk + 0x0C) = &::FreeLibrary;


	PBYTE pbyImageRemote = NULL;
	PBYTE pbyThunkRemote = NULL;
	DWORD dwOldProtect = 0;
	DWORD dwNumBytesXferred = 0;
	HANDLE hThread = NULL;
	DWORD dwThreadId = 0;


	// 在目标进程申请地址,写入DLL 的数据
	pbyImageRemote = (PBYTE)VirtualAllocEx(hProcess, NULL, cbFileSize,
		MEM_COMMIT | MEM_TOP_DOWN,
		PAGE_READWRITE);
	if(!pbyImageRemote)
	{
		goto finish;
	}

	if (!VirtualProtectEx(hProcess, pbyImageRemote, cbFileSize,
		PAGE_EXECUTE_READWRITE, &dwOldProtect)) 
	{
		goto finish;
	}

	if (!WriteProcessMemory(hProcess, pbyImageRemote,
		pbyImage, cbFileSize, &dwNumBytesXferred)) 
	{
		goto finish;
	}

	// 将image地址填写到code中
	*(PBYTE *)(pbyThunk + 0x0) = pbyImageRemote;


	// 在目标进程申请地址,写入代码并启动远程线程
	pbyThunkRemote = (PBYTE)VirtualAllocEx(hProcess, NULL, cbThunkSize,
		MEM_COMMIT | MEM_TOP_DOWN,
		PAGE_EXECUTE_READWRITE);
	if(!pbyThunkRemote)
	{
		goto finish;
	}

	if (!VirtualProtectEx(hProcess, pbyThunkRemote, cbThunkSize,
		PAGE_EXECUTE_READWRITE, &dwOldProtect)) 
	{
		goto finish;
	}

	if (!WriteProcessMemory(hProcess, pbyThunkRemote,
		pbyThunk, cbThunkSize, &dwNumBytesXferred)) 
	{
		goto finish;
	}

	if ((hThread = CreateRemoteThread(hProcess, NULL, 65536, 
		(LPTHREAD_START_ROUTINE)(pbyThunkRemote+cbCodeOffset),
		NULL, 0, &dwThreadId)) == NULL)
	{
		goto finish;
	}

	fSucceeded = TRUE;

finish:
	if (pbyImage)
	{
		delete[] pbyImage;
	}

	if(pbyThunk)
	{
		delete[] pbyThunk;
	}

	GetLastError();
	return fSucceeded;
}


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 8
支持
分享
最新回复 (11)
雪    币: 74
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
下载了,有空试试
2009-12-25 20:08
0
雪    币: 130
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
顶,收藏一个先
2009-12-25 21:55
0
雪    币: 70
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
楼主很强大,下来耍耍
2010-1-4 10:43
0
雪    币: 284
活跃值: (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
这可是好东西啊,感谢楼主。
2010-1-6 11:13
0
雪    币: 61
活跃值: (51)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
收藏了,希望以后用到

谢谢楼主啊
2010-5-13 09:30
0
雪    币: 291
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
收藏了先
2010-5-19 10:55
0
雪    币: 367
活跃值: (20)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
8
MemoryModule + RemoteThread.
2010-5-19 13:19
0
雪    币: 10
活跃值: (26)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
morning MemoryModule + RemoteThread.
这个怎么实现,有源码吗,参考一下!
2018-8-13 16:41
0
雪    币: 2375
活跃值: (433)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
skykrnl 楼主很强大,下来耍耍
用新版vs能编译成功么
2019-6-9 19:45
0
雪    币: 9941
活跃值: (2143)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
11
代码不错
没想到居然是十年的前的帖子了
以前居然都没见过这个帖子
2019-6-9 20:24
0
雪    币: 37
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
12
大佬,在一个别人的dll里加入我写的dll代码怎么做。有例子吗
2020-7-25 22:48
0
游客
登录 | 注册 方可回帖
返回
//