一:extern C的用法
#ifdef __cplusplus //如果下面的myFunc函數的實現是在c文件中,則當需要和cpp混編時這些代碼是必不可少的
extern "C"
{
#endif
void myFunc();
#ifdef __cplusplus
}
#endif</span>
extern "C"包含雙重含義,從字面上可以知道,首先,被它修飾的目標是"extern"的;其次,被它修飾的目標代碼是"C"的。
extern是C/C++語言中表明函數和全局變量的作用範圍的關鍵字,該關鍵字告訴編譯器,其申明的函數和變量可以在本模塊或其他模塊中使用。
同時注意下面的語句:
extern int a; 僅僅是一個變量的聲明,其並不是在定義變量a,並未爲a分配空間。變量a在所有模塊中作爲一種全局變量只能被定義一次,否則會出錯。
二:無導入表PE的實現
步驟:
1、自定義入口點,代碼如下:
#pragma comment(linker, "/subsystem:\"windows\"")
#pragma comment(linker, "/entry:\"mySun\"")
2、實現入口點函數,例如:
int mySun()
{
//add your code here
return 0;
}
3、用Release模式編譯程序
4、這樣就得到了一個沒有導入表的程序,但是這個程序什麼也做不了,而且可能還無法退出, 但這確實是合法的pe程序
如果你想實現一點功能,例如彈出一個窗口的函數MessageBox或者是讓exe程序能夠退出的函數ExitProcess(0),這樣的話功能雖然有了,但是也帶來了導入表。
5、去掉導入表
5.1、找到kernel32.dll在內存中的位置,下面的代碼可以實現(不僅限於該代碼):
__declspec(naked) DWORD get_k32()
{
__asm
{
mov eax, fs:[030h] ;
test eax,eax ;
js finished ;
mov eax, [eax + 0ch] ;
mov eax, [eax + 14h] ;
mov eax, [eax] ;
mov eax, [eax] ;
mov eax, [eax + 10h] ;
finished:
ret
}
}
再之後如下調用即可獲得kernel32.dll的內存地址:
HMODULE hModuleBase = (HMODULE)get_k32();
5.2、實現一個自己的GetProcAddress函數,這裏使用的是利用HASH的方法獲取相應的API地址,大致思路如下:
將想要獲取的某個DLL中的導出函數名用某種算法獲取其對應的HASH值,接着在相應的DLL中遍歷每個到處函數,對其函數名用同樣的算法獲取HASH後進行比對,相同則獲取其地址,具體方法請網上搜尋
5.3、用自己的GetProcAddress和已知的kernel32.dll的地址加載出一些關鍵函數如LoadLibraryA、ExitProcess。
5.4、用LoadLibraryA加載user32.dll,然後用GetProcAddress加載MessageBoxA
5.5、至此,所需要的函數都有了,可以實現了,更豐富的功能也都可以實現,無非是動態加載api函數罷了。
原則:所有需要用到的api函數都用LoadLibraryA和GetProcAddress來動態加載