2262343003 发表于 2021-7-20 23:12:13

自己写的PEtools

本帖最后由 2262343003 于 2021-7-20 23:14 编辑

                                                                                                                                                功能
每一个功能自己都测试过,自己测试的时候没有问题,包括文件对齐和内存对齐不一样时。
自己需要就拿走把,下面直接是源码

对了,是用c语言写的

//判断文件是否为PE文件

//文件与内存连接

//rva转换foa

//foa转rva

//得到导出表

//打印导出表

//打印导出表的函数名称

//得到pe头

//由名字或者序号函数函数地址

//打印重定位表

//给PE文件新增节

//pe文件由filebuffer手动转iamgebuffer

//pe文件由iamgebuffer手动转filebuffer

//存盘

//加入meassageboxa(简单的加入shellcode)

//打印PE

//移动导出表

//移动重定位表

//修改PE的imagebase,同时修复重定位表

//得到导入表

//打印导入表

//得到绑定导入表

//打印绑定导入表

//移动导入表加注入自己的导入表


                                                                                                                                                   源码
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include <windows.h>
#include <string.h>

//判断buffer是否为PE文件
BOOL judgePE(char* buffer);

//file与buffer连接
char* FILEtoBUFFER(FILE* hfile);//返回连接后的地址

//rva转换foa
unsigned long RVAtoFOA(char* buffer, unsigned long hRVA);//返回foa

//foa转rva
unsigned long FOAtoRVA(char* buffer, unsigned long hFOA);//返回RVA

//得到输出表
PIMAGE_EXPORT_DIRECTORY Get_Export_directory(char* buffer);

//打印输出表
void print_export(char* buffer);

//打印输出表的函数名称
void print_function_name(char* buffer);

//得到pe头
PIMAGE_NT_HEADERS GET_nt_header(char* buffer);

//得到函数地址
void* GetFunctionAddrByName(char* buffer, const char* Function_Name);
void* GetFunctionAddrByOrdinals(char* buffer, short Ordinal);

//打印重定位表
void print_base_relocation(char* buffer);

//新增节
char* increase_section(char* imagebuffer, DWORD size);   //返回增加后节的地址

//拉伸
char* filebuffertoimagebuffer(char* buffer, int judge, DWORD size);

//还原
char* iamgebuffertonewbuffer(char* imagebuffer, int judge, DWORD size);

//存盘
void savebuffer(char* buffer, int judge, DWORD size);

//加入meassageboxa
char* shellcodetoimagebuffer(char* imagebuffer);

//打印PE
void print_PE();

//移动导出表
void move_export_directory(char* filebuffer);

//移动重定位表
void move_base_relocation(char* filebuffer);

//修改PE的imagebase,同时修复重定位表
char* modify_imagebase(char* filebuffer, DWORD newimagebase);

//得到导入表
PIMAGE_IMPORT_DESCRIPTOR Get_Import_descrtiptor(char* buffer);

//打印导入表
void print_import_descriptor(char* buffer);

//得到绑定导入表
PIMAGE_BOUND_IMPORT_DESCRIPTOR Get_Bound_import_descriptor(char* buffer);

//打印绑定导入表
void print_bound_import_descriptor(char* buffer);

//移动导入表加注入导入表
void move_import_descriptor(char* filebuffer);



#define FILENAME_ONE "C:\\Users\\Admin\\Desktop\\111.exe"   //内存对齐0x1000文件对齐0x200
//#define FILENAME_TWO "D:\\学习\逆向破解合集\\新建文件夹\\其他精品逆向\\01NCK-逆向破解初级班__线上班\\破解工具\\OllyDbg.exe"   //有输出表内存对齐0x1000文件对齐0x200
#define FILENAME_THREE "C:\\Users\\Admin\\Desktop\\4.1.exe"      //内存对齐0x1000文件对齐0x1000
#define FILENAME_ERROR "C:\\Users\\Admin\\Desktop\\笔记.txt"   //查看是否能判断
#define BUFFERNAME "C:\\Users\\Admin\\Desktop\\222.exe"   //打开方式为wb+

#define SHELLCODE 18
#define SIZE_SECTION 0x10000

char shellcode[] = {
                  0X6A,0X00,0X6A,0X00,0X6A,0X00,0X6A,0X00,
                  0XE8,0X00,0X00,0X00,0X00,
                  0XE9,0X00,0X00,0X00,0X00
};


#pragma warning(disable:4996)


void main()
{
    FILE* hfile = fopen(FILENAME_ONE, "rb+");
    if (NULL == hfile)
    {
      printf("请输入正确的地址\n");
      return;
    }
    char* filebuffer = FILEtoBUFFER(hfile);
    if (NULL == filebuffer)
    {
      fclose(hfile);
      return;
    }
    if (FALSE == judgePE(filebuffer))
    {
      free(filebuffer);
      fclose(hfile);
      return;
    }


    char* imagebuffer = filebuffertoimagebuffer(filebuffer, 1, SIZE_SECTION);//拉伸
    increase_section(imagebuffer, SIZE_SECTION);//增节
    filebuffer = iamgebuffertonewbuffer(imagebuffer, 1, SIZE_SECTION);//还原
    //jiami_PE(filebuffer,hfile, SIZE_SECTION);//加密    节区的内容都加1
    jiemi_PE(filebuffer, hfile,SIZE_SECTION);//解密    节区的内容都减1
    savebuffer(filebuffer, 1, SIZE_SECTION);//存盘


    free(imagebuffer);
    free(filebuffer);
    fclose(hfile);
    return;
}





BOOL judgePE(char* buffer)
{
    if (IMAGE_DOS_SIGNATURE != *((short*)buffer))
    {
      printf("该文件不是PE文件         judgePE\n");
      return FALSE;
    }
    //dos
    PIMAGE_DOS_HEADER f_dos_header = (PIMAGE_DOS_HEADER)buffer;
    //pe
    PIMAGE_NT_HEADERS f_nt_header = (PIMAGE_NT_HEADERS)((unsigned long)buffer + (unsigned long)f_dos_header->e_lfanew);
    if (IMAGE_NT_SIGNATURE != f_nt_header->Signature)
    {
      printf("该文件不是PE文件\n");
      return FALSE;
    }
    return TRUE;
}

unsigned long RVAtoFOA(char* buffer ,unsigned long hRVA)
{
    unsigned long hfov = 0;
    PIMAGE_NT_HEADERS f_nt_header = GET_nt_header(buffer);
    //section;
    PIMAGE_SECTION_HEADER f_section_header = (PIMAGE_SECTION_HEADER)((unsigned long)f_nt_header + (unsigned long)24 + (unsigned long)f_nt_header->FileHeader.SizeOfOptionalHeader);
    //numberofsection
    int numer_section = f_nt_header->FileHeader.NumberOfSections;
    //计算foa
    while (numer_section--)
    {

      if (hRVA < f_section_header->VirtualAddress)
      {
            hfov = hRVA;
            break;
      }
      if (hRVA >= f_section_header->VirtualAddress && hRVA < f_section_header->VirtualAddress + f_section_header->Misc.VirtualSize)
      {
            hfov = hRVA - f_section_header->VirtualAddress + f_section_header->PointerToRawData;
            break;
      }

      f_section_header++;
    }
    if (hfov != 0)
    {
      return hfov;
    }
    else
    {
      printf("RVA错误            RVAtoFOA\n");
      return hfov;
    }
}

unsigned long FOAtoRVA(char* buffer, unsigned long hFOA)
{
    unsigned long hRVA = 0;
    PIMAGE_NT_HEADERS f_nt_header = GET_nt_header(buffer);
    //section;
    PIMAGE_SECTION_HEADER f_section_header = (PIMAGE_SECTION_HEADER)((unsigned long)f_nt_header + (unsigned long)24 + (unsigned long)f_nt_header->FileHeader.SizeOfOptionalHeader);
    //numberofsection
    int numer_section = f_nt_header->FileHeader.NumberOfSections;
    //计算rva
    while (numer_section--)
    {
      if (hFOA < f_section_header->PointerToRawData)
      {
            hRVA = hFOA;
            break;
      }
      if (hFOA >= f_section_header->PointerToRawData && hFOA < f_section_header->PointerToRawData + f_section_header->SizeOfRawData)
      {
            hRVA = hFOA - f_section_header->PointerToRawData + f_section_header->VirtualAddress;
            break;
      }

      f_section_header++;
    }
    if (hRVA != 0)
    {
      return hRVA;
    }
    else
    {
      printf("RVA错误            FOAtoRVA\n");
      return hRVA;
    }
}

char* FILEtoBUFFER(FILE* hfile)
{
    //计算hfile的大小
    fseek(hfile, 0, SEEK_END);
    long hsize = ftell(hfile);
    fseek(hfile, 0, SEEK_SET);
    //申请
    char* buffer = (char*)malloc(hsize);
    if (NULL == buffer)
    {
      printf("申请内存错误      FILEtoBUFFER \n");
      return NULL;
    }
    //写内存
    fread(buffer, hsize, 1, hfile);
    return buffer;
}

PIMAGE_NT_HEADERS GET_nt_header(char* buffer)
{
    //dos
    PIMAGE_DOS_HEADER f_dos_header = (PIMAGE_DOS_HEADER)buffer;
    //pe
    PIMAGE_NT_HEADERS f_nt_header = (PIMAGE_NT_HEADERS)((unsigned long)buffer + (unsigned long)f_dos_header->e_lfanew);
    return f_nt_header;

}

void print_export(char* buffer)
{
    //得到输出表
    PIMAGE_EXPORT_DIRECTORY f_export_directory = Get_Export_directory(buffer);
    if (0 == f_export_directory)
    {
      printf("错误            Get_Export_directory\n");
      return;
    }
    printf("文件名      %s\n", buffer+ RVAtoFOA(buffer,f_export_directory->Name));
    printf("起始序号地址%x\n", f_export_directory->Base);
    printf("函数总数      %x\n", f_export_directory->NumberOfFunctions);
    printf("有名字个数    %x\n", f_export_directory->NumberOfNames);
    printf("导出函数地址表地址    %x\n", (unsigned long)buffer + (unsigned long)RVAtoFOA(buffer, f_export_directory->AddressOfFunctions));
    printf("导出函数名称表地址    %x\n", (unsigned long)buffer + (unsigned long)RVAtoFOA(buffer, f_export_directory->AddressOfNames));
    printf("导出函数序号表地址    %x\n", (unsigned long)buffer+(unsigned long)RVAtoFOA(buffer, f_export_directory->AddressOfNameOrdinals));
   

    return;
}

PIMAGE_EXPORT_DIRECTORY Get_Export_directory(char* buffer)
{
    //得到PE头
    PIMAGE_NT_HEADERS f_nt_headers = GET_nt_header(buffer);
    //得到输出表地址
    unsigned long export_add = f_nt_headers->OptionalHeader.DataDirectory.VirtualAddress;
    unsigned long export_add_foa = RVAtoFOA(buffer, export_add);
    //得到输出表
    PIMAGE_EXPORT_DIRECTORY f_export_directory = (PIMAGE_EXPORT_DIRECTORY)((unsigned long)buffer + (unsigned long)export_add_foa);
    return f_export_directory;
}

void print_function_name(char* buffer)
{
    //得到输出表
    PIMAGE_EXPORT_DIRECTORY f_export_directory = Get_Export_directory(buffer);
    if (0 == f_export_directory)
    {
      printf("可能是改文件没有输出表            print_function_name\n");
      return;
    }
    //得到有名字函数的数量
    short number_namefunctions = f_export_directory->NumberOfNames;
    printf("有名字函数的数量为%d\n\n", number_namefunctions);
    //得到函数名称表    注意转换成foa
    int* namefunction_table = (int*)(buffer + RVAtoFOA(buffer, f_export_directory->AddressOfNames));
    //得到表里面的地址并打印      注意函数名称地址转换成foa
    int i = 1;
    while (number_namefunctions--)
    {
      DWORD function_add_rva = *(namefunction_table++);
      DWORD function_add_foa = RVAtoFOA(buffer, function_add_rva);
      printf("第%d个函数名称:%s\n", i++,buffer + function_add_foa);
    }
}

void* GetFunctionAddrByName(char* buffer, const char* Function_Name)
{
    PIMAGE_EXPORT_DIRECTORY f_export_directory = Get_Export_directory(buffer);
    int* namefunction_table = (int*)(buffer + RVAtoFOA(buffer, f_export_directory->AddressOfNames));
    int i = f_export_directory->NumberOfNames;
    short jishu = 0;
    while (i--)
    {
      DWORD function_add_rva = *(namefunction_table++);
      DWORD function_add_foa = RVAtoFOA(buffer, function_add_rva);;
      if (0 == strcmp(buffer+ function_add_foa, Function_Name))
      {
            //得到序号表
            char* ordial_table = (buffer + RVAtoFOA(buffer, f_export_directory->AddressOfNameOrdinals));
            //得到序号
            ordial_table = ordial_table + jishu * 2;
            short ordinal_foa = *(short*)ordial_table;
            //得到函数表
            char* function_table = buffer + RVAtoFOA(buffer, f_export_directory->AddressOfFunctions);
            //取地址表里面的值
            char* p_function_add = function_table + ordinal_foa * 4;
            unsigned long function_foa = *((int*)p_function_add);

             return (void*)function_foa;
      }
      jishu++;
    }

    return 0;
}

void* GetFunctionAddrByOrdinals(char* buffer, short Ordinal)
{
    PIMAGE_EXPORT_DIRECTORY f_export_directory = Get_Export_directory(buffer);
    //得到base
    short base = f_export_directory->Base;
    //printf("%s的序号是%d", Function_Name, ordinal_foa);
    //得到函数表
    char* function_table = buffer + RVAtoFOA(buffer, f_export_directory->AddressOfFunctions);
    //取地址表里面的值
    function_table = function_table + (Ordinal- base) * 4;
    unsigned long function_foa = *((int*)function_table);

    return (void*)function_foa;
}

void print_base_relocation(char* buffer)
{
    //得到PE头
    PIMAGE_NT_HEADERS f_nt_headers = GET_nt_header(buffer);
    //得到重定位表地址
    char* f_base_relocation_add = buffer + RVAtoFOA(buffer,f_nt_headers->OptionalHeader.DataDirectory.VirtualAddress);

    PIMAGE_BASE_RELOCATION f_base_relocation = (PIMAGE_BASE_RELOCATION)f_base_relocation_add;
    int i = 1;
    while (0 != f_base_relocation->SizeOfBlock && 0 != f_base_relocation->VirtualAddress)
    {
      printf("分割线***********************\n\n");
      printf("第%d分块的初始地址%x\n",i++, f_base_relocation->VirtualAddress);
      unsigned long number_of_add = (f_base_relocation->SizeOfBlock - 8) / 2;
      //得到地址
      short* a = (short*)f_base_relocation + 4;
      while (number_of_add--)
      {
            short b = *(a);
            if (3 == b >> 12)
            {
                b = b & 4095;
                printf("地址是%x   属性是3\n", b + f_base_relocation->VirtualAddress);
                printf("                %x\n", *(int*)(buffer + RVAtoFOA(buffer, b + f_base_relocation->VirtualAddress)));
            }
            else if(b != 0x3000)
            {
                printf("地址是%x   属性是0\n", b + f_base_relocation->VirtualAddress);
            }
            a++;
      }
      f_base_relocation = (PIMAGE_BASE_RELOCATION)((unsigned long)f_base_relocation + f_base_relocation->SizeOfBlock);
    }
}

char* filebuffertoimagebuffer(char* filebuffer,int judge,DWORD size)
{
    //得到PE头
    PIMAGE_NT_HEADERS f_nt_headers = GET_nt_header(filebuffer);
    //得到节表
    PIMAGE_SECTION_HEADER f_section_header = (PIMAGE_SECTION_HEADER)((DWORD)f_nt_headers + 24 + (DWORD)f_nt_headers->FileHeader.SizeOfOptionalHeader);
    //得到imagebuffer的大小
    DWORD size_iamgebuffer = f_nt_headers->OptionalHeader.SizeOfImage;
    //申请imagebuffer
    char* imagebuffer = NULL;
    if (0 != judge)
    {
      imagebuffer = (char*)malloc(size_iamgebuffer+ size);
      if (NULL == imagebuffer)
      {
            printf("申请iamgebuffer错误\n");
            return 0;
      }
      //初始化iamgebuffer
      memset(imagebuffer, 0, size_iamgebuffer+ size);
    }

    else
    {
      imagebuffer = (char*)malloc(size_iamgebuffer);
      if (NULL == imagebuffer)
      {
            printf("申请iamgebuffer错误\n");
            return 0;
      }
      //初始化iamgebuffer
      memset(imagebuffer, 0, size_iamgebuffer);
    }
    //开始拉伸
    //1 copy头和节表
    memcpy(imagebuffer, filebuffer, f_nt_headers->OptionalHeader.SizeOfHeaders);
    //2 copy节
    DWORD number_section = f_nt_headers->FileHeader.NumberOfSections;
    while (number_section--)
    {
      memcpy(imagebuffer + f_section_header->VirtualAddress, filebuffer + f_section_header->PointerToRawData, f_section_header->SizeOfRawData);
      f_section_header++;
    }
    return imagebuffer;
}

