
实现目标: 开辟新的节并将导出表与重定位表的数据移到新的节中
代码如下
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<Windows.h>
FILE* OpenFile(char path[]);
char* GetMemory(FILE* file_point);
void FreeMemory(FILE* file_point, char* memory_point[], int memory_size);
void conversion(PIMAGE_SECTION_HEADER section);
PIMAGE_DOS_HEADER dos_ptr(char* memory);
PIMAGE_NT_HEADERS nt_ptr(char* memory);
PIMAGE_FILE_HEADER file_ptr(char* memory);
PIMAGE_OPTIONAL_HEADER optional_ptr(char* memory);
PIMAGE_SECTION_HEADER section_ptr(char* memory);
PIMAGE_SECTION_HEADER last_section_ptr(char* memory);
void export_file(char* memory);
char* transform_to_file(char* memory, char* first);
char* transform_to_memory(char* memory, char* first);
DWORD get_largest_size(DWORD virtual_size, DWORD file_size);
DWORD* data_directory(char* memory);
char* add_table(char* memory, FILE* file_point);
DWORD get_int(DWORD alignment, DWORD Size);
char* move_export(char* memory);
void move_reloc(char* space, char* memory);
void move_table(char path[]);
DWORD* table_address(char* memory);
DWORD need_space(char* memory);
void export_file(char* memory);
FILE* OpenFile(char path[]) {
//打开文件
FILE* file_point;
int return1 = fopen_s(&file_point, path, "rb");
if (return1 != 0) {
printf("获取文件指针错误\n");
}
return file_point;
}
//得到开辟内存所需要的大小
char* GetMemory(FILE* file_point) {
//开辟空间
fseek(file_point, 0, SEEK_END);
int file_size = ftell(file_point);
fseek(file_point, 0, SEEK_SET);
DWORD needed_size = sizeof(char) * file_size;
char* enter_memory = (char*)malloc(needed_size);
memset(enter_memory, 0, needed_size);
fread(enter_memory, file_size, 1, file_point);
return enter_memory;
}
//释放空间
void FreeMemory(FILE* file_point, char* memory_point[], int memory_size) {
for (int i = 0; i < memory_size; i++) {
free(memory_point[i]);
}
fclose(file_point);
}
void conversion(PIMAGE_SECTION_HEADER section) {
char* point = (char*)section;
printf("节表: ");
for (int i = 0; i < 8; i++) {
printf("%c", *point);
point++;
}
}
PIMAGE_DOS_HEADER dos_ptr(char* memory) {
return (PIMAGE_DOS_HEADER)(memory);
}
PIMAGE_NT_HEADERS nt_ptr(char* memory) {
return (PIMAGE_NT_HEADERS)((DWORD)dos_ptr(memory) + dos_ptr(memory)->e_lfanew);
}
PIMAGE_FILE_HEADER file_ptr(char* memory) {
return (PIMAGE_FILE_HEADER)((DWORD)nt_ptr(memory) + 4);
}
PIMAGE_OPTIONAL_HEADER optional_ptr(char* memory) {
return (PIMAGE_OPTIONAL_HEADER)((DWORD)file_ptr(memory) + 20);
}
PIMAGE_SECTION_HEADER section_ptr(char* memory) {
return (PIMAGE_SECTION_HEADER)(optional_ptr(memory) + 1);
}
PIMAGE_SECTION_HEADER last_section_ptr(char* memory) {
PIMAGE_SECTION_HEADER section = section_ptr(memory);
PIMAGE_FILE_HEADER file = file_ptr(memory);
int circle_num = file->NumberOfSections;
for (int i = 0; i < circle_num - 1; i++) {
section++;
}
return section;
}
//导出文件
void export_file(char* memory) {
FILE* win_file = NULL;
fopen_s(&win_file, "D:\\Ddisk\\last_memory.exe", "wb");
fseek(win_file, 0, SEEK_SET);
PIMAGE_OPTIONAL_HEADER optional = optional_ptr(memory);
//先导出头部数据
int sizeofHeaders = optional->SizeOfHeaders;
int fileAlignment = optional->FileAlignment;
if ((sizeofHeaders % fileAlignment) > 0) {
DWORD header_data = fileAlignment * ((sizeofHeaders / fileAlignment) + 1);
fwrite(memory, 1, header_data, win_file);
}
else if ((sizeofHeaders % fileAlignment) == 0) {
DWORD header_data2 = fileAlignment * (sizeofHeaders / fileAlignment);
fwrite(memory, 1, header_data2, win_file);
}
//导出各个节
int section_num = file_ptr(memory)->NumberOfSections;
PIMAGE_SECTION_HEADER section = section_ptr(memory);
for (int i = 0; i < section_num; i++) {
fseek(win_file, section->PointerToRawData, SEEK_SET);
fwrite((char*)(section->PointerToRawData + (DWORD)memory), 1, section->SizeOfRawData, win_file);
section++;
}
fclose(win_file);
}
//将RVA转为FOA
char* transform_to_file(char* memory, char* first) {
//定位file并获取节表数量
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)first;
PIMAGE_FILE_HEADER file = (PIMAGE_FILE_HEADER)((DWORD)dos + dos->e_lfanew + 4);
int table_num = file->NumberOfSections;
//定位optional并获取内存基址与对齐
PIMAGE_OPTIONAL_HEADER optional = (PIMAGE_OPTIONAL_HEADER)(DWORD(file) + 20);
DWORD image_base = optional->ImageBase;
DWORD align = optional->SectionAlignment;
if ((int)(memory - first) >= (int)image_base) { memory = memory - image_base; }
if ((int)memory < (int)align) { return memory; }
PIMAGE_SECTION_HEADER section = NULL;
section = (PIMAGE_SECTION_HEADER)(optional + 1);
for (int i = 0; i < table_num; i++) {
if ((section->VirtualAddress + get_largest_size(section->Misc.VirtualSize, section->SizeOfRawData)) >= (DWORD)memory && (DWORD)memory >= section->VirtualAddress) {
return (char*)((DWORD)section->PointerToRawData + ((DWORD)memory - (DWORD)section->VirtualAddress));
break;
}
section++;
}
return (char*)-1;
}
//将FOA转为RVA
char* transform_to_memory(char* memory, char* first) {
//定位file并获取节表数量
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)first;
PIMAGE_FILE_HEADER file = (PIMAGE_FILE_HEADER)((DWORD)dos + dos->e_lfanew + 4);
int table_num = file->NumberOfSections;
//定位optional并获取内存基址与对齐
PIMAGE_OPTIONAL_HEADER optional = (PIMAGE_OPTIONAL_HEADER)(DWORD(file) + 20);
DWORD image_base = optional->ImageBase;
DWORD align = optional->SectionAlignment;
if ((int)(memory - first) >= (int)image_base) { memory = memory - image_base; }
if ((int)memory < (int)align) { return memory; }
PIMAGE_SECTION_HEADER section = NULL;
section = (PIMAGE_SECTION_HEADER)(optional + 1);
for (int i = 0; i < table_num; i++) {
if (section->PointerToRawData + get_largest_size(section->Misc.VirtualSize, section->SizeOfRawData) >= (DWORD)memory && (DWORD)memory >= section->PointerToRawData) {
return (char*)((DWORD)section->VirtualAddress + ((DWORD)memory - (DWORD)section->PointerToRawData));
break;
}
section++;
}
return (char*)-1;
}
//判断节表中的virtual_size与file_size的大小
DWORD get_largest_size(DWORD virtual_size, DWORD file_size) {
if (virtual_size > file_size) {
return virtual_size;
}
else {
return file_size;
}
return 0;
}
//得到数据目录表中所有相关的数据
DWORD* data_directory(char* memory) {
PIMAGE_OPTIONAL_HEADER optional = optional_ptr(memory);
DWORD* data_directory = (DWORD*)&optional->DataDirectory;
int directory_circle = optional->NumberOfRvaAndSizes;
DWORD sum_arr[32] = { 0 };
for (int i = 0; i < directory_circle; i++) {
sum_arr[i + 16] = *data_directory;
sum_arr[i] = (DWORD)(transform_to_file((char*)*data_directory, memory));
data_directory = data_directory + 2;
}
return sum_arr;
}
//新增一个节
// 不拉伸, 使用file_buffer
// 1. 修改numberOfSection
// 2. 修改SizeOfImage=原来的sizeofImage+节对齐后的长度
// 3. 向节表中添加信息
// (1)判断sizeofHeaders-最后一个节表位置判断是否足够添加节(是否够40字节))
// (2)够的话添加, 不够的话将节表的数据向前移,修改e_lfanew的值, 继续添加, 还不够的话添加失败(或将两个节表合并, 空出一个节表)
// (3)判断加多少: 遍历导出表与导入表的数据, 根据其结果得到大小
DWORD get_int(DWORD alignment, DWORD Size) {
if (Size % alignment == 0) {
return alignment * (Size / alignment);
}
else {
return ((Size / alignment) * alignment) + alignment;
}
}
//得到数据目录表存储的各个表的数据
DWORD* table_address(char* memory) {
PIMAGE_OPTIONAL_HEADER optional = optional_ptr(memory);
DWORD* data_directory = (DWORD*)&optional->DataDirectory;
int directory_circle = optional->NumberOfRvaAndSizes;
DWORD sum_arr[32] = { 0 };
for (int i = 0; i < directory_circle; i++) {
sum_arr[i + 16] = *data_directory;
sum_arr[i] = (DWORD)(transform_to_file((char*)*data_directory, memory));
data_directory = data_directory + 2;
}
return sum_arr;
}
//计算开辟新的节表所需要的空间
DWORD need_space(char* memory) {
//求出节需要的空间, 目前需要的空间为导出表的数据+重定位表的数据
//使用数组存储所有表的地址
DWORD* ptr_one = table_address(memory);
DWORD directory_arr[32] = { 0 };
for (int i = 0; i < 32; i++) {
directory_arr[i] = *ptr_one;
ptr_one++;
}
PIMAGE_OPTIONAL_HEADER optional = optional_ptr(memory);
//得到导出表需要的空间
DWORD export_sum_space = 0;
if (directory_arr[0] != 0) {
PIMAGE_EXPORT_DIRECTORY export_table2 = (PIMAGE_EXPORT_DIRECTORY)(directory_arr[0] + (DWORD)memory);
char* name_base = (char*)(transform_to_file((char*)export_table2->Name, memory) + (DWORD)memory);
//得到导出表需要的空间
DWORD function_space = 4 * export_table2->NumberOfFunctions;
DWORD name_order_space = (strlen(name_base)) + (6 * export_table2->NumberOfNames);
DWORD export_space = ((DWORD)(export_table2 + 1) - (DWORD)(export_table2));
export_sum_space = function_space + name_order_space + export_space;
}
DWORD reloc_size = 0;
//得到重定位表需要的空间
if (directory_arr[5] != 0) {
PIMAGE_BASE_RELOCATION reloc_table = (PIMAGE_BASE_RELOCATION)(directory_arr[5] + (DWORD)memory);
while (reloc_table->SizeOfBlock != 0 && reloc_table->VirtualAddress != 0) {
reloc_size = reloc_size + reloc_table->SizeOfBlock;
reloc_table = (PIMAGE_BASE_RELOCATION)((DWORD)reloc_table + reloc_table->SizeOfBlock);
}
}
return reloc_size + export_sum_space;
}
//添加新的节表
char* add_table(char* memory, FILE* file_point) {
//得到各个头的指针
PIMAGE_DOS_HEADER dos = dos_ptr(memory);
PIMAGE_NT_HEADERS nt = nt_ptr(memory);
PIMAGE_FILE_HEADER file = file_ptr(memory);
PIMAGE_OPTIONAL_HEADER optional = optional_ptr(memory);
PIMAGE_SECTION_HEADER section = section_ptr(memory);
int section_num = file->NumberOfSections;
int size_of_header = optional->SizeOfHeaders;
PIMAGE_SECTION_HEADER last_site = section;
for (int i = 0; i < section_num; i++) {
last_site++;
}
//将第一个节表的数据复制到要添加的最后一个节表中
if ((size_of_header - ((DWORD)(last_site)-(DWORD)(memory))) >= 80 && *(char*)last_site == 0x00) {
DWORD add_data = (DWORD)(section + 1) - (DWORD)(section);
char* first_site = (char*)section;
char* last_site2 = (char*)last_site;
for (int i = 0; i < add_data; i++) {
*last_site2 = *first_site;
first_site++;
last_site2++;
}
//更改节表的名称
char* correct_added_data = (char*)last_site;
char myName[] = "BruceLi";
for (int i = 0; i < 8; i++) {
*correct_added_data = myName[i];
correct_added_data++;
}
//修改新的节表的起始地址, 大小属性
PIMAGE_SECTION_HEADER dao2_last_site = last_site - 1;
last_site->PointerToRawData = (dao2_last_site->PointerToRawData + get_int(optional->FileAlignment, dao2_last_site->SizeOfRawData));
last_site->VirtualAddress = (dao2_last_site->VirtualAddress + get_int(optional->SectionAlignment, dao2_last_site->Misc.VirtualSize));
DWORD last_size = get_int(optional->SectionAlignment, need_space(memory));
last_site->SizeOfRawData = last_size;
last_site->Misc.VirtualSize = last_size;
//修改Number of section,修改SizeOfImage
file->NumberOfSections = file->NumberOfSections + 1;
optional->SizeOfImage = optional->SizeOfImage + last_size;
//开辟新的空间
fseek(file_point, 0, SEEK_END);
int file_size = ftell(file_point);
char* ptr = memory;
ptr = (char*)realloc(memory, (file_size + last_size) * sizeof(char));
return ptr;
}
else {
if (((size_of_header - ((DWORD)last_site - (DWORD)memory)) + (dos->e_lfanew - 0x40)) >= 80) {
//空间不够但将节表的数据向前移>=40字节, 修改e_lfanew的值
dos->e_lfanew = 0x40;
int circle_times = (DWORD)last_site - (DWORD)nt;
char* correct_ptr = (char*)nt;
char* correct_ptr2 = (char*)(memory + 64);
for (int i = 0; i < circle_times; i++) {
*correct_ptr2 = *correct_ptr;
*correct_ptr = 0;
correct_ptr2++;
correct_ptr++;
}
printf("Error\n");
return 0;
}
else {
printf("Error\n");
return 0;
}
}
return 0;
}
//将file_address转为virtual_address
//移动导出表
char* move_export(char* memory) {
//得到数据目录表与需要填充数据的空间
PIMAGE_SECTION_HEADER last_section = last_section_ptr(memory);
char* space_site = (char*)last_section->PointerToRawData;
DWORD arr[32] = { 0 };
DWORD* ptr = table_address(memory);
for (int i = 0; i < 32; i++) {
arr[i] = *ptr;
ptr++;
}
//填充名称表的数据
char* space2 = space_site + (DWORD)memory;
if (arr[0] != 0) {
//根据得到的名称表的大小将名称表移至地址处
//得到导出表的地址
PIMAGE_EXPORT_DIRECTORY export_table = (PIMAGE_EXPORT_DIRECTORY)(memory + arr[0]);
int numberOfNames = export_table->NumberOfNames;
//得到导出表→ 名称表的地址
char* addressOfNames_address = transform_to_file((char*)export_table->AddressOfNames, memory) + (DWORD)memory;
//得到名称表存储名称的真实的值
char* addressOfNames = (char*)(transform_to_file((char*)*(DWORD*)addressOfNames_address, memory) + (DWORD)memory);
DWORD* name_address = (DWORD*)addressOfNames_address;
for (int i = 0; i < numberOfNames; i++) {
char* address_name = (char*)(transform_to_file((char*)*(DWORD*)name_address, memory) + (DWORD)memory);
*name_address = (DWORD)transform_to_memory((char*)(space2 - (DWORD)memory), memory);
for (int i = 0; i < strlen((char*)addressOfNames) + 1; i++) {
if (i == strlen((char*)(addressOfNames))) {
*space2 = 0;
space2++;
break;
}
*space2 = *address_name;
space2++;
address_name++;
}
name_address++;
}
//修改导出表名称表的地址的指针
export_table->AddressOfNames = (DWORD)transform_to_memory((char*)((DWORD)space2 - (DWORD)memory), memory);
//将名称表复制到新的空间
DWORD* space3 = (DWORD*)space2;
DWORD* need_copy_name = (DWORD*)addressOfNames_address;
for (int i = 0; i < numberOfNames; i++) {
*space3 = *need_copy_name;
space3++;
need_copy_name++;
}
//根据名称表的space3将序号表中的数据遍历至新的地址
short* space4 = (short*)space3;
int order_num = export_table->NumberOfNames;
short* order_site = (short*)(transform_to_file((char*)export_table->AddressOfNameOrdinals, memory) + (DWORD)memory);
//修改导出表->序号表的地址的指针
export_table->AddressOfNameOrdinals = (DWORD)transform_to_memory((char*)((DWORD)space3 - (DWORD)memory), memory);
for (int i = 0; i < order_num; i++) {
*space4 = *order_site;
space4++;
order_site++;
}
//根据名称表的space4将函数表中的数据遍历至新的地址
DWORD* space5 = (DWORD*)space4;
int function_num = export_table->NumberOfFunctions;
DWORD* function_site = (DWORD*)(transform_to_file((char*)export_table->AddressOfFunctions, memory) + (DWORD)memory);
//修改导出表->函数表的地址的指针
export_table->AddressOfFunctions = (DWORD)transform_to_memory((char*)((DWORD)space4 - (DWORD)memory), memory);
for (int i = 0; i < function_num; i++) {
*space5 = *function_site;
space5++;
function_site++;
}
//根据返回的space5将导出表的名称导至新的空间, 返回space6
DWORD* space6 = space5;
DWORD* function_name_site = (DWORD*)(transform_to_file((char*)export_table->Name, memory) + (DWORD)memory);
export_table->Name = (DWORD)transform_to_memory((char*)((DWORD)space5 - (DWORD)memory), memory);
*space6 = *function_name_site;
space6++;
//将导出表的数据根据space6移至新的空间
char* export_data_move = (char*)export_table;
PIMAGE_OPTIONAL_HEADER optional_last = optional_ptr(memory);
char* transform_export_address = (char*)optional_last->DataDirectory;
DWORD* export_table_site = (DWORD*)(transform_to_file((char*)*transform_export_address, memory) + (DWORD)memory);
*export_table_site = (DWORD)space6;
char* space7 = (char*)space6;
for (int i = 0; i < ((DWORD)(export_table + 1) - (DWORD)(export_table)); i++) {
*space7 = *export_data_move;
space7++;
export_data_move++;
}
return space7;
}
else {
printf("不存在导出表, 无法移动\n");
return 0;
}
return 0;
}
//移动重定位表
void move_reloc(char* space, char* memory) {
if (space != 0) {
//找到重定位表的位置
PIMAGE_OPTIONAL_HEADER optional = optional_ptr(memory);
DWORD* reloc = (DWORD*)optional->DataDirectory;
int circle_times = optional->NumberOfRvaAndSizes;
for (int i = 0; i < circle_times; i++) {
if (i == 5) {
break;
}
reloc = reloc + 2;
}
DWORD* reloc2 = (DWORD*)*reloc;
*reloc = (DWORD)transform_to_memory((char*)(space - memory), memory);
char* new_space = (char*)space;
PIMAGE_BASE_RELOCATION reloc3 = (PIMAGE_BASE_RELOCATION)(transform_to_file((char*)reloc2, memory) + (DWORD)memory);
char* reloc4 = NULL;
while (reloc3->SizeOfBlock != 0 && reloc3->VirtualAddress != 0) {
reloc4 = (char*)reloc3;
for (int i = 0; i < reloc3->SizeOfBlock; i++) {
*new_space = *reloc4;
new_space++;
reloc4++;
}
reloc3 = (PIMAGE_BASE_RELOCATION)((reloc3->SizeOfBlock) + (DWORD)reloc3);
}
for (int i = 0; i < 8; i++) {
*new_space = 0;
new_space++;
}
printf("移动重定位表成功\n");
}
else{
printf("导出表未移动成功, 重定位表移动失败\n");
}
}
void move_table(char path[]) {
FILE* file_point = OpenFile(path);
char* memory_point = GetMemory(file_point);
char* added_memory = add_table(memory_point, file_point);
char* space = move_export(added_memory);
move_reloc(space, added_memory);
export_file(added_memory);
char* memory[] = { added_memory };
int num = (sizeof(memory)) / 4;
FreeMemory(file_point, memory, num);
}
int main() {
char dll[] = "D:\\Ddisk\\逆向\\AutoUpdateUtil.dll";
char last_memory[] = "D:\\Ddisk\\last_memory.exe";
char notepad[] = "C:\\Windows\\System32\\notepad.exe";
char crack[] = "D:\\Ddisk\\逆向\\CrackMe.exe";
move_table(dll);
}
该代码实现读取PE文件,将导出表和重定位表的数据移到新节中,涉及内存分配、文件操作及PE结构解析。通过新增节、调整内存布局,并更新文件头信息来保存修改。
547

被折叠的 条评论
为什么被折叠?



