通用DLL注入模版

Loading

好久没有更新博客了,真是懒惰,想写一点win32编程方面的积累,又想写逆向的新知识,拖着拖着就忘记了。
半期考后还是要多多更新博客。

今天说一下一个通用的DLL注入模板,以前注入DLL,只是32位注入32位,64位注入64位。

而今天这个模板支持64位程序注入32位和64位,注入64位不赘述,前两篇讲的很清楚,主要说一下64位程序注入32位。
1.之前有说到过PE结构,不知道那篇文章有没有说到过EXPORT TABLE
2.注入32位程序的关键就是在32位程序的导出表里面导出LoadLibrary
3.通过这个LoadLibrary代替传统DLL注入的GetProcAddress导出LoadLibrary

这里主要用到的是PE头的遍历
我们的顺序是DOS头->NT头->export table

dos有e_lfanew跳到NT头
NT头有OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress跳到export table
export table有结构体IMAGE_EXPORT_DIRECTORY(不知道为什么,MSDN上被删除了)
贴一篇文章,大家自己看:
http://win32assembly.programminghorizon.com/pe-tut7.html

1

NumberOfFunctions       实际Export函数的个数
NumberOfNames           Export函数中具名的函数个数
AddressOfFunctions      Export函数地址数组(数组元素个数=NumberOfFunctions)
AddressOfNames          函数名称地址数组(数组元素个数=NumberOfNames)
AddressOfNameOrdinals   Ordinal地址数组(数组元素个数=NumberOfNames)

我用GetProcAddress来讲一下EAT
1.利用AddressOfNames成员转到“函数名称数组”
2.“函数名称数组”中储存着字符串的地址。通过比较(strcmp)字符串,查找指定的函数名称,此时数组的索引称为name_index
3.利用AddressOfNameOrdinals成员,转到ordinal数组
4.在ordinal数组中通过name_index查找相应ordinal值
5.利用AddressOfFunctions成员转到“函数地址数组”(EAT)
6.在“函数地址数组”中将刚刚求得的ordinal用作数组索引,获得指定函数的起始地址

(上面这段话摘自《逆向工程核心原理》)

直接看代码吧

// UniversalDllInjectTemplate.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include 
#include 
#include 
#include 

/*
记录导出表信息
*/
typedef struct _IAT_EAT_INFO
{
	TCHAR ModuleName[256];
	char FuncName[64];
	ULONG64 Address;
	ULONG64 RecordAddr;
	ULONG64 ModBase;
} IAT_EAT_INFO, *PIAT_EAT_INFO;

/*
取出所有模块,并且比较是否为kernel.dll
*/
HMODULE GetRemoteModuleHandleByProcessHandle(HANDLE hProcess, TCHAR *szModuleName)
{
	HMODULE hMods[1024] = { 0 };
	DWORD cbNeeded = 0, i = 0;
	TCHAR szModName[MAX_PATH];
	TCHAR *lastString;

	if (EnumProcessModulesEx(hProcess, hMods, sizeof(hMods), &cbNeeded, LIST_MODULES_ALL))
	{
		for (i = 0; i <= cbNeeded / sizeof(HMODULE); i++)
		{
			if (GetModuleFileNameEx(hProcess, hMods[i], szModName, sizeof(szModName)))
			{
				lastString = wcsrchr(szModName, '\\');
				if (!_wcsicmp(lastString + 1, szModuleName))
				{
					return hMods[i];
				}
			}
		}
	}
	return NULL;
}

/*
导出32位程序中的LoadLibraryW
*/
long GetProcessExportTable32(HANDLE hProcess, TCHAR *ModuleName, IAT_EAT_INFO tbinfo[], int tb_info_max)
{
	ULONG count = 0, mBase = 0;
	PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)new BYTE[sizeof(IMAGE_DOS_HEADER)];
	PIMAGE_NT_HEADERS32 pNtHeader = (PIMAGE_NT_HEADERS32)new BYTE[sizeof(IMAGE_NT_HEADERS32)];
	PIMAGE_EXPORT_DIRECTORY pExport = (PIMAGE_EXPORT_DIRECTORY)new BYTE[sizeof(IMAGE_EXPORT_DIRECTORY)];
	DWORD dwStup = 0, dwOffset = 0;
	char strName[130];

	mBase =(ULONG) GetRemoteModuleHandleByProcessHandle(hProcess, ModuleName);
	if (!mBase)
	{
		_tprintf(L"GetRemoteModuleHandleByProcessHandle Failed!\n");
		system("pause");
	}

	//读取DOS头和NT头
	ReadProcessMemory(hProcess, (PVOID)mBase, pDosHeader, sizeof(IMAGE_DOS_HEADER), NULL);
	ReadProcessMemory(hProcess, (PVOID)(mBase + pDosHeader->e_lfanew), pNtHeader, sizeof(IMAGE_NT_HEADERS32), NULL);
	if (pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress == 0)
	{
		_tprintf(L"Directory entry export do not exist!\n");
		system("pause");
	}

	//读取EXPORT表
	ReadProcessMemory(hProcess,
		(PVOID)(mBase + pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress),
		pExport,
		sizeof(IMAGE_EXPORT_DIRECTORY),
		NULL);
	ReadProcessMemory(hProcess, (PVOID)(mBase + pExport->Name), strName, sizeof(strName), NULL);

	if (pExport->NumberOfNames < 0 || pExport->NumberOfNames>8192)
	{
		return 0;
	}

	//遍历导出表,保存所有数据
	for (DWORD i = 0; i < pExport->NumberOfNames; i++)
	{
		char bFuncName[100];
		ULONG ulPointer;
		USHORT usFuncId;
		ULONG64 ulFuncAddr;
		ReadProcessMemory(hProcess, (PVOID)(mBase + pExport->AddressOfNames + i * 4), &ulPointer, 4, 0);
		RtlZeroMemory(bFuncName, sizeof(bFuncName));
		ReadProcessMemory(hProcess, (PVOID)(mBase + ulPointer), bFuncName, 100, 0);
		ReadProcessMemory(hProcess, (PVOID)(mBase + pExport->AddressOfNameOrdinals + i * 2), &usFuncId, 2, 0);
		ReadProcessMemory(hProcess, (PVOID)(mBase + pExport->AddressOfFunctions + 4 * usFuncId), &ulPointer, 4, 0);
		ulFuncAddr = mBase + ulPointer;
		//printf("\t%llx\t%s\n", ulFuncAddr, bFuncName);
		//MultiByteToWideChar(0, 0, bFuncName);
		wcscpy_s(tbinfo[count].ModuleName, sizeof(tbinfo[count].ModuleName), ModuleName);
		strcpy_s(tbinfo[count].FuncName, sizeof(tbinfo[count].FuncName), bFuncName);
		tbinfo[count].Address = ulFuncAddr;
		tbinfo[count].RecordAddr = (ULONG64)(mBase + pExport->AddressOfFunctions + 4 * usFuncId);
		tbinfo[count].ModBase = mBase;
		count++;
		if (count > (ULONG)tb_info_max)
			break;
	}
	delete[]pDosHeader;
	delete[]pExport;
	delete[]pNtHeader;
	return count;
}

