Skip to content

Instantly share code, notes, and snippets.

@mpurzynski
Created May 25, 2019 08:38
Show Gist options
  • Save mpurzynski/445007783bbb251d924b797ae5cdb355 to your computer and use it in GitHub Desktop.
Save mpurzynski/445007783bbb251d924b797ae5cdb355 to your computer and use it in GitHub Desktop.
Some quick hack for a naive (but working) userspace rootkit detection
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <dlfcn.h>
#include <fcntl.h>
#define LIBC "/lib/x86_64-linux-gnu/libc.so.6"
#define PCAP "/usr/lib/x86_64-linux-gnu/libpcap.so"
#define PAM "/usr/lib64/libpam.so"
int main(int argc, char *argv[]) {
FILE * fp;
int bytes;
char * smapsl;
Dl_info dlInfo_libc, dlInfo_next;
static FILE *(*old_fopen) (const char *filename, const char *mode);
void *libc = dlopen(LIBC, RTLD_LAZY); // Directly open the libc ".so"
void *pcap = dlopen(PCAP, RTLD_LAZY); // Directly open the pcap ".so"
void *pam = dlopen(PAM, RTLD_LAZY); // Directly open the PAM ".so"
char *syscalls[] = {"open", "readdir", "readdir64", "fopen", "accept", "access", "link", "unlink", "read", "write", "rmdir", "stat", "stat64", "lstat", "lstat64", "__lxstat", "__lxstat64", "xstat", "xstat64", "unlink", "unlinkat", "opendir", "execve", "accept"};
uint32_t i;
// Pointers to functions, to be filled when resolving
void *(*libc_func)();
void *(*pcap_func)();
void *(*pam_func)();
void *(*next_func)();
for (i = 0; i < 24; ++i) {
printf("[+] Checking %s syscall.\n", syscalls[i]);
// Straight outta libc
next_func = dlsym(RTLD_NEXT, syscalls[i]);
libc_func = dlsym(libc, syscalls[i]);
dladdr(next_func, &dlInfo_next);
dladdr(libc_func, &dlInfo_libc);
// Resolve symbols from the default library search order (thus infected by LD_PRELOAD)
printf("Libc address: %p\n", libc_func);
printf("Found in %s\n", dlInfo_libc.dli_fname);
printf("Next address: %p\n", next_func);
printf("Found in %s\n", dlInfo_next.dli_fname);
if (libc_func != next_func) {
printf("[!] Preload hooks dectected!\n");
printf("Libc address: %p\n", libc_func);
printf("Next address: %p\n", next_func);
}
}
printf("[+] Checking if pcap_loop is hooked.\n");
// Same dance as before
pcap_func = dlsym(pcap, "pcap_loop");
next_func = dlsym(RTLD_NEXT, "pcap_loop");
if (pcap_func != next_func) {
printf("[!] Preload hooks dectected!\n");
printf("Pcap address: %p\n", pcap_func);
printf("Next address: %p\n", next_func);
}
// Azzazello!!
printf("[+] Checking if PAM is hooked.\n");
// Same dance, once again
pam_func = dlsym(pam, "pam_authenticate");
next_func = dlsym(RTLD_NEXT, "pam_authenticate");
if (pam_func != next_func) {
printf("[!] Preload hooks dectected!\n");
printf("PAM address: %p\n", pam_func);
printf("Next address: %p\n", next_func);
}
old_fopen = dlsym(libc, "fopen");
fp = old_fopen("/proc/self/smaps", "r");
smapsl = malloc(1024);
while (bytes = fread(smapsl, 1, sizeof(smapsl), fp)) {
fwrite(smapsl, 1, bytes, stdout);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment