#include <stdio.h> #include <dlfcn.h> extern void payload(); typedef double (*proto)(double); proto _exp = (proto) (void *) &payload; /* once no exp found, use this */ static double failback(double x) { return 0.0; } static void lookup() { void *handle = dlopen("libm.so", RTLD_LAZY); if (!handle) { fprintf(stderr, "E: unable to load libm\n" ); _exp = (proto) (void *) &failback; return; } _exp = (proto) dlsym(handle, "exp"); if (!_exp) { dlclose(handle); _exp = (proto) (void *) &failback; fprintf(stderr, "E: unable to find exp\n"); } } static void do_magic() { __asm__ __volatile__ ( " .section .bss\n" " .align 4\n" "external_ebp: .type external_ebp, @object\n" " .size external_ebp, 4\n" " .text\n" "payload:\n" " mov %ebp, external_ebp\n" " mov %esp, %ebp\n" " call lookup\n" " mov external_ebp, %ebp\n" " jmp *_exp\n" ); } int main() { printf("e = %f\n", _exp(1.0)); return 0; }透過調整 IA32 stack 的 %ebp,將變數 _exp 指向由 dlopen + dlsym 找出的 libm::exp() 位址,進一步跳躍到函式進入點,達到所設立的目標。參考的編譯與執行輸出:
$ gcc -o findsym{,.c} -O0 -ldl && ./findsym e = 2.718282由 jserv 發表於 July 6, 2009 05:43 PM
人黑真好
由 aguai 發表於 July 31, 2009 04:46 AM其實可以不用維護 ebp 的值呀~
若為了方便 call stack 重建而保存 ebp, 應該要 push 進 stack 唷~