将Dll加载进内存

20210715更新MmLoadDll.h

MmLoadDll.h

#ifndef _MM_LOAD_DLL_H_
#define _MM_LOAD_DLL_H_


#include <Windows.h>


typedef BOOL(__stdcall *typedef_DllMain)(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved);


void ShowError(char *lpszText);

// 模拟LoadLibrary加载内存DLL文件到进程中
// lpData: 内存DLL文件数据的基址
// dwSize: 内存DLL文件的内存大小
// 返回值: 内存DLL加载到进程的加载基址
LPVOID MmLoadLibrary(LPVOID lpData, DWORD dwSize);

// 根据PE结构,获取PE文件加载到内存后的镜像大小
// lpData: 内存DLL文件数据的基址
// 返回值: 返回PE文件结构中IMAGE_NT_HEADERS.OptionalHeader.SizeOfImage值的大小
DWORD GetSizeOfImage(LPVOID lpData);

// 将内存DLL数据按SectionAlignment大小对齐映射到进程内存中
// lpData: 内存DLL文件数据的基址
// lpBaseAddress: 内存DLL数据按SectionAlignment大小对齐映射到进程内存中的内存基址
// 返回值: 成功返回TRUE,否则返回FALSE
BOOL MmMapFile(LPVOID lpData, LPVOID lpBaseAddress);

// 对齐SectionAlignment
// dwSize: 表示未对齐前内存的大小
// dwAlignment: 对齐大小值
// 返回值: 返回内存对齐之后的值
DWORD Align(DWORD dwSize, DWORD dwAlignment);

// 修改PE文件重定位表信息
// lpBaseAddress: 内存DLL数据按SectionAlignment大小对齐映射到进程内存中的内存基址
// 返回值: 成功返回TRUE,否则返回FALSE
BOOL DoRelocationTable(LPVOID lpBaseAddress);

// 填写PE文件导入表信息
// lpBaseAddress: 内存DLL数据按SectionAlignment大小对齐映射到进程内存中的内存基址
// 返回值: 成功返回TRUE,否则返回FALSE
BOOL DoImportTable(LPVOID lpBaseAddress);

// 修改PE文件加载基址IMAGE_NT_HEADERS.OptionalHeader.ImageBase
// lpBaseAddress: 内存DLL数据按SectionAlignment大小对齐映射到进程内存中的内存基址
// 返回值: 成功返回TRUE,否则返回FALSE
BOOL SetImageBase(LPVOID lpBaseAddress);

// 调用DLL的入口函数DllMain,函数地址即为PE文件的入口点IMAGE_NT_HEADERS.OptionalHeader.AddressOfEntryPoint
// lpBaseAddress: 内存DLL数据按SectionAlignment大小对齐映射到进程内存中的内存基址
// 返回值: 成功返回TRUE,否则返回FALSE
BOOL CallDllMain(LPVOID lpBaseAddress);

// 模拟GetProcAddress获取内存DLL的导出函数
// lpBaseAddress: 内存DLL文件加载到进程中的加载基址
// lpszFuncName: 导出函数的名字
// 返回值: 返回导出函数的的地址
LPVOID MmGetProcAddress(LPVOID lpBaseAddress, PCHAR lpszFuncName);

// 释放从内存加载的DLL到进程内存的空间
// lpBaseAddress: 内存DLL数据按SectionAlignment大小对齐映射到进程内存中的内存基址
// 返回值: 成功返回TRUE,否则返回FALSE
BOOL MmFreeLibrary(LPVOID lpBaseAddress);


#endif

MmLoadDll.cpp

#include "stdafx.h"
#include <windows.h>
#include "MmLoadDll.h"




void ShowError(char *lpszText)
{
	char szErr[MAX_PATH] = { 0 };
	sprintf(szErr, "%s Error [%d]\n", lpszText, GetLastError());
	MessageBoxA(NULL, szErr, "ERROR", MB_OK | MB_ICONERROR);

}


