fc2ブログ

制作日記

こういうの作った方が、逃げにくいじゃない

特に意味のない更新

_reimu_ver191.ico

1.90は%HOME%直下にファイル作ってたけど
自分のwindows10は環境変数HOMEが設定されてないから、動作内容変更
わかりやすく、cmdをexecするだけ

L霊夢only大会

そんな大会が存在するらしいが、ほんとにあった
曰く、ver1.90でちょうど30体らしい

見た目が同じ霊夢を30体も公開してる製作者は他にいないんじゃないだろうか?

実際は、無限ロダだっけかに上げてた初期バージョンとかあるから
そのあたり含めると多分35体ぐらい

ここで公開してるのは、操作不可というかanimを削除した辺り以降

他は本当に非公開がいくつか
放棄した並キャラ版、これがver0.2で見た目はここからほぼ変化なし
defオバフロでのメッセージボックス表示、これがver0.7で記事にはしてる
DTCのとあるバグ解析用、一応mugensiteiって名前
重複混線とか積んで飽きた奴、日付だけついてて2011_11_20
強制タゲ搭載したの、手元にすら残ってない
explodでの変数保存のお試し実装

あとは解析して、公開するネタにすらならなければ放棄だしなあ
ヒープ破壊で起動時攻撃とか、sff弄って色々試したのとか

ネタないけど、そのうちver2.0出せると良いな

1.90でやってること

cnsだけだと厳しいかと思うので
1.90でやってること解説

要はLoadLibraryを叩いてる、その方法を考えてみる

前提条件というか前提知識
DEPを回避する、これ今回の目的
つまり、実行権限の付いていない箇所のコードを実行しない
Ver1.8xとかみたいにdataセクションのコード埋め込んで実行したり
Defオバフロみたいにcns内というか実行権限ついてないヒープ内のコード実行するのはアウト

LoadLibrary関数は引数が1個でライブラリ名を指定する
つまり、スタックの一番上にライブラリ名の先頭アドレスを積んだ状態でLoadLibraryを呼ぶ必要がある

OS等の実行環境に極力依存しない方法
要は、リンクしているライブラリ内の関数を直接呼ぶとかしない
Windowsのdllは全く同じdllなら基本的には全く同じアドレスにマッピングされるから
単一の環境の対象とすれば、もっと手軽に出来る

攻撃の入口はDTCでのスタックオーバーフロー、つまりリターンアドレスの改竄
リンクしているライブラリは呼ばない、winmuge.exe内のみがリターン先の対象
winmugen.exeは0x00400000からマッピングされるから、最上位バイトは必ず0x00=null文字
最上位バイトのnull文字で文字列が終端するため、それ以降はオーバーフローさせられない
改竄可能は範囲は直近のリターンアドレスまでの1024+4バイトのみ
つまり、ここでLoadLibraryの引数をスタックに積むことはできない
ちなみに、dllのアドレス固定(環境依存)で良いならここで引数も積めるから、かなり楽になるはず

引数のライブラリ名は1.8xのコード埋め込み見たいに適当なとこに埋めておけば良いので、割愛

本題
LoadLibraryを叩く方法として思い付くのものを、実行可能か検証していく

1.直接リターンアドレスをLoadLibraryに差し替え
前提条件で否定してるけど、引数をスタックに積めないから無理

2.Defオバフロみたいにスタックポインタが良い感じになったうえでLoadLibraryに飛ぶようなコードを探してそこにリターンする
想定としては、LoadLibrary呼び出し箇所に戻りつつ、引数を積む
LoadLibrary呼び出し箇所はwinmugen.exe内に2か所あるけど、どっちも無理そう
片方は直前に詰んでるし、片方はアドレスゴリゴリ辿ってる
どっちにしろ単体だと無理そう

3.2に加えてスタックの調整とかリターンアドレスの工夫
DTCの出力結果はスタック上にもう1つ保存されてるので、
上手いことリターン先を調整して、そっちの値も使う
懸念はライブラリ名を埋め込む場所、コードはよく0x004Bxxxx辺りに埋めるけど、
あれと同じようにすると0x00=null文字のせいで文字列が終端してしまう、つまりリターンアドレス改竄ができない
よって0x10000000~から変な値を書きこんでも問題ないヒープを探してこないといけない
高位のここら辺必ず使えるとかがあれば解決するが、そういう話は知らない

4.2に加えて関数ポインタを差し替えつつ、上手いこと辿る
で、探してて見つけたのがここ

