Created
November 13, 2024 11:30
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
// gcc -shared -fPIC -I/usr/local/cuda-12.0/targets/x86_64-linux/include/ hook.c -o hook.so -ldl && LD_PRELOAD=./hook.so python3.11 obfuscated_file.py | |
// Thanks Claude! | |
#include <nvml.h> | |
#define _GNU_SOURCE | |
#define PAGE_SIZE 4096 | |
#include <stdio.h> | |
#include <dlfcn.h> | |
#include <stdint.h> | |
#include <sys/mman.h> | |
#include <unistd.h> | |
#include <string.h> | |
typedef nvmlReturn_t (*nvmlDeviceGetCount_v2_t)(unsigned int*); | |
typedef nvmlReturn_t (*nvmlInitWithFlags_t)(unsigned int); | |
typedef nvmlReturn_t (*nvmlDeviceGetName_t)(nvmlDevice_t device, char* name, unsigned int length); | |
typedef nvmlReturn_t (*nvmlDeviceGetMemoryInfo_t)(nvmlDevice_t device, nvmlMemory_t* memory); | |
// Storage for original function bytes | |
static unsigned char orig_nvmlDeviceGetCount_v2_bytes[14]; | |
static unsigned char orig_nvmlInitWithFlags_bytes[14]; | |
static unsigned char orig_nvmlDeviceGetName_bytes[14]; | |
static unsigned char orig_nvmlDeviceGetMemoryInfo_bytes[14]; | |
// Global handle to the NVIDIA library | |
static void* nvml_handle = NULL; | |
// Our hook functions | |
nvmlReturn_t hook_nvmlDeviceGetCount_v2(unsigned int* deviceCount) { | |
// Restore original bytes to call the real function | |
void* func_addr = dlsym(nvml_handle, "nvmlDeviceGetCount_v2"); | |
mprotect((void*)((uintptr_t)func_addr & ~(PAGE_SIZE-1)), PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC); | |
memcpy(func_addr, orig_nvmlDeviceGetCount_v2_bytes, sizeof(orig_nvmlDeviceGetCount_v2_bytes)); | |
// Call original | |
nvmlReturn_t result = ((nvmlDeviceGetCount_v2_t)func_addr)(deviceCount); | |
// Log the call | |
fprintf(stderr, "nvmlDeviceGetCount_v2(0x%p) = %d, count=%u\n", | |
deviceCount, result, deviceCount ? *deviceCount : 0); | |
// Restore our hook | |
unsigned char jump[] = { | |
0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp qword ptr [rip] | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // absolute address | |
}; | |
*(uint64_t*)(jump + 6) = (uint64_t)hook_nvmlDeviceGetCount_v2; | |
memcpy(func_addr, jump, sizeof(jump)); | |
return result; | |
} | |
nvmlReturn_t hook_nvmlInitWithFlags(unsigned int flags) { | |
// Restore original bytes to call the real function | |
void* func_addr = dlsym(nvml_handle, "nvmlInitWithFlags"); | |
mprotect((void*)((uintptr_t)func_addr & ~(PAGE_SIZE-1)), PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC); | |
memcpy(func_addr, orig_nvmlInitWithFlags_bytes, sizeof(orig_nvmlInitWithFlags_bytes)); | |
// Call original | |
nvmlReturn_t result = ((nvmlInitWithFlags_t)func_addr)(flags); | |
// Log the call | |
fprintf(stderr, "nvmlInitWithFlags(0x%x) = %d\n", flags, result); | |
// Restore our hook | |
unsigned char jump[] = { | |
0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp qword ptr [rip] | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // absolute address | |
}; | |
*(uint64_t*)(jump + 6) = (uint64_t)hook_nvmlInitWithFlags; | |
memcpy(func_addr, jump, sizeof(jump)); | |
return result; | |
} | |
nvmlReturn_t hook_nvmlDeviceGetName(nvmlDevice_t device, char* name, unsigned int length) { | |
// Restore original bytes to call the real function | |
void* func_addr = dlsym(nvml_handle, "nvmlDeviceGetName"); | |
mprotect((void*)((uintptr_t)func_addr & ~(PAGE_SIZE-1)), PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC); | |
memcpy(func_addr, orig_nvmlDeviceGetName_bytes, sizeof(orig_nvmlDeviceGetName_bytes)); | |
// Call original | |
nvmlReturn_t result = ((nvmlDeviceGetName_t)func_addr)(device, name, length); | |
// Log the call | |
fprintf(stderr, "nvmlDeviceGetName(device=%p, name_buf=%p, len=%u) = %d", | |
device, name, length, result); | |
if (result == NVML_SUCCESS && name) { | |
fprintf(stderr, ", name='%s'", name); | |
} | |
fprintf(stderr, "\n"); | |
char* newName = "NVIDIA DeezNuts RTX 6969"; | |
fprintf(stderr, "Setting new name: '%s'\n", newName); | |
strncpy(name, newName, length); | |
// Restore our hook | |
unsigned char jump[] = { | |
0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp qword ptr [rip] | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // absolute address | |
}; | |
*(uint64_t*)(jump + 6) = (uint64_t)hook_nvmlDeviceGetName; | |
memcpy(func_addr, jump, sizeof(jump)); | |
return result; | |
} | |
nvmlReturn_t hook_nvmlDeviceGetMemoryInfo(nvmlDevice_t device, nvmlMemory_t* memory) { | |
// Restore original bytes to call the real function | |
void* func_addr = dlsym(nvml_handle, "nvmlDeviceGetMemoryInfo"); | |
mprotect((void*)((uintptr_t)func_addr & ~(PAGE_SIZE-1)), PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC); | |
memcpy(func_addr, orig_nvmlDeviceGetMemoryInfo_bytes, sizeof(orig_nvmlDeviceGetMemoryInfo_bytes)); | |
// Call original | |
nvmlReturn_t result = ((nvmlDeviceGetMemoryInfo_t)func_addr)(device, memory); | |
// Log the call | |
fprintf(stderr, "nvmlDeviceGetMemoryInfo(device=%p, memory=%p) = %d", | |
device, memory, result); | |
if (result == NVML_SUCCESS && memory) { | |
fprintf(stderr, ", total=%llu bytes, free=%llu bytes, used=%llu bytes", | |
memory->total, memory->free, memory->used); | |
} | |
fprintf(stderr, "\n"); | |
uint64_t fakeMemory = 69420ULL*1024ULL*1024ULL; | |
fprintf(stderr, "Actually I have %llu megabytes of memory lol\n", fakeMemory>>20); | |
memory->free = fakeMemory - memory->used; | |
memory->total = fakeMemory; | |
// Restore our hook | |
unsigned char jump[] = { | |
0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp qword ptr [rip] | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // absolute address | |
}; | |
*(uint64_t*)(jump + 6) = (uint64_t)hook_nvmlDeviceGetMemoryInfo; | |
memcpy(func_addr, jump, sizeof(jump)); | |
return result; | |
} | |
// Function to install a hook | |
static void install_hook(const char* symbol_name, void* hook_func, unsigned char* orig_bytes) { | |
// Get address of target function | |
void* func_addr = dlsym(nvml_handle, symbol_name); | |
if (!func_addr) { | |
fprintf(stderr, "Failed to find %s: %s\n", symbol_name, dlerror()); | |
return; | |
} | |
fprintf(stderr, "Found %s at %p\n", symbol_name, func_addr); | |
// Save original bytes | |
memcpy(orig_bytes, func_addr, 14); | |
// Make page writable | |
mprotect((void*)((uintptr_t)func_addr & ~(PAGE_SIZE-1)), PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC); | |
// Write jump instruction | |
unsigned char jump[] = { | |
0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp qword ptr [rip] | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // absolute address | |
}; | |
*(uint64_t*)(jump + 6) = (uint64_t)hook_func; | |
memcpy(func_addr, jump, sizeof(jump)); | |
} | |
__attribute__((constructor)) | |
static void init(void) { | |
// Load NVIDIA library first | |
nvml_handle = dlopen("libnvidia-ml.so.1", RTLD_LAZY | RTLD_GLOBAL); | |
if (!nvml_handle) { | |
fprintf(stderr, "Failed to load libnvidia-ml.so.1: %s\n", dlerror()); | |
return; | |
} | |
fprintf(stderr, "Successfully loaded libnvidia-ml.so.1\n"); | |
// Install hooks | |
install_hook("nvmlDeviceGetCount_v2", hook_nvmlDeviceGetCount_v2, orig_nvmlDeviceGetCount_v2_bytes); | |
install_hook("nvmlInitWithFlags", hook_nvmlInitWithFlags, orig_nvmlInitWithFlags_bytes); | |
install_hook("nvmlDeviceGetName", hook_nvmlDeviceGetName, orig_nvmlDeviceGetName_bytes); | |
install_hook("nvmlDeviceGetMemoryInfo", hook_nvmlDeviceGetMemoryInfo, orig_nvmlDeviceGetMemoryInfo_bytes); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment