前言:本文源於對CSDN論壇中一個問題的解答,現將其整理出來,以協助有相同需求的朋友。
對dll進行過動態載入的朋友應該清楚GetProcAddress這個API,其作用是通過一個函數名稱從dll模組中獲得這個函數的地址,然後將其轉換成相應的函數指標供我們調用。這便是通過函數名稱來調用函數的一個典型例子。下面我們就模擬一下這個函數,主要思路就是建立一張函數映射表。
#include <iostream>
using namespace std;
// 定義函數入口結構
typedef void (*FUN_PTR)(void);
struct fun_entry
{
const char* fun_name; // 函數名稱
FUN_PTR fun_ptr; // 函數指標,實際上這裡的資料類型也可以是整型
};
// 定義了兩個原型不同的函數
void foo1() { cout << "foo1" << endl; }
int foo2(int i) { cout << "foo2:" << i << endl; return 0; }
// 定義函數映射表
fun_entry fun_entry_table[] =
{
{"foo1", (FUN_PTR)foo1},
{"foo2", (FUN_PTR)foo2}
};
// 類比GetProcAddress
FUN_PTR get_proc_address(const char* fun_name)
{
for(int i=0; i<sizeof(fun_entry_table)/sizeof(fun_entry_table[0]); i++)
{
if(strcmp(fun_name, fun_entry_table[i].fun_name) == 0)
return fun_entry_table[i].fun_ptr;
}
return NULL;
}
int main()
{
typedef void (*foo1_ptr)(void);
typedef int (*foo2_ptr)(int);
foo1_ptr pfoo1 = (foo1_ptr)get_proc_address("foo1"); // 獲得函數入口地址,並轉換成函數指標
if( pfoo1 ) pfoo1(); // 通過函數指標調用函數
foo2_ptr pfoo2 = (foo2_ptr)get_proc_address("foo2");
if( pfoo2 ) pfoo2( 100 );
system("pause");
return 0;
}
是不是很簡單,可GetProcAddress究竟是怎麼實現的呢?這個我目前還不太清楚,不過我們知道dll中有函數符號資訊,可以方便的定位一個函數的入口地址。要是普通的程式的二進位代碼中也有函數名稱,那且不是很爽!但這樣就暴露了程式的內部實現,這可大大方便了駭客,:)。
今天是9.18,勿忘國恥,振興中華!
(freefalcon於2004.09.18)