做了一个Dump exe文件的工具

5 篇文章 0 订阅
5 篇文章 0 订阅

为了加深对PE文件的理解,以及和进程有关的WIN32 API的应用,就做出了这么一个东西。DUMP的话只需要DUMP出DOS头 + PE头 + 区块即可。

#include "stdafx.h"
typedef struct 
{
	WORD e_magic;
	char Data[23 + sizeof(DWORD) * 3];
	LONG e_lfanew;
}Dos,*pDos;
int GetPageSize(void) /* 获取内存页大小 */
{
	SYSTEM_INFO SystemInformation;
	GetSystemInfo(&SystemInformation);
	return SystemInformation.dwPageSize;
}
int main(void)
{
	HANDLE Handle;
	PROCESSENTRY32W pe;
	LPPROCESSENTRY32W ppe;
	CHAR szExeFile[MAX_PATH];
	CHAR szExePath[MAX_PATH];
	MODULEENTRY32W ModuleEntry32W;
	HANDLE ProcessHandle;
	DWORD old;
	HANDLE Process;
	HANDLE hFile;
	HANDLE hMap;
	FILE *File;
	CHAR szDumpedFileName[MAX_PATH];
	DWORD Oep;
	DWORD CodeBaseAddr_;
	DWORD DataBaseAddr_;
	DWORD pBuf;
	PIMAGE_NT_HEADERS32 pNtHeaders32;
	PIMAGE_DOS_HEADER pDosHeader;
	PIMAGE_SECTION_HEADER pSecHeader;
	PIMAGE_SECTION_HEADER pSec;
	pDos MyDosHeader;
	char Msg[] = " DumpExeFile Coded by yeeeee           ";
	unsigned char Buffer[8192] = {0};
	unsigned char *pSectionBuffer;
	unsigned char *pBuffer;
	int Number;
	char IsXz[123];
	int num;
	int Num;
	int size;
	int i;
	Num ^= Num;
	Number ^= Number;
	/* 获取进程数量 */
	SetConsoleTitleW(L"DumpExeFile Coded by yeeeee QQ群:Alg & Sec lab of China 群号:254394017");
	Handle = CreateToolhelp32Snapshot(TH32CS_SNAPALL,NULL);
	if(Handle == INVALID_HANDLE_VALUE)
	{
		puts("创建快照失败!");
		goto Exit;
	}
	pe.dwSize = sizeof(PROCESSENTRY32W);
	if(!Process32FirstW(Handle,&pe))
	{
		puts("获取进程列表失败!");
		goto Exit;
	}
	do
		Number++;
	while(Process32NextW(Handle,&pe));
	/* 获取系统全部进程 */
	ppe=(LPPROCESSENTRY32W)malloc(Number * sizeof(PROCESSENTRY32W));
	if(!ppe)
	{
		puts("申请内存失败!");
		goto Exit;
	}
	for(i = 0;i < Number;i++)
		ppe[i].dwSize = sizeof(PROCESSENTRY32W);
	if(!Process32FirstW(Handle,&ppe[0]))
	{
		puts("获取进程列表失败!");
		goto Exit;
	}
	WideCharToMultiByte(CP_ACP,
		WC_NO_BEST_FIT_CHARS,
		ppe[0].szExeFile,
		sizeof(ppe[0].szExeFile),
		szExeFile,
		sizeof(szExeFile),
		NULL,
		FALSE);
	printf("1.进程名:%s\n",szExeFile);
	for(i = 1;i < Number;i++)
	{
		if(!Process32NextW(Handle,&ppe[i]))
			break;
		WideCharToMultiByte(CP_ACP,
			WC_NO_BEST_FIT_CHARS,
			ppe[i].szExeFile,
			sizeof(ppe[i].szExeFile),
			szExeFile,
			sizeof(szExeFile),
			NULL,
			FALSE);
		printf("%d.进程名:%s\n",i + 1,szExeFile);
	}
	printf("一共有 %d 个进程\n要Dump的Exe文件进程序号:",Number);
	scanf("%d",&num);
	ProcessHandle = CreateToolhelp32Snapshot(TH32CS_SNAPALL,ppe[num - 1].th32ProcessID);
	if(ProcessHandle == INVALID_HANDLE_VALUE)
	{
		puts("创建快照失败!");
		CloseHandle(Handle);
		free(ppe);
		goto Exit;
	}
	ModuleEntry32W.dwSize = sizeof(MODULEENTRY32W);
	if(!Module32FirstW(ProcessHandle,&ModuleEntry32W))
	{
		WideCharToMultiByte(CP_ACP,
			WC_NO_BEST_FIT_CHARS,
			ppe[num - 1].szExeFile,
			sizeof(ppe[num - 1].szExeFile),
			szExeFile,
			sizeof(szExeFile),
			NULL,
			FALSE);
		printf("%d:%s\n",num,szExeFile);
		printf("检索进程信息失败!错误号:%d\n",GetLastError());
		goto Clean;
	}
	WideCharToMultiByte(CP_ACP,
		WC_NO_BEST_FIT_CHARS,
		ppe[num - 1].szExeFile,
		sizeof(ppe[num - 1].szExeFile),
		szExeFile,
		sizeof(szExeFile),
		NULL,
		FALSE);
	WideCharToMultiByte(CP_ACP,
		WC_NO_BEST_FIT_CHARS,
		ModuleEntry32W.szExePath,
		sizeof(ModuleEntry32W.szExePath),
		szExePath,
		sizeof(szExePath),
		NULL,
		FALSE);
	printf("%d:%s\n\t- %s\nBase address:%xh\nBase size:%xh\n",
		num,
		szExeFile,
		szExePath,
		ModuleEntry32W.modBaseAddr,
		ModuleEntry32W.modBaseSize);
	Process = OpenProcess(PROCESS_VM_OPERATION|
		PROCESS_VM_READ|
		PROCESS_VM_WRITE|
		PROCESS_TERMINATE,
		FALSE,
		ModuleEntry32W.th32ProcessID);
	if(!Process)
	{
		printf("打开进程失败!错误号:%d\n",GetLastError());
		goto Clean;
	}
	printf("Exe文件入口点(RVA):");
	scanf("%x",&Oep);
	printf("代码基址(RVA):");
	scanf("%x",&CodeBaseAddr_);
	printf("数据基址(RVA):");
	scanf("%x",&DataBaseAddr_);
	printf("Virtual protect:%d\nLast error:%d\n",
		VirtualProtectEx(Process,
			ModuleEntry32W.modBaseAddr,
			sizeof(Buffer),
			PAGE_EXECUTE_READWRITE,
			&old),
			GetLastError());
	ReadProcessMemory(Process,
		ModuleEntry32W.modBaseAddr,
		Buffer,
		sizeof(Buffer),
		0),
		GetLastError();
	strcpy(szDumpedFileName,szExePath);
	strcat(szDumpedFileName,".Dumped.exe");
	pDosHeader = (PIMAGE_DOS_HEADER)Buffer;
	if(pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
	{
		puts("不是有效的PE文件!");
		goto Clean;
	}
	pNtHeaders32 = (PIMAGE_NT_HEADERS32)&Buffer[pDosHeader->e_lfanew];
	if(pNtHeaders32->Signature != IMAGE_NT_SIGNATURE)
	{
		puts("不是PE文件,这像一个DOS文件!");
		goto Clean;
	}
	printf("申请内存大小:%xh\n",
		(pNtHeaders32->OptionalHeader.SizeOfImage + 
			pNtHeaders32->OptionalHeader.SizeOfHeaders +
			GetPageSize()) * sizeof(unsigned char));
	pBuf = (DWORD)VirtualAlloc(NULL,
		(pNtHeaders32->OptionalHeader.SizeOfImage + 
		pNtHeaders32->OptionalHeader.SizeOfHeaders + GetPageSize()),
		MEM_RESERVE|MEM_COMMIT,
		PAGE_READWRITE);
	if(!pBuf)
	{
		puts("申请内存失败!");
		CloseHandle(Process);
		goto Clean;
	}
	printf("头大小:%xh\n",pNtHeaders32->OptionalHeader.SizeOfHeaders);
	puts("Dump文件头......");
	/* Dump头 */
	memcpy((char*)pBuf,Buffer,pNtHeaders32->OptionalHeader.SizeOfHeaders);
	puts("Dump文件头完毕\nDump区块......");
	pSecHeader = IMAGE_FIRST_SECTION(pNtHeaders32);
	for(i = 0;i < pNtHeaders32->FileHeader.NumberOfSections;i++)
	{
		printf("区块名 %s\t区块大小:%xh\t区块虚拟地址:%xh\t区块映像地址:%xh\n",
			pSecHeader->Name,
			pSecHeader->SizeOfRawData,
			pSecHeader->VirtualAddress,
			pSecHeader->PointerToRawData);
		pSectionBuffer = (unsigned char*)malloc(pSecHeader->Misc.VirtualSize * sizeof(unsigned char));
		if(!pSectionBuffer)
		{
			puts("Dump区块失败!无法分配内存!");
			VirtualFree((char*)pBuf,0,MEM_RESERVE);
			goto Clean;
		}
		printf("VirtualProtect:%d Last error:%d\n",
			VirtualProtectEx(Process,
				ModuleEntry32W.modBaseAddr + pSecHeader->VirtualAddress,
				pSecHeader->Misc.VirtualSize,
				PAGE_EXECUTE_READWRITE,
				&old),
			GetLastError());
		printf("Dumped:%d\n",
			ReadProcessMemory(Process,
				ModuleEntry32W.modBaseAddr + pSecHeader->VirtualAddress,
				pSectionBuffer,
				pSecHeader->Misc.VirtualSize,
				NULL));
		memcpy((char*)pBuf + pSecHeader->PointerToRawData,pSectionBuffer,pSecHeader->Misc.VirtualSize);
		free(pSectionBuffer);
		pSecHeader++;
	}
	puts("Dump区块完毕!\n开始保存文件......");
	File = fopen(szDumpedFileName,"wb+");
	if(!File)
	{
		puts("保存文件失败!无法创建文件");
		VirtualFree((char*)pBuf,0,MEM_RESERVE);
		goto Clean;
	}
	fwrite((char*)pBuf,
		pNtHeaders32->OptionalHeader.SizeOfImage + 
		pNtHeaders32->OptionalHeader.SizeOfHeaders + GetPageSize(),
		1,
		File);
	fseek(File,78,SEEK_SET);/* 移动78个字节,到 'This program cannot be run in dos mode' */
	fwrite(Msg,strlen(Msg),1,File);/* 写入信息 */
	fclose(File);
	puts("文件保存完毕!\n开始修复入口点,代码基址,数据基址");
	VirtualFree((char*)pBuf,0,MEM_RESERVE);
	/* 修复入口点,代码基址,数据基址 */
	hFile = CreateFileA(szDumpedFileName,
		GENERIC_WRITE|GENERIC_READ,
		FILE_SHARE_READ,
		NULL,
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,
		NULL);
	if(hFile == INVALID_HANDLE_VALUE)
	{
		printf("修复文件失败!打开Dump文件失败.文件名:%s Last error:%d\n",szDumpedFileName,GetLastError());
		goto Clean;
	}
	size = GetFileSize(hFile,0);
	hMap = CreateFileMapping(hFile,NULL,PAGE_READWRITE,0,size,NULL);
	if(hMap == INVALID_HANDLE_VALUE)
	{
		goto UnView;
UnView:
		printf("映射Dump文件到磁盘失败!文件名:%s Last error:%d\n",szExePath,GetLastError());
		CloseHandle(hFile);
		goto Clean;
	}
	pBuffer = (unsigned char*)MapViewOfFile(hMap,FILE_MAP_WRITE|FILE_MAP_READ,0,0,size);
	if(!pBuffer)
	{
		CloseHandle(hMap);
		goto UnView;
	}
	pDosHeader = (PIMAGE_DOS_HEADER)pBuffer;
	pNtHeaders32 = (PIMAGE_NT_HEADERS32)&pBuffer[pDosHeader->e_lfanew];
	pNtHeaders32->OptionalHeader.AddressOfEntryPoint = Oep;
	pNtHeaders32->OptionalHeader.BaseOfCode = CodeBaseAddr_;
	pNtHeaders32->OptionalHeader.BaseOfData = DataBaseAddr_;
	printf("修正脱壳镜像中物理地址和物理大小(Y or N):");
	scanf("%s",IsXz);
	if(!stricmp(IsXz,"Y"))
	{
		puts("修正物理地址和物理大小......");
		/* 修正物理地址和物理大小 */
		pSec = IMAGE_FIRST_SECTION(pNtHeaders32);
		for(i = 0;i < pNtHeaders32->FileHeader.NumberOfSections;i++)
			pSecHeader--;
		for(i = 0;i < pNtHeaders32->FileHeader.NumberOfSections;i++)
		{
			pSec->SizeOfRawData = pSecHeader->Misc.VirtualSize;
			pSec->PointerToRawData = pSecHeader->VirtualAddress;
			pSec++;
			pSecHeader++;
		}
		puts("修正物理地址和物理大小完毕");
	}
	MyDosHeader = (pDos)pBuffer;
	strcpy(MyDosHeader->Data," QQ群:Alg & Sec lab of China 群号:254394017 ");/* 写入信息 */
	UnmapViewOfFile(pBuffer);
	CloseHandle(hFile);
	CloseHandle(hMap);
	puts("Dump完成");
	goto Clean;
Clean:
	CloseHandle(ProcessHandle);
	CloseHandle(Handle);
	free(ppe);
	goto Exit;
Exit:
	system("pause");
	return 0;
}

stdafx.h

// stdafx.h : 标准系统包含文件的包含文件,
// 或是经常使用但不常更改的
// 特定于项目的包含文件
//

#pragma once

#include "targetver.h"

#include <stdio.h>
#include <tchar.h>



// TODO: 在此处引用程序需要的其他头文件
#include <stdlib.h>
#include <windows.h>
#include <TlHelp32.h>
程序截图:

DUMP一个文件后,用记事本打开这个文件,会看到这样的东西:


嘿嘿。。。。


参考资料:http://blog.csdn.net/iiprogram/article/details/2298838(我是从这里才知道的 DUMP文件只需要DUMP出DOS头 + PE头 + 区块)就行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值