mirror of
https://github.com/maxDcb/C2Core
synced 2026-06-08 15:48:01 +00:00
266 lines
7.5 KiB
C++
266 lines
7.5 KiB
C++
#include "peb.hpp"
|
|
|
|
|
|
#if _WIN32
|
|
|
|
|
|
// Relative Virtual Address to Virtual Address
|
|
#define RVA2VA(type, base, rva) (type)((ULONG_PTR) base + rva)
|
|
|
|
|
|
// find a DLL with a certain export, used by xGetProcAddress and FindExport
|
|
LPVOID find_reference(
|
|
IN LPVOID original_dll,
|
|
IN PCHAR dll_name,
|
|
IN PCHAR api_name)
|
|
{
|
|
PPEB2 peb = NULL;
|
|
PPEB_LDR_DATA2 ldr = NULL;
|
|
PLDR_DATA_TABLE_ENTRY2 dte = NULL;
|
|
LPVOID addr = NULL;
|
|
LPVOID base = NULL;
|
|
|
|
peb = (PPEB2)READ_MEMLOC(PEB_OFFSET);
|
|
ldr = (PPEB_LDR_DATA2)peb->Ldr;
|
|
|
|
// for each DLL loaded
|
|
for (dte=(PLDR_DATA_TABLE_ENTRY2)ldr->InLoadOrderModuleList.Flink;
|
|
dte->DllBase != NULL && addr == NULL;
|
|
dte=(PLDR_DATA_TABLE_ENTRY2)dte->InLoadOrderLinks.Flink)
|
|
{
|
|
base = dte->DllBase;
|
|
// if this is the dll with the reference, continue
|
|
if (base == original_dll) continue;
|
|
|
|
addr = xGetProcAddress(base, api_name, 0);
|
|
}
|
|
if (addr == NULL)
|
|
{
|
|
// we did not find the reference, use LoadLibrary
|
|
// DPRINT("Could not find %s, using LoadLibraryA", dll_name);
|
|
HMODULE hModule = LoadLibraryA(dll_name);
|
|
if (hModule != NULL)
|
|
{
|
|
// DPRINT("Calling GetProcAddress(%s, %s)", dll_name, api_name);
|
|
addr = GetProcAddress(hModule, api_name);
|
|
}
|
|
}
|
|
|
|
return addr;
|
|
}
|
|
|
|
|
|
// size_t StringLengthA(const char* str)
|
|
// {
|
|
// if (str == nullptr)
|
|
// return 0;
|
|
|
|
// size_t length = 0;
|
|
// while (str[length] != '\0')
|
|
// {
|
|
// ++length;
|
|
// }
|
|
// return length;
|
|
// }
|
|
|
|
|
|
// search for an export in a DLL
|
|
LPVOID xGetProcAddress(
|
|
IN LPVOID base,
|
|
IN PCHAR api_name,
|
|
IN DWORD ordinal)
|
|
{
|
|
PIMAGE_DOS_HEADER dos = NULL;
|
|
PIMAGE_NT_HEADERS nt = NULL;
|
|
PIMAGE_DATA_DIRECTORY dir = NULL;
|
|
PIMAGE_EXPORT_DIRECTORY exp = NULL;
|
|
LPVOID addr = NULL;
|
|
DWORD rva = 0;
|
|
DWORD cnt = 0;
|
|
PDWORD adr = NULL;
|
|
PDWORD sym = NULL;
|
|
PWORD ord = NULL;
|
|
PCHAR api = NULL;
|
|
CHAR dll_name[256] = { 0 };
|
|
CHAR new_api[256] = { 0 };
|
|
DWORD i = 0;
|
|
PCHAR p = NULL;
|
|
DWORD len = 0;
|
|
PVOID newbase = NULL;
|
|
|
|
if (base == NULL) return NULL;
|
|
|
|
dos = (PIMAGE_DOS_HEADER)base;
|
|
nt = RVA2VA(PIMAGE_NT_HEADERS, base, dos->e_lfanew);
|
|
dir = (PIMAGE_DATA_DIRECTORY)nt->OptionalHeader.DataDirectory;
|
|
rva = dir[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
|
|
|
|
// if no export table, return NULL
|
|
if (rva == 0) return NULL;
|
|
|
|
exp = RVA2VA(PIMAGE_EXPORT_DIRECTORY, base, rva);
|
|
adr = RVA2VA(PDWORD,base, exp->AddressOfFunctions);
|
|
sym = RVA2VA(PDWORD,base, exp->AddressOfNames);
|
|
ord = RVA2VA(PWORD, base, exp->AddressOfNameOrdinals);
|
|
|
|
if (api_name != NULL)
|
|
{
|
|
// exported by name
|
|
cnt = exp->NumberOfNames;
|
|
// if no api names, return NULL
|
|
if (cnt == 0) return NULL;
|
|
|
|
do {
|
|
api = RVA2VA(PCHAR, base, sym[cnt-1]);
|
|
// check if the export name matches the API we are looking for
|
|
if (!_stricmp(api, api_name))
|
|
{
|
|
// get the address of the API
|
|
addr = RVA2VA(LPVOID, base, adr[ord[cnt-1]]);
|
|
}
|
|
} while (--cnt && addr == NULL);
|
|
}
|
|
else
|
|
{
|
|
// exported by ordinal
|
|
addr = RVA2VA(PVOID, base, adr[ordinal - exp->Base]);
|
|
}
|
|
|
|
// // is this a forward reference?
|
|
// if ((PBYTE)addr >= (PBYTE)exp &&
|
|
// (PBYTE)addr < (PBYTE)exp +
|
|
// dir[IMAGE_DIRECTORY_ENTRY_EXPORT].Size)
|
|
// {
|
|
// //DPRINT("%s is forwarded to %s", api_name, (char*)addr);
|
|
|
|
// // copy DLL name to buffer
|
|
// p=(char*)addr;
|
|
// len=StringLengthA(p);
|
|
|
|
// for (i=0; p[i] != 0 && i < sizeof(dll_name) - 4; i++)
|
|
// {
|
|
// dll_name[i] = p[i];
|
|
// }
|
|
|
|
// for (i=len-1; i > 0; i--)
|
|
// {
|
|
// if(p[i] == '.') break;
|
|
// }
|
|
|
|
// dll_name[i+1] = 'd';
|
|
// dll_name[i+2] = 'l';
|
|
// dll_name[i+3] = 'l';
|
|
// dll_name[i+4] = 0;
|
|
|
|
// p += i + 1;
|
|
|
|
// // copy API name to buffer
|
|
// for(i = 0; p[i] != 0 && i < sizeof(new_api) - 1; i++)
|
|
// {
|
|
// new_api[i] = p[i];
|
|
// }
|
|
// new_api[i] = 0;
|
|
|
|
// newbase = handle_dependency(NULL, dll_name);
|
|
// if (base == newbase)
|
|
// {
|
|
// /*
|
|
// * the api set seems to resolve to itself...
|
|
// * lets just iterate over all loaded modules and
|
|
// * find a module with the export we are looking for
|
|
// */
|
|
|
|
// addr = find_reference(base, dll_name, new_api);
|
|
// }
|
|
// else
|
|
// {
|
|
// /*
|
|
// * we got a different DLL, call xGetProcAddress recursively
|
|
// */
|
|
|
|
// addr = xGetProcAddress(newbase, new_api, 0);
|
|
// }
|
|
// }
|
|
|
|
return addr;
|
|
}
|
|
|
|
|
|
// find a DLL by name, load it if not found
|
|
LPVOID xGetLibAddress(
|
|
IN PCHAR search,
|
|
IN BOOL load,
|
|
OUT PBOOL loaded)
|
|
{
|
|
PPEB2 peb = NULL;
|
|
PPEB_LDR_DATA2 ldr = NULL;
|
|
PIMAGE_DOS_HEADER dos = NULL;
|
|
PIMAGE_NT_HEADERS nt = NULL;
|
|
PLDR_DATA_TABLE_ENTRY2 dte = NULL;
|
|
PIMAGE_EXPORT_DIRECTORY exp = NULL;
|
|
LPVOID addr = NULL;
|
|
LPVOID base = NULL;
|
|
DWORD rva = 0;
|
|
PCHAR name = NULL;
|
|
CHAR dll_name[64] = { 0 };
|
|
DWORD i = 0;
|
|
int correct = -1;
|
|
|
|
if (loaded)
|
|
*loaded = FALSE;
|
|
|
|
for(i = 0; search[i] != 0 && i < 64; i++)
|
|
{
|
|
dll_name[i] = search[i];
|
|
}
|
|
dll_name[i] = 0;
|
|
// make sure the name ends with '.dll'
|
|
if (dll_name[i-4] != '.')
|
|
{
|
|
dll_name[i++] = '.';
|
|
dll_name[i++] = 'd';
|
|
dll_name[i++] = 'l';
|
|
dll_name[i++] = 'l';
|
|
dll_name[i++] = 0;
|
|
}
|
|
|
|
peb = (PPEB2)READ_MEMLOC(PEB_OFFSET);
|
|
ldr = (PPEB_LDR_DATA2)peb->Ldr;
|
|
|
|
// for each DLL loaded
|
|
for (dte=(PLDR_DATA_TABLE_ENTRY2)ldr->InLoadOrderModuleList.Flink;
|
|
correct != 0 && dte->DllBase != NULL && addr == NULL;
|
|
dte=(PLDR_DATA_TABLE_ENTRY2)dte->InLoadOrderLinks.Flink)
|
|
{
|
|
base = dte->DllBase;
|
|
dos = (PIMAGE_DOS_HEADER)base;
|
|
nt = RVA2VA(PIMAGE_NT_HEADERS, base, dos->e_lfanew);
|
|
rva = nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
|
|
if (rva == 0) continue;
|
|
|
|
exp = RVA2VA(PIMAGE_EXPORT_DIRECTORY, base, rva);
|
|
name = RVA2VA(PCHAR, base, exp->Name);
|
|
|
|
correct = _stricmp(dll_name, name);
|
|
|
|
if (correct == 0) {
|
|
addr = base;
|
|
}
|
|
}
|
|
|
|
//DPRINT("Address of %s: %p", dll_name, addr);
|
|
|
|
// if the DLL was not found, load it
|
|
if (!addr && load)
|
|
{
|
|
addr = LoadLibraryA(dll_name);
|
|
// DPRINT("Dll not found. Loaded %s via LoadLibrary at 0x%p", dll_name, addr);
|
|
if (addr && loaded)
|
|
*loaded = TRUE;
|
|
}
|
|
|
|
return addr;
|
|
}
|
|
|
|
|
|
#endif |