首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > VC/MFC >

看了几个源代码 为什么不直接使用API解决方法

2012-02-11 
看了几个源代码为什么不直接使用API都是类似这样间接调用APItypedefstruct_API{#ifdefWIN32//Kernel32Func

看了几个源代码 为什么不直接使用API
都是类似这样     间接   调用API
typedef   struct   _API   {
#ifdef   WIN32
//   Kernel32   Functions.   ----------------------
FARPROC(BOAPI*pGetProcAddress)   (   HMODULE   hModule,   LPCSTR   lpProcName   );
HANDLE(WINAPI   *pGetProcessHeap)   (   void   );
void   *(WINAPI   *pHeapAlloc)(   HANDLE   hHeap,   DWORD   dwFlags,   DWORD   dwBytes   );
HINSTANCE(WINAPI   *pLoadLibrary)   (   LPCTSTR   lpLibFileName   );
BOOL(WINAPI   *pFreeLibrary)(   HMODULE   hLibModule);

BOOL(WINAPI   *pCloseHandle)(   HANDLE   hObject   );
BOOL(WINAPI   *pCopyFile)(   LPCTSTR   lpExistingFileName,   LPCTSTR   lpNewFileName,   BOOL   bFailIfExists   );
BOOL(WINAPI*pCreateDirectory)   (   LPCTSTR   lpPathName,   LPSECURITY_ATTRIBUTES   lpSecurityAttributes   );
HANDLE(WINAPI   *pCreateFile)(   LPCTSTR   lpFileName,   DWORD   dwDesiredAccess,   DWORD   dwShareMode,   LPSECURITY_ATTRIBUTES   lpSecurityAttributes,   DWORD   dwCreationDisposition,   DWORD   dwFlagsAndAttributes,   HANDLE   hTemplateFile   );
HANDLE(WINAPI   *pCreateFileMapping)   (   HANDLE   hFile,   LPSECURITY_ATTRIBUTES   lpFileMappingAttributes,   DWORD   flProtect,   DWORD   dwMaximumSizeHigh,   DWORD   dwMaximumSizeLow,   LPCTSTR   lpName);
HANDLE(WINAPI   *pCreateMutex)(   LPSECURITY_ATTRIBUTES   lpMutexAttributes,   BOOL   bInitialOwner,   LPCTSTR   lpName   );
BOOL(WINAPI   *pCreateProcess)   (   LPCTSTR   lpApplicationName,   LPTSTR   lpCommandLine,   LPSECURITY_ATTRIBUTES   lpProcessAttributes,   LPSECURITY_ATTRIBUTES   lpThreadAttributes,   BOOL   bInheritHandles,   DWORD   dwCreationFlags,LPVOID   lpEnvironment,   LPCTSTR   lpCurrentDirectory,   LPSTARTUPINFO   lpStartupInfo,   LPPROCESS_INFORMATION   lpProcessInformation   );
HANDLE(WINAPI   *pCreateRemoteThread)   (   HANDLE   hProcess,   LPSECURITY_ATTRIBUTES   lpThreadAttributes,   DWORD   dwStackSize,   LPTHREAD_START_ROUTINE   lpStartAddress,   LPVOID   lpParameter,   DWORD   dwCreationFlags,     LPDWORD   lpThreadId   );
HANDLE(WINAPI   *pCreateThread)(   LPSECURITY_ATTRIBUTES   lpThreadAttributes,   DWORD   dwStackSize,   LPTHREAD_START_ROUTINE   lpStartAddress,   LPVOID   lpParameter,   DWORD   dwCreationFlags,   LPDWORD   lpThreadId);
BOOL(WINAPI   *pDuplicateHandle)   (   HANDLE   hSourceProcessHandle,   HANDLE   hSourceHandle,   HANDLE   hTargetProcessHandle,   LPHANDLE   lpTargetHandle,   DWORD   dwDesiredAccess,   BOOL   bInheritHandle,   DWORD   dwOptions   );
BOOL(WINAPI   *pDeleteFile)(   LPCTSTR   lpFileName   );
void(WINAPI   *pExitProcess)(   UINT   uExitCode   );
VOID(WINAPI   *pExitThread)(   DWORD   dwExitCode   );
void(WINAPI   *pEnterCriticalSection)   (   LPCRITICAL_SECTION   lpCriticalSection   );
BOOL(WINAPI   *pFileTimeToLocalFileTime)(   CONST   FILETIME   *lpFileTime,   LPFILETIME   lpLocalFileTime   );
BOOL(WINAPI   *pFileTimeToSystemTime)(     CONST   FILETIME   *lpFileTime,   LPSYSTEMTIME   lpSystemTime   );


BOOL(WINAPI*pFindClose)(   HANDLE   hFindFile   );
HANDLE(WINAPI   *pFindFirstFile)   (   LPCTSTR   lpFileName,   LPWIN32_FIND_DATA   lpFindFileData   );
BOOL(WINAPI*pFindNextFile)(   HANDLE   hFindFile,   LPWIN32_FIND_DATA   lpFindFileData   );
BOOL(WINAPI   *pFlushFileBuffers)   (   HANDLE   hFile   );
BOOL(WINAPI   *pFlushViewOfFile)   (   LPCVOID   lpBaseAddress,   DWORD   dwNumberOfBytesToFlush   );
LPTSTR(WINAPI   *pGetCommandLine)   (   VOID   );
BOOL(WINAPI   *pGetComputerName)   (   LPTSTR   lpBuffer,   LPDWORD   nSize   );
DWORD(WINAPI   *pGetCurrentDirectory)   (   DWORD   nBufferLength,   LPTSTR   lpBuffer   );
HANDLE(WINAPI   *pGetCurrentProcess)   (   VOID   );
DWORD(WINAPI   *pGetCurrentProcessId)   (   VOID   );
HANDLE(WINAPI   *pGetCurrentThread)   (   VOID   );
DWORD(WINAPI   *pGetCurrentThreadId)   (   VOID   );
BOOL(WINAPI   *pGetDiskFreeSpace)   (   LPCTSTR   lpRootPathName,   LPDWORD   lpSectorsPerCluster,   LPDWORD   lpBytesPerSector,   LPDWORD   lpNumberOfFreeClusters,   LPDWORD   lpTotalNumberOfClusters   );
UINT(WINAPI   *pGetDriveType)(   LPCTSTR   lpRootPathName   );
BOOL(WINAPI   *pGetExitCodeThread)   (   HANDLE   hThread,   LPDWORD   lpExitCode   );  
DWORD(WINAPI   *pGetFileAttributes)   (   LPCTSTR   lpFileName   );
DWORD(WINAPI   *pGetFileSize)(   HANDLE   hFile,   LPDWORD   lpFileSizeHigh   );
VOID(WINAPI   *pGetLocalTime)(   LPSYSTEMTIME   lpSystemTime   );
DWORD(WINAPI   *pGetLogicalDriveStrings)(   DWORD   nBufferLength,   LPTSTR   lpBuffer   );  
DWORD(WINAPI   *pGetModuleFileName)   (   HMODULE   hModule,   LPTSTR   lpFilename,   DWORD   nSize   );
HMODULE(WINAPI   *pGetModuleHandle)   (   LPCTSTR   lpModuleName   );
UINT(WINAPI   *pGetPrivateProfileInt)   (   LPCTSTR   lpAppName,   LPCTSTR   lpKeyName,   INT   nDefault,   LPCTSTR   lpFileName   );
DWORD(WINAPI   *pGetPrivateProfileSection)(   LPCTSTR   lpAppName,   LPTSTR   lpReturnedString,   DWORD   nSize,   LPCTSTR   lpFileName   );
DWORD(WINAPI   *pGetPrivateProfileSectionNames)             (     LPTSTR   lpszReturnBuffer,   DWORD   nSize,   LPCTSTR   lpFileName   );
DWORD(WINAPI   *pGetPrivateProfileString)(   LPCTSTR   lpAppName,   LPCTSTR   lpKeyName,   LPCTSTR   lpDefault,   LPTSTR   lpReturnedString,   DWORD   nSize,   LPCTSTR   lpFileName   );
BOOL(WINAPI   *pGetPrivateProfileStruct)(   LPCTSTR   lpszSection,   LPCTSTR   lpszKey,   LPVOID   lpStruct,   UINT   uSizeStruct,   LPCTSTR   szFile   );
VOID(WINAPI   *pGetSystemInfo)   (   LPSYSTEM_INFO   lpSystemInfo   );
UINT(WINAPI   *pGetSystemDirectory)   (   LPTSTR   lpBuffer,   UINT   uSize   );
VOID(WINAPI   *pGetSystemTime)   (   LPSYSTEMTIME   lpSystemTime   );
DWORD(WINAPI   *pGetTickCount)(   VOID   );


DWORD(WINAPI*pGetTempPath)(   DWORD   nBufferLength,   LPTSTR   lpBuffer   );

为什么不直接使用API?

[解决办法]
使用中间函数指针,可以有好几方面的好处,比如跨平台的代理函数实现,中间代理HOOK,以及自定义函数。同样一个东西,并不是操作系统API的就是最好的,最实用的。
[解决办法]
这是要在内存中搜索API入口。病毒和木马自己一般是不link到kernel32.dll这样的库的,都是运行起来之后,在内存里搜索API入口。
[解决办法]
使用如上的代码是为了实现所谓的“代码完全重定位”的目的,就是代码可以随意放置到合法的内存地址里面执行,克服普通PE文件的固定地址的束缚。主要用途是代码注入,无进程运行代码,多为蠕虫和木马所用。
  一个普通的PE加载过程大约是:申请Pe文件建议的内存地址,沿此地址将磁盘中的Pe文件按内存对齐拷贝到内存中,按节属性初始化节,初始化导入函数表,跳入Pe入口执行之。
  在一个普通的PE文件中正常调用一个API要用到“导入函数表”这样一个结构,在代码中调用MessageBox(),程序并不直接调用MessageBox函数,而是调用该函数导入表中的FirstShrink,再由FirstShrink跳转到MessageBox()执行。这些都是固定地址方式下的调用,可以说是环环相扣,缺一不可。
  假设把一段代码注入到“记事本”进程里面,代码如何知道导入表在哪儿?即使知道了,但导入表中没有注入代码的导入函数又该怎么办?
  所以得使用楼主帖出来的API巢(API nest)。API nest可以解决上面提到的难题。
  API巢初始化以后,在同一个进程内实现完全重定位的、地址无关的API调用。但代码注入如果到了另一个进程中,就得再次初始化API nest。
  这些问题不是三言两语就说完的,有很多知识。


[解决办法]
他说的大概是这个:
.text:00401596 push ebx ; uType
.text:00401597 push offset Caption ; "SetLowerFilters "
.text:0040159C push offset Text ; "Install failed! "
.text:004015A1 push ebx ; hWnd
.text:004015A2 call ds:MessageBoxA ;要调用MessageBoxA,跳过去:

.idata:0041D420 ; int __stdcall MessageBoxA(HWND hWnd,LPCSTR lpText,LPCSTR lpCaption,UINT uType)
.idata:0041D420 extrn MessageBoxA:dword ; DATA XREF: sub_401310+292r
.idata:0041D420 ; sub_401310+314r ...

你可以看到PE文件的导入节其实也是和函数指针差不多的,因为编译这个exe的时候,编译器显然是不知道这个MessagBoxA的入口地址在哪里的,因此也就无法生成绝对地址,它只能做个标记,记录调用了哪个模块里的什么函数,装载器在把exe装入内存时会一并将用到的dll装入内存,这时候装载器会用MessageBoxA真实的地址去替换,你可以看到IDA用extrn MessageBoxA:dword 来修饰这个函数指针。这个dword存放的就是MessageBoxA的真实的绝对地址了。

热点排行