使用gcc的attribute,修改pe的内容
起因
利用gcc section特性,将数组放到指定节中,然后通过读取PE修改节的内容,从而实现程序不用重新编译,就能修改exe输出的内容.__attribute__((section(".mydata")))
#include <stdio.h>
#include <stdlib.h>
//myname在gcc编译时,将myname放到节名为.mydata中
char myname[1024] __attribute__((section(".mydata"))) = "hello gcc ,hello section";
int main(int argc, char* argv[])
{
printf("%s\n", myname);
return 0;
}
通过读取pe修改.mydata中的内容
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
//获取文件大小
int file_size(char* file)
{
FILE* fp = fopen(file, "r");
fseek(fp, 0, SEEK_END);
int size = ftell(fp);
fclose(fp);
return size;
}
//将文件读取到内存中
int file_to_memory(char* file, int size, char** buffer)
{
FILE* fp = fopen(file, "rb+");
if (fp == NULL)
{
return -1;
}
else
{
//size = size + 1;
char* file_buffer = calloc(size, sizeof(char));
if (file_buffer == NULL)
{
return -2;
}
*buffer = NULL;
int result = fread(file_buffer, sizeof(char), size, fp);
fclose(fp);
//file_buffer[size - 1] = '\0';
*buffer = file_buffer;
return 0;
}
}
unsigned long buffer_to_image(char** file_buffer, char** image_buffer)
{
PIMAGE_DOS_HEADER dos_header = NULL;
PIMAGE_NT_HEADERS nt_header = NULL;
PIMAGE_FILE_HEADER file_header = NULL;
PIMAGE_OPTIONAL_HEADER optional_header = NULL;
PIMAGE_SECTION_HEADER section_header = NULL;
char* ptemp = *file_buffer;
void* temp_buffer = NULL;
if (file_buffer == NULL)
{
printf("file_buff is null\n");
return 0;
}
if (*(short*)ptemp != IMAGE_DOS_SIGNATURE)
{
printf("%08x\n", *(short*)ptemp);
//校验是否为dos头 pe开头为mz
return 0;
}
dos_header = (PIMAGE_DOS_HEADER)ptemp;
if (*((unsigned long*)(ptemp + dos_header->e_lfanew)) != IMAGE_NT_SIGNATURE)
{
//校验nt头是否有pe标志 PE
return 0;
}
nt_header = (PIMAGE_NT_HEADERS)((unsigned long)ptemp + dos_header->e_lfanew);
file_header = (PIMAGE_FILE_HEADER)((unsigned long)nt_header + 4);
optional_header = (PIMAGE_OPTIONAL_HEADER)((unsigned long)file_header + IMAGE_SIZEOF_FILE_HEADER);
section_header = (PIMAGE_SECTION_HEADER)((unsigned long)optional_header + file_header->SizeOfOptionalHeader);
//分配空间
temp_buffer = calloc(1, optional_header->SizeOfImage);
if (!temp_buffer)
{
temp_buffer = NULL;
return 0;
}
//先拷贝头
memcpy(temp_buffer, dos_header, optional_header->SizeOfHeaders);
PIMAGE_SECTION_HEADER temp_section_header = section_header;
for (int i = 0; i < file_header->NumberOfSections; i++)
{
PIMAGE_SECTION_HEADER psection = temp_section_header + i;
void* des = (void*)((unsigned long)temp_buffer + psection->VirtualAddress);
void* src = (void*)((unsigned long)ptemp + psection->PointerToRawData); //temp_section_header + 1,移动多少呢?
memcpy(des, src, psection->SizeOfRawData);
}
*image_buffer = temp_buffer;
temp_buffer = NULL;
return optional_header->SizeOfImage;
}
int recory_file(void** image_buffer, char* file, int size)
{
PIMAGE_DOS_HEADER dos_header = NULL;
PIMAGE_NT_HEADERS nt_header = NULL;
PIMAGE_FILE_HEADER file_header = NULL;
PIMAGE_OPTIONAL_HEADER optional_header = NULL;
PIMAGE_SECTION_HEADER section_header = NULL;
char* ptemp = *image_buffer;
dos_header = (PIMAGE_DOS_HEADER)ptemp;
if (*(short*)((unsigned long)ptemp + dos_header->e_lfanew) != IMAGE_NT_SIGNATURE)
{
//校验nt头是否有pe标志 PE
return 0;
}
nt_header = (PIMAGE_NT_HEADERS)((unsigned long)ptemp + dos_header->e_lfanew);
file_header = (PIMAGE_FILE_HEADER)((unsigned long)nt_header + 4);
optional_header = (PIMAGE_OPTIONAL_HEADER)((unsigned long)file_header + IMAGE_SIZEOF_FILE_HEADER);
section_header = (PIMAGE_SECTION_HEADER)((unsigned long)optional_header + file_header->SizeOfOptionalHeader);
char* file_buffer = calloc(1, size);
memcpy(file_buffer, dos_header, optional_header->SizeOfHeaders);
PIMAGE_SECTION_HEADER temp_section_header = section_header;
for (int i = 0; i < file_header->NumberOfSections; i++)
{
PIMAGE_SECTION_HEADER psection = temp_section_header + i;
void* des = (void*)((unsigned long)file_buffer + psection->PointerToRawData);
void* src = (void*)((unsigned long)ptemp + psection->VirtualAddress); //temp_section_header + 1,移动多少呢?
memcpy(des, src, psection->SizeOfRawData);
}
FILE* fp = fopen(file, "wb+");
if (fp != NULL)
{
fwrite((void*)file_buffer, size, 1, fp);
}
fclose(fp);
}
int test_write_code(char* file, int size)
{
PIMAGE_DOS_HEADER dos_header = NULL;
PIMAGE_NT_HEADERS nt_header = NULL;
PIMAGE_FILE_HEADER file_header = NULL;
PIMAGE_OPTIONAL_HEADER optional_header = NULL;
PIMAGE_SECTION_HEADER section_header = NULL;
char* buf;
file_to_memory(file, size, &buf);
char* img_buf;
buffer_to_image(&buf, &img_buf);
dos_header = (PIMAGE_DOS_HEADER)img_buf;
nt_header = (PIMAGE_NT_HEADERS)((unsigned long)img_buf + dos_header->e_lfanew);
file_header = (PIMAGE_FILE_HEADER)((unsigned long)nt_header + 4);
optional_header = (PIMAGE_OPTIONAL_HEADER)((unsigned long)file_header + IMAGE_SIZEOF_FILE_HEADER);
section_header = (PIMAGE_SECTION_HEADER)((unsigned long)optional_header + file_header->SizeOfOptionalHeader);
PIMAGE_SECTION_HEADER temp_section_header = section_header;
char* name = ".mydata";
for (int i = 0; i < file_header->NumberOfSections; i++)
{
PIMAGE_SECTION_HEADER psection = temp_section_header + i;
if (strcmp(psection->Name, name) == 0)
{
char* dest = img_buf+ psection->VirtualAddress;
char* src = "pe write:hello section";
strcpy(dest, src);
break;
}
}
recory_file(&img_buf, "pe-section.exe", size);
if (buf)
{
free(buf);
}
if (img_buf)
{
free(img_buf);
}
}
int main(int argc, char* argv[])
{
char* file = "test-section.exe";
int size = file_size(file);
test_write_code(file, size);
return 0;
}
效果

没有重新编译test-section.exe,实现输出不同的内容
秋风
2019-07-30