自己写的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);
} 没人啊{:5_104:}
页:
[1]