利用winpcap获取网络数据传输

说明:在我没转到linux之前,我粗略的学过windows内核编程,以下是在学习过程中编录的内容,以供参考

工具:WDK 7+VS2015 测试平台:虚拟机 WINDOWS XP

  • 包含的头文件
1
#include <ntifs.h>#include <ntstrsafe.h>
  • 声明的API函数
1
2
3
4
5
6
7
8
9
NTKERNELAPI HANDLE PsGetProcessInheritedFromUniqueProcessId(IN PEPROCESS Process);
NTKERNELAPI PPEB_EX PsGetProcessPeb(PEPROCESS Process);
NTKERNELAPI NTSTATUS PsLookupProcessByProcessId(HANDLE Id, PEPROCESS *Process);
NTKERNELAPI NTSTATUS PsLookupThreadByThreadId(HANDLE Id, PETHREAD *Thread);
NTKERNELAPI PEPROCESS IoThreadToProcess(PETHREAD Thread);
//NTKERNELAPI VOID NTAPI KeAttachProcess(PEPROCESS Process);
//NTKERNELAPI VOID NTAPI KeDetachProcess();
//NTKERNELAPI VOID NTAPI KeStackAttachProcess(PEPROCESS Process, PKAPC_STATE ApcState);
//NTKERNELAPI VOID NTAPI KeUnstackDetachProcess(PKAPC_STATE ApcState);
  • 因为要通过 PEPROCESS 来获取进程和模块,所以还要用到几个结构体,在WinDbg 可看到。
    这里新建一个头文件,包含了PEB等信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#include "peb.h"
如下:
#pragma once
#include <ntifs.h>
typedef struct _PEB_LDR_DATA_EX
{
ULONG Length; // +0x00
BOOLEAN Initialized; // +0x04
PVOID SsHandle; // +0x08
LIST_ENTRY InLoadOrderModuleList; // +0x0c
LIST_ENTRY InMemoryOrderModuleList; // +0x14
LIST_ENTRY InInitializationOrderModuleList;// +0x1c
}PEB_LDR_DATA_EX, *PPEB_LDR_DATA_EX;
typedef struct _LDR_DATA_TABLE_ENTRY_EX {
LIST_ENTRY InLoadOrderLinks;
LIST_ENTRY InMemoryOrderLinks;
LIST_ENTRY InInitializationOrderLinks;
PVOID DllBase;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
ULONG Flags;
USHORT LoadCount;
USHORT TlsIndex;
union {
LIST_ENTRY HashLinks;
struct {
PVOID SectionPointer;
ULONG CheckSum;
};
};
union {
ULONG TimeDateStamp;
PVOID LoadedImports;
};
PVOID EntryPointActivationContext;
PVOID PatchInformation;
LIST_ENTRY ForwarderLinks;
LIST_ENTRY ServiceTagLinks;
LIST_ENTRY StaticLinks;
PVOID ContextInformation;
PVOID OriginalBase;
LARGE_INTEGER LoadTime;
} LDR_DATA_TABLE_ENTRY_EX, *PLDR_DATA_TABLE_ENTRY_EX;
typedef struct _CURDIR {
UNICODE_STRING DosPath;
PVOID Handle;
}CURDIR, *PCURDIR;
typedef struct _RTL_DRIVE_LETTER_CURDIR {
USHORT Flags;
USHORT Length;
ULONG TimeStamp;
STRING DosPath;
}RTL_DRIVE_LETTER_CURDIR, *PRTL_DRIVE_LETTER_CURDIR;
//进程参数
typedef struct _RTL_USER_PROCESS_PARAMETERS{
ULONG MaximumLength;
ULONG Length;
ULONG Flags;
ULONG DebugFlags;
PVOID ConsoleHandle;
ULONG ConsoleFlags;
PVOID StandardInput;
PVOID StandardOutput;
PVOID StandardError;
CURDIR CurrentDirectory;
UNICODE_STRING DllPath;
UNICODE_STRING ImagePathName;
UNICODE_STRING CommandLine;
PVOID Environment;
ULONG StartingX;
ULONG StartingY;
ULONG CountX;
ULONG CountY;
ULONG CountCharsX;
ULONG CountCharsY;
ULONG FillAttribute;
ULONG WindowFlags;
ULONG ShowWindowFlags;
UNICODE_STRING WindowTitle;
UNICODE_STRING DesktopInfo;
UNICODE_STRING ShellInfo;
UNICODE_STRING RuntimeData;
RTL_DRIVE_LETTER_CURDIR CurrentDirectores[32];
}RTL_USER_PROCESS_PARAMETERS,*PRTL_USER_PROCESS_PARAMETERS;
//进程环境块(因为Windows内核有一个机构PEB,为了不重定义,所以就另起一个名字)
typedef struct _PEB_EX {
UCHAR InheritedAddressSpace;
UCHAR ReadImageFileExecOptions;
UCHAR BeingDebugged;
UCHAR SpareBool;
PVOID Mutant;
PVOID ImageBaseAddress;
PPEB_LDR_DATA_EX Ldr;
PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
UCHAR Reserved4[104];
PVOID Reserved5[52];
PVOID PostProcessInitRoutine;
PVOID Reserved7;
UCHAR Reserved6[128];
ULONG SessionId;
} PEB_EX, *PPEB_EX;
  • 用于遍历进程函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
