In 32-bit Windows we have many methods for locating SSDT, most directly using the export symbols to find SSDT. And then there is through the nt! Disassembly search in the Keaddsystemservicetable function. However, neither of these methods is feasible in 64-bit Windows. In 64-bit Windows, you are not exporting SSDT, and nt! Keaddsystemservicetable is no longer out of SSDT (here is the error, it should not appear as a direct SSDT address, the personal level of limited feeling calculation is too troublesome. )。 The first problem with the hook SSDT table is how do I find it? I think of three ideas.
Idea 1:
A hard-coded offset of NTOSKRNL to SSDT is determined for each version of the system. Oh, this method may be more silly but the simplest and directly effective. is to maintain a very troublesome, to each version into a separate processing, if the different patch version has changed also to deal with.
Idea 2:
The ingress offset for each service routine is stored in 64-bit Windows (this offset is relative to the start address of SSDT). I take a general non-hook service routine entry offset, and then search from the start address of the NTOSKRNL to the end to find the four bytes, and then navigate to the beginning of SSDT based on the index of the service routine. It is possible that different versions of the operating system have different offsets and indexes that need to be handled separately, but are more generic than the first idea.
Idea 3:
or using the Disassembly method, but nt! No direct SSDT address has been found in the Keaddsystemservicetable function. Later I wondered if the image could be searched for the address of SSDT.
Kd> DQ nt! Keservicedescriptortable
fffff800 ' 03eab840 fffff800 ' 03c75b00 00000000 ' 00000000
fffff800 ' 03eab850 00000000 ' 00000191 fffff800 ' 03c7678c
fffff800 ' 03eab860 00000000 ' 00000000 00000000 ' 00000000
fffff800 ' 03eab870 00000000 ' 00000000 00000000 ' 00000000
fffff800 ' 03eab880 fffff800 ' 03c75b00 00000000 ' 00000000
fffff800 ' 03eab890 00000000 ' 00000191 fffff800 ' 03c7678c
fffff800 ' 03eab8a0 fffff960 ' 00111c00 00000000 ' 00000000
fffff800 ' 03eab8b0 00000000 ' 0000033b fffff960 ' 0011391c
Kd> LM m NT
Start End Module Name
fffff800 ' 03c03000 fffff800 ' 041e0000 NT (PDB symbols)
kd> s-q fffff800 ' 03c03000 l600000 fffff800 ' 03eab840
Unfortunately I didn't find any relevant information. Oh, but I zeixin not dead, I believe there will be a reference somewhere. So I searched for symbols with service words in all the names.
kd> x nt! ki*service*
fffff800 ' 03c73e40 nt! kiserviceinternal = <no Type information>
fffff800 ' 03c7415b nt! Kisystemserviceexit = <no Type information>
fffff800 ' 03c73fde nt! Kisystemservicestart = <no Type information>
fffff800 ' 03c76788 nt! Kiservicelimit = <no Type information>
fffff800 ' 03c73b00 nt! Kidebugservicetrap = <no Type information>
fffff800 ' 03c74140 nt! Kisystemservicecopyend = <no Type information>
fffff800 ' 03c75b00 nt! kiservicetable = <no Type information>
fffff800 ' 03c74037 nt! kisystemservicegditebaccess = <no Type information>
fffff800 ' 03c73ff2 nt! Kisystemservicerepeat = <no type information>
fffff800 ' 03c740d0 nt! Kisystemservicecopystart = <no Type information>
fffff800 ' 03c706f0 nt! Kiservicelinkage = <no Type information>
fffff800 ' 03c73d40 nt! Kisystemservicehandler = <no Type information>
Finally in nt! Find the information for SSDT in Kisystemservicerepeat.
Nt! Kisystemservicerepeat:
fffff800 ' 03c73ff2 4c8d1547782300 Lea r10,[nt! Keservicedescriptortable (fffff800 ' 03eab840)]
fffff800 ' 03c73ff9 4c8d1d80782300 Lea r11,[nt! Keservicedescriptortableshadow (fffff800 ' 03eab880)]
fffff800 ' 03c74000 f7830001000080000000 test DWORD ptr [rbx+100h],80h
fffff800 ' 03c7400a 4d0f45d3 cmovne r10,r11
fffff800 ' 03c7400e 423b441710 cmp eax,dword ptr [rdi+r10+10h]
fffff800 ' 03c74013 0f83e9020000 Jae nt! Kisystemserviceexit+0x1a7 (fffff800 ' 03c74302)
fffff800 ' 03c74019 4e8b1417 mov r10,qword ptr [rdi+r10]
fffff800 ' 03c7401d 4d631c82 movsxd r11,dword ptr [r10+rax*4]
But a new problem arises at the same time, nt!. Kisystemservicerepeat is not an export function of the system. So how do I find it? Then I thought that although it does not export, there should be at least one call path from the outside to it! Then I'll just find it through this path. Think of it and make a breakpoint to see who will call it. The result is the same as I thought, but found that I was really a rookie, find SSDT value too happy to have not looked closely at its assembly code. Nt! Kisystemservicerepeat is the completion of obtaining a service routine entry from SSDT based on the call number and invoking it. That means that every function of the Zwxxx class is called to it, and the function of the ZW class is the system export so that we can find the nt! by any function of the ZW class. Kisystemservicerepeat thus navigates to SSDT. So I tried it by hand. The following is the process of the attempt.
kd> u nt! Zwclose L20
Nt! Zwclose:
fffff800 ' 03c6d640 488BC4 mov rax,rsp
fffff800 ' 03c6d643 fa CLI
fffff800 ' 03c6d644 4883ec10 Sub rsp,10h
fffff800 ' 03c6d648 push Rax
fffff800 ' 03c6d649 9c Pushfq
fffff800 ' 03c6d64a 6a10 push 10h
fffff800 ' 03c6d64c 488d059d300000 Lea rax,[nt! Kiservicelinkage (fffff800 ' 03c706f0)]
fffff800 ' 03c6d653 push Rax
fffff800 ' 03c6d654 b80c000000 mov eax,0ch
fffff800 ' 03c6d659 e9e2670000 jmp nt! Kiserviceinternal (fffff800 ' 03c73e40)
fffff800 ' 03c6d65e 6690 xchg ax,ax
In the Zwclose (other similar) jumps to the nt! Kiserviceinternal, we'll track nt!. Kiserviceinternal
Nt! Kiserviceinternal:
fffff800 ' 03c73e40 4883ec08 Sub rsp,8
fffff800 ' 03c73e44-Push RBP
fffff800 ' 03c73e45 4881ec58010000 Sub rsp,158h
fffff800 ' 03c73e4c 488dac2480000000 Lea rbp,[rsp+80h]
fffff800 ' 03c73e54 48899dc0000000 mov qword ptr [rbp+0c0h],rbx
fffff800 ' 03c73e5b 4889bdc8000000 mov qword ptr [rbp+0c8h],rdi
fffff800 ' 03c73e62 4889b5d0000000 mov qword ptr [rbp+0d0h],rsi
fffff800 ' 03c73e69 fb sti
fffff800 ' 03c73e6a 65488b1c2588010000 mov rbx,qword ptr gs:[188h]
fffff800 ' 03c73e73 0f0d8bd8010000 prefetchw [rbx+1d8h]
fffff800 ' 03c73e7a 0fb6bbf6010000 movzx edi,byte ptr [rbx+1f6h]
fffff800 ' 03c73e81 40887da8 mov byte ptr [rbp-58h],dil
fffff800 ' 03c73e85 c683f601000000 mov byte ptr [rbx+1f6h],0
fffff800 ' 03c73e8c 4c8b93d8010000 mov r10,qword ptr [rbx+1d8h]
fffff800 ' 03c73e93 4c8995b8000000 mov qword ptr [rbp+0b8h],r10
fffff800 ' 03c73e9a 4c8d1d3d010000 Lea r11,[nt! Kisystemservicestart (fffff800 ' 03c73fde)]
fffff800 ' 03c73ea1 41ffe3 jmp R11
fffff800 ' 03c73ea4 666666666666660f1f840000000000 nop word ptr [Rax+rax]
fffff800 ' 03c73eb3 66666666660f1f840000000000 nop word ptr [Rax+rax]
And in this function, we jump to nt!. Kisystemservicestart, here 4c8d1d3d010000 this instruction needs to refer to the x64 assembly for REX.W prefix and mod r/m addressing knowledge to explain this offset. Here is fffff800 ' 03c73ea1+013d is nt! Kisystemservicestart entry address. The next step is to disassemble from this address.
Nt! Kisystemservicestart:
fffff800 ' 03c73fde 4889a3d8010000 mov qword ptr [rbx+1d8h],rsp
fffff800 ' 03c73fe5 8bf8 mov edi,eax
fffff800 ' 03c73fe7 c1ef07 shr edi,7
fffff800 ' 03c73fea 83e720 and edi,20h
fffff800 ' 03c73fed 25ff0f0000 and EAX,0FFFH
Nt! Kisystemservicerepeat:
fffff800 ' 03c73ff2 4c8d1547782300 Lea r10,[nt! Keservicedescriptortable (fffff800 ' 03eab840)]
fffff800 ' 03c73ff9 4c8d1d80782300 Lea r11,[nt! Keservicedescriptortableshadow (fffff800 ' 03eab880)]
fffff800 ' 03c74000 f7830001000080000000 test DWORD ptr [rbx+100h],80h
fffff800 ' 03c7400a 4d0f45d3 cmovne r10,r11
fffff800 ' 03c7400e 423b441710 cmp eax,dword ptr [rdi+r10+10h]
fffff800 ' 03c74013 0f83e9020000 Jae nt! Kisystemserviceexit+0x1a7 (fffff800 ' 03c74302)
fffff800 ' 03c74019 4e8b1417 mov r10,qword ptr [rdi+r10]
fffff800 ' 03c7401d 4d631c82 movsxd r11,dword ptr [r10+rax*4]
fffff800 ' 03c74021 498BC3 mov rax,r11
fffff800 ' 03c74024 49c1fb04 SAR r11,4
fffff800 ' 03c74028 4d03d3 add R10,r11
fffff800 ' 03c7402b 83ff20 cmp edi,20h
fffff800 ' 03c7402e 7550 jne nt! kisystemservicegditebaccess+0x49 (fffff800 ' 03c74080)
fffff800 ' 03c74030 4c8b9bb8000000 mov r11,qword ptr [rbx+0b8h]
Finally found us to find the function, 4c8d1547782300,4c8d1d80782300 according to these two instructions I can locate the location of SSDT. Finally the dispel. These two instructions all add the REX.W prefix to the meaning of the specific field to explain it can be found ssdt,4c8d1547782300 this instruction of 64 immediate number addressing should be fffff800 ' 03c73ff9+237847 to expand, that is, rip+ offset. The immediate number in a similar 4c8d1d80782300 instruction should be extended to fffff800 ' 03c74000+237880, which is the content of SSDT through the DQ command.
Kd> dq fffff800 ' 03c74000+237880
fffff800 ' 03eab880 fffff800 ' 03c75b00 00000000 ' 00000000
fffff800 ' 03eab890 00000000 ' 00000191 fffff800 ' 03c7678c
fffff800 ' 03eab8a0 fffff960 ' 00111c00 00000000 ' 00000000
fffff800 ' 03eab8b0 00000000 ' 0000033b fffff960 ' 0011391c
fffff800 ' 03eab8c0 00000000 ' 7771fdd6 00000000 ' 00000000
fffff800 ' 03eab8d0 fffff800 ' 00a01400 fffff800 ' 00a013b0
fffff800 ' 03eab8e0 00000000 ' 00000002 00000000 ' 00005bdb
fffff800 ' 03eab8f0 00000000 ' 00023f05 00000000 ' 00000000
Kd> DQ nt! Keservicedescriptortableshadow
fffff800 ' 03eab880 fffff800 ' 03c75b00 00000000 ' 00000000
fffff800 ' 03eab890 00000000 ' 00000191 fffff800 ' 03c7678c
fffff800 ' 03eab8a0 fffff960 ' 00111c00 00000000 ' 00000000
fffff800 ' 03eab8b0 00000000 ' 0000033b fffff960 ' 0011391c
fffff800 ' 03eab8c0 00000000 ' 7771fdd6 00000000 ' 00000000
fffff800 ' 03eab8d0 fffff800 ' 00a01400 fffff800 ' 00a013b0
fffff800 ' 03eab8e0 00000000 ' 00000002 00000000 ' 00005bdb
fffff800 ' 03eab8f0 00000000 ' 00023f05 00000000 ' 00000000
The two methods find the same location. The output I have here is for WIN7 64-bit systems, and it is also true that this method is used to debug 2003. Because there is no other version of the operating system temporarily. The applicability of other operating systems is unknown. Personal speculation that Xp,vista should be similar but need to prove. However, the Win7 is slightly different from the 2003 SSDT table entries, although all four sections the last four bits are the number of parameters of the routine, but the calculation on 2003 is the SSDT base address + table key value &0xfffffff0, and Win7 becomes the SSDT base address + table key value > >4. If the hook table item is still to be treated separately. I am the first time to post, everyone tap AH. The above elaborated if has the mistake please the single hero many advice, the younger brother greatly appreciates.
WINDOWS 64-bit SSDT location ideas