char* iamgebuffertonewbuffer(char* imagebuffer,int judge, DWORD size)
{
    //得到PE头
    PIMAGE_NT_HEADERS f_nt_headers = GET_nt_header(imagebuffer);
    //得到节表
    PIMAGE_SECTION_HEADER f_section_header = (PIMAGE_SECTION_HEADER)((DWORD)f_nt_headers + 24 + (DWORD)f_nt_headers->FileHeader.SizeOfOptionalHeader);
    //计算hfile的大小
    FILE* hfile = fopen(FILENAME_ONE, "rb+");
    fseek(hfile, 0, SEEK_END);
    DWORD size_filebuffer = ftell(hfile);
    fseek(hfile, 0, SEEK_SET);
    //申请imagebuffer
    char* newbuffer = NULL;
    if (0 != judge)
    {
      newbuffer = (char*)malloc(size_filebuffer+ size);
      if (NULL == newbuffer)
      {
            printf("申请newbuffer错误\n");
            return 0;
      }
      //初始化iamgebuffer
      memset(newbuffer, 0, size_filebuffer+ size);
    }
    else
    {
      newbuffer = (char*)malloc(size_filebuffer);
      if (NULL == newbuffer)
      {
            printf("申请newbuffer错误\n");
            return 0;
      }
      //初始化iamgebuffer
      memset(newbuffer, 0, size_filebuffer);
    }
    //开始还原
    //1 copy头和节表
    memcpy(newbuffer, imagebuffer, f_nt_headers->OptionalHeader.SizeOfHeaders);
    //2 copy节
    DWORD number_section = f_nt_headers->FileHeader.NumberOfSections;
    while (number_section--)
    {
      memcpy(newbuffer + f_section_header->PointerToRawData, imagebuffer + f_section_header->VirtualAddress, f_section_header->SizeOfRawData);
      f_section_header++;
    }
    return newbuffer;
}

void savebuffer(char* buffer,int judge, DWORD size)
{
    FILE* hfile1 = fopen(FILENAME_ONE, "rb+");
    //计算hfile的大小
    fseek(hfile1, 0, SEEK_END);
    long size_file = 0;
    if (0 != judge)
    {
      size_file = ftell(hfile1)+ size;
    }
    else
    {
      size_file = ftell(hfile1);
    }
    fseek(hfile1, 0, SEEK_SET);
    //得到PE头
    PIMAGE_NT_HEADERS f_nt_headers = GET_nt_header(buffer);
    FILE* savebuffer_add=fopen(BUFFERNAME, "wb+");
    fseek(savebuffer_add, 0, SEEK_SET);
    if (NULL==savebuffer_add)
    {
      printf("打开BUFFERNAME失败\n");
      return;
    }
    fwrite(buffer, size_file, 1, savebuffer_add);
    printf("存盘成功\n");                      //大部分存完盘后直接退出,所以这里加free
    fclose(savebuffer_add);
    return;
}

char* shellcodetoimagebuffer(char* imagebuffer)
{
    //得到PE头
    PIMAGE_NT_HEADERS f_nt_headers = GET_nt_header(imagebuffer);
    //得到节表
    PIMAGE_SECTION_HEADER f_section_header = (PIMAGE_SECTION_HEADER)((DWORD)f_nt_headers + 24 + (DWORD)f_nt_headers->FileHeader.SizeOfOptionalHeader);
    //得到节的数量并找到可运行shellcode的节
    short number_section = f_nt_headers->FileHeader.NumberOfSections;
    while (number_section--)
    {
      if (0x80000020 == f_section_header->Characteristics)
      {
            //判断该节是否够加入shellcode
            if (f_section_header->SizeOfRawData - f_section_header->Misc.VirtualSize < SHELLCODE)
            {
                printf("该节剩下的空间不够存储shellcode\n");
                if (0 == number_section)
                {
                  printf("该文件没有想要的内存存储shellcode\n");
                  return 0;
                }
            }
            else
            {
                break;
            }
      }
      f_section_header++;
    }
    //找到该节的空白位置并写入初始化的shellcode
    char* section_shellcode = imagebuffer + FOAtoRVA(imagebuffer, f_section_header->PointerToRawData + f_section_header->Misc.VirtualSize);
    memcpy(section_shellcode, shellcode, SHELLCODE);
    DWORD EntryPoint = (DWORD)section_shellcode - (DWORD)imagebuffer;
    //修改E8   0x77A9ED60   MessageBoxA
    section_shellcode = section_shellcode + 9;
    *(int*)section_shellcode = 0X777AED60 - (DWORD)(f_nt_headers->OptionalHeader.ImageBase+FOAtoRVA(imagebuffer, f_section_header->PointerToRawData + f_section_header->Misc.VirtualSize) + 13);
    //修改E9
    section_shellcode = section_shellcode + 5;
    *(int*)section_shellcode = (DWORD)(f_nt_headers->OptionalHeader.ImageBase + f_nt_headers->OptionalHeader.AddressOfEntryPoint - (DWORD)(f_nt_headers->OptionalHeader.ImageBase + FOAtoRVA(imagebuffer, f_section_header->PointerToRawData + f_section_header->Misc.VirtualSize) + 18));
    //修改AddressOfEntryPoint
    f_nt_headers->OptionalHeader.AddressOfEntryPoint = EntryPoint;
    return imagebuffer;
}

