pslib/ps_image.cpp
2021-12-04 05:23:44 +02:00

201 lines
No EOL
5.4 KiB
C++

#include "ps_image.h"
static DWORD _ps_section_flags[PS_IMAGE_SECTIONS] = {
PAGE_EXECUTE_READ,
PAGE_READWRITE,
PAGE_READONLY
};
static DWORD _ps_image_vsec_init_size = PS_DEFAULT_RDATA_RSIZE;
static BOOL _ps_in_section(ULONG_PTR Base, PIMAGE_SECTION_HEADER pSection, ULONG_PTR Addr)
{
ULONG_PTR Start = Base + pSection->VirtualAddress;
ULONG_PTR End = Start + ps_section_size(pSection);
return (Addr >= Start) && (Addr < End);
}
static INT _ps_determine_section(ULONG_PTR Base,PIMAGE_SECTION_HEADER* pHeaders, DWORD dwNum, ULONG_PTR Addr)
{
for (DWORD i = 0; i < dwNum; i++)
{
ULONG_PTR Start = Base + pHeaders[i]->VirtualAddress;
ULONG_PTR End = Start + ps_round_to_page(pHeaders[i]->SizeOfRawData);
if (Addr >= Start && Addr < End)
return (INT)i;
}
return -1;
}
ps_image_t* ps_image_create(pe_t* mod, ULONG_PTR VirtualBase,
LPCSTR lpCodeSectionName, LPCSTR lpDataSectionName)
{
PIMAGE_SECTION_HEADER pHeaders[PS_IMAGE_SECTIONS];
pHeaders[PS_IMAGE_SECTION_CODE] = ps_get_section_header(mod, lpCodeSectionName);
pHeaders[PS_IMAGE_SECTION_DATA] = ps_get_section_header(mod, lpDataSectionName);
pHeaders[PS_IMAGE_SECTION_RDATA] = NULL;
if (!pHeaders[PS_IMAGE_SECTION_CODE] || !pHeaders[PS_IMAGE_SECTION_DATA])
return NULL;
ps_image_t* image = (ps_image_t*)malloc(sizeof(ps_image_t));
image->VirtualBase = VirtualBase;
image->dwImports = 0;
image->import = NULL;
//Initialize sections
image->dwVirtualSize = 0;
for (DWORD i = 0; i < PS_IMAGE_SECTIONS; i++)
{
image->RSec[i].dwRealSize = pHeaders[i]
? pHeaders[i]->SizeOfRawData : _ps_image_vsec_init_size;
image->RSec[i].pData = (PCHAR)malloc(image->RSec[i].dwRealSize);
image->VSec[i].dwRVA = image->dwVirtualSize;
image->VSec[i].dwSize = ps_round_to_page(image->RSec[i].dwRealSize);
image->VSec[i].dwFlags = _ps_section_flags[i];
if (pHeaders[i])
{
LPCVOID lpSource = (LPCVOID)(mod->BaseAddress + pHeaders[i]->VirtualAddress);
CopyMemory(image->RSec[i].pData, lpSource, image->RSec[i].dwRealSize);
}
else ZeroMemory(image->RSec[i].pData, image->RSec[i].dwRealSize);
image->dwVirtualSize += image->VSec[i].dwSize;
}
ULONG_PTR ModBase = mod->BaseAddress;
#ifndef _WIN64
pe_reloc_t* rel = reloc_load(ps_this_process, mod);
WORD wReloc;
pe_import_t* imp = import_load(ps_this_process, mod);
CHAR szLibName[64];
CHAR szFuncName[64];
while ((wReloc = reloc_next(rel)) != PS_NO_RELOC)
{
WORD wType = wReloc >> 12;
ULONG_PTR RelocAddr = ModBase + (rel->pBlock->VirtualAddress | (wReloc & 0xFFF));
if (wType != IMAGE_REL_BASED_HIGHLOW && wType != IMAGE_REL_BASED_DIR64)
continue;
INT iSrcSec = _ps_determine_section(ModBase, pHeaders, 2, RelocAddr);
if (iSrcSec == -1) continue;
PULONG_PTR DestAddr = (PULONG_PTR)(image->RSec[iSrcSec].pData +
((RelocAddr - pHeaders[iSrcSec]->VirtualAddress) - ModBase));
if (import_find_thunk(imp, *(PULONG_PTR)RelocAddr, szLibName, sizeof(szLibName),
szFuncName, sizeof(szFuncName)))
{
ps_import_thunk_t* thunk = ps_image_import_add(image, szLibName, szFuncName);
*DestAddr = image->VirtualBase + image->VSec[PS_IMAGE_SECTION_RDATA].dwRVA
+ (thunk->dwIndex * sizeof(ULONG_PTR));
}
else
{
INT iDstSec = _ps_determine_section(ModBase, pHeaders, 2, *(PULONG_PTR)RelocAddr);
if (iDstSec == -1) continue;
*DestAddr = image->VirtualBase + image->VSec[iDstSec].dwRVA
+ ((*(PULONG_PTR)RelocAddr - ModBase) - pHeaders[iDstSec]->VirtualAddress);
}
}
#endif
reloc_unload(rel);
import_unload(imp);
return image;
}
//ps_image_import_add: Find or create thunk import
ps_import_thunk_t* ps_image_import_add(ps_image_t* image, LPCSTR lpLibName, LPCSTR lpFuncName)
{
ps_import_lib_t* lib = NULL;
ps_import_lib_t* lastLib = NULL;
ps_import_thunk_t* thunk = NULL;
ps_import_thunk_t* lastThunk = NULL;
//Find or create ps_import_lib_t
lastLib = image->import;
while (lastLib)
{
SIZE_T uNameLen = strlen(lpLibName);
if (!memcmp(lastLib->szLibName, lpLibName,
min(uNameLen, sizeof(lastLib->szLibName))))
{
if (!lib) lib = lastLib;
}
if (!lastLib->next) break;
else lastLib = lastLib->next;
}
if (!lib)
{
lib = (ps_import_lib_t*)malloc(sizeof(ps_import_lib_t));
lib->thunk = NULL;
lib->next = NULL;
strcpy_s(lib->szLibName, sizeof(lib->szLibName), lpLibName);
if (lastLib) lastLib->next = lib;
else image->import = lib;
}
//Find or create ps_import_thunk_t
lastThunk = lib->thunk;
while (lastThunk)
{
SIZE_T uNameLen = strlen(lpFuncName);
if (!memcmp(lastThunk->szFuncName, lpFuncName,
min(uNameLen, sizeof(lastThunk->szFuncName))))
{
if (!thunk) thunk = lastThunk;
}
if (!lastThunk->next) break;
else lastThunk = lastThunk->next;
}
if (!thunk)
{
thunk = (ps_import_thunk_t*)malloc(sizeof(ps_import_thunk_t));
thunk->dwIndex = image->dwImports++;
thunk->next = NULL;
strcpy_s(thunk->szFuncName, sizeof(thunk->szFuncName), lpFuncName);
if (lastThunk) lastThunk->next = thunk;
else lib->thunk = thunk;
}
return thunk;
}
static void _ps_image_import_free(ps_import_lib_t* lib)
{
ps_import_lib_t* libItem = lib;
while (libItem)
{
ps_import_thunk_t* thunkItem = libItem->thunk;
while (thunkItem)
{
ps_import_thunk_t* thunkNext = thunkItem->next;
free(thunkItem);
thunkItem = thunkNext;
}
ps_import_lib_t* libNext = libItem->next;
free(libItem);
libItem = libNext;
}
}
void ps_image_free(ps_image_t* image)
{
_ps_image_import_free(image->import);
for (DWORD i = 0; i < PS_IMAGE_SECTIONS; i++)
free(image->RSec[i].pData);
free(image);
}