#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <Windows.h>
//此处是禁用函数警报
#define _CRT_SECURE_NO_DEPRECATE
#pragma warning(disable:4996)
FILE* openFile(char* filePath, char* type);//打开文件函数 返回指向文件缓冲区流头指针
int getFileSize(FILE* fileAdress);//得到文件大小函数 返回文件大小
char* allotspace(int size);//分配内存空间函数 根据得到的文件大小 返回内存空间首地址
char* readFiletoMemory(FILE* fileHeadAdress, char* head, int size);//将文件写入分配好的空间的函数 返回已经写入数据的内存空间首地址
int writeMemorytoFile(char* filePath, char* type, char* head, int size);//将内存中的数据写出到文件函数
int parsePEHead(LPSTR pFileBuffer);
//fileBuffer拉伸成ImgBuffer
LPSTR fileBuffertoImageBuffer(LPSTR pfileBuffer);
//将file写入内存转为fileBuffer
LPSTR filetoFileBuffer(char* filePath);
//将ImgBuffer转为newBuffer
LPSTR ImageBuffertoNewBuffer(LPSTR pImageBuffer);
//RVA转换成FOA
DWORD convertRVAtoFOA(DWORD pRVA,LPSTR pImageBuffer);
//DOS头解析 返回指向DOS头结构体指针类型
PIMAGE_DOS_HEADER parsePEDosHeader(LPSTR pfileBuffer);
//NT头解析 返回指向NT头结构体指针类型
PIMAGE_NT_HEADERS parsePENTHeader(LPSTR pfileBuffer);
//标准头解析 返回指向标准头结构体指针类型
PIMAGE_FILE_HEADER parsePEStandarHeader(LPSTR pfileBuffer);
//可选PE头解析 返回指向选PE头结构体指针类型
PIMAGE_OPTIONAL_HEADER32 parsePEOptionHeader(LPSTR pfileBuffer);
//节表头解析 返回指向节表头结构体指针类型
PIMAGE_SECTION_HEADER parsePESectionHeader(LPSTR pfileBuffer);
//返回节表数量
int getSectionNumber(PIMAGE_FILE_HEADER pPEStandarHeader);
//显示函数
void displayPEHeader(PIMAGE_DOS_HEADER pPEDosHeader);
void displayPEHeader(PIMAGE_FILE_HEADER pPEStandarHeader);
void displayPEHeader(PIMAGE_OPTIONAL_HEADER32 pPEOptionHeader);
void displayPEHeader(PIMAGE_SECTION_HEADER pPESectionHeader,int sectionNumber);
int main()
{
//parsePEHead(filetoFileBuffer("D:7.EXE"));
//writeMemorytoFile("D:11.exe","wb+", ImageBuffertoNewBuffer(filetoFileBuffer("D:7.exe")), getFileSize(openFile("D:7.exe","rb+")));
LPSTR imageBuffer = fileBuffertoImageBuffer(filetoFileBuffer("D:7.EXE"));
//convertRVAtoFOA((0Xbf000+(DWORD)imageBuffer), imageBuffer);
MessageBox(0,0,0,0);
getchar();
return 0;
}
//打开文件函数 返回指向文件缓冲区流头指针
FILE* openFile(char* filePath, char* type) {
FILE* fileAdress;
//通过传入的文件地址以及读写类型打开文件创建文件流
if (!(fileAdress = fopen(filePath, type)))
{
printf("获取文件出错!n");
return 0;
}
return fileAdress;
}
//得到文件大小函数 返回文件大小
int getFileSize(FILE* fileAdress) {
int size;
//定位文件末尾
fseek(fileAdress, NULL, SEEK_END);
//得到文件流大小
size = ftell(fileAdress);
//重定位文件开头
fseek(fileAdress, NULL, SEEK_SET);
return size;
}
//分配内存空间函数 根据得到的文件大小 返回内存空间首地址
char* allotspace(int size) {
char* head;
//根据文件大小分配内存空间
if (!(head = (char*)malloc(size))) {
printf("分配空间失败!n");
return 0;
}
//使用1初始化size大小已经分配的内存空间
memset(head, 0, size);
//返回分配初始化完毕的内存空间首地址
return head;
}
//将文件写入分配好的空间的函数 返回已经写入数据的内存空间首地址
char* readFiletoMemory(FILE* fileHeadAdress, char* head, int size) {
//通过传入的文件地址以及开辟的内存空间首地址和文件大小将文件数据写入分配好的内存空间中
if (!(fread(head, 1, size, fileHeadAdress) == size)) {
printf("文件数据写入内存出错!");
return 0;
}
//读取文件数据写入内存
return head;
}
//将内存中的数据写出到文件函数
int writeMemorytoFile(char* filePath, char* type, char* head, int size) {
//定义创建文件流
FILE* fileAdress = openFile(filePath, type);
//读取内存数据写出到文件
if (!(fwrite(head, 1, size, fileAdress) == size)) {
printf("内存数据写出到文件出错!n");
return 0;
}
return 1;
}
//传入文件路径 将文件写入内存并返回其首地址
LPSTR filetoFileBuffer(char* filePath) {
//打开文件传递文件流首地址
FILE* fileAdress = openFile(filePath, "rb+");
//通过文件流首地址得到文件大小
int fileSize = getFileSize(fileAdress);
//通过文件大小开辟内存空间并初始化
char* fileBuffer = allotspace(fileSize);
//将文件流中数据读入开辟的内存空间内
fileBuffer = readFiletoMemory(fileAdress, fileBuffer, fileSize);
fclose(fileAdress);
return fileBuffer;
}
LPSTR ImageBuffertoNewBuffer(LPSTR pfileBuffer)
{
LPSTR imageBuffer = fileBuffertoImageBuffer(pfileBuffer);
LPSTR pNewBuffer = NULL;
//int newBufferSize = getFileSize((FILE*)pfileBuffer);
int newBufferSize = getFileSize(openFile("D:7.exe", "rb+"));
//首先需获取开辟内存空间大小 其值存于可选PE头的SizeOfImage中
//解析可选PE头 得到镜像流大小
PIMAGE_OPTIONAL_HEADER32 pPEOptionHeader = parsePEOptionHeader(pfileBuffer);
//DWORD imageSize = pPEOptionHeader->SizeOfImage;
//开辟内存空间
pNewBuffer = allotspace(newBufferSize);
DWORD headerSize = pPEOptionHeader->SizeOfHeaders;
//内存拷贝函数 将pfileBuffer指向的地址的内存拷贝headerSize个字节到imageBuffer指向的内存中去
memcpy(pNewBuffer, pfileBuffer, headerSize);
PIMAGE_SECTION_HEADER pPESectionHeader = parsePESectionHeader(pfileBuffer);
//调用函数得到节表数
int sectionNumber = getSectionNumber(parsePEStandarHeader(pfileBuffer));
for (int count = 0; count < sectionNumber; count++) {
//将该节表中的Misc内VirtualSize的值取出 即是该节区的真正的数据宽度
//DWORD VirtualSize = *((DWORD*)((DWORD)pPESectionHeader + 8));
//将文件流拷入镜像流 需要节区在文件中的偏移和在内存中的偏移
//从(pfileBuffer+pPESectionHeader->PointerToRawData)开始拷贝,拷贝VirtualSize个字节到(imageBuffer+pPESectionHeader->VirtualAddress)
memcpy((pNewBuffer + (DWORD)(pPESectionHeader->PointerToRawData)), (imageBuffer + (DWORD)(pPESectionHeader->VirtualAddress)),pPESectionHeader->SizeOfRawData);
pPESectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pPESectionHeader + sizeof(_IMAGE_SECTION_HEADER));
}
//返回文件镜像流地址
return pNewBuffer;
}
DWORD convertRVAtoFOA(DWORD pRVA,LPSTR pImageBuffer)
{
//得到返回可选PE头地址
PIMAGE_OPTIONAL_HEADER32 pPEOptionHeader = parsePEOptionHeader(pImageBuffer);
//得到sizeOfimage的值用于比较节区地址是否真实
DWORD sizeOfImage = pPEOptionHeader->SizeOfImage;
//得到节表头地址
PIMAGE_SECTION_HEADER pPESectionHeader = parsePESectionHeader(pImageBuffer);
//得到标准PE头地址
PIMAGE_FILE_HEADER pPEStandarHeader = parsePEStandarHeader(pImageBuffer);
//得到节数量
WORD sectionNumber = pPEStandarHeader->NumberOfSections;
//取出ImageBase的值
DWORD imageBase = pPEOptionHeader->ImageBase;
printf("-----------------------pRVA的值为:%X-----------n",pRVA);
printf("n");
//displayPEHeader(pPESectionHeader, sectionNumber);
//创建一个变量记录后一个节
PIMAGE_SECTION_HEADER pPESectionHeaderNew = pPESectionHeader;
PIMAGE_SECTION_HEADER pPESectionHeaderOld = pPESectionHeader;
DWORD offset = 0;
int count = 1;//定义记录在第几节区count
for (;count <= sectionNumber; count++)
{
printf("********************Name的值为:%s***********n", pPESectionHeaderOld->Name);
printf("********************VirtualAddress的值为:%x***********n", pPESectionHeaderOld->VirtualAddress + (DWORD)pImageBuffer);
printf("n");
//如果没有遍历到最后一个节区位置时
if (!(count == sectionNumber))
{
//取得后一个节区的地址
pPESectionHeaderNew = (PIMAGE_SECTION_HEADER)((DWORD)pPESectionHeaderOld + sizeof(_IMAGE_SECTION_HEADER));
DWORD VirtualAddressNew = pPESectionHeaderNew->VirtualAddress;
//如果是第一个节表 RVA值小于第一个节的位置 那么RVA是无效的 不在节区
if ((count==1) && (pRVA < (pPESectionHeaderOld->VirtualAddress + (DWORD)pImageBuffer)))
{
printf("该值不在节区,在节区之前n");
break;
}//如果不是第一个节表 那么用RVA的值和当前遍历的节地址 和后一个节地址比较 是否在其中 如果在 得到当前的count值
else if (pRVA > (pPESectionHeaderOld->VirtualAddress + (DWORD)pImageBuffer) && pRVA < (VirtualAddressNew+(DWORD)pImageBuffer))
{
offset = (pRVA - (pPESectionHeaderOld->VirtualAddress + (DWORD)pImageBuffer));
printf("找到了! pRVA:%x 在第%d节区中!n",pRVA,count);
break;
}
}//当节表遍历到最后一个时 肯定就是当前count的值 还需判断是否超出内存区
else if (pRVA > ((DWORD)pImageBuffer+sizeOfImage))
{
printf("该值已经远远超出内存中分配地址 请检查是否有误!n");
break;
}
else
{
offset = (pRVA - (pPESectionHeaderOld->VirtualAddress + (DWORD)pImageBuffer));
printf("找到了! pRVA:%x 在第%d节区中!n", pRVA, count);
break;
}
pPESectionHeaderOld = (PIMAGE_SECTION_HEADER)((DWORD)pPESectionHeaderOld + sizeof(_IMAGE_SECTION_HEADER));
}
//已经得到该地址所在的节区
//找到对应节表 得到改节表的PointerToRawData
PIMAGE_SECTION_HEADER pPESectionHeaderSeek = pPESectionHeader;
pPESectionHeaderSeek = (PIMAGE_SECTION_HEADER)((DWORD)pPESectionHeaderSeek + (count-1)*sizeof(_IMAGE_SECTION_HEADER));
printf("%Xn", (pPESectionHeaderSeek->PointerToRawData)+offset);
printf("%Xn", offset);
return (pPESectionHeaderSeek->PointerToRawData) + offset;
}
//传入fileBuffer空间地址 转换imageBuffer 并返回其首地址
LPSTR fileBuffertoImageBuffer(LPSTR pfileBuffer) {
LPSTR imageBuffer = NULL;
//首先需获取开辟内存空间大小 其值存于可选PE头的SizeOfImage中
//解析可选PE头 得到镜像流大小
PIMAGE_OPTIONAL_HEADER32 pPEOptionHeader = parsePEOptionHeader(pfileBuffer);
DWORD imageSize = pPEOptionHeader->SizeOfImage;
//开辟内存空间
imageBuffer = allotspace(imageSize);
DWORD headerSize = pPEOptionHeader->SizeOfHeaders;
//内存拷贝函数 将pfileBuffer指向的地址的内存拷贝headerSize个字节到imageBuffer指向的内存中去
memcpy(imageBuffer,pfileBuffer,headerSize);
PIMAGE_SECTION_HEADER pPESectionHeader = parsePESectionHeader(pfileBuffer);
//调用函数得到节表数
int sectionNumber = getSectionNumber(parsePEStandarHeader(pfileBuffer));
for (int count = 0; count < sectionNumber;count++) {
//将该节表中的Misc内VirtualSize的值取出 即是该节区的真正的数据宽度
//DWORD VirtualSize = *((DWORD*)((DWORD)pPESectionHeader + 8));
//将文件流拷入镜像流 需要节区在文件中的偏移和在内存中的偏移
//从(pfileBuffer+pPESectionHeader->PointerToRawData)开始拷贝,拷贝VirtualSize个字节到(imageBuffer+pPESectionHeader->VirtualAddress)
memcpy((imageBuffer + (DWORD)(pPESectionHeader->VirtualAddress)), (pfileBuffer + (DWORD)(pPESectionHeader->PointerToRawData)), pPESectionHeader->SizeOfRawData);
pPESectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pPESectionHeader + sizeof(_IMAGE_SECTION_HEADER));
}
//返回文件镜像流地址
return imageBuffer;
}
//解析PE头函数 打印输出信息
int parsePEHead(LPSTR pFileBuffer) {
PIMAGE_DOS_HEADER pDosHeader = NULL; //结构体指针类型 DOS头结构大小
PIMAGE_NT_HEADERS pNTHeader = NULL;//结构体指针类型 NT头结构大小
PIMAGE_FILE_HEADER pPEStandarHeader = NULL; //标准PE头结构指针类型
PIMAGE_OPTIONAL_HEADER32 pPEOptionHeader = NULL; //可选PE头结构指针类型
PIMAGE_SECTION_HEADER pPESectionHeader = NULL; //节表结构指针类型
pDosHeader = parsePEDosHeader(pFileBuffer);
pNTHeader = parsePENTHeader(pFileBuffer);
pPEStandarHeader = parsePEStandarHeader(pFileBuffer);
pPEOptionHeader =parsePEOptionHeader(pFileBuffer);
pPESectionHeader = parsePESectionHeader(pFileBuffer);
//打印PE头数据
displayPEHeader(pDosHeader);
displayPEHeader(pPEStandarHeader);
displayPEHeader(pPEOptionHeader);
displayPEHeader(pPESectionHeader,getSectionNumber(pPEStandarHeader));
return 0;
}
//传入文件流地址 成功返回DOS头地址 失败返回0
PIMAGE_DOS_HEADER parsePEDosHeader(LPSTR pfileBuffer)
{
PIMAGE_DOS_HEADER pPEDosHeader =(PIMAGE_DOS_HEADER)pfileBuffer; //将fileBuffer首地址强转赋值给pDosHeader
//IMAGE_DOS_SIGNATURE int类型 常量值:5A4D MC标记,用于判读是否属于可执行文件
//if (!(*((PWORD)pDosHeader) == IMAGE_DOS_SIGNATURE)) { //PWORD WORD*类型
if (!(pPEDosHeader->e_magic == IMAGE_DOS_SIGNATURE)) {
printf("此文件不是可执行文件,请检查!");
return 0;
}
return pPEDosHeader;
}
//传入文件流地址 成功返回NT头地址 失败返回0
PIMAGE_NT_HEADERS parsePENTHeader(LPSTR pfileBuffer)
{
//通过得到DOS头的内的e_lfanew的值得到NT头的首地址
//pNTHeader = (PIMAGE_NT_HEADERS)(pFileBuffer + pDosHeader->e_lfanew);
PIMAGE_NT_HEADERS pPENTHeader = (PIMAGE_NT_HEADERS)((DWORD)parsePEDosHeader(pfileBuffer)+parsePEDosHeader(pfileBuffer)->e_lfanew);
if (!(pPENTHeader->Signature == IMAGE_NT_SIGNATURE)) //判断Signature值是否为PE标记 IMAGE_NT_SIGNATURE常量值 0x00004550 PE00
{
printf("PE标识错误!!!请检查n");
return 0;
}
return pPENTHeader;
}
//传入文件流地址 成功返回标准PE头地址
PIMAGE_FILE_HEADER parsePEStandarHeader(LPSTR pfileBuffer)
{
//标准PE头的地址 = PE标识4字节 +DOS头内的e_lfanew值
return (PIMAGE_FILE_HEADER)((DWORD)parsePENTHeader(pfileBuffer) + 4);
}
//传入文件流地址 成功返回可选PE头地址
PIMAGE_OPTIONAL_HEADER32 parsePEOptionHeader(LPSTR pfileBuffer)
{
//可选PE头的地址为标准PE头地址加上自身大小即为可选PE头的地址
return (PIMAGE_OPTIONAL_HEADER32)((DWORD)parsePEStandarHeader(pfileBuffer) + sizeof(_IMAGE_FILE_HEADER));
}
//传入文件流地址 成功返回可选节表头地址
PIMAGE_SECTION_HEADER parsePESectionHeader(LPSTR pfileBuffer)
{
//节表位置 = DOS头+PE标识+标准PE大小+可选PE大小
//也可 = 指向可选PE头指针 + 可选PE结构大小
//可选PE头大小又存在标准PE头的SizeOfOptionheader值中
return (PIMAGE_SECTION_HEADER)((DWORD)parsePEOptionHeader(pfileBuffer) + parsePEStandarHeader(pfileBuffer)->SizeOfOptionalHeader);
}
//返回节表个数 传入标准PE头地址
int getSectionNumber(PIMAGE_FILE_HEADER pPEStandarHeader) {
return pPEStandarHeader->NumberOfSections;
}
//传入dos头地址 打印DOS头信息函数
void displayPEHeader(PIMAGE_DOS_HEADER pPEDosHeader)
{
printf("********************DOS头解析********************n");
printf("********************e_magic的值为:%x***********n", pPEDosHeader->e_magic);
printf("********************e_lfanew的值为:%x***********n", pPEDosHeader->e_lfanew);
printf("********************DOS头解析完成****************n");
printf("n");
}
//传入标准头地址 打印标准头信息函数
void displayPEHeader(PIMAGE_FILE_HEADER pPEStandarHeader)
{
printf("********************标准PE头解析** ******************n");
printf("********************Machine的值为:%x***********n", pPEStandarHeader->Machine);
printf("***********NumberOfSections的值为:%x***********n", pPEStandarHeader->NumberOfSections);
printf("***********TimeDateStamp的值为:%x**********n", pPEStandarHeader->TimeDateStamp);
printf("***********Characteristics的值为:%x*********n", pPEStandarHeader->Characteristics);
printf("***********SizeOfOptionalHeader的值为:%x*********n", pPEStandarHeader->SizeOfOptionalHeader);
printf("n");
}
//传入可选PE头地址 打印可选PE头信息函数
void displayPEHeader(PIMAGE_OPTIONAL_HEADER32 pPEOptionHeader)
{
printf("********************可选PE头解析********************n");
printf("********************Magic的值为:%x***********n", pPEOptionHeader->Magic);
printf("***********SizeOfCode的值为:%x***********n", pPEOptionHeader->SizeOfCode);
printf("***********SizeOfInitializedData的值为:%x**********n", pPEOptionHeader->SizeOfInitializedData);
printf("***********SizeOfUninitializedData的值为:%x*********n", pPEOptionHeader->SizeOfUninitializedData);
printf("***********AddressOfEntryPoint的值为:%x*********n", pPEOptionHeader->AddressOfEntryPoint);
printf("***********BaseOfCode的值为:%x*********n", pPEOptionHeader->BaseOfCode);
printf("***********BaseOfData的值为:%x*********n", pPEOptionHeader->BaseOfData);
printf("***********ImageBase的值为:%x*********n", pPEOptionHeader->ImageBase);
printf("***********SectionAlignment的值为:%x*********n", pPEOptionHeader->SectionAlignment);
printf("***********FileAlignment的值为:%x*********n", pPEOptionHeader->FileAlignment);
printf("***********SizeOfImage的值为:%x*********n", pPEOptionHeader->SizeOfImage);
printf("***********SizeOfHeaders的值为:%x*********n", pPEOptionHeader->SizeOfHeaders);
printf("n");
}
//传入节表地址和节表数量 打印节表信息函数
void displayPEHeader(PIMAGE_SECTION_HEADER pPESectionHeader,int sectionNumber)
{
for (int count = 0; count < sectionNumber; count++) {
printf("********************第%d个节表********************n", count + 1);
printf("********************Name的值为:%s***********n", pPESectionHeader->Name);
printf("********************Misc的值为:%x***********n", pPESectionHeader->Misc);
printf("********************转换Misc的值为:%x***********n", (*(DWORD*)((DWORD)pPESectionHeader + 8)));
printf("********************VirtualAddress的值为:%x***********n", pPESectionHeader->VirtualAddress);
printf("********************SizeOfRawData的值为:%x***********n", pPESectionHeader->SizeOfRawData);
printf("********************PointerToRawData的值为:%x***********n", pPESectionHeader->PointerToRawData);
printf("********************Characteristics的值为:%x***********n", pPESectionHeader->Characteristics);
printf("n");
pPESectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pPESectionHeader + sizeof(_IMAGE_SECTION_HEADER));
}
}
安卓接受后台数据转换解析出错_滴水三期 fileBuffer->imageBuffer 并还原写出文件 以及RVA转换成FOA...
最新推荐文章于 2022-06-24 17:37:29 发布