滴水逆向三期 PE基础 移动导出表

分析

源码
要移动导出表, 需要改变的地方有:
1 DataDirectory[5]->VirtualAddress
2 ExportDirector中的三个地址

代码

按照课程内容的顺序依次进行
步骤如下:
在这里插入图片描述

新增节省略
初始化
Header header;
SList slist;
DWORD fileSize = 0;
DWORD foaOfNewSection = 0;
DWORD foaExportDirectory = 0;
PIMAGE_DATA_DIRECTORY pDataDirectory = NULL;
PIMAGE_EXPORT_DIRECTORY pExportDirectory = NULL;

pFileBuffer = ReadPeFile(inFilePath, &fileSize);
InitializePheader(pFileBuffer, &header, &slist);
pDataDirectory = header.pOptionalHeader->DataDirectory;
foaExportDirectory = RvaDataToFoaData(pFileBuffer, (*pDataDirectory).VirtualAddress, FALSE);
pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)(foaExportDirectory + (DWORD)pFileBuffer);
二三四 复制地址

需要用三个变量存放存储当前片段的偏移, 方便后面修复

DWORD sizeOf_AddressOfFunctions = 4 * pExportDirectory->NumberOfFunctions;
DWORD sizeOf_AddressOfNames = 4 * pExportDirectory->NumberOfFunctions;
DWORD sizeOf_AddressOfNameOrdinals = 2 * pExportDirectory->NumberOfNames;

DWORD copyAddressOfFunctions = (DWORD)pFileBuffer + (header.pSecitonHeader + slist.numOfSections - 1)->PointerToRawData;
DWORD orginalAddressOfFunctions= (DWORD)pFileBuffer + RvaDataToFoaData(pFileBuffer, pExportDirectory->AddressOfFunctions, FALSE);
DWORD foaOf_AddressOfFunctions = copyAddressOfFunctions - (DWORD)pFileBuffer;
memcpy((LPVOID)copyAddressOfFunctions, (LPVOID)orginalAddressOfFunctions, sizeOf_AddressOfFunctions);	//复制AddressOfFunctions
copyAddressOfFunctions += sizeOf_AddressOfFunctions;
orginalAddressOfFunctions = (DWORD)pFileBuffer + RvaDataToFoaData(pFileBuffer, pExportDirectory->AddressOfNames, FALSE);
DWORD foaOf_AddressOfNames = copyAddressOfFunctions - (DWORD)pFileBuffer;	//为了后面修复
memcpy((LPVOID)copyAddressOfFunctions, (LPVOID)orginalAddressOfFunctions, sizeOf_AddressOfNames);
copyAddressOfFunctions += sizeOf_AddressOfNames;
orginalAddressOfFunctions = (DWORD)pFileBuffer + RvaDataToFoaData(pFileBuffer, pExportDirectory->AddressOfNameOrdinals, FALSE);
DWORD foaOf_AddressOfNameOrdinals = copyAddressOfFunctions - (DWORD)pFileBuffer;;
memcpy((LPVOID)copyAddressOfFunctions, (LPVOID)orginalAddressOfFunctions, sizeOf_AddressOfNameOrdinals);
copyAddressOfFunctions += sizeOf_AddressOfNameOrdinals;
五 复制函数名

strlen记得加1

DWORD oringinalAddressOfName = (DWORD)pFileBuffer + RvaDataToFoaData(pFileBuffer, pExportDirectory->AddressOfNames, FALSE);
DWORD sizeOfNames = 0;
char *nameOfFunction = (char *)((DWORD)(pFileBuffer)+RvaDataToFoaData(pFileBuffer, *(DWORD *)(oringinalAddressOfName),  FALSE));
for (DWORD i = 0; i < pExportDirectory->NumberOfNames; i++) 
{
	puts(nameOfFunction);
	sizeOfNames += strlen(nameOfFunction);
	memcpy((DWORD *)copyAddressOfFunctions, nameOfFunction, sizeOfNames);

	copyAddressOfFunctions = copyAddressOfFunctions + strlen(nameOfFunction) + 1;
	nameOfFunction = (char *)((DWORD)nameOfFunction + strlen(nameOfFunction) + 1);
}
六 复制导出表结构
DWORD foaOf_AddressOfExportDirectory = copyAddressOfFunctions - (DWORD)pFileBuffer;
memcpy((PIMAGE_EXPORT_DIRECTORY)copyAddressOfFunctions, pExportDirectory, SIZE_OF_EXPORTDIRECTORY);
七 八 修复结构
PIMAGE_EXPORT_DIRECTORY movedExportDirectory = (PIMAGE_EXPORT_DIRECTORY)copyAddressOfFunctions;
movedExportDirectory->AddressOfFunctions = FoaDataToRvaData(pFileBuffer, (DWORD)foaOf_AddressOfFunctions);
movedExportDirectory->AddressOfNames = FoaDataToRvaData(pFileBuffer, (DWORD)foaOf_AddressOfNames);
movedExportDirectory->AddressOfNameOrdinals = FoaDataToRvaData(pFileBuffer, (DWORD)foaOf_AddressOfNameOrdinals);

pDataDirectory->VirtualAddress = FoaDataToRvaData(pFileBuffer, foaOf_AddressOfExportDirectory);

测试

ps: 没考虑过64位问题, 只用于32位测试
测试文件: cloudmusic.dll 某云

原始dll

在这里插入图片描述

移动导出表后dll

在这里插入图片描述
使用也无问题

一些问题

1 首先是新节的大小, 一开始用的0x10000感觉已经很大了, 没想到在测试的时候出了问题, 拖进lordpe一看, 这么多函数名字还都不短, 立马就又加了个0, 成功. 所以稳妥的做法是先判断所有name大小再开辟新节

2 关于FOA RVA惭愧的说, 这两个东西学到这才弄懂含义, FILE OFFSET ADDRESS 之前觉着是FILE OF ADDRESS…就导致写代码的时候会把加上缓冲区的地址当作foa, 意思就是单纯的偏移, 并不包含缓冲区的地址. 弄明白就不用在加不加缓冲区地址上浪费时间. 但这个并不影响关于移动表的理解.

3 尽管已经写完了 打印导出表, 在写这个函数的时候还是在转来转去的过程中差点晕过去, 但现在写完变得很清晰, 对PE结构的理解帮助很大.

建了个学习讨论q群, 欢迎新朋友加入:1094301686

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

四位

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值