吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 3451|回复: 26
收起左侧

[分享] PE结构代码

  [复制链接]
Huanghousec 发表于 2022-6-2 15:11
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[4];         //00 00 00 00 00 00 00 00 
WORD   e_oemid;           //0000
WORD   e_oeminfo;         //0000
WORD   e_res2[10];        //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[IMAGE_SIZEOF_SHORT_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);
        return  ptr;
}

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[IMAGE_DIRECTORY_ENTRY_EXPORT].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[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress));

//        printf("DIRECTORY_ENTRY_EXPORT VirtualAddress:%x\n", POptionHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
//        printf("FOA:%x\n", convertRVAtoFOA(dllbuffer, POptionHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].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[i]);
        }
        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[j]);
                }
                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
感激不尽!

免费评分

参与人数 13吾爱币 +15 热心值 +10 收起 理由
manyou + 1 + 1 谢谢@Thanks!
s_xiaoli + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
jolly_800 + 1 谢谢@Thanks!
ghimi + 1 我很赞同!
Tonyha7 + 1 用心讨论,共获提升!
笙若 + 1 + 1 谢谢@Thanks!
lingyun011 + 1 + 1 用心讨论,共获提升!
zhczf + 1 我很赞同!
默默看着你 + 1 + 1 我很赞同!
xyz2000cn007 + 1 + 1 我很赞同!
Hmily + 5 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
chinasmu + 1 + 1 大佬教我渗-透啊
untest001 + 1 + 1 流啤

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| Huanghousec 发表于 2022-6-2 18:44
writeMemorytoFile2这个函数只是读入内存再读出来,所以是没什么区别的,但是newbuffer那一块我加入了shellcode,那段shellcode是扣的message的代码。所以是不一样的大小的。messagebox的入口是在xp上寻的。如果需要在64上运行,需要重新计算。我现在在回家的路上,需要讲解的话您私聊我,我到家了再讲给你听
addon007 发表于 2022-6-2 15:21
email123 发表于 2022-6-2 16:01
试了一下,输出的ipmsg_Imagebuffer.exe和原文件不一样啊
xtkj 发表于 2022-6-2 16:25
学习了。
 楼主| Huanghousec 发表于 2022-6-2 16:43
email123 发表于 2022-6-2 16:01
试了一下,输出的ipmsg_Imagebuffer.exe和原文件不一样啊

主函数的filepath那里路径改一下就好了,我那里读的是一个dll,用来测导出表的
 楼主| Huanghousec 发表于 2022-6-2 16:45
email123 发表于 2022-6-2 16:01
试了一下,输出的ipmsg_Imagebuffer.exe和原文件不一样啊

[C++] 纯文本查看 复制代码
char filepath[] = "c:\\ipmsg.exe"
ymnj11 发表于 2022-6-2 17:47
学习了,感谢大佬分享。
email123 发表于 2022-6-2 18:31

C:\ant_1.3.4\1.pngiTOTALCM.EXE是原文件,按说写出来的文件应该一样大小,但实际上不一样
1.png
 楼主| Huanghousec 发表于 2022-6-2 18:49
email123 发表于 2022-6-2 18:31
iTOTALCM.EXE是原文件,按说写出来的文件应该一样大小,但实际上不一样

不急的话回去给你调试,我现在在回家的路上,您私聊我就好了
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-5-13 22:09

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表