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

 

上一篇:RobotFramework--API高级网页跳转小练习


下一篇:PE复写:模仿PE加载过程