Windows系统程序设计之插入DLL和挂接API
【作者】北极星2003
【来源】看雪技术论坛(bbs.pediy.com)
【时间】2006年6月12日
【说明】关于本文的所有信息都可以在附件中下载
首先简要介绍一下内容要点。
在WINDOWS中,每个进程都有自己的私有地址空间,当用指针访问内存的时候只能访问到自己进程的地址空间,而无法进入其他进程的地址空间。而当自己的进程需要对其他进程进行一系列操作的时候,一个比较好的选择就是把这些操作封装在一个DLL中,然后把DLL插入到目标进程的私有地址空间中。这样,如果DLL中使用指针的话,就可以访问目标进程的地址空间。
在程序中通常有两种方法来实现插入DLL:(1)使用远程线程(2)HOOK
挂接API的目标是当系统调用API函数的时候能够执行我们的自定义函数,需要注意的是自定义函数的参数、返回类型、调用方式都必须和原API函数完全相同。这样我们就可以很便捷的取得或者修改参数来实现相应的目标,而无需考虑该API的内部实现。
通常有两种方法可以实现挂接API:(1)修改IAT(2)API入口的覆盖。
需要说明的是对知识点的简要概括,至于具体信息,无论在书本或者网络上都有很多,不再赘述。
使用远程线程方法实现插入DLL可以参考我以前的文章《QQ盗号的核心技术(简单版)》http://bbs.pediy.com/showthread.php?threadid=14203
这里主要讲解两个软件的制作。
(1) IPPack――IP封包截获工具
原理:使用挂钩(HOOK)插入DLL,覆盖API入口地址挂接API
(2) Watch IAT ――查看IAT信息
关于修改IAT来实现挂接API已经很普遍了,我也懒的再重复。这个工具软件是我很早以前写的,用来查看可执行文件的IAT信息,但有一个难点,由于IAT信息是在加载时候动态产生的,那么什么时候是最佳时机呢??
实例一 : IPPack ―― IP封包截获工具
1、设计目标
把基本的DLL插入技术和HOOK API技术相联系,应用到实际。另外,在该软件中还设计进程间通信、线程同步、DLL实现等多种Windows程序设计中的基本技术。(经常有朋友说这个软件不能截获数据包,这里需要说明的是这个软件仅仅是一个技术实例,并不是工具软件。对目标进程进行测试的时候,最好先用PE分析工具查看一下,确认导入表中有send,recv,sendto,recvfrom这四个函数。)
2、设计思路
第一步:把DLL插入到目标进程地址空间
第二步:挂接API,取得相关的参数信息并传送到IPPack.exe
如果不熟悉管道通信机制,可以参考《Windows系统程序设计之进程间通信》
http://bbs.pediy.com/showthread.php?s=&threadid=26252
3、难点
插入DLL和挂接API的应用比较多,基本上没什么难度。
4、详细设计
(1)当启动IPPack.exe进行初始化时,启动命名管道线程服务
UINT ServerThread ( LPVOID lpParameter )
{
……
while ( true )
{
ConnectNamedPipe ( CurPipeInst.hPipe, &OverLapStruct ) ;
WaitForSingleObject ( CurPipeInst.hEvent, INFINITE ) ;
if ( !GetOverlappedResult ( CurPipeInst.hPipe, &OverLapStruct, &dwByte, true ) )
break ;
……
// 从管道中读取数据并显示到界面
……
// 断开客户端的连接,以便等待下一客户的到来
DisconnectNamedPipe ( CurPipeInst.hPipe ) ;
}
return 0 ;
}
void CIPPackDlg::LookUpProcessPriviege ()
{
TOKEN_PRIVILEGES tkp;
HANDLE hToken;
if (!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken))
return ;
LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&tkp.Privileges[0].Luid); tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0);
}
void CSPDlg::UpdateProcess ()
{
DWORD cbNeededProcess, cbNeededModule;
HMODULE hMod ;
CString TempStr ;
EnumProcesses ( dwProcessId, sizeof(dwProcessId), &cbNeededProcess ) ;
for ( unsigned i = 0; i < ( cbNeededProcess/sizeof(DWORD) ); i++ )
{
HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | \
PROCESS_VM_READ, FALSE, dwProcessId[i] );
if ( hProcess != INVALID_HANDLE_VALUE )
{
EnumProcessModules( hProcess, &hMod, sizeof(hMod), &cbNeededModule ) ;
GetModuleBaseName ( hProcess, hMod, szProcessName[i].GetBuffer(512), 512 ) ;
TempStr.Format ( "%d", dwProcessId[i] ) ;
m_ListCon.InsertItem ( i, TempStr, 0 ) ;
m_ListCon.SetItemText ( i, 1, szProcessName[i] ) ;
CloseHandle ( hProcess ) ;
}
}
}
[注意]APP应用上架合规检测服务,协助应用顺利上架!