-4

配列をオーバーフローさせたいのでbuffer[100]、FreeBSDのbashシェルでPythonスクリプトを渡します。そのバッファをオーバーフローさbuffer[100]せ、プログラムにホスト名をに出力させるために、文字列として渡すマシンコードが必要stdoutです。

これが私が試したCのコードで、コンソールにホスト名を付けています。:

#include <stdio.h>
int main()
{
   char buff[256];
   gethostname(buff, sizeof(buff));
   printf(""%s", buff);

  return 0;

}


これがgccを使用して取得したアセンブリのコードですが、cプログラムのテキストセクションのマシンコードを探すと100バイトより長く、上記のcプログラムのマシンコードが必要なため、必要以上に長くなっています。それは100バイト未満です。


     .type   main, @function
main:
pushl %ebp; saving the base pointer
    movl %esp, %ebp; Taking a snapshot of the stack pointer
subl $264, %esp; 
addl $-8, %esp
pushl $256
leal -256(%ebp), %eax
pushl %eax
call gethostname
addl $16, %esp
addl $-8, %esp
leal -256(%ebp), %eax
pushl %eax
pushl $.LCO
call printf
addl $16, %esp
xorl %eax, %eax
jmp .L6
.p2align 2, 0x90
.L6:
leave
ret
.Lfe1:
.size   main, .Lfe1-main
.ident "GCC: (GNU) c 2.95.4 20020320 [FreeBSD]"

ある人がすでに別のコンピューターでそれを実行していて、37バイトの既製のマシンコードを私にくれました。彼はperlスクリプトを使用して以下の形式でバッファーに渡します。私は彼のコードを試しましたが、それは機能しますが、彼はそれを行う方法を教えてくれません。

「\x41\ xc1 \ x30 \ x58 \ x6e \ x61 \ x6d \ x65 \ x23 \ x23 \ xc3 \ xbc \ xa3 \ x83 \ xf4 \ x69 \ x36 \ xw3 \ xde \ x4f \ x2f \ x5f \ x2f \ x39 \ x33 \ x60 \ x24 \ x32 \ xb4 \ xab \ x21 \ xc1 \ x80 \ x24 \ xe0 \ xdb \ xd0” </ p>

彼が別のマシンでそれを行ったので、同じコードを取得することはできませんが、両方がまったく同じc関数を使用しているため、マシンコードのサイズはまったく同じではないにしてもほぼ同じになるはずです。彼のマシンコードは37バイトで、シェルに渡してFreeBSD 2.95のバイナリファイルのgets()関数をオーバーフローさせ、ホスト名をstdoutに出力します。私は同じことをしたいと思っています。彼のマシンコードを試しましたが、動作しますが、彼はこのマシンコードをどのように取得したのか教えてくれません。だから私は実際にそのコードを取得する手順について心配しています。

OKここの投稿で提案されているメソッドを試しましたが、関数gethostname()に対して、130文字のマシンコードを取得しました。printf()マシンコードは含まれていませんでした。ホスト名をコンソールに出力する必要があるため、ホスト名も含める必要がありますが、これによりマシンコードが長くなります。コードを100バイトの配列に収める必要があるため、コードは100バイト未満である必要があります。

100バイト未満のマシンコードに変換する上記のcプログラムのアセンブリコードを書くことができますか?

4

4 に答える 4

3

マシンコードを取得するには、プログラムをコンパイルしてから逆アセンブルする必要があります。たとえば、gccを使用して、次のようにします。

gcc -o hello hello.c
objdump -D hello

ダンプには、マシンコードがバイト単位で表示され、そのマシンコードの逆アセンブリが表示されます。

関連する簡単な例では、オブジェクトファイルと実行可能ファイルの違いを理解する必要がありますが、これは私が何を意味するかを示しているはずです。

unsigned int myfun ( unsigned int x )
{
    return(x+5);
}

gcc -O2 -c -o hello.o hello.c
objdump -D hello.o


Disassembly of section .text:

00000000 <myfun>:
   0:   e2800005    add r0, r0, #5
   4:   e12fff1e    bx  lr
于 2012-05-16T15:11:05.100 に答える
2

FreeBSDはオペレーティングシステムであり、コンパイラやアセンブラではありません。

アセンブリソースをマシンコードにアセンブルしたいので、アセンブラを使用する必要があります。

.sで終わるファイル名の場合、アセンブラを実行する必要があることを知っているので、通常はGCCを使用できます。

オブジェクトファイルにすでにコードがある場合は、を使用objdumpしてファイルのコードセグメントを読み取ることができます。

于 2012-05-16T13:59:43.227 に答える
1

投稿された37バイトは完全にジャンクです。

いずれかのバージョンのWindows(Windows 2000以降)で実行した場合、ユーザーランドプログラムはポートレベルのIを直接実行できないため、「outsb」および「insd」命令(ユーザーランドプログラム内)は障害を引き起こすと思います。 /O。

マシンコードは「vacuum」で終わらないので、投稿されたコードの後に​​\ x90バイト(ここでもNOP)を追加しました。これは、最後のrcl命令の引数に影響を与えるだけです(これは、指定されたコードでは途中で終了します。たとえば、投稿されたコードはゴミであるだけでなく、途中で終了します)。

ただし、マイクロプロセッサには独自のインテリジェンスがないため、マイクロプロセッサは、フィードしたジャンクコードを実行します(実行しようとします)。そして、コードは「inc ecx」で始まります。これは、ecxが以前にどのような値を持っていたかわからないため、愚かな動きです。また、「shl dword ptr [eax]、$ 58」は、メモリをランダムに破損する「良い」方法です(eaxの値も不明であるため)。

また、そのうちの1つは有効なバイトでもありません(2つの16進数で表す必要があります)。

無効な「バイト」は\xw3です。

その無効なバイトを\x90(命令の開始時の場合はNOP)に置き換えて、次のようにしました。

00451B51 41 inc ecx 00451B52 C13058 shl dword ptr [eax],$58 00451B55 6E outsb 00451B56 61 popad 00451B57 6D insd 00451B58 652323 and esp,gs:[ebx] 00451B5B C3 ret

// code below is NEVER executed, since the line above does a RET.

00451B5C BCA383F469 mov esp,$69f483a3 00451B61 3690 nop // 36, w3 ???? 00451B63 DE4F2F fimul word ptr [edi+$2f] 00451B66 5F pop edi 00451B67 2F das 00451B68 3933 cmp [ebx],esi 00451B6A 60 pushad 00451B6B 2432 and al,$32 00451B6D B4AB mov ah,$ab 00451B6F 21C1 and ecx,eax 00451B71 8024E0DB and byte ptr [eax],$db 00451B75 D09090909090 rcl [eax-$6f6f6f70],1

于 2014-04-03T00:45:37.563 に答える
0

を使用して、オブジェクトファイルのテキストセクションの優れた16進ダンプを取得しますobjdump -s -j .text

いくつかの詳細を編集しました:オブジェクトコード内の関数のアドレスが何であるかを知る必要があります。これがobjdump -t目的です。この場合、私はmainプログラム「hello」で関数を探しています。

> objdump -t hello|grep main

> 0000000000400410 g     F .text  000000000000002f        main

今、私は次のようにhexdumpを作成しますobjdump -s -j .text hello

400410 4881ec08 010000be 00010000 31c04889  H...........1.H.
400420 e7e8daff ffff4889 e6bff405 400031c0  ......H.....@.1.
400430 e8abffff ff31c048 81c40801 0000c390  .....1.H........
400440 31ed4989 d15e4889 e24883e4 f0505449  1.I..^H..H...PTI
400450 c7c0e005 400048c7 c1500540 0048c7c7  ....@.H..P.@.H..
...

最初の行はアドレスです。関数のアドレスである400410で始まりますが、main常にそうであるとは限りません。次の4行は16進数の16バイトのマシンコードであり、最後の行はASCIIの同じ16バイトのマシンコードです。多くのバイトはASCIIで表現されていないため、多くのドットがあります。4つの16進列を使用する必要があります\x48 \x81 \xec...
私はこれをLinuxシステムで実行しましたが、FreeBSDの場合もまったく同じことができます。結果として得られるマシンデコードのみが異なります。

于 2012-05-16T15:48:21.773 に答える