LPVOID MmLoadLibrary(LPVOID lpdata, DWORD dwSize)
{
	LPVOID lpBassAddress = NULL;

	DWORD dwSizeOfImage = GetSizeOfImage(lpdata);

	lpBassAddress = VirtualAlloc(NULL, dwSizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

	if (NULL == lpBassAddress)
	{
		ShowError("VirtualAlloc");
		return FALSE;
	}

	RtlZeroMemory(lpBassAddress, dwSizeOfImage);

	if (FALSE == MmMapFile(lpdata, lpBassAddress))
	{
		ShowError("MmMapFile");
		return FALSE;
	}

	if (FALSE == DoRelocationTable(lpBassAddress))
	{
		ShowError("DoRelocationTable");
		return FALSE;
	}

	if (FALSE == DoImportTable(lpBassAddress))
	{
		ShowError("DoImportTable");
		return FALSE;
	}

	DWORD dwOldProtect = 0;
	if (FALSE == VirtualProtect(lpBassAddress, dwSizeOfImage, PAGE_EXECUTE_READWRITE, &dwOldProtect))
	{
		ShowError("VirtualProtect");
		return FALSE;
	}

	if (FALSE == SetImageBase(lpBassAddress))
	{
		ShowError("SetImageBase");
		return FALSE;
	}

	if (FALSE == CallDllMain(lpBassAddress))
	{
		ShowError("CallDllMain");
		return FALSE;
	}

	return lpBassAddress;



}


DWORD GetSizeOfImage(LPVOID lpdata)
{
	DWORD dwSizeOfImage = 0;
	PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)lpdata;
	PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((ULONG32)pDosHeader + pDosHeader->e_lfanew);
	dwSizeOfImage = pNtHeaders->OptionalHeader.SizeOfImage;
	return dwSizeOfImage;
}

BOOL MmMapFile(LPVOID lpdata, LPVOID lpBaseAddress)
{
	PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)lpdata;
	PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((ULONG32)pDosHeader + pDosHeader->e_lfanew);

	//获取所有头+节区头的大小
	DWORD dwSzieOfHeaders = pNtHeaders->OptionalHeader.SizeOfHeaders;

	//获取所有节区的数量
	WORD wNumberOfSections = pNtHeaders->FileHeader.NumberOfSections;

	//获取第一个节区头的地址
	PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pNtHeaders + sizeof(IMAGE_NT_HEADERS));

	RtlCopyMemory(lpBaseAddress, lpdata, dwSzieOfHeaders);

	WORD i = 0;
	LPVOID lpSrcMem = NULL;
	LPVOID lpDestMem = NULL;
	DWORD dwSizeOfRawData = 0;

	for (i = 0; i < wNumberOfSections; i++)
	{
		if ((0 == pSectionHeader->VirtualAddress) || (0 == pSectionHeader->SizeOfRawData))
		{
			pSectionHeader++;
			continue;
		}

		lpSrcMem = (LPVOID)((DWORD)lpdata + pSectionHeader->PointerToRawData);
		lpDestMem = (LPVOID)((DWORD)lpBaseAddress + pSectionHeader->VirtualAddress);
		dwSizeOfRawData = pSectionHeader->SizeOfRawData;
		RtlCopyMemory(lpDestMem, lpSrcMem, dwSizeOfRawData);

		pSectionHeader++;

	}
	return TRUE;

}

BOOL DoRelocationTable(LPVOID lpBaseAddress)
{
	PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)lpBaseAddress;
	PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((ULONG32)pDosHeader + pDosHeader->e_lfanew);
	PIMAGE_BASE_RELOCATION pLoc = (PIMAGE_BASE_RELOCATION)((unsigned long)pDosHeader + pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);

	//判断是否有重定位
	if ((PVOID)pLoc == (PVOID)pDosHeader)
	{
		//没有重定位
		return TRUE;
	}

	while ((pLoc->VirtualAddress + pLoc->SizeOfBlock) != 0)
	{
		WORD *pLocData = (WORD *)((PBYTE)pLoc + sizeof(IMAGE_BASE_RELOCATION));

		int nNumberOfReloc = (pLoc->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD);

		for (int i = 0; i < nNumberOfReloc; i++)
		{
			if ((DWORD)(pLocData[i] & 0x0000F000) == 0x00003000)
			{
				DWORD * pAddress = (DWORD *)((PBYTE)pDosHeader + pLoc->VirtualAddress + (pLocData[i] & 0x0FFF));
				DWORD dwDelta = (DWORD)pDosHeader - pNtHeaders->OptionalHeader.ImageBase;
				*pAddress += dwDelta;
			}
		}

		pLoc = (PIMAGE_BASE_RELOCATION)((PBYTE)pLoc + pLoc->SizeOfBlock);
	}
	return TRUE;
}

BOOL DoImportTable(LPVOID lpBaseAddress)
{
	PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)lpBaseAddress;
	PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((ULONG32)pDosHeader + pDosHeader->e_lfanew);
	PIMAGE_IMPORT_DESCRIPTOR pImportTable = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pDosHeader + pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);

	//循环遍历DLL导入表中的DLL及获取导入表中的函数地址
	char *lpDllName = NULL;
	HMODULE hDll = NULL;
	PIMAGE_THUNK_DATA lpImportNameArray = NULL;
	PIMAGE_IMPORT_BY_NAME lpImportByName = NULL;
	PIMAGE_THUNK_DATA lpImportFuncAddrArray = NULL;
	FARPROC lpFuncAddress = NULL;
	DWORD i = 0;

	while (TRUE)
	{
		if (0 == pImportTable->OriginalFirstThunk)
		{
			break;
		}

		//获取导入表中dll的名称并加载dll
		lpDllName = (char *)((DWORD)pDosHeader + pImportTable->Name);
		hDll = GetModuleHandleA(lpDllName);
		if (NULL == hDll)
		{
			hDll = LoadLibraryA(lpDllName);
			if (NULL == hDll)
			{
				pImportTable++;
				continue;
			}
		}
		i = 0;

		lpImportNameArray = (PIMAGE_THUNK_DATA)((DWORD)pDosHeader + pImportTable->OriginalFirstThunk);

		lpImportFuncAddrArray = (PIMAGE_THUNK_DATA)((DWORD)pDosHeader + pImportTable->FirstThunk);

		while (TRUE)
		{
			if (0 == lpImportNameArray[i].u1.AddressOfData)
			{
				break;
			}

			lpImportByName = (PIMAGE_IMPORT_BY_NAME)((DWORD)pDosHeader + lpImportNameArray[i].u1.AddressOfData);

			if (0x80000000 & lpImportNameArray[i].u1.Ordinal)
			{
				lpFuncAddress = GetProcAddress(hDll, (LPCSTR)(lpImportNameArray[i].u1.Ordinal & 0x0000FFFF));
			}
			else
			{
				lpFuncAddress = GetProcAddress(hDll, (LPCSTR)(lpImportByName->Name));
			}
			lpImportFuncAddrArray[i].u1.Function = (DWORD)lpFuncAddress;
			i++;
		}
		pImportTable++;


	}
	return TRUE;
}

BOOL SetImageBase(LPVOID lpBaseAddress)
{
	PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)lpBaseAddress;
	PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((ULONG32)pDosHeader + pDosHeader->e_lfanew);
	pNtHeaders->OptionalHeader.ImageBase = (ULONG32)lpBaseAddress;
	return TRUE;
}

BOOL CallDllMain(LPVOID lpBaseAddress)
{
	typedef_DllMain DllMain = NULL;
	PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)lpBaseAddress;
	PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((ULONG32)pDosHeader + pDosHeader->e_lfanew);
	DllMain = (typedef_DllMain)((ULONG32)pDosHeader + pNtHeaders->OptionalHeader.AddressOfEntryPoint);
	// 调用入口函数,附加进程DLL_PROCESS_ATTACH
	BOOL bRet = DllMain((HINSTANCE)lpBaseAddress, DLL_PROCESS_ATTACH, NULL);
	if (FALSE == bRet)
	{
		ShowError("DllMain");
	}

	return bRet;
}

LPVOID MmGetProAddress(LPVOID lpBaseAddress, PCHAR lpszFuncName)
{
	LPVOID lpFunc = NULL;
	PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)lpBaseAddress;
	PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((ULONG32)pDosHeader + pDosHeader->e_lfanew);
	PIMAGE_EXPORT_DIRECTORY pExporTable = (PIMAGE_EXPORT_DIRECTORY)((DWORD)pDosHeader + pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
	
	PDWORD lpAddressOfNameArray = (PDWORD)((DWORD)pDosHeader + pExporTable->AddressOfNames);
	PCHAR lpFuncName = NULL;
	PWORD lpAddressOfNameOrdinalsArray = (PWORD)((DWORD)pDosHeader + pExporTable->AddressOfNameOrdinals);
	WORD wHint = 0;
	PDWORD lpAddressOfFuncationsArray = (PDWORD)((DWORD)pDosHeader + pExporTable->AddressOfFunctions);

	DWORD dwNumberOfNames = pExporTable->NumberOfNames;
	DWORD i = 0;

	for (i = 0; i < dwNumberOfNames; i++)
	{
		lpFuncName = (PCHAR)((DWORD)pDosHeader + lpAddressOfNameArray[i]);
		if (0 == lstrcmpiA(lpFuncName, lpszFuncName))
		{
			wHint = lpAddressOfNameOrdinalsArray[i];
			lpFunc = (LPVOID)((DWORD)pDosHeader + lpAddressOfFuncationsArray[wHint]);
			break;
		}
	}
	return lpFunc;

}

BOOL MmFreeLibrary(LPVOID lpBaseAddress)
{
	BOOL bRet = FALSE;
	if (NULL == lpBaseAddress)
	{
		return bRet;
	}

	bRet = VirtualFree(lpBaseAddress, 0, MEM_RELEASE);
	lpBaseAddress = NULL;
	return bRet;
}

rundll_in_memory_exe.cpp

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

#include "stdafx.h"
#include <windows.h>
#include "MmLoadDll.h"


int _tmain(int argc, _TCHAR* argv[])
{
	char szFileName[MAX_PATH] = "I:\\VS2013Project\\windows_hack_base_code\\excute_exe\\rundll_in_memory\\Debug\\rundll_in_memory.dll";

	HANDLE hFile = CreateFileA(szFileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, NULL);
	if (INVALID_HANDLE_VALUE == hFile)
	{
		ShowError("CreateFile");
		return FALSE;
	}

	DWORD dsFileSize = GetFileSize(hFile, NULL);

	BYTE *lpData = new BYTE[dsFileSize];
	if (NULL == lpData)
	{
		ShowError("new");
		return FALSE;

	}
	DWORD bRet = 0;
	ReadFile(hFile, lpData, dsFileSize, &bRet, NULL);

	LPVOID lpBaseAdress = MmLoadLibrary(lpData, dsFileSize);
	if (NULL == lpBaseAdress)
	{
		ShowError("MmLoadLibrary");
		return FALSE;
	}

	printf("加载dll成功!");

	typedef BOOL(*typedef_ShowMessage)(char *lpszText, char *lpszCation);
	typedef_ShowMessage ShowMessage = (typedef_ShowMessage)MmGetProAddress(lpBaseAdress, "ShowMessage");
	if (NULL == ShowMessage)
	{
		ShowError("MmGetProAddress");
		return FALSE;
	}
	ShowMessage("I am Hello\n", "HELLO WORLD!");

	BOOL bRetOK = MmFreeLibrary(lpBaseAdress);
	if (FALSE == bRetOK)
	{
		ShowError("MmFreeLibrary");
		return FALSE;
	}

	delete[] lpData;
	lpData = NULL;
	CloseHandle(hFile);

	system("pause");

	return 0;
}

内存加载动态库 MemoryLoadLibrary 有例子。 /* * Memory DLL loading code * Version 0.0.3 * * Copyright (c) 2004-2013 by Joachim Bauch / mail@joachim-bauch.de * http://www.joachim-bauch.de * * The contents of this file are subject to the Mozilla Public License Version * 2.0 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is MemoryModule.h * * The Initial Developer of the Original Code is Joachim Bauch. * * Portions created by Joachim Bauch are Copyright (C) 2004-2013 * Joachim Bauch. All Rights Reserved. * */ #ifndef __MEMORY_MODULE_HEADER #define __MEMORY_MODULE_HEADER #include typedef void *HMEMORYMODULE; typedef void *HMEMORYRSRC; typedef void *HCUSTOMMODULE; #ifdef __cplusplus extern "C" { #endif typedef HCUSTOMMODULE (*CustomLoadLibraryFunc)(LPCSTR, void *); typedef FARPROC (*CustomGetProcAddressFunc)(HCUSTOMMODULE, LPCSTR, void *); typedef void (*CustomFreeLibraryFunc)(HCUSTOMMODULE, void *); /** * Load DLL from memory location. * * All dependencies are resolved using default LoadLibrary/GetProcAddress * calls through the Windows API. */ HMEMORYMODULE MemoryLoadLibrary(const void *); /** * Load DLL from memory location using custom dependency resolvers. * * Dependencies will be resolved using passed callback methods. */ HMEMORYMODULE MemoryLoadLibraryEx(const void *, CustomLoadLibraryFunc, CustomGetProcAddressFunc, CustomFreeLibraryFunc, void *); /** * Get address of exported method. */ FARPROC MemoryGetProcAddress(HMEMORYMODULE, LPCSTR); /** * Free previously loaded DLL. */ void MemoryFreeLibrary(HMEMORYMODULE); /** * Find the location of
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值