一: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来动态加载