void print_PE()
{
    printf("打印DOS头请按1,\n打印FILE头请按2,\n打印OPTIONAL头请按3,\n打印节表请按4,\n打印输出表请按5,\n打印重定位表请按7");
    FILE* hfile = fopen(FILENAME_ONE, "rb+");
    if (NULL == hfile)
    {
      printf("请输入正确的地址\n");
      return;
    }
    char* filebuffer = FILEtoBUFFER(hfile);
    if (FALSE == judgePE(filebuffer))
    {
      fclose(hfile);
      return;
    }
    int i = 0;
    scanf("%d", &i);
    switch (i)
    {
    //case 1:print_DOS(filebuffer); break;
    //case 2:print_FILE(filebuffer); break;
    //case 3:print_OPTIONAL(filebuffer); break;
    //case 4:print_SECTIONS(filebuffer); break;
    }
}

char* increase_section(char* imagebuffer, DWORD size)
{
    //得到PE头
    PIMAGE_NT_HEADERS f_nt_headers = GET_nt_header(imagebuffer);
    //得到节表
    PIMAGE_SECTION_HEADER f_section_header = (PIMAGE_SECTION_HEADER)((DWORD)f_nt_headers + 24 + (DWORD)f_nt_headers->FileHeader.SizeOfOptionalHeader);
    //得到节的数量
    short number_section = f_nt_headers->FileHeader.NumberOfSections;
    //得到最后一个节
    PIMAGE_SECTION_HEADER use_section = f_section_header + number_section - 1;
    //得到最后一个节在内存中对齐后的大小
    DWORD use_section_misc = 0;
    if (0 == use_section->Misc.VirtualSize % 0x1000)
    {
      use_section_misc = use_section->Misc.VirtualSize;
    }
    else
    {
      use_section_misc = 0x1000 * (use_section->Misc.VirtualSize / 0x1000 + 1);
    }
    //得到最后一个节在内存中的偏移和大小
    DWORD use_section_pointertorawdata = use_section->PointerToRawData;
    DWORD use_section_sizeodrawdata = use_section->SizeOfRawData;
    //得到添加节的地址
    PIMAGE_SECTION_HEADER increase_section_add = f_section_header + number_section;
    //判断是否够添加节
    if (f_section_header->PointerToRawData - ((DWORD)increase_section_add -(DWORD)imagebuffer) < 80)
    {
      printf("剩下的内存不够添加新节\n");
      return 0;
    }
    //给节增加信息
    memcpy(increase_section_add->Name, "jinsen", 7);//节的名字
    increase_section_add->Misc.VirtualSize = size;//节在内存中展开后的实际大小
    increase_section_add->VirtualAddress = use_section->VirtualAddress + use_section_misc;//得到在内存中的偏移
    increase_section_add->SizeOfRawData = size;//在文件中对齐的尺寸
    increase_section_add->PointerToRawData = use_section_pointertorawdata + use_section_sizeodrawdata;//得到在文件中的偏移
    increase_section_add->Characteristics = 0x80000020;
    //修改文件节的数量
    f_nt_headers->FileHeader.NumberOfSections = f_nt_headers->FileHeader.NumberOfSections + 1;
    //修改sizeofimage
    f_nt_headers->OptionalHeader.SizeOfImage = f_nt_headers->OptionalHeader.SizeOfImage + size;
    return imagebuffer;
}

