330 lines
9.6 KiB
C
330 lines
9.6 KiB
C
//License: GPLv3.0
|
|
#include "sections.h"
|
|
#include "misc.h"
|
|
|
|
IMAGE_SECTION_HEADER *sections_by_index_get_sh(void *image, int index)
|
|
{
|
|
hdrs h;
|
|
IMAGE_SECTION_HEADER *sh;
|
|
|
|
if (-1 == hdrs_init(&h, image))
|
|
return NULL;
|
|
if (index >= hdrs_get_number_of_sections(&h))
|
|
return NULL;
|
|
sh = hdrs_get_first_section_header(&h);
|
|
if (-1 == test_for_list_end(sh, index, sizeof (IMAGE_SECTION_HEADER)))
|
|
return NULL;
|
|
hdrs_destroy(&h);
|
|
return &sh[index];
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
|
|
IMAGE_SECTION_HEADER* sections_by_name_get_sh(void *image, const char *name)
|
|
{
|
|
hdrs h;
|
|
IMAGE_SECTION_HEADER *currSh;
|
|
|
|
if (-1 == hdrs_init(&h, image))
|
|
goto sections_by_name_get_sh_error;
|
|
for (int i = 0; i < hdrs_get_number_of_sections(&h); i++)
|
|
{
|
|
currSh = sections_by_index_get_sh(image, i);
|
|
if (0 == pic_strncmp(name, currSh->Name, IMAGE_SIZEOF_SHORT_NAME))
|
|
{
|
|
hdrs_destroy(&h);
|
|
return currSh;
|
|
}
|
|
}
|
|
sections_by_name_get_sh_error:
|
|
hdrs_destroy(&h);
|
|
return NULL;
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
|
|
int sections_by_name_get_index(void *image, const char *name)
|
|
{
|
|
hdrs h;
|
|
IMAGE_SECTION_HEADER *currSh;
|
|
|
|
if (-1 == hdrs_init(&h, image))
|
|
goto sections_by_name_get_index_error;
|
|
for (int i = 0; i < hdrs_get_number_of_sections(&h); i++)
|
|
{
|
|
currSh = sections_by_index_get_sh(image, i);
|
|
if (0 == pic_strncmp(name, currSh->Name, IMAGE_SIZEOF_SHORT_NAME))
|
|
{
|
|
hdrs_destroy(&h);
|
|
return i;
|
|
}
|
|
}
|
|
sections_by_name_get_index_error:
|
|
hdrs_destroy(&h);
|
|
return -1;
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
|
|
char *sections_by_index_get_name(void *image, int idx)
|
|
{
|
|
IMAGE_SECTION_HEADER *sh;
|
|
|
|
sh = sections_by_index_get_sh(image, idx);
|
|
if (NULL == sh) return NULL;
|
|
return sh->Name;
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
|
|
void *sections_by_name_get_pointer_to_memory(void *image, const char *name)
|
|
{
|
|
IMAGE_SECTION_HEADER *sh = sections_by_name_get_sh(image, name);
|
|
return &((char*)image)[sh->PointerToRawData];
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
|
|
void sections_by_name_set_name(void *image, const char *name, const char *replace)
|
|
{
|
|
IMAGE_SECTION_HEADER *sh;
|
|
|
|
sh = sections_by_name_get_sh(image, name);
|
|
pic_memset(sh->Name, 0, IMAGE_SIZEOF_SHORT_NAME);
|
|
pic_memcpy(sh->Name, replace, IMAGE_SIZEOF_SHORT_NAME);
|
|
return;
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
|
|
void sections_by_name_set_characteristics(void *image, const char *name, uint32_t characteristics)
|
|
{
|
|
IMAGE_SECTION_HEADER *sh;
|
|
|
|
sh = sections_by_name_get_sh(image, name);
|
|
sh->Characteristics = characteristics;
|
|
return;
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
|
|
uint32_t sections_by_name_get_characteristics(void *image, const char *name)
|
|
{
|
|
IMAGE_SECTION_HEADER *sh;
|
|
|
|
sh = sections_by_name_get_sh(image, name);
|
|
return sh->Characteristics;
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
|
|
int sections_by_name_is_writable(void *image, const char *name)
|
|
{
|
|
uint32_t flags = sections_by_name_get_characteristics(image, name);
|
|
|
|
if (IMAGE_SCN_MEM_WRITE & flags)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
//////////////////////////////////////////////////
|
|
|
|
int sections_by_name_is_readable(void *image, const char *name)
|
|
{
|
|
uint32_t flags = sections_by_name_get_characteristics(image, name);
|
|
|
|
if (IMAGE_SCN_MEM_READ & flags)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
////////////////////////////////////////////////
|
|
|
|
int sections_by_name_is_executable(void *image, const char *name)
|
|
{
|
|
uint32_t flags = sections_by_name_get_characteristics(image, name);
|
|
|
|
if (IMAGE_SCN_MEM_EXECUTE & flags)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
|
|
void sections_by_name_set_writable(void *image, const char *name)
|
|
{
|
|
IMAGE_SECTION_HEADER *sh;
|
|
|
|
sh = sections_by_name_get_sh(image, name);
|
|
sh->Characteristics = (sh->Characteristics | IMAGE_SCN_MEM_WRITE);
|
|
}
|
|
//////////////////////////////////////////////////
|
|
|
|
void sections_by_name_set_readable(void *image, const char *name)
|
|
{
|
|
IMAGE_SECTION_HEADER *sh;
|
|
|
|
sh = sections_by_name_get_sh(image, name);
|
|
sh->Characteristics = (sh->Characteristics | IMAGE_SCN_MEM_READ);
|
|
}
|
|
|
|
////////////////////////////////////////////////
|
|
|
|
void sections_by_name_set_executable(void *image, const char *name)
|
|
{
|
|
IMAGE_SECTION_HEADER *sh;
|
|
|
|
sh = sections_by_name_get_sh(image, name);
|
|
sh->Characteristics = (sh->Characteristics | IMAGE_SCN_MEM_EXECUTE);
|
|
}
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////
|
|
|
|
void *sections_add_section(void *image, int imageSz, void *spaceRetImage,
|
|
int spaceSz, const char *name, uint32_t size)
|
|
{
|
|
void *newImage;
|
|
int newImageSz;
|
|
IMAGE_SECTION_HEADER *newSection, *lastSection;
|
|
hdrs h;
|
|
|
|
if (-1 == hdrs_init(&h, image))
|
|
return NULL;
|
|
newImageSz = imageSz + align(size, hdrs_get_file_alignment(&h));
|
|
if (newImageSz > spaceSz) return NULL;
|
|
newImage = spaceRetImage;
|
|
hdrs_destroy(&h);
|
|
pic_memcpy(newImage, image, imageSz);
|
|
if (-1 == hdrs_init(&h, newImage))
|
|
goto sections_add_section_error;
|
|
/*hdrs_get_number_of_sections returns the index of the last section+1
|
|
because indexes start counting with 0*/
|
|
newSection = sections_by_index_get_sh(newImage,
|
|
(hdrs_get_number_of_sections(&h)-1));
|
|
newSection++;
|
|
pic_memcpy(newSection->Name, name, IMAGE_SIZEOF_SHORT_NAME);
|
|
newSection->Misc.VirtualSize = size;
|
|
lastSection = sections_by_index_get_sh(newImage,
|
|
hdrs_get_number_of_sections(&h)-1);
|
|
newSection->VirtualAddress = lastSection->VirtualAddress
|
|
+ lastSection->Misc.VirtualSize;
|
|
newSection->VirtualAddress = align(newSection->VirtualAddress,
|
|
hdrs_get_section_alignment(&h));
|
|
newSection->SizeOfRawData = align(size, hdrs_get_file_alignment(&h));
|
|
newSection->PointerToRawData = lastSection->PointerToRawData
|
|
+ lastSection->SizeOfRawData;
|
|
newSection->Characteristics = 0;
|
|
hdrs_set_number_of_sections(&h, hdrs_get_number_of_sections(&h)+1);
|
|
hdrs_set_size_of_image(&h, hdrs_get_size_of_image(&h)
|
|
+ align(newSection->Misc.VirtualSize,
|
|
hdrs_get_section_alignment(&h)));
|
|
/*relocate the symbol table*/
|
|
int stripSz;
|
|
char *stripBuf;
|
|
if (hdrs_get_pointer_to_symbol_table(&h))
|
|
{
|
|
stripSz = imageSz - hdrs_get_pointer_to_symbol_table(&h);
|
|
stripBuf = pic_malloc(stripSz);
|
|
pic_memcpy(stripBuf, &((char*)newImage)[hdrs_get_pointer_to_symbol_table(&h)], stripSz);
|
|
hdrs_set_pointer_to_symbol_table(&h, newSection->PointerToRawData
|
|
+ newSection->SizeOfRawData);
|
|
pic_memcpy(&((char*)newImage)[hdrs_get_pointer_to_symbol_table(&h)], stripBuf,
|
|
stripSz);
|
|
pic_free(stripBuf);
|
|
}
|
|
return &((char *)newImage)[newSection->PointerToRawData];
|
|
sections_add_section_error:
|
|
pic_free(newImage);
|
|
return NULL;
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
|
|
uint32_t sections_get_sizeof_image_after_add_section(void *oldImage,
|
|
uint32_t oldSz,
|
|
uint32_t addedSz)
|
|
{
|
|
hdrs h;
|
|
uint32_t newImageSz;
|
|
|
|
hdrs_init(&h, oldImage);
|
|
newImageSz = oldSz + align(addedSz, hdrs_get_file_alignment(&h));
|
|
hdrs_destroy(&h);
|
|
return newImageSz;
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
|
|
void *sections_by_name_enlarge(void *image, const char *name,
|
|
char *bytes, uint32_t bytesLen)
|
|
{
|
|
IMAGE_SECTION_HEADER *enlargeSec;
|
|
char *writePtr;
|
|
|
|
enlargeSec = sections_by_name_get_sh(image, name);
|
|
|
|
if (NULL == enlargeSec) return NULL;
|
|
|
|
if ((enlargeSec->SizeOfRawData - enlargeSec->Misc.VirtualSize) < bytesLen)
|
|
return NULL;
|
|
writePtr = rva_to_ptr(image, (enlargeSec->VirtualAddress));
|
|
writePtr += enlargeSec->Misc.VirtualSize;
|
|
enlargeSec->Misc.VirtualSize += bytesLen;
|
|
if (NULL != bytes)
|
|
pic_memcpy(writePtr, bytes, bytesLen);
|
|
return (void *)writePtr;
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
|
|
uint32_t rva_to_raw(char *image, uint32_t rva)
|
|
{
|
|
hdrs h;
|
|
hdrs_init(&h, image);
|
|
IMAGE_SECTION_HEADER *sh;
|
|
|
|
for(int i = 0; i < hdrs_get_number_of_sections(&h); i++)
|
|
{
|
|
sh = sections_by_index_get_sh(image, i);
|
|
if (sh->VirtualAddress <= rva
|
|
&& rva < (sh->VirtualAddress + sh->Misc.VirtualSize))
|
|
return (rva - sh->VirtualAddress + sh->PointerToRawData);
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
|
|
void *rva_to_ptr(void *image, uint32_t rva)
|
|
{
|
|
return &((char *)image)[rva_to_raw(image, rva)];
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
|
|
uint32_t raw_to_rva(char *image, uint32_t raw)
|
|
{
|
|
hdrs h;
|
|
IMAGE_SECTION_HEADER *sh;
|
|
hdrs_init(&h, image);
|
|
|
|
for (int i = 0; i < hdrs_get_number_of_sections(&h); i++)
|
|
{
|
|
sh = sections_by_index_get_sh(image, i);
|
|
if (sh->PointerToRawData <= raw
|
|
&& raw < (sh->PointerToRawData + sh->SizeOfRawData))
|
|
return (raw - sh->PointerToRawData + sh->VirtualAddress);
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
/////////////////////////////////////////////////
|
|
|
|
uint32_t ptr_to_rva(void *image, void *ptr)
|
|
{
|
|
uint32_t raw;
|
|
raw = (uint32_t)(ptr - image);
|
|
return raw_to_rva(image, raw);
|
|
}
|