0

「Hello World」をコンソールに書き込んで (Windows XP 32 ビットを使用して) バッファ オーバーフローをテストしたいと考えています。シェルコードは、「scanf」によってオーバーフローしたいプログラムに渡されるために、ヌルフリーである必要があります。Linux 用のアセンブリ チュートリアルはたくさんありますが、Windows 用はありません。誰かがNASMを使用してこれを教えてもらえますか? どすけべ!

4

2 に答える 2

2

アセンブリ オペコードは同じであるため、null のないシェルコードを生成する通常のトリックは引き続き適用されますが、システム コールを作成する方法は異なります。

Linux では、"int 0x80" 命令を使用してシステム コールを行いますが、Windows では、DLL ライブラリを使用し、エクスポートされた関数に対して通常のユーザーモード コールを実行する必要があります。

そのため、Windows では、シェルコードは次のいずれかでなければなりません。

  • Win32 API 関数のアドレスをハードコーディングします (ほとんどの場合、使用しているマシンでのみ機能します)。
  • Win32 API リゾルバー シェルコードを使用する (すべての Windows バージョンで動作します)

学習中の場合は、現時点では、デバッガーで表示されるアドレスをハードコーディングする方がおそらく簡単です。呼び出しを位置独立にするために、アドレスをレジスタにロードできます。たとえば、4 つの引数を持つ関数の呼び出し:

PUSH 4                  ; argument #4 to the function
PUSH 3                  ; argument #3 to the function
PUSH 2                  ; argument #2 to the function
PUSH 1                  ; argument #1 to the function
MOV EAX, 0xDEADBEEF     ; put the address of the function to call
CALL EAX

引数は逆の順序でプッシュされることに注意してください。CALL 命令の後、EAX には戻り値が含まれ、スタックは以前と同じようになります (つまり、関数は独自の引数をポップします)。ECX および EDX レジスタにはガベージが含まれている可能性があるため、呼び出し後にそれらの値が保持されることに依存しないでください。

それらは位置に依存するため、直接の CALL 命令は機能しません。

アドレス自体にゼロが含まれないようにするには、x86 シェルコードの null を使用しないトリックを試してください。多くの方法がありますが、私のお気に入り (長いですが) は、XOR 命令を使用して値をエンコードすることです。

MOV EAX, 0xDEADBEEF ^ 0xFFFFFFFF   ; your value xor'ed against an arbitrary mask
XOR EAX, 0xFFFFFFFF                ; the arbitrary mask

NEG EAX または NOT EAX (符号反転とビット反転) を試して、それらが機能するかどうかを確認することもできます。はるかに安価です (それぞれ 2 バイト)。

ここで呼び出すことができるさまざまな API 関数に関するヘルプを得ることができます: http://msdn.microsoft.com

必要になる最も重要なものは、おそらく次のとおりです。

最初のコマンドはコマンドを起動し、次の 2 つは DLL ファイルをロードしてその関数のアドレスを取得するためのものです。

Windows シェルコードの記述に関する完全なチュートリアルは次のとおりです: http://www.codeproject.com/Articles/325776/The-Art-of-Win32-Shellcoding

于 2013-01-13T15:18:11.683 に答える
0

アセンブリ言語はプロセッサによって定義され、アセンブリ構文はアセンブラによって定義されます (したがって、at&t および intel 構文) 主な違い (少なくとも以前はそうであったと思います...) は、ウィンドウがリアルモード (call物事を行うための実際の割り込み、およびプログラムだけでなく、コンピューターにアクセス可能なすべてのメモリを使用できます)およびLinuxは保護モードです(プログラムの小さな小さなメモリのメモリにのみアクセスでき、呼び出す必要がありますint 0x80 を実行し、ハードウェアと BIOS を呼び出す代わりにカーネルを呼び出します) とにかく、互換性のあるプロセッサである限り、Linux と Windows の間で hello world タイプのものは多かれ少なかれ同じです。

作成したプログラムからシェルコードを取得するには、それをターゲット システムのデバッガー (Linux の場合は gdb、Windows の場合は debug) にロードし、デバッグで d (または u でしたか? h (ヘルプ)) と、命令とメモリの間がオペコードになります。それらをすべてテキスト エディタに 1 つの文字列にコピーするだけで、それらすべてを ASCII 値に変換するプログラムを作成できます。gdb thoでこれを行う方法がわからない...

とにかく、bof エクスプロイトにするためには、aaaaa... と入力し、バッファ オーバーフロー エラーでクラッシュするまで a を追加し続けます。しかし、クラッシュするのに必要な a の数を正確に見つけてください。次に、それがどのメモリアドレスであったかを教えてくれるはずです。通常、エラー メッセージで通知されます。「9797[元の返品先住所の残り]」と表示されている場合は、取得済みです。ここで、デバッガを使用して、これがどこにあったかを調べる必要があります。デバッガーでプログラムを逆アセンブルし、scanf が呼び出された場所を探します。そこにブレークポイントを設定し、実行してスタックを調べます。すべての 97 を探して (これは 'a' の ASCII 番号であることに言及するのを忘れていました)、それらがどこで終わるかを確認します。次に、ブレークポイントを削除し、必要な a の量 (正確な量) を入力します。エラー メッセージが「バッファ オーバーフロー アット '

幸せなハッキング...

于 2011-12-29T02:40:55.513 に答える