void move_export_directory(char* filebuffer)
{
    //得到PE头
    PIMAGE_NT_HEADERS f_nt_headers = GET_nt_header(filebuffer);
    //得到节表
    PIMAGE_SECTION_HEADER f_section_header = (PIMAGE_SECTION_HEADER)((DWORD)f_nt_headers + 24 + (DWORD)f_nt_headers->FileHeader.SizeOfOptionalHeader);
    //得到节的数量
    short number_section = f_nt_headers->FileHeader.NumberOfSections;
    //得到最后一个节
    PIMAGE_SECTION_HEADER use_section = f_section_header + number_section - 1;
    //得到输出表
    PIMAGE_EXPORT_DIRECTORY f_export_directory = Get_Export_directory(filebuffer);
    if (0 == f_export_directory)
    {
      printf("错误            Get_Export_directory\n");
      return;
    }
    //开始移动
    //1 移动函数地址表
    char* move_start_add = filebuffer + use_section->PointerToRawData;//得到移动的起始地址
    char* function_add_backup = move_start_add;
    char* f_function_add_table = filebuffer + RVAtoFOA(filebuffer, f_export_directory->AddressOfFunctions);//得到函数地址表的地址
    DWORD size_byte_function = f_export_directory->NumberOfFunctions * 4;//得到函数地址的大小
    memcpy(move_start_add, f_function_add_table, size_byte_function);//成功
    //2 移动函数序号表
    move_start_add = move_start_add + size_byte_function;//得到移动的起始地址
    char* ordinal_add_backup = move_start_add;
    char* f_function_ordinal = filebuffer + RVAtoFOA(filebuffer, f_export_directory->AddressOfNameOrdinals);//得到函数序号表地址
    DWORD size_byte_ordinal = f_export_directory->NumberOfNames * 2;//得到序号表的大小
    memcpy(move_start_add, f_function_ordinal, size_byte_ordinal);//成功
    //3 移动函数名称表
    move_start_add = move_start_add + size_byte_ordinal;//得到移动的起始地址   名字地址
    char* name_add_backup = move_start_add;//备份,用于同时进行复制名字的同时修改名字的地址
    char* name_add_backup_two = move_start_add;//二次备份
    int* f_function_name = (int*)(filebuffer + RVAtoFOA(filebuffer, f_export_directory->AddressOfNames));//得到函数名称表的地址
    DWORD size_byte_function_name = f_export_directory->NumberOfNames * 4;//得到名称表的大小
    memcpy(move_start_add, f_function_name, size_byte_function_name);//成功
    DWORD number_function_name = f_export_directory->NumberOfNames;//得到名字函数的数量
    move_start_add = move_start_add + size_byte_function_name;//得到移动的起始地址    名字
    while (number_function_name--)//移一个名字换一个地址
    {
      char* function_name_add = filebuffer + RVAtoFOA(filebuffer, *f_function_name++);//得到函数名字的地址
      DWORD size_name = strlen(function_name_add) + 1;//得到函数名字的大小
      memcpy(move_start_add, function_name_add, size_name);//成功
      DWORD function_name_rva = FOAtoRVA(filebuffer, (DWORD)move_start_add - (DWORD)filebuffer);//把foa转换成rva
      int move_second = { function_name_rva };
      memcpy(name_add_backup, move_second, 4);//修改函数名字的地址                               !!!!RVA
      name_add_backup = name_add_backup + 4;
      move_start_add = move_start_add + size_name;//得到下一个名字移动的起始地址
    }
    //4 移动输出表
    memcpy(move_start_add, f_export_directory,40);
    //5 修改导出表的地址
    f_nt_headers->OptionalHeader.DataDirectory.VirtualAddress = FOAtoRVA(filebuffer, (DWORD)move_start_add - (DWORD)filebuffer);
    //6 修改导出表中内容的地址
    PIMAGE_EXPORT_DIRECTORY senond_export_directory = (PIMAGE_EXPORT_DIRECTORY)move_start_add;
    senond_export_directory->AddressOfFunctions = FOAtoRVA(filebuffer, (DWORD)function_add_backup - (DWORD)filebuffer);
    senond_export_directory->AddressOfNameOrdinals= FOAtoRVA(filebuffer, (DWORD)ordinal_add_backup - (DWORD)filebuffer);
    senond_export_directory->AddressOfNames= FOAtoRVA(filebuffer, (DWORD)name_add_backup_two - (DWORD)filebuffer);

    memset(f_export_directory, 0, 40);//把原来的导出表置零

}

void move_base_relocation(char* filebuffer)
{
    //得到PE头
    PIMAGE_NT_HEADERS f_nt_headers = GET_nt_header(filebuffer);
    //得到节表
    PIMAGE_SECTION_HEADER f_section_header = (PIMAGE_SECTION_HEADER)((DWORD)f_nt_headers + 24 + (DWORD)f_nt_headers->FileHeader.SizeOfOptionalHeader);
    //得到节的数量
    short number_section = f_nt_headers->FileHeader.NumberOfSections;
    //得到最后一个节
    PIMAGE_SECTION_HEADER use_section = f_section_header + number_section - 1;
    //得到该节的文件对齐地址
    char* use_section_foa_add = filebuffer+use_section->PointerToRawData;
    //得到重定位表地址
    char* f_base_relocation_add = filebuffer + RVAtoFOA(filebuffer, f_nt_headers->OptionalHeader.DataDirectory.VirtualAddress);
    PIMAGE_BASE_RELOCATION f_base_relocation = (PIMAGE_BASE_RELOCATION)f_base_relocation_add;
    //遍历得到重定位表的大小
    DWORD size_all_base = 0;//记录
    char* f_base_relocation_backup = (char*)f_base_relocation;//备份
    while (0 != f_base_relocation->SizeOfBlock && 0 != f_base_relocation->VirtualAddress)
    {
      size_all_base = size_all_base + f_base_relocation->SizeOfBlock;
      f_base_relocation = (PIMAGE_BASE_RELOCATION)((unsigned long)f_base_relocation + f_base_relocation->SizeOfBlock);
    }
    //移动重定位表
    memcpy(use_section_foa_add, f_base_relocation_backup, size_all_base);
    //修改重定位表地址
    f_nt_headers->OptionalHeader.DataDirectory.VirtualAddress = FOAtoRVA(filebuffer, (DWORD)use_section_foa_add - (DWORD)filebuffer);
    //原来的重定位表置零
    memset(f_base_relocation_backup, 0, size_all_base);
}

char* modify_imagebase(char* filebuffer, DWORD newimagebase)
{
    //得到PE头
    PIMAGE_NT_HEADERS f_nt_headers = GET_nt_header(filebuffer);
    //得到重定位表地址
    char* f_base_relocation_add = filebuffer + RVAtoFOA(filebuffer, f_nt_headers->OptionalHeader.DataDirectory.VirtualAddress);//得到重定位表的foa地址
    PIMAGE_BASE_RELOCATION f_base_relocation = (PIMAGE_BASE_RELOCATION)f_base_relocation_add;//得到重定位表结构体
    while (0 != f_base_relocation->SizeOfBlock && 0 != f_base_relocation->VirtualAddress)
    {
      unsigned long number_of_add = (f_base_relocation->SizeOfBlock - 8) / 2;//得到每个块中地址的数量
      //得到地址
      short* twobyte_add = (short*)f_base_relocation + 4;//得到地址的首地址,因为是short*类型,这里加4等于加8
      while (number_of_add--)//遍历这个块
      {
            short twobyte_value = *(twobyte_add);//得到指针中的值
            if (3 == twobyte_value >> 12)
            {
                twobyte_value = twobyte_value & 0x0fff;//去掉前面的属性
                int* forebyte_add = (int*)(filebuffer + RVAtoFOA(filebuffer, twobyte_value + f_base_relocation->VirtualAddress));//得到在文件中的地址
                *forebyte_add = *forebyte_add + newimagebase - f_nt_headers->OptionalHeader.ImageBase;//取值并修改
            }
            twobyte_add++;
      }
      f_base_relocation = (PIMAGE_BASE_RELOCATION)((unsigned long)f_base_relocation + f_base_relocation->SizeOfBlock);//得到下一个块的首地址
    }
    f_nt_headers->OptionalHeader.ImageBase = newimagebase;//更改为新的imagebase
    return filebuffer;
}

