
Реализация техники RunPE на VBA или как обойти белые списки приложений.
Простая, но эффективная реализация техники RunPE на VBA. Этот код может использоваться для запуска исполняемых файлов из памяти Word или Excel. Он совместим как с 32-битными, так и с 64-битными версиями Microsoft Office 2010 и выше.
Подробнее здесь:
https://itm4n.github.io/vba-runpe-part1/
https://itm4n.github.io/vba-runpe-part2/

Exploit в конце кода укажите путь к файлу, который вы хотите запустить.strSrcFile = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"
/!\ Если вы используете 32-битную версию Microsoft Office на 64-битной ОС, необходимо указать 32-битные двоичные файлы.
strSrcFile = "C:\Windows\SysWOW64\cmd.exe"
strSrcFile = "C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe"
strArguments = "-exec Bypass"
Это будет использовано для формирования командной строки, эквивалентной:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -exec Bypass
(Необязательно) Включите Вид > Окно Immediate (Ctrl+G), чтобы проверить журналы выполнения и ошибок.
Запустите макрос Exploit!
pe2vba.py для преобразования PE-файла в VBA. Таким образом, его можно напрямую встроить в макрос.user@host:~/Tools/VBA-RunPE$ ./pe2vba.py meterpreter.exe
[+] Created file 'meterpreter.exe.vba'.
RunPE.vba содержимым файла .vba, который был создан на предыдущем шаге.' ================================================================================
' ~~~ ВСТРОЕННЫЙ PE ~~~
' ================================================================================
' КОД, СГЕНЕРИРОВАННЫЙ PE2VBA
' ===== НАЧАЛО PE2VBA =====
Private Function PE() As String
Dim strPE As String
strPE = ""
PE = strPE
End Function
' ===== КОНЕЦ PE2VBA =====
(Необязательно) Включите Вид > Окно Immediate (Ctrl+G), чтобы проверить журналы выполнения и ошибок.
Запустите макрос Exploit!
/!\ При использовании встроенного PE макрос автоматически переключится в этот режим, потому что метод PE() вернёт непустую строку.
GetThreadContext() завершается ошибкой с кодом 998.Вы можете получить эту ошибку, если запускаете макрос из 64-битной версии Office. В качестве обходного пути вы можете переместить код в модуль, а не выполнять его из объектов Word. Спасибо @joeminicucci за подсказку.
================================================================================
[*] Исходный файл: 'C:\Windows\System32\cmd.exe'
[*] Проверка исходного PE...
[*] Создание нового процесса в приостановленном состоянии...
[*] Получение контекста основного потока...
|__ GetThreadContext() не удался (Ошибка: 998)
Пока неясно, почему этот обходной путь работает. Я немного исследовал это. Похоже, ошибка вызвана тем, что структура CONTEXT неправильно выровнена в 64-битной версии. Я заметил, что размер структуры также неверен ([VBA] LenB(CONTEXT) != [C++] sizeof(CONTEXT)), в то время как в 32-битной версии всё нормально. У меня есть рабочее решение, которое позволяет правильно выполнить GetThreadContext(), но затем оно ломает другие вещи в процессе выполнения.
Редакция 2019-12-15: определение 64-битной версии структуры CONTEXT действительно было неверным, но его исправление не устранило ошибку. Поэтому я реализовал обходной путь для 64-битной версии. Я заменил аргумент структуры CONTEXT функций GetThreadContext() и SetThreadContext() массивом Byte того же размера.
Редакция 2019-12-17: Наконец-то я нашёл проблему. Моё первоначальное предположение было верным: структура CONTEXT должна быть выровнена по 16 байт в памяти. В C это можно контролировать с помощью align(16) в определении структуры, но в VBA вы не можете это контролировать. Поэтому GetThreadContext() и SetThreadContext() могут "случайно" завершаться ошибкой. С другой стороны, массивы Byte всегда, похоже, выравниваются по 16 байт, поэтому этот обходной путь эффективен, но нет гарантии, если только я не сделаю реверс-инжиниринг интерпретатора/компилятора VBA и не разберусь в этом?!
LongPtr — Определённый пользователем тип не определёнЕсли вы получаете эту ошибку, это означает, что вы запускаете макрос из старой версии Office (<=2007). Тип LongPtr был введён в VBA7 (Office 2010) вместе с поддержкой 64-битного Windows API. Он очень полезен для обработки указателей без необходимости беспокоиться об архитектуре (32-бит / 64-бит).
В качестве обходного пути вы можете заменить все вхождения LongPtr на Long (32-бит) или LongLong (64-бит). Используйте Ctrl+H в вашем любимом текстовом редакторе.
@hasherezade — Полная реализация RunPE (https://github.com/hasherezade/)
@Zer0Mem0ry — 32-битная реализация RunPE на C++ (https://github.com/Zer0Mem0ry/RunPE)
@DidierStevens — Встраивание PE в VBA
Этот код был протестирован на следующих платформах:
Вот таблица соответствия некоторых типов Win32 и VBA:
(*) LongPtr — это "динамический" тип, он занимает 4 байта в 32-битной версии Office и 8 байт в 64-битной версии Office. https://msdn.microsoft.com/fr-fr/library/office/ee691831(v=office.14).aspx
| C++ | VBA | Архитектура |
|---|
| BYTE | Byte | 32 и 64 |
| WORD | Integer | 32 и 64 |
| DWORD, ULONG, LONG | Long | 32 и 64 |
| DWORD64 | LongLong | 64 |
| HANDLE | LongPtr(*) | 32 и 64 |
| LPSTR | String | 32 и 64 |
| LPBYTE | LongPtr(*) | 32 и 64 |