前の記事への
コメントでは、「set localecho」コマンドがbat.orgサーバーとやり取りする際のエコーの欠如の問題を解決するのに役立つかどうかについて少し
議論しました。 私はこのチームが検討中の状況を修正するために絶対に何もしないという事実に立っていました、そして私は理由でこれを言いました-特にコメントの1つの後、私はもう一度この問題の自分の正当性を確認することにしました。 必要なすべてのアクション(telnet.exeを起動し、Ctrl-]を押し、コマンド "set localecho"を入力し、Enterキーを2回押す)を行った後、私は自分が正しいと確信しました。 では、他の人は何を自信を持って繰り返しているのでしょうか?
「稼働中の」telnetクライアントのバイナリと、PMで起動されたOSのバージョンを送信するように依頼しました。 OSバージョンが一致していることを確認した後(Windows 7 SP1 x64を使用)、telnetクライアント自体に注意を向けました。 ハッシュが一致しました。 ユーザー
k0ldbl00dによって保証された「動作する」バイナリを起動すると、コンピューターでも動作しないことがわかって驚いた。
たぶん、telnet.exeが実行されている環境ですか? 元の実行可能ファイルは「%WINDIR%\ System32」ディレクトリから取得されたため、そこからtelnetクライアントを起動しました。このロケールではset localechoコマンドが正しく機能することがわかりました。 そして、同じ実行可能ファイルを他のディレクトリにコピーして既に使用している場合、メインのtelnet.exe機能が引き続き機能するにもかかわらず、コマンドはそれらに必要なものの実行を停止します。
問題は何ですか? 出ましょう。
プロセスがどのように進んだか、そしてその結果は、カットの下で読みました。 この記事を読む前に、以前の記事をよく理解しておくことを強くお勧めします。 ここでは省略された多くの点について既に説明しています。
第一に、telnet.exeが「%WINDIR%\ System32」以外のディレクトリで実行された場合、「welcome」メッセージがないことに私の意見は当てはまりました。
正しい操作の場合 (「%WINDIR%\ System32」から開始)
誤った操作の場合 (「C:\」から開始)
さて、これらの行を参照する命令にブレークを付けましょう。 しかし、これを行う前に、
ASLRをオフにしましょう。 「%WINDIR%\ System32」ディレクトリ内の実行可能ファイルの通常の置き換えは
ほとんど不可能であるため、
前の記事で使用した方法(バイナリの「DLLフラグ」フィールドの編集)を使用してこれを行うことはできません。 したがって、システム全体でASLRを無効にすることを提案します。 Win-Rを押します-> regedit->「HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Control \ Session Manager \ Memory Management」に進みます->「MoveImages」という既存のオプションを作成または編集して、ゼロに等しくします。 その後、システムを再起動し、無効化されたASLRをお楽しみください。
OllyDbgのディレクトリ「%WINDIR%\ System32」にある
telnet.exeを実行し 、エントリポイントで停止し、telnetモジュールの指示で参照される見つかったOllyDbg行のリストで「Welcome to」を探します。 「アイテムが見つかりません」というメッセージが表示され、サードパーティのリソースから行を動的にロードする方向について考え始めます。
F9を押して、Telnetクライアントが開始するのを待ち、再び同じ行を探します。
見つけた行を選択した後、Enterキーを押すと、「welcome」メッセージから行にアクセスする指示が表示されます。
0x01029C40のレコードにハードウェアブレークポイントを設定し、アプリケーションを再起動して、これらの行がどこから来ているかを確認しましょう。 ここでブレークポイントトリガー:
ご覧のとおり、WinAPI関数
LoadStringのどこかにいます(はい、明らかに、残念ながら、これは目立ちませんが、おそらく、
LoadStringBaseExが呼び出されます)。 最も近いユーザーコードにジャンプします。この場合、このコードは
0x0100C788にあり、他の行を受信するために同じ呼び出しが近くにあることがわかります。
少し上を見て、
LoadStringが実際にこれらの場所で呼び出されたことを確認してみましょう。
どのモジュールからtelnet.exeが行データを取得するかを調べてみましょう。 アドレス
0x0100C62Aにブレークを置き、デバッグを再開し、WinAPI関数
GetModuleHandleのモジュール名に対応する引数がゼロであることを確認します。
ドキュメントによると、この場合、
GetModuleHandleは実際には現在のプロセスのファイルハンドルを返します。
lpModuleName [入力、オプション]
[...]
このパラメーターがNULLの場合、GetModuleHandleは呼び出しプロセスの作成に使用されるファイル(.exeファイル)のハンドルを返します
F8を2回押すと、これが本当にそうであることがわかります。
さらに、このハンドルは、
会ったLoadStringのすべての呼び出しで使用されます。 例えば
しかし、問題は何ですか?
LoadStringが同じファイルから行を
取得する場合、作業ディレクトリを変更すると抽出の成功にどのように影響しますか?
始めるために、
リソースハッカーをピックアップして、telnet.exeで
STRINGTABLEを
見つけるかどうかを確認しましょう。
ご覧のとおり、彼女はそうではありません。 なに? これらの行はどこから来るのでしょうか? 実行時に同じモジュールにロードされますか? デバッグを再開して、アプリケーションの開始時にすでにプロセスメモリにあるかどうかを確認しましょう。 OllyDbgでCtrl-F2を押し、Alt-Mを押して「メモリ」ウィンドウを開き、マウスの左ボタンで最初の行を選択し、Ctrl-Bを押してUnicode文字列「Welcome」を探します。 これと残りの行は、この段階で実際にプロセスメモリにあります。
このメモリの断片がどこから出現したかを見てみましょう。 Alt-Mを押して、以下を確認します。
これで明らかです-これは
MUIです。 たとえば、Cドライブのルートに「en-US」というディレクトリを作成し、そこにtelnet.exe.muiファイルを置いて、以前に動作していたtelnetクライアントを誤って実行すると、「set localecho」コマンドが完全に正しく動作することがわかります。
しかし、ちょっと待ってください。 telnet.exeが行を表示できなかったとしても、これは同じセットlocalechoの結果にどのように影響しますか? 結局のところ、1つのことを推測することはできず、まったく異なることは、ユーザーが入力したコマンドに適切に応答しないことです。
次のコマンドを入力するための「招待」である「Microsoft Telnet>」行のアドレスの内訳を見てみましょう。 このような命令は
0x0100BEAAにあります。
telnetウィンドウでCtrl-]を押し、F8を使用してデバッグ済みアプリケーションを実行し、
ReadConsole WinAPI関数の次の呼び出しで停止します。
コマンド「set localecho」を入力し、標準入力ストリームから行を読み取った後の動作を調べます。
最初に、プログラムは
ReadConsole関数の正しさをチェックします(戻り値がゼロではない、読み込まれたバイト数がゼロより大きいなど):
この後しばらくすると、ユーザーが入力したコマンドの最初の文字(この場合は「s」)が、「quit」や「set」などのコマンドの最初の文字と等しいかどうかがチェックされるサイクルになります。
必要な.muiファイルを含む「en-US」ディレクトリが存在しない別の場所からデバッグを開始すると、コマンド名の行が空になることがわかります。 これは、それらがtelnet.exe.muiファイルに保存されていることを示唆しています。 プロセスメモリで対応する行を検索することで、これを確認できます。
したがって、.muiファイルがないと、telnetクライアントはユーザーが入力したコマンドの種類を理解することさえできませんでした。 比較のための行がロードされませんでした。
これらの行を.muiファイルに入れることさえ、私には個人的には謎でした。 おそらくマイクロソフトは、製品の国際化がどこまで進むか(たとえば、「ローカルエコーを有効にする」)を知らなかったか、プログラムで使用されるすべての行が完全に格納される単一の場所が必要でした。
あとがき
時々、調査中のアプリケーションが実行される条件のわずかな変更でさえ、最も予期しない動作に影響を与える可能性があります。 可能性のあるすべてのオプションを再確認し、アプリケーションロジックの変更に気を配らないでください。
ご清聴ありがとうございました。また、この記事が誰かに役立つことを願っています。