強力Debug技巧: 攔截function & Backtrace (2)
第一招是攔截任意 standard C library 的 function
在下面的範例裡, 攔截的對象是 atoi()
首先主程式長這個樣子...
Main program (hello.c)
用 gcc 編譯這個程式並且執行, 結果大概長這樣子:
----
所謂的攔截atoi(), 就是寫了另一個atoi(), 名字和 standard C library 的一樣.
讓程式在執行時, 呼叫到自己寫的atoi(), 而不是library提供的.
這個偽atoi()的程式碼如下:
Wrapper function (atoi_wrapper.c)
這個偽atoi()是一個wrapper, 呼叫的時候, 會先加點料, 然後才呼叫真的atoi().
我在這個偽 atoi() 裡印了一些東西, 順便把輸出的結果竄改 (+100)
如果動得起來, 表示我們能攔截任意函數, 並且在呼叫前, 以及呼叫後動手腳.
編譯的手段是建立一個 shared library:
順利的話, 上面兩步做完, 目錄裡會多出一個 libatoiwrap.so
----
接下來, 讓 hello 執行時, 呼叫的 atoi() 被 libatoiwrap.so 的 atoi() 攔截
先看一下正常的執行結果:
如果動點手腳, 攔截 atoi() , 用 libatoiwrap.so 裡的取代 :
----
在上面的範例裡, atoi()的結果被竄改, 我們可以用這招來追蹤程式.
他做的事, 其實是改變 shared library 載入的程序, 看的更仔細的話
還可以順便認識 shared library 運作的機制.
特別推薦這篇由 SETIATHOME 團隊發表的文章:
Intercepting Arbitrary Functions on Windows, UNIX, and
Macintosh OS X Platforms
http://lattice.umiacs.umd.edu/files/functions_tr.pdf
這篇文章的範例都是從這裡出來的
在下面的範例裡, 攔截的對象是 atoi()
首先主程式長這個樣子...
Main program (hello.c)
#include <stdio.h>
int main()
{
printf("I love debug >_<\n");
printf("atoi(100) = %d\n", atoi("100"));
return 0;
}
用 gcc 編譯這個程式並且執行, 結果大概長這樣子:
gcc hello.c -o hello
./hello
I love debug >_<
atoi(100) = 100
----
所謂的攔截atoi(), 就是寫了另一個atoi(), 名字和 standard C library 的一樣.
讓程式在執行時, 呼叫到自己寫的atoi(), 而不是library提供的.
這個偽atoi()的程式碼如下:
Wrapper function (atoi_wrapper.c)
#define _GNU_SOURCE
#include <stdio.h>
#include <dlfcn.h>
// ATOI-wrapper
int atoi(const char *nptr)
{
int ret;
// Get pointer of REAL-atoi by shared library
int (*real_atoi)(const char *nptr) =
dlsym(RTLD_NEXT, “atoi”);
// Before REAL-atoi, do some hacking
printf(“[ATOI] before REAL atoi()\n”);
// Call REAL-atoi
ret = (*real_atoi)(nptr);
// After REAL-atoi, do some hacking...
printf(“[ATOI] after REAL atoi()\n”);
ret = ret + 100;
return ret;
}
這個偽atoi()是一個wrapper, 呼叫的時候, 會先加點料, 然後才呼叫真的atoi().
我在這個偽 atoi() 裡印了一些東西, 順便把輸出的結果竄改 (+100)
如果動得起來, 表示我們能攔截任意函數, 並且在呼叫前, 以及呼叫後動手腳.
編譯的手段是建立一個 shared library:
gcc -fPIC -rdynamic -c atoi_wrapper.c
gcc -shared -o libatoiwrap.so atoi_wrapper.o -ldl
順利的話, 上面兩步做完, 目錄裡會多出一個 libatoiwrap.so
----
接下來, 讓 hello 執行時, 呼叫的 atoi() 被 libatoiwrap.so 的 atoi() 攔截
先看一下正常的執行結果:
./hello
I love debug >_<
atoi(100) = 100
如果動點手腳, 攔截 atoi() , 用 libatoiwrap.so 裡的取代 :
LD_LIBRARY_PATH=. LD_PRELOAD=libatoiwrap.so ./hello
I love debug >_<
[ATOI] before REAL atoi()
[ATOI] after REAL atoi()
atoi(100) = 200
----
在上面的範例裡, atoi()的結果被竄改, 我們可以用這招來追蹤程式.
他做的事, 其實是改變 shared library 載入的程序, 看的更仔細的話
還可以順便認識 shared library 運作的機制.
特別推薦這篇由 SETIATHOME 團隊發表的文章:
Intercepting Arbitrary Functions on Windows, UNIX, and
Macintosh OS X Platforms
http://lattice.umiacs.umd.edu/files/functions_tr.pdf
這篇文章的範例都是從這裡出來的
留言