LordPe dump进程内存实现

本文介绍了一种利用Windows API函数创建进程快照的方法,并详细解释了如何获取进程的基地址和映像大小,最终实现对指定进程的完整内存映像进行转储。
#include <windows.h>
#include <tlhelp32.h>
#include <stdio.h>
#include <string.h>


//进程的第一个模块即为进程的 基址 (这里顺便获取进程内存映像的大小)
DWORD GetProcessBaseAndImageSize(DWORD dwPID, DWORD *dwImageSize)
{
	HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
	MODULEENTRY32 me32;

	// Take a snapshot of all modules in the specified process.
	hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwPID );
	if( hModuleSnap == INVALID_HANDLE_VALUE )
	{
		printf( "CreateToolhelp32Snapshot (of modules) ,error code :%d\n",GetLastError() );
		return FALSE;
	}

	// Set the size of the structure before using it.
	me32.dwSize = sizeof( MODULEENTRY32 );

	// Retrieve information about the first module,
	// and exit if unsuccessful
	if( !Module32First( hModuleSnap, &me32 ) )
	{
		printf( "Module32First" );  // show cause of failure
		CloseHandle( hModuleSnap );           // clean the snapshot object
		return FALSE;
	}

	//printf( "\n     Base address   = 0x%08X", (DWORD) me32.modBaseAddr );   //第一个模块即进程基址

	CloseHandle( hModuleSnap );

	if(dwImageSize != NULL)
		*dwImageSize = me32.modBaseSize;  //进程映像大小
	return (DWORD)me32.modBaseAddr;
}

//对所有进程进行快照,找出指定进程的pid
DWORD GetProcessPid(char strPocName[])
{
	HANDLE hProcessSnap;
	HANDLE hProcess;
	PROCESSENTRY32 pe32;

	// Take a snapshot of all processes in the system.
	hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
	if( hProcessSnap == INVALID_HANDLE_VALUE )
	{
		printf("Failed to CreateToolhelp32Snapshot...\n");
		return FALSE;
	}

	// Set the size of the structure before using it.
	pe32.dwSize = sizeof( PROCESSENTRY32 );

	// Retrieve information about the first process,
	// and exit if unsuccessful
	if( !Process32First( hProcessSnap, &pe32 ) )
	{
		printf("error in Process32First...\n");
		CloseHandle( hProcessSnap );          // clean the snapshot object
		return FALSE;
	}

	// Now walk the snapshot of processes, and
	// display information about each process in turn

	do
	{
		//printf("process name : %s\n",pe32.szExeFile);
		if(stricmp(strPocName, pe32.szExeFile) == 0)  //忽略大小写
		{
			//printf("process name : %s\n",pe32.szExeFile);
			CloseHandle(hProcessSnap);
			return pe32.th32ProcessID;
		}

	} while( Process32Next( hProcessSnap, &pe32 ) );

	CloseHandle( hProcessSnap );
	return FALSE;
}

//方式一:
//通过PE文件头确定镜像的大小,如果文件头被壳修改则无法得到镜像大小
DWORD GetImageSize(HANDLE hProc, DWORD dwImageBase)
{
	DWORD dwRetSize;

	IMAGE_DOS_HEADER ImageDosHeader;
	IMAGE_NT_HEADERS ImageNtHeader;

	if(ReadProcessMemory(hProc, (char*)dwImageBase, &ImageDosHeader, sizeof(IMAGE_DOS_HEADER), NULL) == 0)
	{
		printf("lasterror : %d\n", GetLastError());
	}

	PIMAGE_NT_HEADERS pNTHeader = (PIMAGE_NT_HEADERS)(dwImageBase + ImageDosHeader.e_lfanew);


	if(ReadProcessMemory(hProc, (char*)(pNTHeader), &ImageNtHeader, sizeof(IMAGE_NT_HEADERS), NULL) == 0)
	{
		printf("lasterror : %d\n", GetLastError());
		return FALSE;
	}

	dwRetSize = ImageNtHeader.OptionalHeader.SizeOfImage;

	return dwRetSize;
}