0049DB25 A178684B00 mov eax, [004B6878h]
0049DB2A 85C0 test eax, eax
0049DB2C 7405 jz 0049DB33h
0049DB2E 53 push ebx
0049DB2F FFD0 call eax
0049DB31 8BD8 mov ebx, eax

* Referenced by an (U)nconditional or (C)onditional Jump or (c)all at Address:
| 0049DB1B(C), 0049DB23(C), 0049DB2C(C)
|
0049DB33 FF742418 push dword ptr [esp+18h]
0049DB37 FF742418 push dword ptr [esp+18h]
0049DB3B FF742418 push dword ptr [esp+18h]
0049DB3F 53 push ebx
0049DB40 FF1570684B00 call dword ptr [004B6870h]

DTCで”%”(0x25)を出力できないからリターン先はもう一つ手前の命令

0049DB23 740E jz 0049DB33h

にリターンしてる、ZFは0だったしjmpはしないと思う

0049DB14 A174684B00 mov eax, [004B6874h]

今更だけど、こっちにリターンしておけば確実だった
0x004B6874は0x004B6878と同じアドレス入れとけば良いし

で、解説

0049DB25 A178684B00 mov eax, [004B6878h]

0x004B6878に入ってるアドレス取ってきて

0049DB2F FFD0 call eax

そこのアドレスのサブルーチン呼び出し


0049DB31 8BD8 mov ebx, eax

戻り値eaxをebxに入れて

0049DB3F 53 push ebx

ebxをスタックに積んで

0049DB40 FF1570684B00 call dword ptr [004B6870h]

0x004B6870に入ってるアドレスのサブルーチン呼び出し

つまり、適当なアドレス引っ張ってくるコードを探して、
そのアドレスを0x004B6878に入れる
文字列を上手いこと埋め込んでおけば、戻り値eaxで取得できる

今回は以下の0x0049D8B8を入れた、0x004B661Cに入ってる値を取り出してる
つまり、適当な場所にライブラリ名(char/_reimu/a.dll)を埋め込んで
その先頭アドレスを0x004B661Cに入れておけばいい

0049D8B8 A11C664B00 mov eax, [004B661Ch]
0049D8BD C7056C684B0001000000 mov dword ptr [004B686Ch], 00000001h

* Referenced by an (U)nconditional or (C)onditional Jump or (c)all at Address:
| 0049D8B6(C)
|
0049D8C7 C3 ret


あとはこいつでLoadLibrary呼べばいいから、

0049DB40 FF1570684B00 call dword ptr [004B6870h]

親捏造でLoadLibraryのアドレスが入っている0x0049F12Cの値を取ってきて
0x004B6870に入れる

これでa.dllのDllMainが呼ばれるから好きにやる
単なるライブラリの動的リンクだから、DEPには引っ掛からない
あと、DllMainから戻ると確実に死ぬから、試合継続したいならDllMainの中で復旧処理が必要

以上、おわり

目新しいことはしてないけど、それをうまく組み合わせた感じ

更新疲れた

LoadLibrary叩くための新ネタもないし、コード実行って点ではDefオバフロがほぼ最速
起動時にrtlHeapのリストぶち壊してってのはあるけど、
ここ10年ぐらいでwindowsのrtlHeapは割とセキュアになってるから、攻撃は難しい。

その辺り、クリック拾うってネタは面白いなーと思った

で、元々DEP回避しようとは思ってて、久しぶりに見てたら先週末頃にできそうってなった
ちょうどEMETをROPで回避って話題もあったしで、流行に載れてる?



徹夜で仕上げたわけだが
mugenの枠内からどうするかってのが面白いのであって
外から攻撃したって難しくないし面白くもない
だから、ツールはデバッグや制作支援用しか作らない

3年ぶりのキャラ更新

_reimu_ver190.ico
ver1.90出来ました

DEP回避した上で、ライブラリをロードして任意コード実行。
ホームディレクトリ(%HOME%)直下にHOGEってファイル作るだけ。
ソース同梱してるから、動作内容が信用できないなら自分でビルドして。
VC入れて、/LDオプションで cl 叩くだけ。

あと、親捏造との合わせ技だからコード実行まで2F掛かる。
dllのパス探査は面倒だからしてない、「char/_reimu/a.dll」をロードする。
a.dllがそれ以外のパスだったら動かん。
プロフィール

Author:drab
霊夢改変キャラ
「12 3 ! {V} [_]」
公開中
L霊夢でもl_reimuでも好きなように読んでください

最新記事
最新コメント
月別アーカイブ
カテゴリ
検索フォーム
RSSリンクの表示
リンク