一些小总结

更换对应的libc和ld

确定给的libc.so.6版本

1
strings libc.so.6 | grep libc

在glibc-all-in-one中下载对应的版本

1
2
cd ~
cd glibc-all-in-one

列出版本列表

1
cat list

下载

1
./download 对应版本

patchelf到程序中

1
2
patchelf --set-interpreter ~/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/ld-2.23.so example
patchelf --replace-needed libc.so.6 ./libc-2.23.so example

查看程序现在的依赖与libc库

1
ldd example

canary泄露

要注意的是即使开了canary保护,程序也有可能没调用检查canary的函数,此时溢出时就不需要泄露canary

格式化字符串

寻找栈上偏移即可,需要注意的是64位程序是从寄存器开始算,而32位直接从栈上

%s覆盖低字节

利用read等输入的函数来覆盖canary低字节,接着%s就能输出了

假设read(0,buf,0x100),而bufrbp-0x20处,那么我只要sendline(b'A'*(0x20-8))即可覆盖到canary最低一位的字节(sendline中最后一个回车刚好覆盖到)

在接收的时候注意要canary=u64(r.recv(8))-0xa,因为回车会改变canary最低字节为0xa,不是真正的canary

ropper

进入

1
ropper

选择要分析的文件

1
file example

搜索gadget(以pop rdi为例子)

1
search pop rdi

搜索string

1
string /bin/sh

共享文件夹

切换到共享文件夹下

1
2
cd ~
cd /mnt/hgfs/VMware-share

将文件夹文件移动到桌面

1
mv example ~/桌面

gadgets

控制寄存器的值

  • 直接控制
    • 能直接找到类似pop rdi; ret;gdagets最好,这样就能直接控制
  • 间接控制
    • 有时候找不到上面的gadgets,但是能找到mov rdi dcx; retrcx可控时,也可以控制rdi的值

利用寄存器写入/bin/sh

存在mov [rax],rcx; ret;类似的gadgets,在raxrcx都可控的情况下,控制rcx/bin/sh\x00,·为可写入且已知的地址,这样就可以将binsh写入rax的地址之中了

gdb指令大全

命令 作用 备注
r 运行
b 函数名/*地址 下断点
n 按源码单步进行 汇编代码单步,不进入函数内部
s 按源码单步 会进入函数内部
finish 跳出函数
c 继续运行 到下个断点处
tele 地址(0x1234) 查看地址上的信息
stack 查看栈信息 可用stack 数字 来确定查看多少条信息
vmmap 查看各种段地址信息及权限
p 函数名 查看该函数地址
x/格式 地址 查看地址上信息 常用x/20gx 20表示显示20条信息,g是表示8字节,x表示16进制b
b *$rebase(偏移) 在开了PIE的程序下断点 注意要运行了才可下断点
ni 按汇编单步进行
si 按汇编单步

tele:

tele

sendline与send

当程序限制read在0x20字节时,而我们要输入的长度恰好在0x20,一定要用send而不是sendline,否则多余的\n可能会残留在缓冲区被下一个read读取/(ㄒoㄒ)/~~

黑名单

比如

1
2
3
4
5
6
7
8
9
10
11
12
13
#!/bin/python3
import os

print("input your command")

blacklist = ['cat','ls',' ','cd','echo','<','${IFS}','sh','\\']

while True:
command = input()
for i in blacklist:
if i in command:
exit(0)
os.system(command)

不允许直接使用 cat flag/bin/sh

可以使用/bin/*h同样可以进入system("/bin/sh")

原理:

1. 通配符 \* 的作用

  • * 在 Shell 中表示 匹配任意长度的任意字符(包括空字符)。
  • 例如:
    • *h 会匹配所有 h 结尾 的文件或目录名。
    • /bin/*h 则会匹配 /bin 目录下所有以 h 结尾的文件。

2. /bin 目录的典型内容

在大多数 Linux 系统中,/bin 目录下通常包含以下文件:

  • /bin/sh:Bourne Shell(或符号链接到其他 Shell,如 bashdash)。
  • 其他文件如 /bin/bash/bin/dash/bin/cat 等,但 不会以 h 结尾

因此,执行 /bin/*h 时,通配符会扩展为 /bin/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
from pwn import *
context.terminal = ['tmux', 'splitw', '-h']
context(arch = 'amd64', os = 'linux')
#context(arch = 'i386', os = 'linux')
context.log_level = 'debug'

#r = process("./pwn1")
r = remote("node4.anna.nssctf.cn", 22956)
elf = ELF("./pwn1")
libc = elf.libc

def debug():
gdb.attach(r)
pause()

sd = lambda s : r.send(s)
sda = lambda s, n : r.sendafter(s, n)
sl = lambda s : r.sendline(s)
sla = lambda s, n : r.sendlineafter(s, n)
rc = lambda n : r.recv(n)
ru = lambda s : r.recvuntil(s)
addr = lambda n : u64(r.recv(n).ljust(8, b'\x00'))
addr32 = lambda s : u32(r.recvuntil(s, drop=True, timeout=1).ljust(4, b'\x00'))
addr64 = lambda s : u64(r.recvuntil(s, drop=True, timeout=1).ljust(8, b'\x00'))
byte = lambda n : str(n).encode()
info = lambda s, n : print("\033[31m["+s+"->"+str(hex(n))+"]\033[0m")
irt = lambda : r.interactive()

关闭ASLR

为了方便调试,经常关闭ASLR

指令:

1
2
cat /proc/sys/kernel/randomize_va_space # 查看ASLR情况 0 关2 FULL
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space # 关闭

利用xinetd部署pwn题目

xinetd

一个开源项目

Eadom/ctf_xinetd: A docker repository for deploying pwnable challenges in CTF

可以很方便的部署pwn题目

bin

将里面的flag换成我们的flag,然后将里面的程序替换成我们的程序

ctf.xinetd

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
service ctf
{
disable = no
socket_type = stream
protocol = tcp
wait = no
user = root
type = UNLISTED
port = 80
bind = 0.0.0.0
server = /usr/sbin/chroot
# replace helloworld to your program
server_args = --userspec=1000:1000 /home/ctf ./shellcode # 这里替换成我们自己的程序
banner_fail = /etc/banner_fail
# safety options
per_source = 10 # the maximum instances of this service per source IP address
rlimit_cpu = 20 # the maximum number of CPU seconds that the service may use
#rlimit_as = 1024M # the Address Space resource limit for the service
#access_times = 2:00-9:00 12:00-24:00
}

Dockerfile

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
FROM ubuntu:22.04 # 这里应该要写自己ubuntu版本

RUN sed -i "s/http:\/\/archive.ubuntu.com/http:\/\/mirrors.tuna.tsinghua.edu.cn/g" /etc/apt/sources.list && \
apt-get update && apt-get -y dist-upgrade && \
apt-get install -y lib32z1 xinetd

RUN useradd -m ctf

WORKDIR /home/ctf

RUN cp -R /usr/lib* /home/ctf

RUN mkdir /home/ctf/dev && \
mknod /home/ctf/dev/null c 1 3 && \
mknod /home/ctf/dev/zero c 1 5 && \
mknod /home/ctf/dev/random c 1 8 && \
mknod /home/ctf/dev/urandom c 1 9 && \
chmod 666 /home/ctf/dev/*

RUN mkdir /home/ctf/bin && \
cp /bin/sh /home/ctf/bin && \
cp /bin/ls /home/ctf/bin && \
cp /bin/cat /home/ctf/bin

COPY ./ctf.xinetd /etc/xinetd.d/ctf
COPY ./start.sh /start.sh
RUN echo "Blocked by ctf_xinetd" > /etc/banner_fail

RUN chmod +x /start.sh

COPY ./bin/ /home/ctf/
RUN chown -R root:ctf /home/ctf && \
chmod -R 750 /home/ctf && \
chmod 740 /home/ctf/flag

CMD ["/start.sh"]

EXPOSE 80

Docker

  • 制作镜像
1
sudo docker build -t "pwn" .
  • 查看所有本地镜像
1
sudo docker images
  • 登陆远程仓库
1
sudo docker login .....

随机数绕过

比如以 time 为种子,利用 ctypes 调用随机数函数来绕过

1
2
3
libc=CDLL('/home/yyyffff/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so') seed=libc.time(0) 
libc.srand(seed)
random_num=libc.rand()%50

一些小总结
http://yyyffff.github.io/2025/05/12/一些小总结/
作者
yyyffff
发布于
2025年5月12日
许可协议