PIMAGE_IMPORT_DESCRIPTOR Get_Import_descrtiptor(char* buffer)
{
    //得到PE头
    PIMAGE_NT_HEADERS f_nt_headers = GET_nt_header(buffer);
    //得到输出表地址
    unsigned long import_add = f_nt_headers->OptionalHeader.DataDirectory.VirtualAddress;
    unsigned long import_add_foa = RVAtoFOA(buffer, import_add);
    //得到输出表
    PIMAGE_IMPORT_DESCRIPTOR f_import_descriptor = (PIMAGE_IMPORT_DESCRIPTOR)((unsigned long)buffer + (unsigned long)import_add_foa);
    return f_import_descriptor;
}

void print_import_descriptor(char* buffer)
{
    //得到PE头
    PIMAGE_NT_HEADERS f_nt_headers = GET_nt_header(buffer);
    //得到导入表FOA地址
    PIMAGE_IMPORT_DESCRIPTOR f_import_descriptor = Get_Import_descrtiptor(buffer);
    int i = 1;
    while (0 != f_import_descriptor->FirstThunk && 0 != f_import_descriptor->Name && 0 != f_import_descriptor->OriginalFirstThunk)
    {
      //得到dll的名字
      char* dll_name_add = buffer+ RVAtoFOA(buffer,f_import_descriptor->Name);
      printf("***************************************************\n");
      printf("第%2d个dll的名字是%s\n\n", i++, dll_name_add);
      //得到INT的地址
      int* int_add= (int*)(buffer + RVAtoFOA(buffer, f_import_descriptor->OriginalFirstThunk));
      //得到IAT的地址
      int* iat_add= (int*)(buffer + RVAtoFOA(buffer, f_import_descriptor->FirstThunk));
      int m = 1;
      printf("******************OriginalFirstThunk*******************\n");
      while (0 != *(int_add))
      {
            if (*(int_add) & 0x80000000)
            {
                printf("第%d个函数没有名字,其索引为:%x\n)", m++, *(int_add) & 0x7FFFFFFF);
            }
            else
            {
                PIMAGE_IMPORT_BY_NAME f_pimage_import_by_name = (PIMAGE_IMPORT_BY_NAME)(buffer + RVAtoFOA(buffer, *(int_add)));
                printf("第%2d个函数的名字为:%s\n", m++, f_pimage_import_by_name->Name);
            }
            int_add++;
      }

      int n = 1;
      printf("******************FirstThunk*******************\n");
      while (0 != *(iat_add))
      {
            if (*(iat_add) & 0x80000000)
            {
                printf("第%d个函数没有名字,其索引为:%x\n)", n++, *(iat_add) & 0x7FFFFFFF);
            }
            else
            {
                PIMAGE_IMPORT_BY_NAME f_pimage_import_by_name = (PIMAGE_IMPORT_BY_NAME)(buffer + RVAtoFOA(buffer, *(iat_add)));
                printf("第%2d个函数的名字为:%s\n", n++, f_pimage_import_by_name->Name);
            }
            iat_add++;
      }
      f_import_descriptor++;
    }
}

PIMAGE_BOUND_IMPORT_DESCRIPTOR Get_Bound_import_descriptor(char* buffer)
{
    //得到PE头
    PIMAGE_NT_HEADERS f_nt_headers = GET_nt_header(buffer);
    //得到输出表地址
    unsigned long bound_import_descriptor_add = f_nt_headers->OptionalHeader.DataDirectory.VirtualAddress;
    unsigned long bound_import_descriptor_add_foa = RVAtoFOA(buffer, bound_import_descriptor_add);
    //得到输出表
    PIMAGE_BOUND_IMPORT_DESCRIPTOR f_bound_import_descriptor = (PIMAGE_BOUND_IMPORT_DESCRIPTOR)((unsigned long)buffer + (unsigned long)bound_import_descriptor_add_foa);
    return f_bound_import_descriptor;

}

void print_bound_import_descriptor(char* buffer)
{
    //得到PE头
    PIMAGE_NT_HEADERS f_nt_headers = GET_nt_header(buffer);
    //得到绑定导入表FOA地址
    PIMAGE_IMPORT_DESCRIPTOR f_import_descriptor = Get_Import_descrtiptor(buffer);
    int i = 1;
    //遍历看是否有绑定导入表
    while (0 != f_import_descriptor->FirstThunk && 0 != f_import_descriptor->Name && 0 != f_import_descriptor->OriginalFirstThunk)
    {
      if (-1 == f_import_descriptor->TimeDateStamp)
      {
            printf("有绑定导入表\n");         //得到绑定导入表
            PIMAGE_BOUND_IMPORT_DESCRIPTOR f_bound_import_descriptor = Get_Bound_import_descriptor(buffer);
            DWORD f_bound_import_descriptor_backup = (DWORD)f_bound_import_descriptor;
            while (0 != f_bound_import_descriptor->TimeDateStamp && 0 != f_bound_import_descriptor->OffsetModuleName)
            {
                printf("****************一级*****************\n");
                printf("TimeDateStamp      %x\n", f_bound_import_descriptor->TimeDateStamp);
                printf("Name               %s\n", f_bound_import_descriptor->OffsetModuleName + f_bound_import_descriptor_backup);
                printf("NumberOfDll      %d\n", f_bound_import_descriptor->NumberOfModuleForwarderRefs);
                if (0 != f_bound_import_descriptor->NumberOfModuleForwarderRefs)
                {
                  int n = f_bound_import_descriptor->NumberOfModuleForwarderRefs;
                  while (n--)
                  {
                        PIMAGE_BOUND_FORWARDER_REF f_bound_ref = (PIMAGE_BOUND_FORWARDER_REF)++f_bound_import_descriptor;
                        printf("****************二级*****************\n");
                        printf("TimeDateStamp      %x\n", f_bound_ref->TimeDateStamp);
                        printf("Name               %s\n", f_bound_ref->OffsetModuleName + f_bound_import_descriptor_backup);
                        printf("Reserved         %d\n\n", f_bound_ref->Reserved);
                  }
                }
                f_bound_import_descriptor++;
            }
            break;
      }
      f_import_descriptor++;
      if (0 == f_import_descriptor->FirstThunk && 0 == f_import_descriptor->Name && 0 == f_import_descriptor->OriginalFirstThunk)
      {
            printf("该PE文件没有绑定重定位表\n");
      }
    }
}

