Skip to content

Instantly share code, notes, and snippets.

@Lekensteyn
Last active April 15, 2024 18:00
Show Gist options
  • Save Lekensteyn/c8d41c02d118aa40bc100020efde3696 to your computer and use it in GitHub Desktop.
Save Lekensteyn/c8d41c02d118aa40bc100020efde3696 to your computer and use it in GitHub Desktop.
Make libnvidia-ml.so (nvidia-smi) write plaintext debug logs (mirror of https://lekensteyn.nl/files/nvml-debugdump.c)
/**
* Make libnvidia-ml.so (nvidia-smi) write plaintext debug logs.
*
* Usage:
*
* gcc -shared -fPIC -ldl nvml-debugdump.c -o nvml-debugdump.so
* LD_PRELOAD=./nvml-debugdump.so nvidia-smi --debug=debug.log -q
*
* For other NVML applications, set env var __NVML_DBG_FILE=debug.log
*
* How it works: the observed call sequence is: vsnprintf, fwrite, fflush where
* vsnprintf and fwrite apparently share the same pointer (in-place encryption
* probably happens netween vsnprintf and fwrite). This library simply copies
* data at vsnprintf time and replaces the encrypted data at fwrite time.
*/
#define _GNU_SOURCE /* for RTLD_NEXT */
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static char *last_str_ptr;
static char last_str[2048];
static int (*vsnprintf_real)(char *str, size_t size, const char *format, va_list ap);
int vsnprintf(char *str, size_t size, const char *format, va_list ap)
{
if (!vsnprintf_real) {
vsnprintf_real = dlsym(RTLD_NEXT, "vsnprintf");
if (!vsnprintf_real) {
fprintf(stderr, "vsnprintf: %s\n", dlerror());
abort();
}
}
int r = vsnprintf_real(str, size, format, ap);
// reduce false matches, logging always seem to happen with fixed size.
if (size != 2048 || r <= 0) {
return r;
}
// Assume that the debug log is written from one function (such that the
// address of the caller is always the same). This case was not seen yet,
// but just in case...
void *ret_addr = __builtin_return_address(0);
static void *expected_caller_addr;
if (expected_caller_addr != ret_addr) {
if (!expected_caller_addr) {
expected_caller_addr = ret_addr;
} else {
// address mismatch, probably a different function
return r;
}
}
memcpy(last_str, str, r + 1);
last_str_ptr = str;
return r;
}
static size_t (*fwrite_real)(const void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
{
if (!fwrite_real) {
fwrite_real = dlsym(RTLD_NEXT, "fwrite");
if (!fwrite_real) {
fprintf(stderr, "fwrite: %s\n", dlerror());
abort();
}
}
if (ptr == last_str_ptr) {
ptr = last_str;
last_str_ptr = NULL;
}
return fwrite_real(ptr, size, nmemb, stream);
}
@jiaoyk
Copy link

jiaoyk commented Aug 22, 2020

Alternative way, we could decrypt the log directly
`

static uint32_t x = 0, y = 0, z = 0,
w = 0, v = 0, d = 0;
void xorwow_init_seed() {
x = 0x0D3DAECB8, y = 0x1D4D4848, z = 0x0AA7B8E81,
w = 0x23CC0EC3, v = 0x7645F3ED, d = 0x0E44A4F49;
}

void xorwow_encrypt(char* buffer, int len) {
int i = 0;
for(i=0 ; i < len; i++){
uint32_t t = (x^(x>>2)); x = y; y = z; z = w; w = v; v = (v^(v<<4))^(t^(t<<1));
uint32_t r = ((d+=362437)+v);
buffer[i] += (r & 0xFF);
}
return;
}

`

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