////方式二:
////通过抓取进程快照获取程序镜像大小(参见函数GetProcessBaseAndImageSize)
//DWORD GetImageSize(DWORD dwPid)
//{
//	HANDLE hMoudleSnap = INVALID_HANDLE_VALUE;
//	MODULEENTRY32 me32;
//	memset(&me32, 0, sizeof(MODULEENTRY32));
//	me32.dwSize = sizeof(MODULEENTRY32);
//	//对进程所有模块进行快照处理
//	hMoudleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPid);
//	if(hMoudleSnap == INVALID_HANDLE_VALUE)
//	{
//		printf("failed to CreateToolhelp32Snapshot of process modules...\n");
//		return FALSE;
//	}
//	//retrieve information about the first module
//	//and exit if unsucessful
//	if(!Module32First(hMoudleSnap, &me32))
//	{
//		printf("Failed to Module32First...\n");
//		CloseHandle(hMoudleSnap);
//		return FALSE;
//	}
//	CloseHandle(hMoudleSnap);
//	return me32.modBaseSize;   //进程镜像的大小
//}


//修改dump文件的区段头结构中 文件偏移 文件大小 值 ,使其与内存偏移,内存大小相等
BOOL ModifySectionHeader(char *strDumpFileName)
{
	HANDLE hFile;
	HANDLE hFileMapping;
	LPVOID lpFileBase;
	hFile = CreateFile(strDumpFileName,
					GENERIC_READ | GENERIC_WRITE,
					FILE_SHARE_READ | FILE_SHARE_WRITE,
					NULL,
					OPEN_EXISTING,
					FILE_ATTRIBUTE_NORMAL,
					0);
	if(hFile == INVALID_HANDLE_VALUE)
	{
		printf("Failed to CreateFile ...\n");
		return FALSE;
	}
	//将文件映射到内存
	hFileMapping = CreateFileMapping(hFile,
									NULL,
									PAGE_READWRITE,
									0, 0, NULL);
	if(hFileMapping == 0)
	{
		CloseHandle(hFile);
		printf("Failed to CreateFileMapping...\n");
		return FALSE;
	}
	lpFileBase = MapViewOfFile(hFileMapping,
						FILE_MAP_ALL_ACCESS,
						0, 0, 0);
	if(lpFileBase == 0)
	{
		CloseHandle(hFileMapping);
		CloseHandle(hFile);
		printf("Failed to MapViewOfFile...\n");
		return FALSE;
	}

	PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)lpFileBase;
	PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((DWORD)lpFileBase + pDosHeader->e_lfanew);
	DWORD dwSectionCount;
	dwSectionCount = pNtHeader->FileHeader.NumberOfSections;

	PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pNtHeader + sizeof(IMAGE_NT_HEADERS));
	for (int i = 0; i < dwSectionCount; i++)
	{
		//printf("before:\nsection%d  VOffset : %x   VSize : %x   ROffset : %x    RSize : %x \n",
		//	i,
		//	pSectionHeader->VirtualAddress,
		//	pSectionHeader->Misc.VirtualSize,
		//	pSectionHeader->PointerToRawData,
		//	pSectionHeader->SizeOfRawData);
		//modify data
		//因为从内存中dump出来后,值都应该保持与区段内存偏移和大小一致
		pSectionHeader->PointerToRawData = pSectionHeader->VirtualAddress;
		pSectionHeader->SizeOfRawData = pSectionHeader->Misc.VirtualSize;


		pSectionHeader++;  //next section
	}
	//FlushViewOfFile()
	UnmapViewOfFile(lpFileBase);
	CloseHandle(hFileMapping);
	CloseHandle(hFile);
	return TRUE;
}



//dump process
DWORD DumpProcess(char strProcName[])
{
	DWORD dwPid;
	DWORD dwImageSize;
	DWORD dwProcBase;

	dwPid = GetProcessPid(strProcName);
	if(dwPid == FALSE)
		return FALSE;

	dwProcBase = GetProcessBaseAndImageSize(dwPid, &dwImageSize);
	if(dwProcBase == FALSE)
		return FALSE;

	printf( "\nBase address   = 0x%08X    , pid = %d, ImageSize = %d ...\n", dwProcBase, dwPid, dwImageSize );   //第一个模块即进程基址


	//dump进程映像
	HANDLE hProc = OpenProcess( PROCESS_VM_READ, FALSE, dwPid );
	if(hProc == NULL)
	{
		printf("Failed to open %d process...\n",dwPid);
		return false;
	}

	//dwImageSize = 0;
	//dwImageSize = GetImageSize(hProc, dwProcBase);
	//if(dwImageSize == 0)
	//	return false;
	//printf("Image size:%d\n",dwImageSize);


	char *procBuff = (char*)malloc(dwImageSize);

	if(ReadProcessMemory(hProc, (char*)dwProcBase, procBuff, dwImageSize, NULL) == 0)
	{
		printf("lasterror : %d\n", GetLastError());
		return false;
	}
	char strFile[MAX_PATH] = "dump.";
	strcat(strFile, strProcName);
	FILE *fp;
	fp = fopen(strFile, "wb");
	fwrite(procBuff, dwImageSize, 1, fp);
	fclose(fp);

	if(procBuff != NULL)
		free(procBuff);

	CloseHandle(hProc);

	ModifySectionHeader(strFile);
	return true;
}


void main( int argc, char** argv )
{
	if(argc != 2)
	{
		printf("error argv...\n");
		return;
	}
	printf("dump %s...\n",argv[1]);
	DumpProcess(argv[1]);
	system("pause");
}

程序名称:LordPE Deluxe 增强版 版 本:1.4 汉 化 人:cao_cong 联系方式:cao_cong_hx@yahoo.com.cn 使用说明: 这个工具大家应该也比较熟悉吧?这是另一款PE编辑工具,号称是“最好的PE文件修改工具”。这个增强版本是我在看雪学院上看到的,原来是看雪兄的大作。正好我以前汉化过这个软件(自己用的,没发布过),顺便套用一下以前的资源,把它给汉化了(里面所附带的工具基本上都汉化了)。可能有许多兄弟都比较喜欢用这个软件,这次发出来希望能给大家带来一点方便。这个增强版的主要更新(根据看雪兄的readme文件): (1) 为LordPE查看输入表部分加上搜索功能 (2) 为LordPE查看输入表部分加右键菜单(仅复制ThunkRVA/FirstThunk列). (3) 当点击LordPE查看输入表部分中"View always FirstThunk",保持光条在原来位置.(LordPE默认会将光条置到0行) (4) 修改FLC(File Location Calulator)窗口中各个文本框(VA,RVA,Offset)为只读属性,此时可以用鼠标复制里面的文本.(LordPE原来是将文本框禁止变灰,此时不可复制) 不过上面的第二条查看输入表部分的右键菜单我没看到。难道是我的系统(XP_SP2)有问题? 其它内容请看附带在内的readme.txt文件。LordPE的原版和增强版的原版我都放在英文原版文件夹中,大家可以进行比较。 声明: 1、此汉化软件是免费软件,请在转载时保留其内容的完整性! 2、此软件仅用于个人学习使用,禁止用于商业用途,否则后果自负! (1) 为LordPE查看输入表部分加上搜索功能 (2) 为LordPE查看输入表部分加右键菜单(仅复制ThunkRVA/FirstThunk列). (3) 当点击LordPE查看输入表部分中"View always FirstThunk",保持光条在原来位置.(LordPE默认会将光条置到0行) (4) 修改FLC(File Location Calulator)窗口中各个文本框(VA,RVA,Offset)为只读属性,此时可以用鼠标复制里面的文本.(LordPE原来是将文本框禁止变灰,此时不可复制) 文件列表: LordPE.EXE .............原版 LordPE_fix.EXE .............增强版 LordPlug.dll .............功能插件 LordPlug.dll_src .............功能插件源码
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值