• PE文件入门(一)


    Shellcode直接注入代码块

    使用代码,在文件中将shellcode注入进程序的text节中,也就是代码块中

    条件:代码块有足够的空间存下shellcode

    思路:获取shellcode的注入位置,然后再通过计算把硬编码应该跳转的地址计算出来  其公式为:要跳转的地址=当前指令的下一条指令地址+5+X——>就可以推出X=要跳转的地址-(当前指令的下一条指令地址+5)

    在通过指针将其值修改

    在最后修改OEP,并使shellcode最后跳回原来的程序入口

    #define _CRT_SECURE_NO_WARNINGS
    #include<iostream>
    #include<Windows.h>
    
    
    #define SHELLCODELENGTH        0x12
    BYTE shellCode[] =
    {
        0x6a,00,0x6a,00,0x6a,00,0x6a,00,
        0xe8,00,00,00,00,
        0xe9,00,00,00,00
    };
    
    PVOID FileToFileBuffer(LPSTR lpszFile)
    {
        FILE* file=NULL;
        PVOID FileBuffer=NULL;
        size_t FileOfSize=0;
    
        file = fopen(lpszFile, "rb+");
        if (!file)
        {
            printf("文件打开错误");
            return NULL;
        }
    
        fseek(file, NULL,SEEK_END);
        FileOfSize=ftell(file);
        fseek(file, NULL, SEEK_SET);
    
        FileBuffer = malloc(FileOfSize);
        if (!FileBuffer)
        {
            printf("内存分配错误");
            fclose(file);
            return NULL;
        }
    
        if (!fread(FileBuffer, FileOfSize, 1, file))
        {
            printf("文件读取错误");
            fclose(file);
            return NULL;
        }
        fclose(file);
        return FileBuffer;
    }
    
    PVOID FileBufferToMemBuffer(LPVOID FileBuffer)
    {
        PVOID MemBuffer = NULL;
        PIMAGE_DOS_HEADER pFileDosHeader = NULL;
        PIMAGE_NT_HEADERS pFileNTHeader = NULL;
        PIMAGE_FILE_HEADER pFilePEHeader = NULL;
        PIMAGE_OPTIONAL_HEADER pFileOptionHeader = NULL;
        PIMAGE_SECTION_HEADER pFileSectionHeader = NULL;
    
        pFileDosHeader = (PIMAGE_DOS_HEADER)FileBuffer;
        pFilePEHeader = (PIMAGE_FILE_HEADER)(pFileDosHeader->e_lfanew + (DWORD)pFileDosHeader + 4);
        pFileOptionHeader = (PIMAGE_OPTIONAL_HEADER)(pFileDosHeader->e_lfanew + (DWORD)pFileDosHeader + 4 + IMAGE_SIZEOF_FILE_HEADER);
        pFileSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pFileOptionHeader+ pFilePEHeader->SizeOfOptionalHeader);
        size_t size = pFileOptionHeader->SizeOfImage;
    
        MemBuffer = malloc(size);
        memset(MemBuffer, 0, size);
        memcpy(MemBuffer, pFileDosHeader, pFileOptionHeader->SizeOfHeaders);
        
    
        for (int i = 0; i < pFilePEHeader->NumberOfSections; i++)
        {
            memcpy((PVOID)((DWORD)MemBuffer + pFileSectionHeader->VirtualAddress), (PVOID)((DWORD)FileBuffer + pFileSectionHeader->PointerToRawData), pFileSectionHeader->Misc.VirtualSize);
            pFileSectionHeader++;
        }
        return MemBuffer;
    }
    
    PVOID MemBufferToFile(LPVOID MemBuffer)
    {
        FILE* file=NULL;
        PVOID FileBuffer = NULL;
        PIMAGE_DOS_HEADER pFileDosHeader = NULL;
        PIMAGE_NT_HEADERS pFileNTHeader = NULL;
        PIMAGE_FILE_HEADER pFilePEHeader = NULL;
        PIMAGE_OPTIONAL_HEADER pFileOptionHeader = NULL;
        PIMAGE_SECTION_HEADER pFileSectionHeader = NULL;
        file = fopen("cpyj.exe", "wb+");
    
        pFileDosHeader = (PIMAGE_DOS_HEADER)MemBuffer;
        pFilePEHeader = (PIMAGE_FILE_HEADER)(pFileDosHeader->e_lfanew + (DWORD)pFileDosHeader + 4);
        pFileOptionHeader = (PIMAGE_OPTIONAL_HEADER)(pFileDosHeader->e_lfanew + (DWORD)pFileDosHeader + 4 + IMAGE_SIZEOF_FILE_HEADER);
        pFileSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pFileOptionHeader + pFilePEHeader->SizeOfOptionalHeader);
        size_t size = pFileOptionHeader->SizeOfHeaders;
        for (int i = 0; i < pFilePEHeader->NumberOfSections; i++)
        {
            size += pFileSectionHeader->SizeOfRawData;
            pFileSectionHeader++;
        }
        pFileSectionHeader= (PIMAGE_SECTION_HEADER)((DWORD)pFileOptionHeader + pFilePEHeader->SizeOfOptionalHeader);
        
        FileBuffer = malloc(size);
        memset(FileBuffer, 0, size);
        memcpy(FileBuffer, MemBuffer, pFileOptionHeader->SizeOfHeaders);
        for (int i = 0; i < pFilePEHeader->NumberOfSections; i++)
        {
            memcpy((PVOID)((DWORD)FileBuffer+pFileSectionHeader->PointerToRawData), (PVOID)((DWORD)MemBuffer + pFileSectionHeader->VirtualAddress), pFileSectionHeader->SizeOfRawData);
            pFileSectionHeader++;
        }
        fwrite(FileBuffer, size, 1, file);
        return FileBuffer;
    }
    
    PVOID TestAddCodeInCodeSec(LPVOID ImageBuffer)
    {
        HMODULE AddressOfDll = GetModuleHandle((LPCWSTR)"user32.dll");//这里本机代码我没有求出来,所以messagebox传出来的值为NULL,所以什么都没变
        FARPROC AddressOfMessage = GetProcAddress(AddressOfDll, (LPCSTR)"MessageBox");
        PIMAGE_DOS_HEADER pFileDosHeader = NULL;
        PIMAGE_NT_HEADERS pFileNTHeader = NULL;
        PIMAGE_FILE_HEADER pFilePEHeader = NULL;
        PIMAGE_OPTIONAL_HEADER pFileOptionHeader = NULL;
        PIMAGE_SECTION_HEADER pFileSectionHeader = NULL;
    
        pFileDosHeader = (PIMAGE_DOS_HEADER)ImageBuffer;
        pFilePEHeader = (PIMAGE_FILE_HEADER)(pFileDosHeader->e_lfanew + (DWORD)pFileDosHeader + 4);
        pFileOptionHeader = (PIMAGE_OPTIONAL_HEADER)(pFileDosHeader->e_lfanew + (DWORD)pFileDosHeader + 4 + IMAGE_SIZEOF_FILE_HEADER);
        pFileSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pFileOptionHeader + pFilePEHeader->SizeOfOptionalHeader);
        if (((pFileSectionHeader->SizeOfRawData) - (pFileSectionHeader->Misc.VirtualSize)) < SHELLCODELENGTH)
        {
            printf("代码区空间不够");
            return NULL;
        }
    
        PVOID codeBegin = (PBYTE)((pFileOptionHeader->SizeOfHeaders) + (DWORD)ImageBuffer + pFileSectionHeader->Misc.VirtualSize);
        memcpy(codeBegin, shellCode, SHELLCODELENGTH);
    
        //修正E8
        DWORD callAddr = ((DWORD)AddressOfMessage - (pFileOptionHeader->ImageBase + (DWORD)codeBegin + 0xD) + (DWORD)ImageBuffer);
        *(PDWORD)((DWORD)codeBegin + 9) = callAddr;
        //修正E9
        DWORD jmpAddr = (pFileOptionHeader->AddressOfEntryPoint+pFileOptionHeader->ImageBase-(pFileOptionHeader->ImageBase + SHELLCODELENGTH) + (DWORD)ImageBuffer);
        *(PDWORD)((DWORD)codeBegin + 0xE) = jmpAddr;
        //修改OEP
        pFileOptionHeader->AddressOfEntryPoint = (DWORD)codeBegin - (DWORD)ImageBuffer;
    
        MemBufferToFile(ImageBuffer);
    }
    
    VOID TestAddSection()
    {
    
    }
    
    int main()
    {
        
        LPSTR lpszFile = (LPSTR)"pe.exe";
        PVOID FileBuffer = FileToFileBuffer(lpszFile);
        PVOID MemBuffer=FileBufferToMemBuffer(FileBuffer);
        TestAddCodeInCodeSec(MemBuffer);
    }

    上面条件不成立的话,可以通过扩展节来进行注入和跳转,请看下面

    通过扩展节来向程序注入shellcode

    使用代码,在文件中先增加一个节在,将shellcode注入进我们自己创建的节中

    条件:当代码节不够空闲块时,就用此方法(还有一种情况,当不够空闲块的时候,由于DOS头下面有一部分没有用的垃圾数据,所以可以把PE整个头上移,并修改DOS头的flnew成员,其他的修改一致)

    思路:在程序最后一个节后面添加字节,因为如果添加到前面,需要改变节表里的多个值,然后在修改节表里的值,也就是在节表后面新增一个SectionHeader,Name8个字节随便设,并用character与text节处的character进行或运算,在修改文件大小和内存大小为相等(这样可以省去一些写入步骤)和偏移地址,在设置标准头里的SizeOfSections,在设置SizeOfImage, 获取shellcode的注入位置,然后再通过计算把硬编码应该跳转的地址计算出来  其公式为:要跳转的地址=当前指令的下一条指令地址+5+X——>就可以推出X=要跳转的地址-(当前指令的下一条指令地址+5)

    在通过指针将其值修改

    在最后修改OEP,并使shellcode最后跳回原来的程序入口

    #define _CRT_SECURE_NO_WARNINGS
    #include<iostream>
    #include<Windows.h>
    
    
    #define SHELLCODELENGTH        0x12
    BYTE shellCode[] =
    {
        0x6a,00,0x6a,00,0x6a,00,0x6a,00,
        0xe8,00,00,00,00,
        0xe9,00,00,00,00
    };
    
    PVOID FileToFileBuffer(LPSTR lpszFile)
    {
        FILE* file=NULL;
        PVOID FileBuffer=NULL;
        size_t FileOfSize=0;
    
        file = fopen(lpszFile, "rb+");
        if (!file)
        {
            printf("文件打开错误");
            return NULL;
        }
    
        fseek(file, NULL,SEEK_END);
        FileOfSize=ftell(file);
        fseek(file, NULL, SEEK_SET);
    
        FileBuffer = malloc(FileOfSize);
        if (!FileBuffer)
        {
            printf("内存分配错误");
            fclose(file);
            return NULL;
        }
    
        if (!fread(FileBuffer, FileOfSize, 1, file))
        {
            printf("文件读取错误");
            fclose(file);
            return NULL;
        }
        fclose(file);
        return FileBuffer;
    }
    
    PVOID FileBufferToMemBuffer(LPVOID FileBuffer)
    {
        PVOID MemBuffer = NULL;
        PIMAGE_DOS_HEADER pFileDosHeader = NULL;
        PIMAGE_NT_HEADERS pFileNTHeader = NULL;
        PIMAGE_FILE_HEADER pFilePEHeader = NULL;
        PIMAGE_OPTIONAL_HEADER pFileOptionHeader = NULL;
        PIMAGE_SECTION_HEADER pFileSectionHeader = NULL;
    
        pFileDosHeader = (PIMAGE_DOS_HEADER)FileBuffer;
        pFilePEHeader = (PIMAGE_FILE_HEADER)(pFileDosHeader->e_lfanew + (DWORD)pFileDosHeader + 4);
        pFileOptionHeader = (PIMAGE_OPTIONAL_HEADER)(pFileDosHeader->e_lfanew + (DWORD)pFileDosHeader + 4 + IMAGE_SIZEOF_FILE_HEADER);
        pFileSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pFileOptionHeader+ pFilePEHeader->SizeOfOptionalHeader);
        size_t size = pFileOptionHeader->SizeOfImage;
    
        MemBuffer = malloc(size);
        memset(MemBuffer, 0, size);
        memcpy(MemBuffer, pFileDosHeader, pFileOptionHeader->SizeOfHeaders);
        
    
        for (int i = 0; i < pFilePEHeader->NumberOfSections; i++)
        {
            memcpy((PVOID)((DWORD)MemBuffer + pFileSectionHeader->VirtualAddress), (PVOID)((DWORD)FileBuffer + pFileSectionHeader->PointerToRawData), pFileSectionHeader->Misc.VirtualSize);
            pFileSectionHeader++;
        }
        return MemBuffer;
    }
    
    PVOID MemBufferToFile(LPVOID MemBuffer)
    {
        FILE* file=NULL;
        PVOID FileBuffer = NULL;
        PIMAGE_DOS_HEADER pFileDosHeader = NULL;
        PIMAGE_NT_HEADERS pFileNTHeader = NULL;
        PIMAGE_FILE_HEADER pFilePEHeader = NULL;
        PIMAGE_OPTIONAL_HEADER pFileOptionHeader = NULL;
        PIMAGE_SECTION_HEADER pFileSectionHeader = NULL;
        file = fopen("cpyj.exe", "wb+");
    
        pFileDosHeader = (PIMAGE_DOS_HEADER)MemBuffer;
        pFilePEHeader = (PIMAGE_FILE_HEADER)(pFileDosHeader->e_lfanew + (DWORD)pFileDosHeader + 4);
        pFileOptionHeader = (PIMAGE_OPTIONAL_HEADER)(pFileDosHeader->e_lfanew + (DWORD)pFileDosHeader + 4 + IMAGE_SIZEOF_FILE_HEADER);
        pFileSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pFileOptionHeader + pFilePEHeader->SizeOfOptionalHeader);
        size_t size = pFileOptionHeader->SizeOfHeaders;
        for (int i = 0; i < pFilePEHeader->NumberOfSections; i++)
        {
            size += pFileSectionHeader->SizeOfRawData;
            pFileSectionHeader++;
        }
        pFileSectionHeader= (PIMAGE_SECTION_HEADER)((DWORD)pFileOptionHeader + pFilePEHeader->SizeOfOptionalHeader);
        
        FileBuffer = malloc(size);
        memset(FileBuffer, 0, size);
        memcpy(FileBuffer, MemBuffer, pFileOptionHeader->SizeOfHeaders);
        for (int i = 0; i < pFilePEHeader->NumberOfSections; i++)
        {
            memcpy((PVOID)((DWORD)FileBuffer+pFileSectionHeader->PointerToRawData), (PVOID)((DWORD)MemBuffer + pFileSectionHeader->VirtualAddress), pFileSectionHeader->SizeOfRawData);
            pFileSectionHeader++;
        }
        fwrite(FileBuffer, size, 1, file);
        return FileBuffer;
    }
    
    PVOID TestAddCodeInCodeSec(LPVOID ImageBuffer)
    {
        HMODULE AddressOfDll = GetModuleHandle((LPCWSTR)"user32.dll");
        FARPROC AddressOfMessage = GetProcAddress(AddressOfDll, (LPCSTR)"MessageBox");
        PIMAGE_DOS_HEADER pFileDosHeader = NULL;
        PIMAGE_NT_HEADERS pFileNTHeader = NULL;
        PIMAGE_FILE_HEADER pFilePEHeader = NULL;
        PIMAGE_OPTIONAL_HEADER pFileOptionHeader = NULL;
        PIMAGE_SECTION_HEADER pFileSectionHeader = NULL;
    
        pFileDosHeader = (PIMAGE_DOS_HEADER)ImageBuffer;
        pFilePEHeader = (PIMAGE_FILE_HEADER)(pFileDosHeader->e_lfanew + (DWORD)pFileDosHeader + 4);
        pFileOptionHeader = (PIMAGE_OPTIONAL_HEADER)(pFileDosHeader->e_lfanew + (DWORD)pFileDosHeader + 4 + IMAGE_SIZEOF_FILE_HEADER);
        pFileSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pFileOptionHeader + pFilePEHeader->SizeOfOptionalHeader);
        if (((pFileSectionHeader->SizeOfRawData) - (pFileSectionHeader->Misc.VirtualSize)) < SHELLCODELENGTH)
        {
            printf("代码区空间不够");
            return NULL;
        }
    
        PVOID codeBegin = (PBYTE)((pFileOptionHeader->SizeOfHeaders) + (DWORD)ImageBuffer + pFileSectionHeader->Misc.VirtualSize);
        memcpy(codeBegin, shellCode, SHELLCODELENGTH);
    
        //修正E8
        DWORD callAddr = ((DWORD)AddressOfMessage - (pFileOptionHeader->ImageBase + ((DWORD)((DWORD)codeBegin + 0xD) - (DWORD)ImageBuffer)));
        *(PDWORD)((DWORD)codeBegin + 9) = callAddr;
        //修正E9
        DWORD jmpAddr = (pFileOptionHeader->AddressOfEntryPoint+pFileOptionHeader->ImageBase-(pFileOptionHeader->ImageBase + SHELLCODELENGTH) + (DWORD)ImageBuffer);
        *(PDWORD)((DWORD)codeBegin + 0xE) = jmpAddr;
        //修改OEP
        pFileOptionHeader->AddressOfEntryPoint = (DWORD)codeBegin - (DWORD)ImageBuffer;
    
        MemBufferToFile(ImageBuffer);
    }
    
    VOID TestAddSection(LPSTR path)
    {
        PVOID FileBuffer = FileToFileBuffer(path);
        PVOID MemBuffer = NULL;
        PIMAGE_DOS_HEADER pFileDosHeader = NULL;
        PIMAGE_NT_HEADERS pFileNTHeader = NULL;
        PIMAGE_FILE_HEADER pFilePEHeader = NULL;
        PIMAGE_OPTIONAL_HEADER pFileOptionHeader = NULL;
        PIMAGE_SECTION_HEADER pFileSectionHeader = NULL;
    
        pFileDosHeader = (PIMAGE_DOS_HEADER)FileBuffer;
        pFilePEHeader = (PIMAGE_FILE_HEADER)(pFileDosHeader->e_lfanew + (DWORD)pFileDosHeader + 4);
        pFileOptionHeader = (PIMAGE_OPTIONAL_HEADER)(pFileDosHeader->e_lfanew + (DWORD)pFileDosHeader + 4 + IMAGE_SIZEOF_FILE_HEADER);
        pFileSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pFileOptionHeader + pFilePEHeader->SizeOfOptionalHeader);
    
        size_t Addsize=pFileOptionHeader->SectionAlignment;
        
        
        pFileOptionHeader->SizeOfImage += Addsize;
        PIMAGE_SECTION_HEADER AddSectionHeader= pFileSectionHeader + pFilePEHeader->NumberOfSections;
    
        AddSectionHeader->SizeOfRawData=AddSectionHeader->Misc.VirtualSize = Addsize;
        AddSectionHeader->PointerToRawData = ((PIMAGE_SECTION_HEADER)((DWORD)AddSectionHeader - 40))->PointerToRawData + ((PIMAGE_SECTION_HEADER)((DWORD)AddSectionHeader - 40))->SizeOfRawData;
        AddSectionHeader->VirtualAddress = ((PIMAGE_SECTION_HEADER)((DWORD)AddSectionHeader - 40))->VirtualAddress + (((PIMAGE_SECTION_HEADER)((DWORD)AddSectionHeader - 40))->Misc.VirtualSize/pFileOptionHeader->SectionAlignment+1)* pFileOptionHeader->SectionAlignment;
        AddSectionHeader->Characteristics |= pFileSectionHeader->Characteristics;
        AddSectionHeader->Name[0] = '.';
        AddSectionHeader->Name[1] = 't';
        AddSectionHeader->Name[2] = 't';
        AddSectionHeader->Name[3] = 't';
        AddSectionHeader->Name[4] = 't';
        pFilePEHeader->NumberOfSections++;
    
        MemBuffer = malloc(pFileOptionHeader->SizeOfImage);
        memset(MemBuffer, 0, pFileOptionHeader->SizeOfImage);
        memcpy(MemBuffer, FileBuffer, pFileOptionHeader->SizeOfHeaders);
        for (int i = 0; i < pFilePEHeader->NumberOfSections; i++)
        {
            memcpy((PVOID)((DWORD)MemBuffer + pFileSectionHeader->VirtualAddress), (PVOID)((DWORD)FileBuffer + pFileSectionHeader->PointerToRawData), pFileSectionHeader->Misc.VirtualSize);
            pFileSectionHeader++;
        }
        MemBufferToFile(MemBuffer);
        return;
    }
    
    
    int main()
    {
        
        LPSTR lpszFile = (LPSTR)"pe.exe";
        PVOID FileBuffer = FileToFileBuffer(lpszFile);
        PVOID MemBuffer=FileBufferToMemBuffer(FileBuffer);
        TestAddSection(lpszFile);
    }

    如果上面两种情况都不适用,那么可以扩大节

    通过扩大节来注入shellcode

    使用代码扩大最后一个节

    条件:暂时不清楚

    思路:在最后一个节里加上一段内存,并且修改sizeofimage和sectionheader里的文件大小和内存大小全部修改,建议修改为一样的。即可

    代码跟上面这种方法差不多

    还有一种方法合并节

    顾名思义就是将所有的节合并为一个节

    思路:把多个节合并为一个,需要修改的值为:sectionheader,内存大小,和文件大小,NumberOfSections需要修改

    需要注意的是文件对齐

    代码先咕一下等基本的PE干了,在过来一次添加上

  • 相关阅读:
    我的软考之路(五)——数据结构与算法(3)之图
    我的软考之路(四)——数据结构与算法(2)之树与二叉树
    程序员学习资料分享---爱分享的程序员(新浪微博)
    HIT CS科班对计算机专业knowledge的compilation
    我的软考之路(三)——数据结构与算法(1)之线性
    我的软考之路(二)——J2SE宏观总结
    python进阶七_文件操作(三)
    python进阶七_文件操作(二)
    python进阶七_文件操作(一)
    python进阶六_封装与继承
  • 原文地址:https://www.cnblogs.com/pppyyyzzz/p/13262139.html
Copyright © 2020-2023  润新知