Dump文件修复

前言

分析windwos下的木马时经常会碰见dump的恶意代码文件无法直接查看。
一是因为文件数据在内存展开,而区段的属性未修改;
二是因为数据在内存展开后,重定位数据被修改。
因此写个工具进行修复。
说明一下dump内存起始地址为dump恶意代码内存块的起始地址。
在这里插入图片描述

一、代码示例

1.文件对齐

//文件对齐   
DWORD CFixDumpDlg::GetOffset(DWORD  argc)
{
	DWORD   a = 0;
	DWORD   b = 0;


	a = argc % 0x200;
	if (a > 0)
	{
		b = (argc / 0x200) + 1;
		return b;
	}
	else
	{
		b = argc / 0x200;
		return b;
	}

}

2.RVA转换FOA

//RVA转换FOA
DWORD  rvaTOfoa(PIMAGE_NT_HEADERS pNT, DWORD rva)
{
	//获取区段头
	PIMAGE_SECTION_HEADER psection = IMAGE_FIRST_SECTION(pNT);
	//循环比较获取所在区段
	for (DWORD i = 0; i < pNT->FileHeader.NumberOfSections; i++)
	{
		if ((rva >= psection[i].VirtualAddress) && (rva <= (psection[i].VirtualAddress + psection[i].SizeOfRawData)))
		{
			return  rva - psection[i].VirtualAddress + psection[i].PointerToRawData;
			// 获取到虚拟地址后加上区段在文件内的起始位置就是文件偏移
		}

	}
}

3.将内存展开数据还原为文件数据

BOOL   CFixDumpDlg::FixPeVirtualData(LPVOID  data,CString filepath)
{
	//声明变量
	PIMAGE_DOS_HEADER   pdos = NULL;
	PIMAGE_NT_HEADERS   pnt = NULL;
	PIMAGE_FILE_HEADER  pfile = NULL;
	PIMAGE_OPTIONAL_HEADER  poptional = NULL;
	DWORD   count = 0;                   //区段数量
	DWORD   AlignmentSize = 0;           //内存对齐后的大小
	LPVOID  p_address = NULL;            //申请的内存地址
	DWORD   size = 0;
	DWORD   index = 0;

	//初始化
	pdos = (PIMAGE_DOS_HEADER)data;
	pnt = (PIMAGE_NT_HEADERS)((DWORD)data + pdos->e_lfanew);
	pfile = &(pnt->FileHeader);
	poptional = &(pnt->OptionalHeader);


	//获取区段的数量和大小
	count = pfile->NumberOfSections;
	//获取区段信息        区段头表在NT头后面
	PIMAGE_SECTION_HEADER psection = IMAGE_FIRST_SECTION(pnt);

	size = psection[count - 1].SizeOfRawData + psection[count - 1].PointerToRawData;
	size = GetOffset(size) * 0x200;
	//在内存中申请展开后的大小
	p_address = VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE);
	Save_address = p_address;
	FileSize = size;
	if (p_address == NULL)  return  FALSE;

	//修复PE头
	memcpy(p_address, data, 0x400);
	p_address = (LPVOID)((DWORD)p_address + 0x400);


	//展开区段数据
	while (count)
	{
		DWORD   rawsize = psection->SizeOfRawData;
		DWORD   v_address = psection->VirtualAddress;
		DWORD   rawdata = psection->PointerToRawData;
		LPVOID  data_addr = (LPVOID)((DWORD)data + v_address);
		if (rawsize != 0)
		{
			rawsize = GetOffset(rawsize) * 0x200;
			memcpy(p_address, data_addr, rawsize);
		}
		p_address = (LPVOID)((DWORD)p_address + rawsize);
		psection++;
		count--;
		index++;
	}
	
	return TRUE;
}

4.修复重定位

//修复重定位
void   CFixDumpDlg::FixReloc(LPVOID   buff)
{
	//声明变量
	PIMAGE_DOS_HEADER   pdos = NULL;
	PIMAGE_NT_HEADERS   pnt = NULL;
	PIMAGE_FILE_HEADER  pfile = NULL;
	PIMAGE_OPTIONAL_HEADER  poptional = NULL;
	DWORD              old_imagebase;
	DWORD              new_imagebase;

	struct  typeoffset
	{
		WORD offset : 12;
		WORD type : 4;
	}*pTpOffset;


	//初始化
	pdos = (PIMAGE_DOS_HEADER)buff;
	pnt = (PIMAGE_NT_HEADERS)((DWORD)buff + pdos->e_lfanew);
	poptional = &(pnt->OptionalHeader);



	//获取重定位表的偏移
	DWORD   RelRva = poptional->DataDirectory[5].VirtualAddress;
	DWORD   RelFoa = rvaTOfoa(pnt,RelRva);
	PIMAGE_BASE_RELOCATION   pRelTable = (PIMAGE_BASE_RELOCATION)((DWORD)buff+RelFoa);
	
	
	
	while (pRelTable->SizeOfBlock != 0)
	{
		pTpOffset = (typeoffset*)(pRelTable + 1);
		DWORD   RELcount = (pRelTable->SizeOfBlock - 8) / 2;
		for (int i = 0; i < RELcount; i++)
		{
			if (pTpOffset[i].type == 3)
			{
				RelFoa= rvaTOfoa(pnt, pRelTable->VirtualAddress);
				DWORD  fix_addr = (DWORD)buff+ RelFoa + pTpOffset[i].offset;
				*(DWORD*)fix_addr -= MemoryAddress;
				*(DWORD*)fix_addr += poptional->ImageBase;
			}
		}
		pRelTable = (IMAGE_BASE_RELOCATION*)((LPBYTE)pRelTable + pRelTable->SizeOfBlock);

	}


}

总结

百度云连接 链接:https://pan.baidu.com/s/19WHJE6iF6mHhC6msOlphsw 提取码:psma
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值