淺述extern C的用法 和 無導入表PE的實現

一: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來動態加載


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章