Sysmon安装后会生成如下两个文件:

C:WindowsSysmon.exe
C:WindowsSysmonDrv.sys

显然Sysmon使用了驱动级监控,需要IDA+WinDBG+VMware组合,搭建双机驱动调试环境才能对SysmonDrv.sys进行有效的调试。

通过IDA+WinDBG的静态分析和动态跟踪,发现其使用PsSetCreateProcessNotifyRoutine函数,来监控进程的创建。关键代码如下:

.text:FFFFF880018AEA99 ; ---------------------------------------------------------------------------
.text:FFFFF880018AEA99
.text:FFFFF880018AEA99 loc_FFFFF880018AEA99:                   ; CODE XREF: sub_FFFFF880018AE730+349
.text:FFFFF880018AEA99 mov     rcx, cs:qword_FFFFF880018B4498
.text:FFFFF880018AEAA0 call    cs:FltStartFiltering
.text:FFFFF880018AEAA6 call    sub_FFFFF880018ADD00
.text:FFFFF880018AEAAB lea     rcx, sub_FFFFF880018ADBA0
.text:FFFFF880018AEAB2 call    cs:PsSetCreateThreadNotifyRoutine
.text:FFFFF880018AEAB8 lea     rcx, sub_FFFFF880018ADC40
.text:FFFFF880018AEABF xor     edx, edx
.text:FFFFF880018AEAC1 call    cs:PsSetCreateProcessNotifyRoutine
.text:FFFFF880018AEAC7 xor     eax, eax

回调函数地址为:sub_FFFFF880018ADC40(动态地址)。每当有新进程创建时,都会回调这个函数。回调时,寄存器RCX保存父进程PID,RDX保存子进程PID。

PsSetCreateProcessNotifyRoutine函数定义如下:

NTSTATUS PsSetCreateProcessNotifyRoutine(
  _In_  PCREATE_PROCESS_NOTIFY_ROUTINE NotifyRoutine,
  _In_  BOOLEAN Remove
);

回调函数定义如下:

VOID
(*PCREATE_PROCESS_NOTIFY_ROUTINE) (
    IN HANDLE  ParentId,
    IN HANDLE  ProcessId,
    IN BOOLEAN  Create
    );

对于文件创建时间修改的监控,则是通过Minifilter驱动实现的。大体原理是,注册一个文件过滤器,监控对文件的操作,一旦发现有修改文件日期的行为,就记录日志。过程如下:

注册过滤器:

.text:FFFFF8800164FA5E                 mov     rcx, rdi
.text:FFFFF8800164FA61                 mov     cs:qword_FFFFF880016554A8, rax
.text:FFFFF8800164FA68                 mov     cs:qword_FFFFF880016554A0, rax
.text:FFFFF8800164FA6F                 call    cs:FltRegisterFilter

启动过滤器:

.text:FFFFF8800164FA99 ; ---------------------------------------------------------------------------
.text:FFFFF8800164FA99
.text:FFFFF8800164FA99 loc_FFFFF8800164FA99:                   ; CODE XREF: sub_FFFFF8800164F730+349
.text:FFFFF8800164FA99                 mov     rcx, cs:qword_FFFFF88001655498
.text:FFFFF8800164FAA0                 call    cs:FltStartFiltering

回调函数:

.text:FFFFF8800164DBD9 loc_FFFFF8800164DBD9:                   ; CODE XREF: sub_FFFFF8800164DB90+39
.text:FFFFF8800164DBD9                 cmp     [rdi+50h], bl
.text:FFFFF8800164DBDC                 jnz     short loc_FFFFF8800164DC21
.text:FFFFF8800164DBDE                 cmp     dword ptr [rax+20h], 4
.text:FFFFF8800164DBE2                 jnz     short loc_FFFFF8800164DC21
.text:FFFFF8800164DBE4                 cmp     dword ptr [rax+18h], 28h ; \'(\'
.text:FFFFF8800164DBE8                 jb      short loc_FFFFF8800164DC21
.text:FFFFF8800164DBEA                 mov     rdi, [rax+38h]
.text:FFFFF8800164DBEE                 test    rdi, rdi
.text:FFFFF8800164DBF1                 jz      short loc_FFFFF8800164DC21
.text:FFFFF8800164DBF3                 mov     rax, [rdi]
.text:FFFFF8800164DBF6                 add     rax, 2
.text:FFFFF8800164DBFA                 cmp     rax, 2
.text:FFFFF8800164DBFE                 jbe     short loc_FFFFF8800164DC21
.text:FFFFF8800164DC00                 mov     rcx, rsi
.text:FFFFF8800164DC03                 call    sub_FFFFF8800164D6B0 ; 这里调用文件信息查询函数FltQueryInformationFile,查询是否符合条件。符合条件返回1,可以人工修改结果使其效果相反。
.text:FFFFF8800164DC08                 test    al, al
.text:FFFFF8800164DC0A                 jz      short loc_FFFFF8800164DC21
.text:FFFFF8800164DC0C                 mov     rdx, [rdi]
.text:FFFFF8800164DC0F                 mov     rcx, rsi
.text:FFFFF8800164DC12                 call    sub_FFFFF8800164D720 ; 如果确实是需要记录的操作,那么调用此子函数,获取文件信息以及调用者的PID。
.text:FFFFF8800164DC17                 test    rax, rax
.text:FFFFF8800164DC1A                 jz      short loc_FFFFF8800164DC21
.text:FFFFF8800164DC1C                 mov     [r14], rax
.text:FFFFF8800164DC1F                 xor     ebx, ebx

每次回调时通过FltQueryInformationFile函数查询文件的信息,来判断是否修改。

NTSTATUS FltQueryInformationFile(
  _In_       PFLT_INSTANCE Instance,
  _In_       PFILE_OBJECT FileObject,
  _Out_      PVOID FileInformation,
  _In_       ULONG Length,
  _In_       FILE_INFORMATION_CLASS FileInformationClass,
  _Out_opt_  PULONG LengthReturned
);

FILE_INFORMATION_CLASS结构体是多种类型的,FILE_NETWORK_OPEN_INFORMATION类型保存了文件的各个时间属性。

通过OD跟踪,很容易发现TCPView使用了Windows的两个关键的API来实现这个功能。两个API的定义:

DWORD GetExtendedTcpTable(
  _Out_    PVOID pTcpTable,
  _Inout_  PDWORD pdwSize,
  _In_     BOOL bOrder,
  _In_     ULONG ulAf,
  _In_     TCP_TABLE_CLASS TableClass,
  _In_     ULONG Reserved
);

DWORD GetExtendedUdpTable(
  _Out_    PVOID pUdpTable,
  _Inout_  PDWORD pdwSize,
  _In_     BOOL bOrder,
  _In_     ULONG ulAf,
  _In_     UDP_TABLE_CLASS TableClass,
  _In_     ULONG Reserved
);

使用这两个函数,可以获取所有的TCP/UDP连接的列表,保存在以下两个结构体中(IPv6类似,这里不列出了):

typedef struct {
  DWORD                dwNumEntries;
  MIB_TCPROW_OWNER_PID table[ANY_SIZE];
} MIB_TCPTABLE_OWNER_PID, *PMIB_TCPTABLE_OWNER_PID;

typedef struct _MIB_UDPTABLE_OWNER_PID {
  DWORD                dwNumEntries;
  MIB_UDPROW_OWNER_PID table[ANY_SIZE];
} MIB_UDPTABLE_OWNER_PID, *PMIB_UDPTABLE_OWNER_PID;

以上结构体中都有一个数组,而进程与端口号的关联信息,都保存在数组中每一个MIB_TCPROW_OWNER_PIDMIB_UDPROW_OWNER_PID结构体中。他们的定义如下:

typedef struct _MIB_TCPROW_OWNER_PID {
  DWORD dwState;
  DWORD dwLocalAddr;
  DWORD dwLocalPort;
  DWORD dwRemoteAddr;
  DWORD dwRemotePort;
  DWORD dwOwningPid;
} MIB_TCPROW_OWNER_PID, *PMIB_TCPROW_OWNER_PID;

typedef struct _MIB_UDPROW_OWNER_PID {
  DWORD dwLocalAddr;
  DWORD dwLocalPort;
  DWORD dwOwningPid;
} MIB_UDPROW_OWNER_PID, *PMIB_UDPROW_OWNER_PID;

结构体中的dwOwningPid就是PID信息。