/*
返回LoadLibraryW位置
*/
ULONG64 GetProcAddressIn32BitProcess(HANDLE hProcess, TCHAR *ModuleName, char *FuncName)
{
	ULONG64 RetAddr = 0;
	PIAT_EAT_INFO pInfo = (PIAT_EAT_INFO)malloc(4096 * sizeof(IAT_EAT_INFO));
	long count = GetProcessExportTable32(hProcess, ModuleName, pInfo, 2048);
	if (!count)
		return NULL;
	for (long i = 0; i < count; i++)
	{
		if (!_stricmp(pInfo[i].FuncName, FuncName))
		{
			RetAddr = pInfo[i].Address;
			break;
		}
	}
	free(pInfo);
	return RetAddr;
}

/*
检查目标程序是32位还是64位
*/
int ProcessBitCheck(HANDLE hProcess)
{
	BOOL Wow64Flag = NULL;
	IsWow64Process(hProcess, &Wow64Flag);
	return Wow64Flag;
}
int SetDebugPrivileges(void) {
	TOKEN_PRIVILEGES priv = { 0 };
	HANDLE hToken = NULL;

	if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
		priv.PrivilegeCount = 1;
		priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

		if (LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &priv.Privileges[0].Luid)) {
			if (AdjustTokenPrivileges(hToken, FALSE, &priv, 0, NULL, NULL) == 0) {
				printf("AdjustTokenPrivilege Error! [%u]\n", GetLastError());
			}
		}

		CloseHandle(hToken);
	}
	return GetLastError();
}
BOOL InjectDll(DWORD dwPID, LPCTSTR szDllPath)
{
	HANDLE hProcess = NULL, hThread = NULL;
	HMODULE hMod = NULL;
	LPVOID pRemoteBuf = NULL;
	DWORD dwBufSize = (DWORD)(_tcslen(szDllPath) + 1) * sizeof(TCHAR);
	LPTHREAD_START_ROUTINE pThreadProc;
	int pBit = 0;

	if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)))
	{
		_tprintf(L"OpenProcess(%d) failed!!! [%d]\n", dwPID, GetLastError());
		return FALSE;
	}
	_tprintf(L"hProcess:%x\n", hProcess);

	pBit = ProcessBitCheck(hProcess);
	
	pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize, MEM_COMMIT, PAGE_READWRITE);
	_tprintf(L"pRemoteBuf:%x\n", pRemoteBuf);

	WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDllPath, dwBufSize, NULL);

	if (pBit==X64)
		pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "LoadLibraryW");
	else
		pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddressIn32BitProcess(hProcess, L"kernel32.dll", "LoadLibraryW");
	_tprintf(L"pThreadProc:%x\n", pThreadProc);

	hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, pRemoteBuf, 0, NULL);
	WaitForSingleObject(hThread, INFINITE);
	CloseHandle(hThread);
	CloseHandle(hProcess);
	
	return TRUE;

}
int _tmain(int argc, TCHAR *argv[])
{
	
	if (argc != 3)
	{
		//printf("argv[0]:%s argv[1]:%s argv[2]:%s\n", argv[0], argv[1], argv[2]);
		_tprintf(L"USAGE : %s pid dll_path\n", argv[0]);
		return 1;
	}

	_tprintf(L"[+] Setting Debug Privileges [%ld]\n", SetDebugPrivileges());
	//printf("argv[0]:%s argv[1]:%s argv[2]:%s\n", argv[0], _tstol(argv[1]), argv[2]);
	if (InjectDll((DWORD)_tstol(argv[1]), argv[2]))
		_tprintf(TEXT("InjectDll(\"%s\") success!!!\n"), argv[2]);
	else
		_tprintf(L"InjectDll(\"%s\") failed!!!\n", argv[2]);
		
	system("pause");
	return 0;
}

Github:https://github.com/plummm/WinProject/tree/master/DLLInject

Share your thoughts

This site uses Akismet to reduce spam. Learn how your comment data is processed.