void move_import_descriptor(char* filebuffer)//移动导入表到新节中并加入新导入表
{
    //得到NT头
    PIMAGE_NT_HEADERS f_nt_headers = GET_nt_header(filebuffer);
    //得到导入表
    PIMAGE_IMPORT_DESCRIPTOR f_import_descriptor = Get_Import_descrtiptor(filebuffer);
    //备份导入表
    PIMAGE_IMPORT_DESCRIPTOR f_import_descriptor_bakup = f_import_descriptor;
    //得到节表
    PIMAGE_SECTION_HEADER f_section_header = (PIMAGE_SECTION_HEADER)((DWORD)f_nt_headers + 4 + 20 + (DWORD)f_nt_headers->FileHeader.SizeOfOptionalHeader);
    //得到节的数量
    char number_sections = f_nt_headers->FileHeader.NumberOfSections;
    //得到最后一个节表的位置
    f_section_header = f_section_header + number_sections - 1;
    //得到最后一个节在文件中的起始地址
    char* last_section_add = filebuffer + f_section_header->PointerToRawData;
    //最后一个节是自己弄的,所有内存肯定够,这里就不判断内存够不够了
    //移动导入表
    //1遍历导入表的数量
    int i = 0;
    while (0 != f_import_descriptor->FirstThunk && 0 != f_import_descriptor->OriginalFirstThunk)
    {
      i++;
      f_import_descriptor++;
    }
    memcpy(last_section_add, f_import_descriptor_bakup, 20 * i);//移动
    memset(f_import_descriptor_bakup, 0, 20 * i);//原来的导入表置零
    //修改optional目录中的地址
    f_nt_headers->OptionalHeader.DataDirectory.VirtualAddress = FOAtoRVA(filebuffer, f_section_header->PointerToRawData);

    //**************************注入导入表*********************************
    //得到位置注入
    PIMAGE_IMPORT_DESCRIPTOR new_import_descriptor = (PIMAGE_IMPORT_DESCRIPTOR)last_section_add + i;
    //得到int表的位置
    int* new_int_table_add = (int*)(last_section_add + 20 * (i + 2));
    //得到iat表的位置
    int* new_iat_table_add = new_int_table_add + 2;
    //得到PIMAGE_IMPORT_BY_NAME位置int
    PIMAGE_IMPORT_BY_NAME new_int_table = (PIMAGE_IMPORT_BY_NAME)(new_iat_table_add + 2);
    *new_int_table_add= FOAtoRVA(filebuffer, (DWORD)new_int_table - (DWORD)filebuffer);//这里直接把PIMAGE_IMPORT_BY_NAME(int)的地址给int表
    //得到PIMAGE_IMPORT_BY_NAME位置iat
    PIMAGE_IMPORT_BY_NAME new_iat_table = (PIMAGE_IMPORT_BY_NAME)(new_iat_table_add + 7);
    *new_iat_table_add = FOAtoRVA(filebuffer, (DWORD)new_iat_table - (DWORD)filebuffer);//这里直接把PIMAGE_IMPORT_BY_NAME(iat)的地址给iat表
    //名字地址   (char*)(new_iat_table + 5)
    char* dll_name_add = (char*)(new_iat_table_add + 12);
    const char* dll_name = "textdll.dll";
    memcpy(dll_name_add, dll_name, 12);
    //写入dll内容
    new_import_descriptor->OriginalFirstThunk = FOAtoRVA(filebuffer, (DWORD)new_int_table_add - (DWORD)filebuffer);//注意!!!int表中存的是PIMAGE_IMPORT_BY_NAME的位置,不是PIMAGE_IMPORT_BY_NAME结构体。
    new_import_descriptor->FirstThunk = FOAtoRVA(filebuffer, (DWORD)new_iat_table_add - (DWORD)filebuffer);//注意!!!iat表中存的是PIMAGE_IMPORT_BY_NAME的位置,不是PIMAGE_IMPORT_BY_NAME结构体。
    new_import_descriptor->TimeDateStamp = 0;
    new_import_descriptor->Name= FOAtoRVA(filebuffer, (DWORD)dll_name_add - (DWORD)filebuffer);
    //写入int内容
    new_int_table->Hint = 0;
    const char* function_name = "process";
    memcpy(new_int_table->Name, function_name, 8);
    //写入iat内容
    new_iat_table->Hint = 0;
    memcpy(new_iat_table->Name, function_name, 8);
}

2262343003 发表于 2021-7-24 11:31:53

没人啊{:5_104:}
页: [1]
查看完整版本: 自己写的PEtools