TCPView程序中使用这两个函数的关键地方:

0040D3B5   .  83C1 07       add ecx,0x7
0040D3B8   .  51            push ecx
0040D3B9   .  6A 02         push 0x2
0040D3BB   .  55            push ebp
0040D3BC   .  52            push edx
0040D3BD   .  55            push ebp
0040D3BE   .  FF15 3C6B4400 call dword ptr ds:[0x446B3C]             ;  IPHLPAPI.GetExtendedTcpTable
0040D3C4   .  83F8 7A       cmp eax,0x7A
0040D3C7   .  75 47         jnz XTcpview.0040D410
0040D3C9   .  8DA424 000000>lea esp,dword ptr ss:[esp]
0040D3D0   >  3BFD          cmp edi,ebp
0040D3D2   .  74 09         je XTcpview.0040D3DD
0040D3D4   .  57            push edi
0040D3D5   .  E8 EB540000   call Tcpview.004128C5
0040D3DA   .  83C4 04       add esp,0x4
0040D3DD   >  8B4424 14     mov eax,dword ptr ss:[esp+0x14]
0040D3E1   .  50            push eax
0040D3E2   .  E8 AC500000   call Tcpview.00412493
0040D3E7   .  83C4 04       add esp,0x4
0040D3EA   .  33C9          xor ecx,ecx
0040D3EC   .  380D 156E4400 cmp byte ptr ds:[0x446E15],cl
0040D3F2   .  55            push ebp
0040D3F3   .  0F95C1        setne cl
0040D3F6   .  8D5424 18     lea edx,dword ptr ss:[esp+0x18]
0040D3FA   .  8BF8          mov edi,eax
0040D3FC   .  83C1 07       add ecx,0x7
0040D3FF   .  51            push ecx
0040D400   .  6A 02         push 0x2
0040D402   .  55            push ebp
0040D403   .  52            push edx
0040D404   .  57            push edi
0040D405   .  FF15 3C6B4400 call dword ptr ds:[0x446B3C]             ;  IPHLPAPI.GetExtendedTcpTable
0040D40B   .  83F8 7A       cmp eax,0x7A
0040D40E   .^ 74 C0         je XTcpview.0040D3D0

0040D494   .  57            push edi
0040D495   .  6A 01         push 0x1
0040D497   .  6A 02         push 0x2
0040D499   .  57            push edi
0040D49A   .  8D5424 24     lea edx,dword ptr ss:[esp+0x24]
0040D49E   .  52            push edx
0040D49F   .  57            push edi
0040D4A0   .  C74424 2C 000>mov dword ptr ss:[esp+0x2C],0x0
0040D4A8   .  FF15 286E4400 call dword ptr ds:[0x446E28]             ;  IPHLPAPI.GetExtendedUdpTable
0040D4AE   .  83F8 7A       cmp eax,0x7A
0040D4B1   .  75 35         jnz XTcpview.0040D4E8
0040D4B3   >  85FF          test edi,edi
0040D4B5   .  74 09         je XTcpview.0040D4C0
0040D4B7   .  57            push edi
0040D4B8   .  E8 08540000   call Tcpview.004128C5
0040D4BD   .  83C4 04       add esp,0x4
0040D4C0   >  8B4424 14     mov eax,dword ptr ss:[esp+0x14]
0040D4C4   .  50            push eax
0040D4C5   .  E8 C94F0000   call Tcpview.00412493
0040D4CA   .  83C4 04       add esp,0x4
0040D4CD   .  6A 00         push 0x0
0040D4CF   .  6A 01         push 0x1
0040D4D1   .  6A 02         push 0x2
0040D4D3   .  6A 00         push 0x0
0040D4D5   .  8D4C24 24     lea ecx,dword ptr ss:[esp+0x24]
0040D4D9   .  8BF8          mov edi,eax
0040D4DB   .  51            push ecx
0040D4DC   .  57            push edi
0040D4DD   .  FF15 286E4400 call dword ptr ds:[0x446E28]             ;  IPHLPAPI.GetExtendedUdpTable
0040D4E3   .  83F8 7A       cmp eax,0x7A
0040D4E6   .^ 74 CB         je XTcpview.0040D4B3
0040D4E8   >  85C0          test eax,eax