PE结构代码
2015年注册的吾爱,这8年一直在做渗透,因为特殊的工作性质,没有在吾爱发过技术贴,对论坛也没有什么贡献,感谢H大提供的平台,我在这里找到了很多技术资料。感觉渗透做累了~没有一点提高这8年,最近打算转逆向,望各位师兄们能够多多指导我这个菜鸡
最近在打基础,学习了一段时间PE,在这里分享一下我的笔记:
PE结构图
```
1、DOS头(64byte)
WORD e_magic; * //5A4D //重要,DOS头的开始MZ(MZ是一个人名,DOS的开发)
WORD e_cblp; //0090
WORD e_cp; //0003
WORD e_crlc; //0000
WORD e_cparhdr; //0004
WORD e_minalloc; //0000
WORD e_maxalloc; //FFFF
WORD e_ss; //0000
WORD e_sp; //00B8
WORD e_csum; //0000
WORD e_ip; //0000
WORD e_cs; //0000
WORD e_lfarlc; //0040
WORD e_ovno; //0000
WORD e_res; //00 00 00 00 00 00 00 00
WORD e_oemid; //0000
WORD e_oeminfo; //0000
WORD e_res2; //20 0
DWORD e_lfanew;* //00 00 00 D8 //重要,指向PE头开始的偏移位置
2、PE头->>(_IMAGE_FILE_HEADER FileHeader)(_IMAGE_OPTIONAL_HEADER OptionalHeader):
DWORD Signature; //00 00 45 50
3、_IMAGE_FILE_HEADER FileHeader: //共20个byte
WORD Machine; //014C * //程序运行的CPU型号,1、0x0能在任何处理器运行 2、0x14c 可以在386及后续处理器运行
WORD NumberOfSections; //0003 * //文件中存在的节(除了PE头(可选头和标准头就是NT)以外的节)的总数,如果要新增一个节那么就需要修改这个值
DWORD TimeDateStamp; //6264 D913 *
DWORD PointerToSymbolTable; //0000 0000
DWORD NumberOfSymbols; //0000 0000
WORD SizeOfOptionalHeader; //00E0 * //option_header pe头的大小,如果是32位的话默认是E0h,64位默认的是F0h,大小可以自定义
WORD Characteristics; //010F * //每个位有不同的含义,可执行文件值为10F,即0 1 2 3 8位置1
4、_IMAGE_OPTIONAL_HEADER OptionalHeader:
WORD Magic; //010B * //说明文件类型,如果是32位则是10B,如果是64位则是20B
BYTE MajorLinkerVersion; //06
BYTE MinorLinkerVersion; //00
DWORD SizeOfCode; //0000 4000 //所有代码节的和,必须是FileAlignment的整数倍 编译器填的 没用(不影响PE文件运行)
DWORD SizeOfInitializedData; //0000 3000 *
DWORD SizeOfUninitializedData;//0000 0000 *
DWORD AddressOfEntryPoint; //0000 1041 * //重要,程序的入口点(OEP) 比如OD加载程序的时候,停的入口点即是Imagebase+AddressOfEntryPoint 的地址
DWORD BaseOfCode; //0000 1000 * //代码段的基址,没有用
DWORD BaseOfData; //0000 0050 * //数据开始的基址,没有用
DWORD ImageBase; //0040 0000 * //重要,内存镜像地址
DWORD SectionAlignment; //0000 0010 * //内存对齐
DWORD FileAlignment; //0000 0010 * //文件对齐
WORD MajorOperatingSystemVersion; //0040
WORD MinorOperatingSystemVersion; //0000
WORD MajorImageVersion; //0000
WORD MinorImageVersion; //0000
WORD MajorSubsystemVersion; //0004
WORD MinorSubsystemVersion; //0000
DWORD Win32VersionValue; //0000 0000
DWORD SizeOfImage; //0001 A000 * //内存中映像(拉伸后(peloader))的大小,可以比实际的值大,但必须是内存对齐的整数倍
DWORD SizeOfHeaders; //0000 1000 * //所有头+节表对齐后的大小,否则加载会出错
DWORD CheckSum; //0000 0000 * //效验和(把一个PE文件按照2个字节循环加,加完的值存到checksum里面),判断文件是否被修改
WORD Subsystem; //0003
WORD DllCharacteristics; //0000
DWORD SizeOfStackReserve; //0010 0000 *
DWORD SizeOfStackCommit; //0010 0000 *
DWORD SizeOfHeapReserve; //0010 0000 *
DWORD SizeOfHeapCommit; //0010 0000 *
DWORD LoaderFlags; //0000 0000
DWORD NumberOfRvaAndSizes; //0000 0010 //目录项数据,编译器用的
```
2、节表
```
BYTE Name; // 8个字节的节区名称
union {
DWORD PhysicalAddress;DWORD VirtualSize;}Misc; //节区真实共有多少个字节,VirtualSize 节真正长度即节结束的偏移
DWORD VirtualAddress; // 从imagebase开始,离imagebase有多远。节的偏移地址,真实节地址为Imagebase+VirtualAddress
DWORD SizeOfRawData; // 节在文件中对齐后的尺寸(当前节在文件中对齐的大小是132h,如果文件对齐是200,那么就是200h。如果是1000h,那么对齐后的尺寸就是1000h。1000的整数倍)
DWORD PointerToRawData; // 在文件中的偏移量(在文件中的起始位置)
DWORD PointerToRelocations;
DWORD PointerToLinenumbers;
WORD NumberOfRelocations;
WORD NumberOfLinenumbers;
DWORD Characteristics; // 节属性如可读,可写,可执行等
```
以上是PE结构参考,下面是用c实现的代码,按照海哥讲的基础分为几个功能模块:读取PE结构,在代码空白区添加节,导入表读取,filebuffer to imagebuffer以及imagebuffer to newbuffer(部分实现参考网上的师哥,其中导出表部分还未完善。64.h是封装的函数体部分。
```
#include"stdafx.h"
#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
#include"64.h"
//#define file_path "c:\\windows\\system32\\notepad.exe"
//open the file and get the files size
/*void Function()
{
printf("Hello\n");
}
*/
int main()
{
// LPVOID PFilebuffer = NULL;
// LPVOID* ptr = &PFilebuffer;
LPSTR PNewImagebuffer =NULL;
char filepath[] = "c:\\dynamic.dll";
char memoryfiletopath[] = "c:\\ipmsg_memory.exe";
char Imagefiletopath[] = "c:\\ipmsg_Imagebuffer.exe";
char opmode[] = "ab+";
FILE* fp = openfile(filepath,opmode);
int size = calcutesize(fp);
char* file_address = allocate_buffer(size);
char* buffer = filebuffer(file_address,size,fp);
WriteMemorytoFile(memoryfiletopath,"wb+",buffer,size);
// ReadPefileDos(buffer); //reade pe
//ilebuffertoImagebuffer(buffer,PPImagebuffer);
//magebuffertoFilebuffer(PPImagebuffer,buffer);
// ImagebuffertoNewbuffer(buffer,PNewImagebuffer);
int SizeOfFileBuffer = size;
LPSTR ImageBuffer = FileBuffertoImageBuffer(buffer);
LPSTR PNewBuffer = ImageBuffertoNewBuffer(ImageBuffer,size);
LPSTR PImageBuffer = ShellCode(SizeOfFileBuffer,ImageBuffer);
writeMemorytoFile2(Imagefiletopath,PNewBuffer,size);
// AddNewSection(buffer);
GetFuncFileAddressOfDll(ImageBuffer);
// GetFunctionAddrByName(ImageBuffer);
//ReadPefileDos(buffer);
// DWORD pRVA =NULL;
// convertRVAtoFOA(pRVA,ImageBuffer);
// Function();
// MessageBox(0,"0",0,0);
return 0;
}
//64.h
#define MESSAGEBOXADDR 0x77D507EA //这个值需要将任一exe文件拖入OD打开,搜索 MessageBoxA 记录它的地址到这里(不同机子的地址不一样)
/*unsigned char ShellCodeData[] =
{
0x6A,0x00,0x6A,0x00,0x6A,0x00,0x6A,0x00,//这行是push 四个0 作为 MessageBox 的参数
0xE8,0x00,0x00,0x00,0x00,
0xE9,0x00,0x00,0x00,0x00
};
*/
unsigned char ShellCodeData[] =
{
0x6A,0x00,0x6A,0x00,0x6A,0x00,0x6A,0x00,//这行是push 四个0 作为 MessageBox 的参数
0xE8,0x00,0x00,0x00,0x00,
0xE9,0x00,0x00,0x00,0x00
};
FILE* openfile(char* file_path,char*opmode);
int calcutesize(FILE* fp);
char* allocate_buffer(int size_t);
char* filebuffer(char* ptr,int size,FILE* fp);
int WriteMemorytoFile(char* file_path,char*opmode,char* buffer,int size);
LPSTR FileBuffertoImageBuffer(LPSTR pfilebuffer);
LPSTR ImageBuffertoNewBuffer(LPSTR pfileBuffer,int NewBufferSize);
DWORD convertRVAtoFOA(PVOID pImageBuffer,DWORD pRVA);
DWORD GetFuncFileAddressOfDll(char* dllbuffer);
FILE* openfile(char* file_path,char*opmode)
{
// char file_path[]="c:\\windows\\system32\\notepad.exe";
FILE* fp=fopen(file_path,opmode);
if(!fp)
{
printf("open file failed!\n");
exit(1);
}
else
{
printf("open file OK!,start load files to memory...\n");
}
return fp;
}
int calcutesize(FILE* fp)
{
fseek(fp,0,SEEK_END);
int size = ftell(fp);
printf("start calculate the file size is : %d\n",size);
fseek(fp,0,SEEK_SET);
return size;
}
char* allocate_buffer(int size_t)
{
//load files to memory,read memory address
char* ptr=(char*)malloc(size_t);
if(!ptr)
{
printf("malloc the memory failed!");
exit(1);
}
else
{
printf("malloc the memory ok!\n");
}
return ptr;
}
char* filebuffer(char* ptr,int size,FILE* fp)
{
if(!(fread(ptr,size,1,fp)))
{
printf("fread files to filebuffer failed!\n");
exit(1);
}
else
{
printf("fread files to filebuffer ok!\n");
}
printf("the filebuffer address is : %x\n",ptr);
returnptr;
}
int WriteMemorytoFile(char* file_path,char*opmode,char* buffer,int size)
{
FILE* fp = fopen(file_path, opmode);
if (!(fwrite(buffer, 1, size, fp))) {
printf("memory write to file failed!\n");
return 0;
}else
{
printf("write to file ok!\n");
}
return 1;
}
LPSTR FileBuffertoImageBuffer(LPSTR pfilebuffer)
{
// char* ImageBuffer = pfilebuffer;
// LPSTR imagebuffer = NULL;
PIMAGE_DOS_HEADER pdos= NULL;
PIMAGE_NT_HEADERS pNTHeader = NULL;
PIMAGE_FILE_HEADER PPeHeader = NULL;
PIMAGE_OPTIONAL_HEADER32 POptionHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
pdos = (PIMAGE_DOS_HEADER)pfilebuffer;
pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pdos+pdos->e_lfanew);
PPeHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader+4);
POptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)PPeHeader+IMAGE_SIZEOF_FILE_HEADER);//nt IS 20 BYTE
pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)POptionHeader+PPeHeader->SizeOfOptionalHeader);
DWORD numbofsections = PPeHeader->NumberOfSections;
DWORD headerSize = POptionHeader->SizeOfHeaders;
// memcpy(PNewImagebuffer, pfileBuffer, headerSize);
DWORD ImageSize = POptionHeader->SizeOfImage;
// DWORD headerSize = POptionHeader->SizeOfHeaders;
char* ImageBuffer = pfilebuffer;
// memcpy(ImageBuffer,pfileBuffer,ImageSize);
ImageBuffer = (char*)malloc(POptionHeader->SizeOfImage);
memset(ImageBuffer,0,POptionHeader->SizeOfImage);
memcpy(ImageBuffer,pdos,POptionHeader->SizeOfHeaders);
for(DWORD i=0;i<numbofsections;i++,pSectionHeader++)
{
memcpy(LPVOID((DWORD)ImageBuffer+pSectionHeader->VirtualAddress),LPVOID((DWORD)pdos+pSectionHeader->PointerToRawData),pSectionHeader->SizeOfRawData);
}
printf("ImageBuffer address is : %x\n",ImageBuffer);
// return (LPSTR)POptionHeader->SizeOfImage;
return ImageBuffer;
}
LPSTR ImageBuffertoNewBuffer(LPSTR pfileBuffer,int NewBufferSize)
{
LPSTR pNewBuffer = NULL;
PIMAGE_DOS_HEADER pdos= NULL;
PIMAGE_NT_HEADERS pNTHeader = NULL;
PIMAGE_FILE_HEADER PPeHeader = NULL;
PIMAGE_OPTIONAL_HEADER32 POptionHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
pdos = (PIMAGE_DOS_HEADER)pfileBuffer;
pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pdos+pdos->e_lfanew);
PPeHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader+4);
POptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)PPeHeader+IMAGE_SIZEOF_FILE_HEADER);//nt IS 20 BYTE
pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)POptionHeader+PPeHeader->SizeOfOptionalHeader);
DWORD numbofsections = PPeHeader->NumberOfSections;
// pNewBuffer= (char*)malloc(NewBufferSize);
pNewBuffer= pfileBuffer;
// DWORD headerSize = POptionHeader->SizeOfHeaders;
//**********************************************************
//void *memcpy(void *str1, const void *str2, size_t n)
//str1 -- 目标数组
//str2 -- 要复制的数据源
//n -- 要被复制的字节数
//**********************************************************
// memcpy(pNewBuffer, pdos, headerSize);
memcpy(pNewBuffer,pdos,POptionHeader->SizeOfHeaders);
for(DWORD i=0;i<numbofsections;i++,pSectionHeader++)
{
// printf(".......the %d Sections Name.........\n",i+1);
memcpy((pNewBuffer + (DWORD)(pSectionHeader->PointerToRawData)), (pNewBuffer + (DWORD)(pSectionHeader->VirtualAddress)),pSectionHeader->SizeOfRawData);
// pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pSectionHeader + sizeof(_IMAGE_SECTION_HEADER));
}
printf("pNewBuffer address is : %x\n",pNewBuffer);
return pNewBuffer;
}
DWORD convertRVAtoFOA(PVOID pImageBuffer,DWORD pRVA)
{
PIMAGE_DOS_HEADER pdos= NULL;
PIMAGE_NT_HEADERS pNTHeader = NULL;
PIMAGE_FILE_HEADER PPeHeader = NULL;
PIMAGE_OPTIONAL_HEADER32 POptionHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
pdos = (PIMAGE_DOS_HEADER)pImageBuffer;
pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pdos+pdos->e_lfanew);
PPeHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader+4);
POptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)PPeHeader+IMAGE_SIZEOF_FILE_HEADER);//nt IS 20 BYTE
pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)POptionHeader+PPeHeader->SizeOfOptionalHeader);
DWORD numbofsections = PPeHeader->NumberOfSections;
int image_panyi = pRVA;// pRVA是在内存中的偏移偏移
// printf("VirtulAddress : %x\n",(DWORD)pSectionHeader->VirtualAddress);
// printf("image_panyi:%#x\n",image_panyi);
// 循环查找在那个imagebuffer节中
PIMAGE_SECTION_HEADER pTempSectionHeader = pSectionHeader;
for(DWORD i = 0;i<PPeHeader->NumberOfSections;i++,pTempSectionHeader++)
{ //判断 :Misc.VirtualSize+ VirtualAddress 内存偏移+节数据没对齐的大小>image_panyi>内存偏移 VirtualAddress (即是在文件的哪个节中)
if(((DWORD)image_panyi>=(DWORD)pTempSectionHeader->VirtualAddress) && ((DWORD)image_panyi<pTempSectionHeader->VirtualAddress+pTempSectionHeader->Misc.VirtualSize))
{
return image_panyi-pTempSectionHeader->VirtualAddress+pTempSectionHeader->PointerToRawData;
}
}
return 0;
}
DWORD GetFunctionAddrByName(char* dllbuffer)
{
PIMAGE_DOS_HEADER pdos= NULL;
PIMAGE_NT_HEADERS pNTHeader = NULL;
PIMAGE_FILE_HEADER PPeHeader = NULL;
PIMAGE_OPTIONAL_HEADER32 POptionHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
PIMAGE_EXPORT_DIRECTORY pExportDirectory = NULL;
DWORD nameFOA = NULL;
DWORD AddressOfNamesFOA = NULL;
DWORD AddressOfNameOrdinalsFOA = NULL;
DWORD AddressOfFunctionsFOA = NULL;
DWORD AddressOfFunctions = NULL;
WORD Ordinal = NULL;
char* name = NULL;
pdos = (PIMAGE_DOS_HEADER)dllbuffer;
pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pdos+pdos->e_lfanew);
PPeHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader+4);
POptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)PPeHeader+IMAGE_SIZEOF_FILE_HEADER);//nt IS 20 BYTE
pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)POptionHeader+PPeHeader->SizeOfOptionalHeader);
DWORD numbofsections = PPeHeader->NumberOfSections;
pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((DWORD)dllbuffer + convertRVAtoFOA(dllbuffer, POptionHeader->DataDirectory.VirtualAddress));
AddressOfFunctionsFOA = convertRVAtoFOA(dllbuffer, pExportDirectory->AddressOfFunctions);
AddressOfNamesFOA = convertRVAtoFOA(dllbuffer,pExportDirectory->AddressOfNames);
for(DWORD k = 0; k < (DWORD)pExportDirectory->NumberOfFunctions; k++)
{
//因Address表元素为4字节,绝对地址加上k*4直接取第k个元素
AddressOfFunctions = *(PDWORD)((DWORD)dllbuffer + AddressOfFunctionsFOA + k*4);
printf("%x\n",AddressOfFunctions);
}
for (DWORD i = 0; i < (DWORD)pExportDirectory->NumberOfNames; i++)
{
printf("*******函数名称表*******\n");
//AddressOfNamesFOA只是Names表的FOA地址,需加上pFileBuffer构成的绝对地址才能取出其中的值。
//取出的值即Names地址表第i个name的Rva地址,转成FOA得到name的FOA地址
nameFOA = convertRVAtoFOA(dllbuffer,*(PDWORD)(AddressOfNamesFOA+(DWORD)dllbuffer));
name = (char*)(nameFOA + (DWORD)dllbuffer);
printf("%s\n",name);
AddressOfNamesFOA = AddressOfNamesFOA + 4;
}
return 0;
}
DWORD GetFuncFileAddressOfDll(char* dllbuffer)
{
PIMAGE_DOS_HEADER pdos= NULL;
PIMAGE_NT_HEADERS pNTHeader = NULL;
PIMAGE_FILE_HEADER PPeHeader = NULL;
PIMAGE_OPTIONAL_HEADER32 POptionHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
PIMAGE_EXPORT_DIRECTORY pExportDirectory = NULL;
DWORD nameFOA = NULL;
DWORD AddressOfNamesFOA = NULL;
DWORD AddressOfNameOrdinalsFOA = NULL;
DWORD AddressOfFunctionsFOA = NULL;
DWORD AddressOfFunctions = NULL;
WORD Ordinal = NULL;
char * name = NULL;
pdos = (PIMAGE_DOS_HEADER)dllbuffer;
pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pdos+pdos->e_lfanew);
PPeHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader+4);
POptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)PPeHeader+IMAGE_SIZEOF_FILE_HEADER);//nt IS 20 BYTE
pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)POptionHeader+PPeHeader->SizeOfOptionalHeader);
DWORD numbofsections = PPeHeader->NumberOfSections;
pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((DWORD)dllbuffer + convertRVAtoFOA(dllbuffer, POptionHeader->DataDirectory.VirtualAddress));
// printf("DIRECTORY_ENTRY_EXPORT VirtualAddress:%x\n", POptionHeader->DataDirectory.VirtualAddress);
// printf("FOA:%x\n", convertRVAtoFOA(dllbuffer, POptionHeader->DataDirectory.VirtualAddress));
// printf("导出表文件名字符串Name:%x\n", pExportDirectory->Name);
// printf("导出函数起始序号Base:%d\n", pExportDirectory->Base);
// printf("导出函数的个数:%d\n", pExportDirectory->NumberOfFunctions);
// printf("以函数名字导出的函数个数NumberOfNames:%d\n", pExportDirectory->NumberOfNames);
printf("*******函数地址表*******\n");
AddressOfFunctionsFOA = convertRVAtoFOA(dllbuffer, pExportDirectory->AddressOfFunctions);
// printf("导出函数RVA:%x\n", AddressOfFunctionsFOA);
for (DWORD i = 0; i < (DWORD)pExportDirectory->NumberOfFunctions; i++)
{
AddressOfFunctions = *(PDWORD)((DWORD)dllbuffer + AddressOfFunctionsFOA + i * 4);//因Address表元素为4字节,绝对地址加上i*4直接取第i个元素
printf("下标:%d,函数地址:%x\n", i, AddressOfFunctions);
}
printf("*******函数名称表*******\n");
//导出表中的AddressOfNames为Rva,将其转换为FOA得到AddressOfNamesFOA
AddressOfNamesFOA = convertRVAtoFOA(dllbuffer, pExportDirectory->AddressOfNames);
for (DWORD k = 0; k < pExportDirectory->NumberOfNames; k++)
{ //AddressOfNamesFOA只是Names表的FOA地址,需加上pFileBuffer构成的绝对地址才能取出其中的值。
//取出的值即Names地址表第i个name的Rva地址,转成FOA得到name的FOA地址
nameFOA = convertRVAtoFOA(dllbuffer, *(PDWORD)((DWORD)dllbuffer + AddressOfNamesFOA));
name = (char *)(nameFOA + (DWORD)dllbuffer);//name的FOA加上pFileBuffer构成绝对地址,该地址才真正指向字符串
printf("下标:%d,函数名称:%s\n", k, name);
AddressOfNamesFOA = AddressOfNamesFOA + 4;//往前走4字节,指向Names地址表下一个元素,即下一个name地址
}
printf("*******函数序号表*******\n");
AddressOfNameOrdinalsFOA = convertRVAtoFOA(dllbuffer, pExportDirectory->AddressOfNameOrdinals); //同Names表找法
for (DWORD f = 0; f < pExportDirectory->NumberOfNames; f++)
{
Ordinal = *(WORD*)((DWORD)dllbuffer + AddressOfNameOrdinalsFOA + f * 2); //因为序号表元素为2字节,绝对地址加上f*2直接取第f个元素
printf("下标:%d,函数序号:%d\n", f, Ordinal);
}
// result = (DWORD)GetFunctionAddrByName(dllbuffer, "plus"); //得到的是函数Rva地址
// printf("result:%x\n", result);
// result = (DWORD)GetFunctionAddrByOrdinals(dllbuffer, 2);
// printf("result:%x\n", result);
return 0;
}
/*
DWORD AddNewSection(LPSTR PFilebuffer)
{
PIMAGE_DOS_HEADER pdos= NULL;
PIMAGE_NT_HEADERS pNTHeader = NULL;
PIMAGE_FILE_HEADER PPeHeader = NULL;
PIMAGE_OPTIONAL_HEADER32 POptionHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
PIMAGE_SECTION_HEADER LastpSectionHeader = NULL;
pdos = (PIMAGE_DOS_HEADER)PFilebuffer;
pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)PFilebuffer+pdos->e_lfanew);
PPeHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader+4);
POptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)PPeHeader+IMAGE_SIZEOF_FILE_HEADER);//nt IS 20 BYTE
pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)POptionHeader+PPeHeader->SizeOfOptionalHeader);
DWORD numbofsections = PPeHeader->NumberOfSections;
//判断条件:
// if ((DWORD)pNewSectionHeader + IMAGE_SIZEOF_SECTION_HEADER * 2 <= (DWORD)pFileBuffer + pOptionalHeader->SizeOfHeaders)
for(DWORD i=0;i<numbofsections;i++,pSectionHeader++){
// printf("%d\n",i);
}
LastpSectionHeader = pSectionHeader + 1;
if ((DWORD)LastpSectionHeader + IMAGE_SIZEOF_SECTION_HEADER * 2 <= (DWORD)PFilebuffer + POptionHeader->SizeOfHeaders)
{
printf("SizeofHeaders >= 2个节表的大小,you can add new sectioncode\n");
}
else
{
printf("SizeofHeaders < 2个节表的大小");
}
printf(".........start add new sectioncode.......\n");
//开始构造新节表
strcpy((char*)LastpSectionHeader->Name,(char*)".NewSec");
LastpSectionHeader->Misc.VirtualSize = sizeof(ShellCodeData);
//节区在内存中的偏移 = 内存中整个PE文件映射的大小
LastpSectionHeader->VirtualAddress = POptionHeader->SizeOfImage;
LastpSectionHeader->SizeOfRawData =POptionHeader->SizeOfImage;
LastpSectionHeader->PointerToRawData = (unsigned)PFilebuffer;//pLastSectionHeader->PointerToRawData + pLastSectionHeader->SizeOfRawData;
LastpSectionHeader->PointerToRelocations = 0;
LastpSectionHeader->PointerToLinenumbers = 0;
LastpSectionHeader->NumberOfRelocations = 0;
LastpSectionHeader->NumberOfLinenumbers = 0;
LastpSectionHeader->Characteristics = 0x60000020;
PPeHeader->NumberOfSections++;
}
*/
BOOL writeMemorytoFile2(char* filePath,LPSTR pNewBuffer,int NewBufferSize)
{
FILE* fpw = fopen(filePath, "wb+");
if (fpw == NULL)
{
printf("fpw fopen fail");
return false;
}
if (fwrite(pNewBuffer, 1, NewBufferSize, fpw) == 0)
{
printf("fpw fwrite fail");
return false;
}
fclose(fpw);
fpw = NULL;
printf("success\n");
return true;
}
LPSTR ShellCode(int SizeOfFileBuffer,LPSTR ImageBuffer)
{
PIMAGE_DOS_HEADER pdos= NULL;
PIMAGE_NT_HEADERS pNTHeader = NULL;
PIMAGE_FILE_HEADER PPeHeader = NULL;
PIMAGE_OPTIONAL_HEADER32 POptionHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
DWORD CallX = NULL; //即E8后跟的4字节
DWORD JmpX = NULL; //即E9后跟的4字节
if (!SizeOfFileBuffer) //SizeOfFileBuffer == size
{
printf("文件读取失败\n");
return 0;
}
if(!ImageBuffer)
{
printf("Filebuffer to Imagebuffer failed!\n");
return 0;
}
pdos = (PIMAGE_DOS_HEADER)ImageBuffer;
pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pdos+pdos->e_lfanew);
PPeHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader+4);
POptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)PPeHeader+IMAGE_SIZEOF_FILE_HEADER);//nt IS 20 BYTE
pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)POptionHeader+PPeHeader->SizeOfOptionalHeader);
if ( pSectionHeader->Misc.VirtualSize + sizeof(ShellCodeData) > pSectionHeader->SizeOfRawData)
{
printf("空间不足");
free(ImageBuffer);
return 0;
}else
{
printf("Congratulations,this space can write!\n");
}
//那么要跳转的地址即messageboxA地址。E8所在地址即 ImageBase内存运行基址 + VirtualAddress节所在偏移 + VirtualSize 节真正长度即节结束的偏移 再加上8才到E8
CallX =MESSAGEBOXADDR - ( POptionHeader->ImageBase + pSectionHeader->VirtualAddress + pSectionHeader->Misc.VirtualSize + 8 +5);
//jump 要跳转的地址即OEP程序入口点, X = 程序入口点 - (E9所在地址 + 5)
//这里程序入口点即ImageBase基址 + AddressOfEntryPoint E9所在地址计算同上
JmpX = POptionHeader->ImageBase + POptionHeader->AddressOfEntryPoint - (POptionHeader->ImageBase + pSectionHeader->VirtualAddress + pSectionHeader->Misc.VirtualSize + 13 + 5);
*(PDWORD)(ShellCodeData + 9) = CallX;
*(PDWORD)(ShellCodeData + 14) = JmpX;
for(int i = 0;i<sizeof(ShellCodeData);i++)
{
printf("%x ", ShellCodeData);
}
printf("\n");
memcpy((void*)((DWORD)ImageBuffer + pSectionHeader->PointerToRawData + pSectionHeader->Misc.VirtualSize), ShellCodeData,sizeof(ShellCodeData));
//修改OEP的值
POptionHeader->AddressOfEntryPoint = pSectionHeader->VirtualAddress + pSectionHeader->Misc.VirtualSize;
return ImageBuffer;
}
void ReadPefileDos(char* buffer)
{
PIMAGE_DOS_HEADER pdos= NULL;
PIMAGE_NT_HEADERS pNTHeader = NULL;
PIMAGE_FILE_HEADER PPeHeader = NULL;
PIMAGE_OPTIONAL_HEADER32 POptionHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
pdos = (PIMAGE_DOS_HEADER)buffer;
pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)buffer+pdos->e_lfanew);
PPeHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader+4);
POptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)PPeHeader+IMAGE_SIZEOF_FILE_HEADER);//nt IS 20 BYTE
pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)POptionHeader+PPeHeader->SizeOfOptionalHeader);
DWORD numbofsections = PPeHeader->NumberOfSections;
printf("..........................................\n");
printf("e_magic\t\t\t%04x\n",pdos->e_magic);
printf("e_lfanew\t\t%08x\n",pdos->e_lfanew);
printf("..........................................\n");
printf("Signature\t\t%08x\n",pNTHeader->Signature);
printf("Machine\t\t\t%04x\n",PPeHeader->Machine);
printf("PE NUMBER Sections\t%x\n",PPeHeader->NumberOfSections);
for(DWORD i=0;i<numbofsections;i++,pSectionHeader++)
{
printf(".......the %d Sections Name.........\n",i+1);
for(DWORD j=0;j<IMAGE_SIZEOF_SHORT_NAME;j++)
{
printf("%c",pSectionHeader->Name);
}
printf("\r\n");
printf("Misc:\t\t\t%08x\n",pSectionHeader->Misc);
printf("VirtualAddress:\t\t%08x\n",pSectionHeader->VirtualAddress);
printf("SizeOfRawData:\t\t%08x\n",pSectionHeader->SizeOfRawData);
printf("Characteristics:\t%08x\n",pSectionHeader->Characteristics);
}
}
```
{:1_906:}
各位师兄有李忠x86保护模式的视频,给师弟我发一份。https://pan.baidu.com/disk/main#/transfer/send?surl=AA4AAAAAAA5lZg
感激不尽! writeMemorytoFile2这个函数只是读入内存再读出来,所以是没什么区别的,但是newbuffer那一块我加入了shellcode,那段shellcode是扣的message的代码。所以是不一样的大小的。messagebox的入口是在xp上寻的。如果需要在64上运行,需要重新计算。我现在在回家的路上,需要讲解的话您私聊我,我到家了再讲给你听 大佬牛逼 十年老兵 试了一下,输出的ipmsg_Imagebuffer.exe和原文件不一样啊 学习了。 email123 发表于 2022-6-2 16:01
试了一下,输出的ipmsg_Imagebuffer.exe和原文件不一样啊
主函数的filepath那里路径改一下就好了,我那里读的是一个dll,用来测导出表的 email123 发表于 2022-6-2 16:01
试了一下,输出的ipmsg_Imagebuffer.exe和原文件不一样啊
char filepath[] = "c:\\ipmsg.exe" 学习了,感谢大佬分享。 Huanghousec 发表于 2022-6-2 16:45
C:\ant_1.3.4\1.pngiTOTALCM.EXE是原文件,按说写出来的文件应该一样大小,但实际上不一样 email123 发表于 2022-6-2 18:31
iTOTALCM.EXE是原文件,按说写出来的文件应该一样大小,但实际上不一样
不急的话回去给你调试,我现在在回家的路上,您私聊我就好了