void EnumProcess(PEPROCESS eprocess)
{
KAPC_STATE ks;
if (!MmIsAddressValid(eprocess))
return;
//获取 PEB信息
PPEB_EX peb = PsGetProcessPeb(eprocess);
if (!peb)
return;
//依附进程!!!!!!!!!!!!!!
KeStackAttachProcess(eprocess, &ks);
__try
{
if (PsGetProcessId(eprocess)!=0)
{
//获取 进程参数
PRTL_USER_PROCESS_PARAMETERS rtl_user_process_param =
(PRTL_USER_PROCESS_PARAMETERS)peb->ProcessParameters;
DbgPrint("CommandLine:%wZ\n", &rtl_user_process_param->CommandLine);
DbgPrint("ImagePath=%wZ\n", &rtl_user_process_param->ImagePathName);
//DbgPrint("Window Title=%wZ\n", &rtl_user_process_param->WindowTitle);
DbgPrint("——————————————————————————————");
}
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
//DbgPrint("Can not Process...");
}
//取消依附进程
KeUnstackDetachProcess(&ks);
}
  • 遍历模块,大体上和遍历进程一样,但也要注意区别
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
void EnumModules(PEPROCESS eprocess)
{
KAPC_STATE ks;
if (!MmIsAddressValid(eprocess))
return;
//获取 PEB信息
PPEB_EX peb = PsGetProcessPeb(eprocess);
if (!peb)
return;
//依附进程!!!!!!!!!!!!!!
KeStackAttachProcess(eprocess, &ks);
__try
{
PPEB_LDR_DATA_EX peb_LDR_data = (PPEB_LDR_DATA_EX)peb->Ldr;
PLIST_ENTRY list_entry = &peb_LDR_data->InLoadOrderModuleList;
//先获取第一个
PLIST_ENTRY currentList = list_entry->Flink;
while (currentList!=list_entry)
{
PLDR_DATA_TABLE_ENTRY_EX ldr_data_table_entry =(PLDR_DATA_TABLE_ENTRY_EX)currentList;
DbgPrint("Module Base=%p DllPath=%wZ\n",ldr_data_table_entry->DllBase, &ldr_data_table_entry->FullDllName);
//指向下一个
currentList = currentList->Flink;
}
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
//DbgPrint("Can not Modules...");
}
//取消依附进程
KeUnstackDetachProcess(&ks);
}
  • 这个函数把上面两个函数整合在一起了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
VOID EnumProcessModuleInformations()
{
//第一个进程环境块
PEPROCESS eprocess=PsGetCurrentProcess();
PEPROCESS eprocess_first = eprocess;
while (1)
{
//获取进程
EnumProcess(eprocess);
//下一个进程,我获取的是WinXP的 EPROCESS !
eprocess = (PEPROCESS)(*(ULONG*)((ULONG)eprocess + 0x88) - 0x88);
if (eprocess == eprocess_first){break;}
}
eprocess= eprocess_first;
while (1)
{
//获取模块
EnumModules(eprocess);
//下一个进程
eprocess = (PEPROCESS)(*(ULONG*)((ULONG)eprocess + 0x88) - 0x88);
if (eprocess == eprocess_first){break;}
}
}
  • 卸载函数很简单
1
2
3
4
VOID unload(PDRIVER_OBJECT p)
{
DbgPrint("UnloadDriver...");
}
  • 驱动入口函数
1
2
3
4
5
6
7
8
9
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver_Obj, PUNICODE_STRING pRegisterPath)
{
DbgPrint("DriverEntry...");
pDriver_Obj->DriverUnload = unload;
DbgPrint("DriverName:%wZ RegisterPath:%wZ \n ", &pDriver_Obj->DriverName,pRegisterPath);
//这里调用
EnumProcessModuleInformations();
return STATUS_SUCCESS;
}