#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 唷~