Created
March 6, 2024 13:00
-
-
Save WKL-Sec/4589927d184d904eed37a572847c72ef to your computer and use it in GitHub Desktop.
Dynamically retrieves the OpenProcess function address by parsing the kernel32.dll export table using Inline Assembly.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// White Knight Labs - Offensive Development | |
// Inline Assembly - Get Function Address | |
#include <iostream> | |
#include <windows.h> | |
// Function definition | |
void* GetFunctionAddress(const char* functionName) { | |
void* getFunctionAddr = nullptr; | |
// Inline assembly to obtain Function Address | |
__asm { | |
// Prepare the stack and save callee-saved registers | |
sub rsp, 200h | |
mov [rsp + 40h], rbp // Save RBP | |
mov [rsp + 48h], rdi // Save RDI | |
mov [rsp + 50h], rsi // Save RSI | |
mov [rsp + 58h], rbx | |
mov [rsp + 60h], rcx // Saving argument from RCX | |
mov [rsp + 68h], r12 | |
mov [rsp + 70h], r13 | |
mov [rsp + 78h], r14 | |
mov [rsp + 80h], r15 | |
// Start of finding kernel32 base address | |
mov rdi, 0xFFFFFFFFFFFFFFFF | |
inc rdi | |
mov rax, 0 | |
lea rsi, [rax + 0x10] | |
add rsi, 0x50 | |
mov rbx, gs:[rsi] // Load GS segment at RSI into RBX (PEB access) | |
lea rsi, [rbx + 0x10 + 0x8] | |
mov rbx, [rsi] | |
lea rsi, [rbx + 0x10 + 0x10] | |
mov rbx, [rsi] | |
mov rbx, [rbx] | |
mov rbx, [rbx] // Find Kernel32 | |
lea rsi, [rbx + 0x10 + 0x10] | |
mov rbx, [rsi] | |
// RBX now contains Kernel32 base address | |
// Preparation for function name comparison | |
mov rax, [rsp + 60h] // Load the address pointing to the target function name string into RAX | |
mov rax, [rax] // Dereference RAX to get the actual function name pointer (corrected) | |
// Setting up for export table parsing | |
sub r8, r8 // Clear R8 | |
mov r8d, [rbx + 0x1e + 0x1e] // Calculate DOS->e_lfanew offset using split offsets for obfuscation | |
mov rdx, r8 // Move DOS->e_lfanew to RDX | |
add rdx, rbx // Calculate PE Header address | |
mov r8d, [rdx + 0x60 + 0x10 + 0x18] // Calculate offset to the export table with split offsets | |
add r8, rbx // Update R8 to point to the export table | |
sub rsi, rsi // Clear RSI | |
mov esi, [r8 + 0x10 + 0x10] // Calculate the offset to the names table with split offsets | |
add rsi, rbx // Update RSI to point to the names table | |
mov rcx, 0 // Initialize RCX to 0 | |
mov r9, rax // Move function name pointer from RAX to R9 for comparison | |
Get_Function: | |
inc rcx // Increment the ordinal | |
mov rax, 0 // Clear RAX | |
mov eax, [rsi + rcx * 4] // Load the next function name offset | |
add rax, rbx // Calculate the actual function name address | |
cmp QWORD ptr [rax], r9 // Compare with the target function name | |
jnz Get_Function // Jump if not equal, continue searching | |
sub rsi, rsi // Clear RSI | |
mov esi, [r8 + 0x20 + 0x4] // Calculate offset to the ordinals table with split offsets | |
add rsi, rbx // Update RSI to point to the ordinals table | |
mov cx, [rsi + rcx * 2] // Load the ordinal number | |
sub rsi, rsi // Clear RSI again | |
mov esi, [r8 + 0x0e + 0x0e] // Calculate offset to the address table with split offsets | |
add rsi, rbx // Update RSI to point to the address table | |
mov rdx, 0 // Clear RDX | |
mov edx, [rsi + rcx * 4] // Load the function address (offset) | |
add rdx, rbx // Calculate the actual function address | |
// Save function address for later use | |
mov getFunctionAddr, rdx // Save the actual address of the target function in getFunctionAddr | |
return_label: | |
// Restore callee-saved registers, cleanup, and return | |
mov rbp, [rsp + 40h] // Restore RBP | |
mov rdi, [rsp + 48h] // Restore RDI | |
mov rsi, [rsp + 50h] // Restore RSI | |
mov rbx, [rsp + 58h] | |
mov r12, [rsp + 68h] | |
mov r13, [rsp + 70h] | |
mov r14, [rsp + 78h] | |
mov r15, [rsp + 80h] | |
add rsp, 200h // Restore the stack pointer | |
} | |
return getFunctionAddr; | |
} | |
int main() { | |
const char* functionName = "OpenProcess"; | |
void* getFunctionAddr = GetFunctionAddress(functionName); | |
std::cout << "Function Address for " << functionName << ": " << getFunctionAddr << std::endl; | |
return 0; | |
} |
This is for Windows x64
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Which operating system and architecture is compatible?