mirror of https://github.com/hfiref0x/UACME.git
182 lines
6.0 KiB
C
182 lines
6.0 KiB
C
/*******************************************************************************
|
|
*
|
|
* (C) COPYRIGHT AUTHORS, 2015 - 2017
|
|
*
|
|
* TITLE: LDR.C
|
|
*
|
|
* VERSION: 2.72
|
|
*
|
|
* DATE: 26 May 2017
|
|
*
|
|
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
|
|
* ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
|
|
* TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
|
|
* PARTICULAR PURPOSE.
|
|
*
|
|
*******************************************************************************/
|
|
|
|
#include "global.h"
|
|
|
|
DWORD align_gt(
|
|
DWORD p,
|
|
DWORD align
|
|
)
|
|
{
|
|
if ((p % align) == 0)
|
|
return p;
|
|
|
|
return p + align - (p % align);
|
|
}
|
|
|
|
DWORD align_le(
|
|
DWORD p,
|
|
DWORD align
|
|
)
|
|
{
|
|
if ((p % align) == 0)
|
|
return p;
|
|
|
|
return p - (p % align);
|
|
}
|
|
|
|
LPVOID PELoaderLoadImage(
|
|
_In_ LPVOID Buffer,
|
|
_Out_opt_ PDWORD SizeOfImage
|
|
)
|
|
{
|
|
LPVOID exeBuffer = NULL;
|
|
PIMAGE_DOS_HEADER dosh = (PIMAGE_DOS_HEADER)Buffer;
|
|
PIMAGE_FILE_HEADER fileh = (PIMAGE_FILE_HEADER)((PBYTE)dosh + sizeof(DWORD) + dosh->e_lfanew);
|
|
PIMAGE_OPTIONAL_HEADER popth = (PIMAGE_OPTIONAL_HEADER)((PBYTE)fileh + sizeof(IMAGE_FILE_HEADER));
|
|
PIMAGE_SECTION_HEADER sections = (PIMAGE_SECTION_HEADER)((PBYTE)fileh + sizeof(IMAGE_FILE_HEADER) + fileh->SizeOfOptionalHeader);
|
|
DWORD c, p, rsz;
|
|
PIMAGE_BASE_RELOCATION rel;
|
|
DWORD_PTR delta;
|
|
LPWORD chains;
|
|
|
|
do {
|
|
|
|
if (SizeOfImage) {
|
|
*SizeOfImage = popth->SizeOfImage;
|
|
}
|
|
|
|
exeBuffer = VirtualAlloc(NULL, popth->SizeOfImage, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
|
|
if (exeBuffer == NULL)
|
|
break;
|
|
|
|
// render image
|
|
memcpy(exeBuffer, Buffer, align_gt(popth->SizeOfHeaders, popth->FileAlignment));
|
|
|
|
for (c = 0; c < fileh->NumberOfSections; c++)
|
|
if ((sections[c].SizeOfRawData > 0) && (sections[c].PointerToRawData > 0))
|
|
memcpy((PBYTE)exeBuffer + sections[c].VirtualAddress,
|
|
(PBYTE)Buffer + align_le(sections[c].PointerToRawData, popth->FileAlignment),
|
|
align_gt(sections[c].SizeOfRawData, popth->FileAlignment));
|
|
|
|
// reloc image
|
|
dosh = (PIMAGE_DOS_HEADER)exeBuffer;
|
|
fileh = (PIMAGE_FILE_HEADER)((PBYTE)dosh + sizeof(DWORD) + dosh->e_lfanew);
|
|
popth = (PIMAGE_OPTIONAL_HEADER)((PBYTE)fileh + sizeof(IMAGE_FILE_HEADER));
|
|
sections = (PIMAGE_SECTION_HEADER)((PBYTE)fileh + sizeof(IMAGE_FILE_HEADER) + fileh->SizeOfOptionalHeader);
|
|
|
|
if (popth->NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_BASERELOC)
|
|
if (popth->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress != 0)
|
|
{
|
|
rel = (PIMAGE_BASE_RELOCATION)((PBYTE)exeBuffer + popth->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
|
|
rsz = popth->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
|
|
delta = (DWORD_PTR)exeBuffer - popth->ImageBase;
|
|
|
|
c = 0;
|
|
while (c < rsz) {
|
|
p = sizeof(IMAGE_BASE_RELOCATION);
|
|
chains = (LPWORD)((PBYTE)rel + p);
|
|
|
|
while (p < rel->SizeOfBlock) {
|
|
|
|
switch (*chains >> 12) {
|
|
case IMAGE_REL_BASED_HIGHLOW:
|
|
*(LPDWORD)((ULONG_PTR)exeBuffer + rel->VirtualAddress + (*chains & 0x0fff)) += (DWORD)delta;
|
|
break;
|
|
case IMAGE_REL_BASED_DIR64:
|
|
*(PULONGLONG)((ULONG_PTR)exeBuffer + rel->VirtualAddress + (*chains & 0x0fff)) += delta;
|
|
break;
|
|
}
|
|
|
|
chains++;
|
|
p += sizeof(WORD);
|
|
}
|
|
|
|
c += rel->SizeOfBlock;
|
|
rel = (PIMAGE_BASE_RELOCATION)((PBYTE)rel + rel->SizeOfBlock);
|
|
}
|
|
}
|
|
|
|
return exeBuffer;
|
|
} while (FALSE);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
LPVOID PELoaderGetProcAddress(
|
|
_In_ LPVOID ImageBase,
|
|
_In_ PCHAR RoutineName
|
|
)
|
|
{
|
|
PIMAGE_EXPORT_DIRECTORY ExportDirectory = NULL;
|
|
PIMAGE_FILE_HEADER fh1 = NULL;
|
|
PIMAGE_OPTIONAL_HEADER32 oh32 = NULL;
|
|
PIMAGE_OPTIONAL_HEADER64 oh64 = NULL;
|
|
|
|
USHORT OrdinalNumber;
|
|
PULONG NameTableBase;
|
|
PUSHORT NameOrdinalTableBase;
|
|
PULONG Addr;
|
|
LONG Result;
|
|
ULONG High, Low, Middle = 0;
|
|
|
|
fh1 = (PIMAGE_FILE_HEADER)((ULONG_PTR)ImageBase + ((PIMAGE_DOS_HEADER)ImageBase)->e_lfanew + sizeof(DWORD));
|
|
oh32 = (PIMAGE_OPTIONAL_HEADER32)((ULONG_PTR)fh1 + sizeof(IMAGE_FILE_HEADER));
|
|
oh64 = (PIMAGE_OPTIONAL_HEADER64)oh32;
|
|
|
|
if (fh1->Machine == IMAGE_FILE_MACHINE_AMD64) {
|
|
ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((ULONG_PTR)ImageBase +
|
|
oh64->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
|
|
}
|
|
else {
|
|
ExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((ULONG_PTR)ImageBase +
|
|
oh32->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
|
|
}
|
|
|
|
NameTableBase = (PULONG)((PBYTE)ImageBase + (ULONG)ExportDirectory->AddressOfNames);
|
|
NameOrdinalTableBase = (PUSHORT)((PBYTE)ImageBase + (ULONG)ExportDirectory->AddressOfNameOrdinals);
|
|
Low = 0;
|
|
High = ExportDirectory->NumberOfNames - 1;
|
|
while (High >= Low) {
|
|
Middle = (Low + High) >> 1;
|
|
Result = _strcmp_a(
|
|
RoutineName,
|
|
(char *)ImageBase + NameTableBase[Middle]
|
|
);
|
|
if (Result < 0) {
|
|
High = Middle - 1;
|
|
}
|
|
else {
|
|
if (Result > 0) {
|
|
Low = Middle + 1;
|
|
}
|
|
else {
|
|
break;
|
|
}
|
|
}
|
|
} //while
|
|
if (High < Low)
|
|
return NULL;
|
|
|
|
OrdinalNumber = NameOrdinalTableBase[Middle];
|
|
if ((ULONG)OrdinalNumber >= ExportDirectory->NumberOfFunctions)
|
|
return NULL;
|
|
|
|
Addr = (PULONG)((PBYTE)ImageBase + (ULONG)ExportDirectory->AddressOfFunctions);
|
|
return (LPVOID)((PBYTE)ImageBase + Addr[OrdinalNumber]);
|
|
}
|