Skip to content

Instantly share code, notes, and snippets.

@WKL-Sec
Created March 6, 2024 13:00
Show Gist options
  • Save WKL-Sec/4589927d184d904eed37a572847c72ef to your computer and use it in GitHub Desktop.
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.
// 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;
}
@CaledoniaProject
Copy link

Which operating system and architecture is compatible?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment