最近需要一个工具实现拦截系统中的IE访问,将访问拦截后发送到指定的代理服务器去处理。
我是通过将一个dll注入到iexplore.exe程序中的。成功的注入进去了。但是我发现并没有拦截到HTTP的数据,在DLL中这样实现对于HTTP协议的拦截,准确的说是TCp拦截:
(本段代码来自网络,主要输出拦截的数据)
#include "stdafx.h"
#include "windows.h"
#include "winnt.h"
PVOID pNtDeviceIoControl = NULL ;
//
#define AFD_RECV 0x12017
#define AFD_SEND 0x1201f
typedef struct AFD_WSABUF{
UINT len ;
PCHAR buf ;
}AFD_WSABUF , *PAFD_WSABUF;
typedef struct AFD_INFO {
PAFD_WSABUF BufferArray ;
ULONG BufferCount ;
ULONG AfdFlags ;
ULONG TdiFlags ;
} AFD_INFO, *PAFD_INFO;
typedef LONG NTSTATUS;
#define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0)
const CHAR GetXX[] = "GET ";
const CHAR PostXX[] = "POST ";
const CHAR HttpXX[] = "HTTP";
//////////////////////////////////////////////////////////////////////////
//
// LookupSendPacket
// 检查Send包
// 目前实现了过滤HTTP请求(GET AND POST)
//
//////////////////////////////////////////////////////////////////////////
BOOL LookupSendPacket(PVOID Buffer , ULONG Len)
{
if (Len < 5)
{
return FALSE ;
}
//外层已有异常捕获
if (memcmp(Buffer , GetXX , 4) == 0
||
memcmp(Buffer , PostXX , 5) == 0 )
{
return TRUE ;
}
return FALSE ;
}
//////////////////////////////////////////////////////////////////////////
//
// LookupRecvPacket
//
// 检查Recv包
// 在这里可以实现Recv包查字典功能
// 目前实现了过滤HTTP返回数据包的功能
//
//
///////////////////////////////////////////////////////////////////////////
BOOL LookupRecvPacket(PVOID Buffer , ULONG Len)
{
if (Len < 4)
{
return FALSE ;
}
if (memcmp(Buffer , HttpXX , 4) == 0 )
{
return TRUE ;
}
return FALSE ;
}
//hook函数
//////////////////////////////////////////////////////////////////////////
//
// NtDeviceIoControlFile的HOOK函数
// ws2_32.dll的send , recv最终会调用到mswsock.dll内的数据发送函数
// mswsock.dll会调用NtDeviceIoControlFile向TDI Client驱动发送Send Recv指令
// 我们在这里做拦截,可以过滤所有的TCP 收发包(UDP之类亦可,不过要更改指令)
//
//////////////////////////////////////////////////////////////////////////
NTSTATUS __stdcall NewNtDeviceIoControlFile(
HANDLE FileHandle,
HANDLE Event OPTIONAL,
PVOID ApcRoutine OPTIONAL,
PVOID ApcContext OPTIONAL,
PVOID IoStatusBlock,
ULONG IoControlCode,
PVOID InputBuffer OPTIONAL,
ULONG InputBufferLength,
PVOID OutputBuffer OPTIONAL,
ULONG OutputBufferLength
)
{
//先调用原始函数
LONG stat ;
__asm
{
push OutputBufferLength
push OutputBuffer
push InputBufferLength
push InputBuffer
push IoControlCode
push IoStatusBlock
push ApcContext
push ApcRoutine
push Event
push FileHandle
call pNtDeviceIoControl
mov stat ,eax
}
//如果原始函数失败了(例如RECV无数据)
if (!NT_SUCCESS(stat))
{
return stat ;
}
//检查是否为TCP收发指令
if (IoControlCode != AFD_SEND && IoControlCode != AFD_RECV)
{
return stat ;
}
//访问AFD INFO结构,获得SEND或RECV的BUFFER信息
//这里可能是有问题的BUFFER,因此我们要加TRY EXCEPT
//
__try
{
//从InputBuffer得到Buffer和Len
PAFD_INFO AfdInfo = (PAFD_INFO)InputBuffer ;
PVOID Buffer = AfdInfo->BufferArray->buf ;
ULONG Len = AfdInfo->BufferArray->len;
if (IoControlCode == AFD_SEND)
{
/*if (LookupSendPacket(Buffer , Len))
{
//输出包内容
//这里输出调试信息,可以用DbgView查看,如果有UI可以做成SendMessage形式~
// MessageBox(NULL,(char*)Buffer,NULL,MB_OK);
OutputDebugString("SendPacket!\n");
OutputDebugString((char*)Buffer);
}
*/
MessageBox(NULL,"You Attached",NULL,MB_OK);
}
else
{
if (LookupRecvPacket(Buffer , Len))
{
OutputDebugString("RecvPacket!\n");
OutputDebugString((char*)Buffer);
}
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
return stat ;
}
return stat ;
}
//////////////////////////////////////////////////////////////////////////
//
// Hook mswsock.dll导出表的Ntdll!NtDeviceIoControlFile
// 并过滤其对TDI Cilent的请求来过滤封包
// 稳定,隐蔽,RING3下最底层的包过滤~
//
//////////////////////////////////////////////////////////////////////////
void SuperHookDeviceIoControl()
{
//得到ws2_32.dll的模块基址
HMODULE hMod = LoadLibrary("mswsock.dll");
if (hMod == 0 )
{
return ;
}
//得到DOS头
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hMod ;
//如果DOS头无效
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
{
return ;
}
//得到NT头
PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((ULONG)hMod + pDosHeader->e_lfanew);
//如果NT头无效
if (pNtHeaders->Signature != IMAGE_NT_SIGNATURE)
{
return ;
}
//检查输入表数据目录是否存在
if (pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress == 0 ||
pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size == 0 )
{
return ;
}
//得到输入表描述指针
PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)((ULONG)hMod + pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
PIMAGE_THUNK_DATA ThunkData ;
//检查每个输入项
while(ImportDescriptor->FirstThunk)
{
//检查输入表项是否为ntdll.dll
char* dllname = (char*)((ULONG)hMod + ImportDescriptor->Name);
//如果不是,则跳到下一个处理
if (stricmp(dllname , "ntdll.dll") !=0)
{
ImportDescriptor ++ ;
continue;
}
ThunkData = (PIMAGE_THUNK_DATA)((ULONG)hMod + ImportDescriptor->OriginalFirstThunk);
int no = 1;
while(ThunkData->u1.Function)
{
//检查函数是否为NtDeviceIoControlFile
char* functionname = (char*)((ULONG)hMod + ThunkData->u1.AddressOfData + 2);
if (stricmp(functionname , "NtDeviceIoControlFile") == 0 )
{
//
//如果是,那么记录原始函数地址
//HOOK我们的函数地址
//
ULONG myaddr = (ULONG)NewNtDeviceIoControlFile;
ULONG btw ;
PDWORD lpAddr = (DWORD *)((ULONG)hMod + (DWORD)ImportDescriptor->FirstThunk) +(no-1);
pNtDeviceIoControl = (PVOID)(*(ULONG*)lpAddr) ;
WriteProcessMemory(GetCurrentProcess() , lpAddr , &myaddr , sizeof(ULONG), &btw );
return ;
}
no++;
ThunkData ++;
}
ImportDescriptor ++;
}
return ;
}
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
//当加载DLL时,进行API HOOK
if (ul_reason_for_call == DLL_PROCESS_ATTACH)
{
//HOOK API
SuperHookDeviceIoControl();
}
return TRUE;
}
最后通过dgbview查看却没有任何信息,只有当IE进程退出后有一个dll卸载信息。不知道怎么回事。请大家帮忙看看怎么回事
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!