壳的加载过程中需要的API用显式调用加载dll
1.无论是显式调用还是隐式调用在反汇编层面上都是调用loadlibrary函数加载dll.
2.显式调用的好处就在动态加载,显式加载的dll以及GetProcAddress函数不会出现在程序的输入表中(Ps:在这个dll之前没有加载过的情况下才可以)。
3.无论是loadlibrary函数还是freelibrary函数,都是改变的是dll模块的引用计数(Ps:当程序加载过的user32.dll的情况下,在loadlibrary user32,不会重新拷贝一份到内存空间中,而是这个user32 的引用次数加1,当freelibrary的时候,同理,不是从内存空间删除这个模块,而是引用次数减1,当引用次数为0时,才将这个模块删除)
4.关于库函数和API的理解,库函数普遍上来讲是编译器提供的函数,以VS2013为例,printf函数和strcmp函数就在其编译器的MSVCR120D.dll中。
#include "stdafx.h" #include <string.h> #include <windows.h> //定义一个函数指针 typedef bool (WINAPI *VirtualProtectFun)( _In_ LPVOID lpAddress, _In_ SIZE_T dwSize, _In_ DWORD flNewProtect, _Out_ PDWORD lpflOldProtect); typedef int (WINAPI *MessageBoxFun)( _In_ LPVOID lpAddress, _In_ SIZE_T dwSize, _In_ DWORD flNewProtect, _Out_ PDWORD lpflOldProtect); int _tmain(int argc, _TCHAR* argv[]) { // 输入表中有无编译器提供的库函数,C++ char s1[10] = "aaaa"; char s2[10] = "bbbbb"; int n = strcmp(s1, s2); printf("%d", n); // 显示调用API //MessageBoxA(0, 0, 0, 0); HMODULE hUser = LoadLibrary(L"user32.dll"); MessageBoxFun MessageBoxAddr = (MessageBoxFun)GetProcAddress(hUser, "MessageBoxA"); MessageBoxAddr(0, 0, 0, 0); FreeLibrary(hUser); HMODULE hKernel=LoadLibrary(L"Kernel32.dll"); VirtualProtectFun addr = (VirtualProtectFun)GetProcAddress(hKernel, "VirtualProtect"); DWORD old=0; addr(0, 10, 0, &old); FreeLibrary(hKernel); //VirtualProtect(0, 10, 0, &old); return 0; }