最終更新: 2014-10-17T00:06+0900
以前書いた不満を解消するべく慣れないことをした。
gdipp_loader_32.exeが、引数として与えられたプロセスが終了するまで終了しなくなってる。WaitForSingleObject(pi.hProcess, INFINITE);してるんだから必要なことなんだろうけど残念。
gdipp_loader_32.exeは第一引数(任意の exeファイル名)のディレクトリをカレントにして exeを起動するけど、そのせいで exeに渡される二番目以降の引数が相対パスだったときにファイルを見つけられない。例えば
検索しもってちなみにたどり着いた手順。
>SetEnv.Cmd >dumpbin /all /disasm gidpp_loader_32.exe
出力を読む。コードは .textセクションに含まれている。/disasmオプションを付けたのでニーモニックで読める。さっき覚えておいた 408008で検索すると次の行(だけ)がヒットした。
004010B3: FF 15 08 80 40 00 call dword ptr ds:[00408008h]
呼び出し規約の違いは知らないが、callにそなえて末尾の引数から順番に pushしてるぽいところから推測する。
CreateProcessW(argv[0], lpCmdLine, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, working_dir, &si, &pi);
004010B2: 52 push edx 00401094: 8D 8D F4 FD FF FF lea ecx,[ebp+FFFFFDF4h] 0040109A: 51 push ecx (これがきっと working_dirに違いない) 0040109B: 6A 00 push 0 (NULL) 0040109D: 6A 04 push 4 (たぶん CREATE_SUSPENDED) 0040109F: 6A 00 push 0 (FALSE) 004010A1: 6A 00 push 0 (NULL) 004010A3: 6A 00 push 0 (NULL)
51(push ecx)を 6A 00(push 0)に書き替えることはサイズが違ってできないので、その前の準備段階を含めた 8D 8D F4 FD FF FF 51(lea ecx,[ebp+FFFFFDF4h]; push ecx)を 90 90 90 90 90 6A 00(NOP;NOP;NOP;NOP;NOP; push 0)に書き替えることにする。
書き替える範囲は 00401094からの7バイトだが Stirlingで開いた gdipp_loader_32.exeにそんなアドレスはない。dumpbinが出力した .textセクションの情報を見る。
68EA virtual size 1000 virtual address (00401000 to 004078E9) 6A00 size of raw data 400 file pointer to raw data (00000400 to 00006DFF)
virtual sizeと size of raw dataの微妙な違いが気になるが、00401094-00401000+00000400 = 494のアドレスを Stirlingで表示すると目当てのバイト列があったので書き替えた。
すごく時間がかかった。『解析魔法少女美咲ちゃん』を参考にしようとしたが、丁度いいところで OllyDbg便利そうということしかわからなかった。済んでしまえばこの程度のことなのでバイナリエディタだけでなんとかしたいが、PEヘッダとインポート情報を読んでアドレスを変換するのが果てしなく面倒で、また、間違えやすい。アドレスもそこから読み取る値も同じバイト列だからか、すぐに区別がつかなくなる。
ちなみに 最初の検索ワードが「disasm」で次が「ディスアセンブラ」それから「逆アセンブラ」「Ordinal Hint」「インポートテーブル」「dumpbin」と変わっていった。並行して、eXeScopeを実行したり bcc55と VCの binディレクトリに dasm.exeみたいな名前(※ildasmからの類推)のファイルを探したりしていた。tdump.exe / dumpbin.exeがそうだとは気付かなかった。