Modern operating systems include hardened security mechanisms to block exploit attempts. ASLR and NX (DEP) are two examples of the mechanisms that are widely implemented for the sake of security. However, there exists ways to bypass such protections by leveraging advanced exploitation techniques. It becomes harder to achieve code execution when the exploitation originates from a remote location, such as when the attack originates from a client, targeting server daemons. In such cases it is harder to find out the context information of target systems and, therefore, harder to achieve code execution. Knowledge on the memory layout of the targeted process is a crucial piece of the puzzle in developing an exploit, but it is harder to figure out when the exploit attempt is performed remotely. Recently, there have been techniques to leverage information disclosure (memory leak) vulnerabilities to figure out where specific library modules are loaded in the memory layout space, and such classes of vulnerabilities have been proven to be useful to bypass ASLR. However, there is also a different way of figuring out the memory layout of a process running in a remote environment. This method involves probing for valid addresses in target remote process. In a Linux environment, forked child processes will inherit already randomized memory layout from the parent process. Thus every client connection made to server daemons will share the same memory layout. The memory layout randomization is only done during the startup of the parent service process, and not randomized again when it is forking a child process to handle client connections. Due to the inheritance of child processes, it is possible to figure out a small piece of different information from every connection, and these pieces can be assembled later to get the idea of a big picture of the target process's remote memory layout. Probing to see if a given address is a valid memory address in context of the target remote process and assembling such information together, an attacker can figure out where the libc library is loaded on the memory, thus allowing exploits to succeed further in code execution. One might call it brute force, but with a smart brute forcing strategy, the number of minimal required attempts are significantly reduced to less than 10 in usual cases. In this talk, we will be talking about how it is possible to probe for memory layout space utilizing a piece of code to put the target in a blocked state, and to achieve stable code execution in remote exploit attempt scenarios using such information, as well as other tricks that are often used in remote exploit development in the Linux environment.
http://codeblue.jp/en-speaker.html#SeokHaLee
3. About me
Name: SeokHa Lee
A.K.A: wh1ant
(white ant or ant)
wh1ant on facebook
I’m A member of ‘WISEGUYS' team, which is a
hacking crew in South Korea.
I have found multiple vulnerabilities.
talked about security-related topics in
Korean conferences.
various CTF competitions in Korea as challenge-
maker with exploitation challenges.
http://wh1ant.kr
http://hackerschool.org
4. About this talk
Remote buffer overflow on linux
• Create file in the server
• NULL byte bypass
• Neutralize some of heap ASLR
• Fast searching libc location
5. Exploit techniques
• Code injection
- Must be NX disable
• RTL (Return-To-Libc)
- Must be ASLR disable
• ROP (Return Oriented Programming)
- There must be gadgets available.
- Too long payload
6. How to find address?
• Brute force
• Memory disclosure
• use send(), write() functions
[&send()] [&exit()] [0x00000004] [&GOT] [0x00000004] [0x00000000]
7. Code and environment
int get_result(const int sock, char odd_or_even)
{
char small_buf[25];
char big_buf[128];
…
write(sock, "pick a number 1 or 2: ", 22);
length = read(sock, big_buf, sizeof(big_buf)-1);
…
strcpy(small_buf, big_buf); // vulnerable code
if((small_buf[0]-0x31)==odd_or_even)
return 1;
else
return 0;
}
Fedora 18
fork-based server
$ gcc server.c –o server -fno-stack-protector
9. Creating file with permission
1 - /tmp directory
- we can use “/tmp” string in the libc library.
2 – log files which
- we can use “log/log_%Y%m%d.log” string.
3 – daemon PID file which
- file to check the process.
10. What kind of functions do we use?
open(), write()
O_WRONLY == 0x1
O_CREAT == 0x40
12. Interesting kernel code
struct file *do_filp_open(int dfd, const char *pathname,
int open_flag, int mode, int acc_mode)
...
if (!(open_flag & O_CREAT))
mode = 0;
/* Must never be set by userspace */
open_flag &= ~FMODE_NONOTIFY;
/*
* O_SYNC is implemented as __O_SYNC|O_DSYNC. As many places only
* check for O_DSYNC if the need any syncing at all we enforce it's
* always set instead of having to deal with possibly weird behaviour
* for malicious applications setting only __O_SYNC.
*/
if (open_flag & __O_SYNC)
open_flag |= O_DSYNC;
if (!acc_mode)
acc_mode = MAY_OPEN | ACC_MODE(open_flag);
/* O_TRUNC implies we need access checks for write permissions */
if (open_flag & O_TRUNC)
acc_mode |= MAY_WRITE;
Check only 0x40
(O_CREAT)
14. Create file
#include <stdio.h>
#include <fcntl.h>
int main(void)
{
close(open("test", 0x11111040, 0xfffff9ff));
return 0;
}
Hex number 0x11111040 means the O_CREAT also 0xfffff9ff means octal
4777 permission. Run a program, you can see create "test" name file.
15. Failed
static inline struct file * fcheck_files(struct files_struct *files,
unsigned int fd)
{
struct file * file = NULL;
struct fdtable *fdt = files_fdtable(files);
if (fd < fdt->max_fds)
file = rcu_dereference_check_fdtable(files, fdt->fd[fd]);
return file;
}
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
File descriptor maximum number over is NULL return.
16. New test
#include <stdio.h>
int main(void)
{
FILE* fp=fopen("test_file", "w");
if(fp==NULL)
{
printf("fopen() errorn");
return -1;
}
fputc(‘A’, fp);
fclose(fp);
return 0;
}
#include <stdio.h>
FILE *fopen(const char *path, const char *mode);
int fputc(int c, FILE *stream);
35. ...
int* p=0x0;
int temp=*p; // If invalid memory address, Segmentation fault occurs
....
...
int* p=0x08048000;
int temp=*p; /* If this memory address exists, Segmentation fault will
not occur */
....
Fast searching libc location 3/5