2023. 5. 29. 14:51ㆍHawkis_CTF
CTF 문제
bof.zip 폴더 다운로드
* bof.c 파일
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void alarm_handler() {
puts("TIME OUT");
exit(-1);
}
void initialize() {
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
signal(SIGALRM, alarm_handler);
alarm(30);
}
void read_me(){
system("/bin/sh");
}
void food() {
puts("do you like fastfood?");
puts("choose!");
puts("[h]amberger");
puts("[p]izza");
puts("[c]hiken");
printf("> ");
}
int main(int argc, char *argv[])
{
char name[0x50] = {};
char choose[2] = {};
initialize();
while(1) {
food();
read(0, choose, 2);
switch(choose[0]){
case 'h':
printf("i like hamberger!");
break;
case 'p':
printf("what do you want?");
read(0,name,79);
break;
case 'c':
printf("i don't like chiken.\n");
printf("pick another one: ");
read(0,name,0x100);
return 0;
default:
break;
}
}
}
read_me 함수를 이용해 /bin/sh 쉘을 실행할 수 있음
buffer 대상 함수 = name [0x50]
스택 버퍼 오버 플로우
■ 버퍼 (Buffer)
: 데이터가 목적지로 이동되기 전에 보관되는 임시 저장소
(사용자의 입력값)
■ 버퍼 오버 플로우 (Buffer overflow)
: 메모리에 할당된 공간인 buffer를 넘어서 SFP와 RET영역까지 사용자가 원하는 값을 채워넣을 수 있는 취약점
gdb로 bof파일 실행
* gdb란?
: GNU DeBugger의 약자로 GNU 소프트웨어를 위한 기본 디버거
* gdb가 지원하는 언어
: Ada, Assembly, C, C++, D, Fortran, Go, Objective-C, OpenCL, Modula-2, Pascal, Rust
gdb bof 명령으로 bof파일을 디버깅
-> No debugging symbols found in bof 라는 오류 뜸 (디버깅 안된다는 뜻)
-> info file 명령어를 통해 파일의 .text 영역의 주소값을 알아냄
-> disas (.text 주소 값) 명령 입력시 어셈블리 코드 출력 가능
* gdb 디스어셈블리는 기본적으로 AT&T문법을 따른다
하지만 우리가 흔히 접한 어셈블 코드는 Intel 문법이기에
$ set disassembly-flavor intel 명령을 통해 설정을 Intel 문법으로 변환하였다
AT&T 문법 | Intel 문법 |
![]() |
![]() |
* bof 어셈블 코드
0x00000000004010b0 <_start+0>: xor ebp,ebp
0x00000000004010b2 <_start+2>: mov r9,rdx
0x00000000004010b5 <_start+5>: pop rsi
0x00000000004010b6 <_start+6>: mov rdx,rsp
0x00000000004010b9 <_start+9>: and rsp,0xfffffffffffffff0
0x00000000004010bd <_start+13>: push rax
0x00000000004010be <_start+14>: push rsp
0x00000000004010bf <_start+15>: xor r8d,r8d
0x00000000004010c2 <_start+18>: xor ecx,ecx
0x00000000004010c4 <_start+20>: mov rdi,0x401290
0x00000000004010cb <_start+27>: call QWORD PTR [rip+0x2f07] # 0x403fd8
0x00000000004010d1 <_start+33>: hlt
0x00000000004010d2: cs nop WORD PTR [rax+rax*1+0x0]
0x00000000004010dc: nop DWORD PTR [rax+0x0]
0x00000000004010e0 <_dl_relocate_static_pie+0>: ret
0x00000000004010e1: cs nop WORD PTR [rax+rax*1+0x0]
0x00000000004010eb: nop DWORD PTR [rax+rax*1+0x0]
0x00000000004010f0 <deregister_tm_clones+0>: mov eax,0x404050
0x00000000004010f5 <deregister_tm_clones+5>: cmp rax,0x404050
0x00000000004010fb <deregister_tm_clones+11>: je 0x401110 <deregister_tm_clones+32>
0x00000000004010fd <deregister_tm_clones+13>: mov eax,0x0
0x0000000000401102 <deregister_tm_clones+18>: test rax,rax
0x0000000000401105 <deregister_tm_clones+21>: je 0x401110 <deregister_tm_clones+32>
0x0000000000401107 <deregister_tm_clones+23>: mov edi,0x404050
0x000000000040110c <deregister_tm_clones+28>: jmp rax
0x000000000040110e <deregister_tm_clones+30>: xchg ax,ax
0x0000000000401110 <deregister_tm_clones+32>: ret
0x0000000000401111 <deregister_tm_clones+33>: data16 cs nop WORD PTR [rax+rax*1+0x0]
0x000000000040111c <deregister_tm_clones+44>: nop DWORD PTR [rax+0x0]
0x0000000000401120 <register_tm_clones+0>: mov esi,0x404050
0x0000000000401125 <register_tm_clones+5>: sub rsi,0x404050
0x000000000040112c <register_tm_clones+12>: mov rax,rsi
0x000000000040112f <register_tm_clones+15>: shr rsi,0x3f
0x0000000000401133 <register_tm_clones+19>: sar rax,0x3
0x0000000000401137 <register_tm_clones+23>: add rsi,rax
0x000000000040113a <register_tm_clones+26>: sar rsi,1
0x000000000040113d <register_tm_clones+29>: je 0x401150 <register_tm_clones+48>
0x000000000040113f <register_tm_clones+31>: mov eax,0x0
0x0000000000401144 <register_tm_clones+36>: test rax,rax
0x0000000000401147 <register_tm_clones+39>: je 0x401150 <register_tm_clones+48>
0x0000000000401149 <register_tm_clones+41>: mov edi,0x404050
0x000000000040114e <register_tm_clones+46>: jmp rax
0x0000000000401150 <register_tm_clones+48>: ret
0x0000000000401151 <register_tm_clones+49>: data16 cs nop WORD PTR [rax+rax*1+0x0]
0x000000000040115c <register_tm_clones+60>: nop DWORD PTR [rax+0x0]
0x0000000000401160 <__do_global_dtors_aux+0>: endbr64
0x0000000000401164 <__do_global_dtors_aux+4>: cmp BYTE PTR [rip+0x2efd],0x0 # 0x404068 <completed.0>
0x000000000040116b <__do_global_dtors_aux+11>: jne 0x401180 <__do_global_dtors_aux+32>
0x000000000040116d <__do_global_dtors_aux+13>: push rbp
0x000000000040116e <__do_global_dtors_aux+14>: mov rbp,rsp
0x0000000000401171 <__do_global_dtors_aux+17>: call 0x4010f0 <deregister_tm_clones>
0x0000000000401176 <__do_global_dtors_aux+22>: mov BYTE PTR [rip+0x2eeb],0x1 # 0x404068 <completed.0>
0x000000000040117d <__do_global_dtors_aux+29>: pop rbp
0x000000000040117e <__do_global_dtors_aux+30>: ret
0x000000000040117f <__do_global_dtors_aux+31>: nop
0x0000000000401180 <__do_global_dtors_aux+32>: ret
0x0000000000401181 <__do_global_dtors_aux+33>: data16 cs nop WORD PTR [rax+rax*1+0x0]
0x000000000040118c <__do_global_dtors_aux+44>: nop DWORD PTR [rax+0x0]
0x0000000000401190 <frame_dummy+0>: endbr64
0x0000000000401194 <frame_dummy+4>: jmp 0x401120 <register_tm_clones>
0x0000000000401196 <alarm_handler+0>: push rbp
0x0000000000401197 <alarm_handler+1>: mov rbp,rsp
0x000000000040119a <alarm_handler+4>: lea rax,[rip+0xe63] # 0x402004
0x00000000004011a1 <alarm_handler+11>: mov rdi,rax
0x00000000004011a4 <alarm_handler+14>: call 0x401030 <puts@plt>
0x00000000004011a9 <alarm_handler+19>: mov edi,0xffffffff
0x00000000004011ae <alarm_handler+24>: call 0x4010a0 <exit@plt>
0x00000000004011b3 <initialize+0>: push rbp
0x00000000004011b4 <initialize+1>: mov rbp,rsp
0x00000000004011b7 <initialize+4>: mov rax,QWORD PTR [rip+0x2ea2] # 0x404060 <stdin@GLIBC_2.2.5>
0x00000000004011be <initialize+11>: mov ecx,0x0
0x00000000004011c3 <initialize+16>: mov edx,0x2
0x00000000004011c8 <initialize+21>: mov esi,0x0
0x00000000004011cd <initialize+26>: mov rdi,rax
0x00000000004011d0 <initialize+29>: call 0x401090 <setvbuf@plt>
0x00000000004011d5 <initialize+34>: mov rax,QWORD PTR [rip+0x2e74] # 0x404050 <stdout@GLIBC_2.2.5>
0x00000000004011dc <initialize+41>: mov ecx,0x0
0x00000000004011e1 <initialize+46>: mov edx,0x2
0x00000000004011e6 <initialize+51>: mov esi,0x0
0x00000000004011eb <initialize+56>: mov rdi,rax
0x00000000004011ee <initialize+59>: call 0x401090 <setvbuf@plt>
0x00000000004011f3 <initialize+64>: lea rax,[rip+0xffffffffffffff9c] # 0x401196 <alarm_handler>
0x00000000004011fa <initialize+71>: mov rsi,rax
0x00000000004011fd <initialize+74>: mov edi,0xe
0x0000000000401202 <initialize+79>: call 0x401080 <signal@plt>
0x0000000000401207 <initialize+84>: mov edi,0x1e
0x000000000040120c <initialize+89>: call 0x401060 <alarm@plt>
0x0000000000401211 <initialize+94>: nop
0x0000000000401212 <initialize+95>: pop rbp
0x0000000000401213 <initialize+96>: ret
0x0000000000401214 <read_me+0>: push rbp
0x0000000000401215 <read_me+1>: mov rbp,rsp
0x0000000000401218 <read_me+4>: lea rax,[rip+0xdee] # 0x40200d
0x000000000040121f <read_me+11>: mov rdi,rax
0x0000000000401222 <read_me+14>: call 0x401040 <system@plt>
0x0000000000401227 <read_me+19>: nop
0x0000000000401228 <read_me+20>: pop rbp
0x0000000000401229 <read_me+21>: ret
0x000000000040122a <food+0>: push rbp
0x000000000040122b <food+1>: mov rbp,rsp
0x000000000040122e <food+4>: lea rax,[rip+0xde0] # 0x402015
0x0000000000401235 <food+11>: mov rdi,rax
0x0000000000401238 <food+14>: call 0x401030 <puts@plt>
0x000000000040123d <food+19>: lea rax,[rip+0xde7] # 0x40202b
0x0000000000401244 <food+26>: mov rdi,rax
0x0000000000401247 <food+29>: call 0x401030 <puts@plt>
0x000000000040124c <food+34>: lea rax,[rip+0xde0] # 0x402033
0x0000000000401253 <food+41>: mov rdi,rax
0x0000000000401256 <food+44>: call 0x401030 <puts@plt>
0x000000000040125b <food+49>: lea rax,[rip+0xddd] # 0x40203f
0x0000000000401262 <food+56>: mov rdi,rax
0x0000000000401265 <food+59>: call 0x401030 <puts@plt>
0x000000000040126a <food+64>: lea rax,[rip+0xdd6] # 0x402047
0x0000000000401271 <food+71>: mov rdi,rax
0x0000000000401274 <food+74>: call 0x401030 <puts@plt>
0x0000000000401279 <food+79>: lea rax,[rip+0xdd0] # 0x402050
0x0000000000401280 <food+86>: mov rdi,rax
0x0000000000401283 <food+89>: mov eax,0x0
0x0000000000401288 <food+94>: call 0x401050 <printf@plt>
0x000000000040128d <food+99>: nop
0x000000000040128e <food+100>: pop rbp
0x000000000040128f <food+101>: ret
0x0000000000401290 <main+0>: push rbp
0x0000000000401291 <main+1>: mov rbp,rsp
0x0000000000401294 <main+4>: sub rsp,0x70
0x0000000000401298 <main+8>: mov DWORD PTR [rbp-0x64],edi
0x000000000040129b <main+11>: mov QWORD PTR [rbp-0x70],rsi
0x000000000040129f <main+15>: mov QWORD PTR [rbp-0x50],0x0
0x00000000004012a7 <main+23>: mov QWORD PTR [rbp-0x48],0x0
0x00000000004012af <main+31>: mov QWORD PTR [rbp-0x40],0x0
0x00000000004012b7 <main+39>: mov QWORD PTR [rbp-0x38],0x0
0x00000000004012bf <main+47>: mov QWORD PTR [rbp-0x30],0x0
0x00000000004012c7 <main+55>: mov QWORD PTR [rbp-0x28],0x0
0x00000000004012cf <main+63>: mov QWORD PTR [rbp-0x20],0x0
0x00000000004012d7 <main+71>: mov QWORD PTR [rbp-0x18],0x0
0x00000000004012df <main+79>: mov QWORD PTR [rbp-0x10],0x0
0x00000000004012e7 <main+87>: mov QWORD PTR [rbp-0x8],0x0
0x00000000004012ef <main+95>: mov WORD PTR [rbp-0x52],0x0
0x00000000004012f5 <main+101>: mov eax,0x0
0x00000000004012fa <main+106>: call 0x4011b3 <initialize>
0x00000000004012ff <main+111>: mov eax,0x0
0x0000000000401304 <main+116>: call 0x40122a <food>
0x0000000000401309 <main+121>: lea rax,[rbp-0x52]
0x000000000040130d <main+125>: mov edx,0x2
0x0000000000401312 <main+130>: mov rsi,rax
0x0000000000401315 <main+133>: mov edi,0x0
0x000000000040131a <main+138>: call 0x401070 <read@plt>
0x000000000040131f <main+143>: movzx eax,BYTE PTR [rbp-0x52]
0x0000000000401323 <main+147>: movsx eax,al
0x0000000000401326 <main+150>: cmp eax,0x70
0x0000000000401329 <main+153>: je 0x401358 <main+200>
0x000000000040132b <main+155>: cmp eax,0x70
0x000000000040132e <main+158>: jg 0x4013c4 <main+308>
0x0000000000401334 <main+164>: cmp eax,0x63
0x0000000000401337 <main+167>: je 0x401384 <main+244>
0x0000000000401339 <main+169>: cmp eax,0x68
0x000000000040133c <main+172>: jne 0x4013c4 <main+308>
0x0000000000401342 <main+178>: lea rax,[rip+0xd0a] # 0x402053
0x0000000000401349 <main+185>: mov rdi,rax
0x000000000040134c <main+188>: mov eax,0x0
0x0000000000401351 <main+193>: call 0x401050 <printf@plt>
0x0000000000401356 <main+198>: jmp 0x4013c5 <main+309>
0x0000000000401358 <main+200>: lea rax,[rip+0xd06] # 0x402065
0x000000000040135f <main+207>: mov rdi,rax
0x0000000000401362 <main+210>: mov eax,0x0
0x0000000000401367 <main+215>: call 0x401050 <printf@plt>
0x000000000040136c <main+220>: lea rax,[rbp-0x50]
0x0000000000401370 <main+224>: mov edx,0x4f
0x0000000000401375 <main+229>: mov rsi,rax
0x0000000000401378 <main+232>: mov edi,0x0
0x000000000040137d <main+237>: call 0x401070 <read@plt>
0x0000000000401382 <main+242>: jmp 0x4013c5 <main+309>
0x0000000000401384 <main+244>: lea rax,[rip+0xcec] # 0x402077
0x000000000040138b <main+251>: mov rdi,rax
0x000000000040138e <main+254>: call 0x401030 <puts@plt>
0x0000000000401393 <main+259>: lea rax,[rip+0xcf2] # 0x40208c
0x000000000040139a <main+266>: mov rdi,rax
0x000000000040139d <main+269>: mov eax,0x0
0x00000000004013a2 <main+274>: call 0x401050 <printf@plt>
0x00000000004013a7 <main+279>: lea rax,[rbp-0x50]
0x00000000004013ab <main+283>: mov edx,0x100
0x00000000004013b0 <main+288>: mov rsi,rax
0x00000000004013b3 <main+291>: mov edi,0x0
0x00000000004013b8 <main+296>: call 0x401070 <read@plt>
0x00000000004013bd <main+301>: mov eax,0x0
0x00000000004013c2 <main+306>: jmp 0x4013ca <main+314>
0x00000000004013c4 <main+308>: nop
0x00000000004013c5 <main+309>: jmp 0x4012ff <main+111>
0x00000000004013ca <main+314>: leave
0x00000000004013cb <main+315>: ret
메모리 구조
buf | SFP | RET |
- 버퍼 (buf) : 사용자의 입력값
- SFP : Stack Frame Pointer
- RET : 다음에 실행시킬 주소값
해당 메모리는 버퍼 (buf) = name 의 메모리가 사용된 뒤에 SFP, RET 영역이 실행 된다
하지만 name 함수에 할당된 메모리 영역 + SFP영역 까지 임의의 문자를 넣고, 쉘 획득 코드를 뒤에 붙이면
RET 영역에서 쉘 코드가 실행이 되고 쉘 권한을 획득할 수 있는것이다.
Buffer + SFP 크기
(*참고)
rbp : 스택의 시작점
rsp : 스택의 꼭대기
bof.c 코드에서 변수는 총 2개가 선언 됨
buffer = name의 크기는 0x50 byte (50 byte)
choose의 크기는 2byte
SFP와 RET의 크기는
운영체제가 32bit이며 4byte, 64bit이면 8byte이다
운영체제 확인시 64bit이므로 각각 8byte의 크기를 가지고있다
따라서, 프로그램을 실행 시켰을때 실행 구조는 다음과 같다
즉, RET 전 = 버퍼 + SFT 의 크기는 0x50 + 0x2 + 0x8 = 0x60으로
총 0x60크기의 문자열을 입력하면 RET 직전까지 입력하게 되는것이다!
결론적으로, 0x60크기의 문자열 + 쉘 실행 코드 입력시 쉘을 획득 가능하다 !!
Shell 권한 획득
'Hawkis_CTF' 카테고리의 다른 글
Babysheets 문제 (0) | 2023.07.05 |
---|---|
Babyforms 문제 (0) | 2023.07.04 |
하위 문제 (0) | 2023.07.04 |
Plz Recovery 문제 (0) | 2023.07.03 |
Hacker Wannabe (Hawkis_CTF) write-up (0) | 2023.05.21 |