2017-09-06 1 views
0

シェルコードを学習しています。私はチュートリアルでこのシェルコードを発見したシェルコード内の文字列を正しく分割する

python -c 'print "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80 "' > shellcode 

私は何をしたいのか、それがどのように機能するかを理解するために、この非常に基本的なシェルコードを分解することです。ここで

は私が行って何です:

$ objdump -D -b binary -m i8086 shellcode 

shellcode:  file format binary 


Disassembly of section .data: 

00000000 <.data>: 
    0: 90      nop 
    1: 90      nop 
    2: 90      nop 
    3: 90      nop 
    4: 90      nop 
    5: 90      nop 
    6: 90      nop 
    7: 90      nop 
    8: 90      nop 
    9: 31 c0     xor %ax,%ax 
    b: 50      push %ax 
    c: 68 2f 2f    push $0x2f2f 
    f: 73 68     jae 0x79 
    11: 68 2f 62    push $0x622f 
    14: 69 6e 89 e3 50   imul $0x50e3,-0x77(%bp),%bp 
    19: 53      push %bx 
    1a: 89 e1     mov %sp,%cx 
    1c: b0 0b     mov $0xb,%al 
    1e: cd 80     int $0x80 

または:

$ ndisasm shellcode 
00000000 90    nop 
00000001 90    nop 
00000002 90    nop 
00000003 90    nop 
00000004 90    nop 
00000005 90    nop 
00000006 90    nop 
00000007 90    nop 
00000008 90    nop 
00000009 31C0    xor ax,ax 
0000000B 50    push ax 
0000000C 682F2F   push word 0x2f2f 
0000000F 7368    jnc 0x79 
00000011 682F62   push word 0x622f 
00000014 696E89E350  imul bp,[bp-0x77],word 0x50e3 
00000019 53    push bx 
0000001A 89E1    mov cx,sp 
0000001C B00B    mov al,0xb 
0000001E CD80    int 0x80 

このシェルコードは、x86命令として解釈される文字列が含まれています。 ジャンプに適切なラベルを貼る方法はありますか?

そして、文字列にx86命令をデコードする代わりに、文字列を表示する方法があります。セクションとヘッダーのあるエルフがないので、これは簡単ではないことが分かります...

+0

これは実際にはhttps://stackoverflow.com/questions/1737095/how-do-i-disassemble-raw-x86-codeの複製です。 ](https://stackoverflow.com/questions/1737095/how-do-i-disassemble-raw-x86-code/34424146#34424146)。)しかし、私はこの質問を、あなたが間違ったモードで逆アセンブルしています...(おそらくそれも重複していますが、/) –

答えて

0

は、あなたが@DavidJが示唆したように、命令としてデータを処理しながら、逆アセンブラが同期の外に出た場合のNOPで文字列を置き換える必要があるだろう。

この場合、あなたはちょうど間違ったモードで逆アセンブルしていますjncは明らかに偽です(あなたが気づいたと思います)。それは、16ビットモードがどのように動作するかだから

逆アセンブラは、push imm16のスタートとしてpushopcode0x68バイト)を処理しています。しかし、32ビットと64ビットモードでは、同じオペコードがpush imm32の先頭になります。したがって、push命令は実際には3バイトではなく5バイトであり、次の命令は実際には次のpushです。

偽の短いjncは、ではないの16ビットコードという大きなヒントです。


使用ndisasm -b32または-b64 Ndisasmはstdinからの入力を読むことができるので、私はpython2 -c 'print "... "' | ndisasm - -b32を使いました。

objdumpを使用する場合は、Intelの構文を使用する場合は、objdump -d -Mintelを使用してください。したがって、objdump -Mintel -bbinary -D -mi386 /tmp/shellcode(32ビット)(-mi386は、ARMまたはMIPSなどではなく、アーキテクチャとしてx86を選択し、-Mi386 32ビットモードも意味します)。

または64ビットの場合、objdump -D -b binary -mi386 -Mx86-64 /tmp/shellcodeの作品です。 (objdumpはstdin:/からバイナリを読み込みません)オプションの詳細については、objdumpのマニュアルページを参照してください。

このエイリアスは~/.bashrcalias disas='objdump -drwC -Mintel'で使用します。これは通常、ELF実行可能ファイル/オブジェクトを逆アセンブルして、コンパイラが何をしたのかを調べるためです。シェルコードではありません。エイリアスに-Dが必要な場合があります。


これは64ビットモードでは2つのプッシュでギャップが残るため、これは32ビットコードであると確信しています。はpush imm64ではありませんが、push imm32は64ビットに直接拡張された64ビットプッシュです。 64ビット・モードでは、"abcdefgh"を指しRSPで終わるために

push 'abcd' 
mov [rsp+4], 'efgh' 

を使用する場合があります。

また、スタックアドレスにint 0x80を使用することは、これが64ビットコードではないという大きな手掛かりになります。 int 0x80は、64ビットモードでLinux上で動作しますが、それは、32ビットへのすべての入力を切り捨て:ndisasmからWhat happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code?


32ビットの解体は、次のとおりです。正気に見え

00000000 90    nop 
00000001 90    nop 
00000002 90    nop 
00000003 90    nop 
00000004 90    nop 
00000005 90    nop 
00000006 90    nop 
00000007 90    nop 
00000008 90    nop 
00000009 31C0    xor eax,eax 
0000000B 50    push eax 
0000000C 682F2F7368  push dword 0x68732f2f 
00000011 682F62696E  push dword 0x6e69622f 
00000016 89E3    mov ebx,esp 
00000018 50    push eax 
00000019 53    push ebx 
0000001A 89E1    mov ecx,esp 
0000001C B00B    mov al,0xb 
0000001E CD80    int 0x80 
00000020 200A    and [edx],cl 

。ブランチは含まれていませんが、

ジャンプに適切なラベルを貼る方法はありますか?

はい、Agner Fogのobjconvディスアセンブラでは、ブランチターゲットにラベルを貼り付けて、どのブランチがどこに行くかを把握するのに役立ちます。 を参照してくださいHow do I disassemble raw x86 code?

0

これはフォンノイマンのアーキテクチャの結果です。コードとデータは、コンピュータのメモリ内の単なる数字です。したがって、逆アセンブラはコードとデータが何であるかを知ることができません(バイトシーケンスに関する情報はありません)。つまり、手作業で行う必要があります。

幸いにもそれは簡単です。文字列データをnop(\ x90)に置き換えて、再度解体してください。次に、nop領域を置き換えることによって、文字列データをソースコードに戻すことができます。

また、逆アセンブルに正しいターゲットCPUを使用していることを確認してください。私はこのシェルコードが16ビットの8086 CPUで動作することは意図されていないと思う。あなたには、いくつかのデータを飛び越えるためにcallまたはjmpを使用しシェルコードを持っていた場合