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

Маппинг модуля в память эффективнее RunPE?

Alexey18

(L3) cache
Пользователь
Регистрация
11.06.2023
Сообщения
163
Реакции
30
Доброго времени суток. Реализовал маппинг файла. Задался вопросом, эффективние ли это RunPE? всё же не дергаются сторонние процессы, да и вызовов винапи гораздо меньше потребовалось.

Является ли эта методика LoadPE? не очень понял. И как вообще эффективна вплане обхода?(при условии скрытых импортов естественно)
 
Пожалуйста, обратите внимание, что пользователь заблокирован
И как вообще эффективна вплане обхода?
Зависит от антивируса: на одном runpe спалится, на другом loadpe спалится.
 
необходимость обработки таких механизмов как TLS-колбэки, SEH, какой-нибудь отложенный импорт

Никогда не понимал, для чего эта херня используется в малвари, да и в принципе в нормальных приложениях.

По теме - главное не использовать RWE память. Интересная идея - подгрузить в процесс-жертву какую-нибудь dll из Windows папки, которая в принципе не используется в этом процессе и использовать её секцию кода под вредоносные писюльки, не знаю есть ли какие-то параноидальные АВ, которые сверяют целостность секций кода dll в памяти и на диске.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Никогда не понимал, для чего эта херня используется в малвари, да и в принципе в нормальных приложениях.

По теме - главное не использовать RWE память. Интересная идея - подгрузить в процесс-жертву какую-нибудь dll из Windows папки, которая в принципе не используется в этом процессе и использовать её секцию кода под вредоносные писюльки, не знаю есть ли какие-то параноидальные АВ, которые сверяют целостность секций кода dll в памяти и на диске.
Способом который ты описал часто инжектят читы в игры, порой успешно даже во многие не ламерские античиты.
С антивирусами думаю такая же история.

Использовали же одно время библиотеку Discord (оверлей) для подмены в играх, а потом стал замечать что и лаунчеры/лоадеры стали использовать ее в малвари. И долгое время это работало, а с каким-то АВ и по сей день работает.
 
Никогда не понимал, для чего эта херня используется в малвари, да и в принципе в нормальных приложениях.
SEH и TLS активно использует малварь по причине, что обе позволяют скрыто выполнять действия. Пользовательский SEH (структурный обработчик исключений) занимает позицию в голове системной цепочки, а потому если умышленно сгенерить исключение в своём коде (например обратиться к памяти нуль AccessViolation = 0xC0000005h), то управление тут-же получит установленный нами обработчик, внутри которого можно сделать что-угодно, после чего передать управление дефолтному обработчику SEH системы, с флагом "Всё Ок".

SEH вставляют в код блоки "Try/Except" в исходники плюсов, но это слишком палевно, поэтому малварь использует самое первое поле "ExceptionList" в структуре TEB потока, адрес которой лежит в регистре FS на х32, или GS на х64. Правда х64 юзает уже не SEH, а VEH (векторная), но суть та же. Если запросить TEB у WinDbg, можно обнаружить там рычаг установки обработчиков "EXCEPTION_REGISTRATION_RECORD":

Код:
0: kd> dt _TEB NtTib.
ntdll!_TEB
   +0x000 NtTib  :
      +0x000 ExceptionList        : Ptr64 _EXCEPTION_REGISTRATION_RECORD
      +0x008 StackBase            : Ptr64 Void
      +0x010 StackLimit           : Ptr64 Void
      +0x018 SubSystemTib         : Ptr64 Void
      +0x020 FiberData            : Ptr64 Void
      +0x028 ArbitraryUserPointer : Ptr64 Void
      +0x030 Self                 : Ptr64 _NT_TIB

Что касается TLS (локальное хранилище потока), так это вообще бомба.
По сути это отдельная РЕ-секция, с неограниченной по длине цепочкой колбэков. Плюс использования этой секции в том, что при загрузке образа в память, она подгружается самой первой так, что на точке-входа в программу, все её колбэки уже отрабатывают свои задачи. Например один колбэк TLS можно использовать для обнаружения отладчика, другим уходить на фиктивную точку-входа, и т.п.

Однако коду в TLS приходится выживать в жёстких условиях. Поскольку в этот момент ни одна из либ импорта ещё не подгружена в память процесса, колбэки не могут звать большинство WinAPI, и всё приходится делать в ручную, через поля тех-же структур PEB/TEB. Команда "lm" отладчика выводит лог последовательности загрузки всех модулей в память, и здесь видно, что импорт парсится уже после самого образа проги, т.е. намного позже секции TLS:

Код:
0:000> lm
start              end                module name
00000000`00400000  00000000`00405000  image00000000_00400000  (no symbols)           
00000000`77840000  00000000`7795f000  kernel32                (pdb symbols)  c:\symbols\kernel32.pdb
00000000`77960000  00000000`77b0a000  ntdll                   (pdb symbols)  c:\symbols\ntdll.pdb
000007fe`fdb70000  000007fe`fdbda000  KERNELBASE              (deferred)             
000007fe`fedc0000  000007fe`fee5f000  msvcrt                  (deferred)
 
Кстати на х32 можно было не указывать бит(E) во-флагах секции, т.к. установленный в записях PTE бит(W) автоматом открывал уже страницу на исполнение. Например код в секции-данных или стеке отрабатывал без проблем. Но с приходом х64 в PTE появился старший бит "XD/NX" (eXecute disable, no execute), который испортил всю малину.
 
Никогда не понимал, для чего эта херня используется в малвари, да и в принципе в нормальных приложениях.

По теме - главное не использовать RWE память. Интересная идея - подгрузить в процесс-жертву какую-нибудь dll из Windows папки, которая в принципе не используется в этом процессе и использовать её секцию кода под вредоносные писюльки, не знаю есть ли какие-то параноидальные АВ, которые сверяют целостность секций кода dll в памяти и на диске.
Есть интересная методика, расширяющая твою идею. В системном каталоге Windows можно найти dll с секциями RWX, для записи в такую память не приходится использовать VirtualAlloc/VirtualProtect и их Nt варианты. Ограничиваемся только размером кодовой секции такой dll. Такие dll есть, но их мало.
 
В каталоге system32 врядли найдёшь готовую dll с атрибутами кода RWE, т.к. это противоречит их-же политике безопасности. В своём процессе чз VirtualProtect() можно свободно менять атрибуты страниц на какие угодно, и аверы на это никак не реагируют. Например любому распаковщику по любому приходится открывать секцию-кода на запись, так авер не ругается-же на это. Другое дело правка атрибутов в чужом процессе - здесь уже некоторые ав подымают визг.

Вот пример подгрузки произвольной либы из папки майков в свой процесс, и присвоение атрибута RWE её секции-кода. Всё проходит успешно, и 14 аверов дружно пропускают это между ног. Соответственно можно затирать оригин.код либы своим, и передавать на него управление. Система Win7 x64:

C-подобный:
format  pe64 console
entry   start
include 'win64ax.inc'
;//------------------
.data
libName    db  'loadperf.dll',0  ;// PerfMon lib
oldFlags   dd  0
;//------------------
section '.text' code executable readable
start:  sub     rsp,8

        invoke  LoadLibrary,libName
        push    rax rax rax    ;// база в памяти

       cinvoke  printf,<10,' DLL name....: %s',\
                        10,' In memory...: 0x%016I64X',0>,libName,rax

        pop     rax
        add     rax,3Ch           ;// e_lfanew
        mov     ebx,dword[rax]
        pop     rax
        add     rax,rbx           ;// РЕ-Header addr
        add     rax,2Ch           ;// BaseOfCode RVA
        mov     ebx,dword[rax]
        pop     rax
        add     rax,rbx           ;// RAX = BaseOfCode VA
        push    rax
       
       cinvoke  printf,<10,' Code section: 0x%016I64X',0>,rax

        pop     rax
        invoke  VirtualProtect,rax,1000h,PAGE_EXECUTE_READWRITE,oldFlags
        or      eax,eax
        jnz     @f
       cinvoke  printf,<10,10,' ***** Change RWE error! *****',0>
        jmp     @exit

@@:    cinvoke  printf,<10,10,' ***** Change RWE OK! ********',0>
@exit: cinvoke  _getch
       cinvoke  exit,0
;//--------------------
section '.idata' import data readable
  library  msvcrt, 'msvcrt.dll', kernel32, 'kernel32.dll'
  include  'api\kernel32.inc'
  include  'api\msvcrt.inc'

vp_rwe.png


jotti.png
 
Последнее редактирование:
В каталоге system32 врядли найдёшь готовую dll с атрибутами кода RWE, т.к. это противоречит их-же политике безопасности.
Конечно противоречит, но периодически такие библиотеки проскакивают. Читал я про это в каком-то вайтхет отчете, долго была в system32 либа с правами rwx, потом пофиксили. Но на стороне можно найти много других библиотек с этим свойством, даже подписанных.
 

Вложения

  • VirtProt.zip
    687 байт · Просмотры: 12
Вот специально набросал код, который находит все DLL в текущем дире, и парсит секции на атрибут RWE. Системные сторожа не дают скопировать exe в папку system32, зато в sysWow64 без проблем. При запуске находит 1892 библиотеки, и как оказалось, только в трёх из них секция-кода открыта на запись. Но и в этом случае имя секции во-всех dll получаю "INIT", что говорит о юм-драйвере. Тестил и во-вложенных папках ProgramFiles типа офис, фотошоп, etc - ни в одной из них нет кода RWE. Может и были такие во-времена Win98/XP, но на 64-бит Win7+ их точно нет, а если и найдётся заблудшая овца, то на таргет машине её может и не быть.

По коду.., чз FindNextFile() ищем dll, читаем из неё в буфер 1К-байт хидера, смещаемся в буфере к РЕ-заголовку, и прыгнув от него на F8h байт, попадаем в таблицу-секций. Оффсет F8h одинаков как для х32, так и для х64 либ, поэтому можно парсить любые (кстати dll попадаются не только РЕ, но и NE-формата, поэтому их следует пропускать). Внутри описателя секции берём последнее поле с атрибутами, и сравниваем их с константой E0000020h = CodeRWE. Cекция может иметь и доп.флаги, поэтому лучше оставить только старшие 4-бита из 32-х = Eh, что я и сделал в своём примере. Дефайны распространённых флагов выглядят так:

C-подобный:
struct SECTION_TABLE
  ObjectName           rb  8      ;// имя секции
  VirtualSize          dd  0      ;// размер в памяти
  VirtualOffsetRVA     dd  0      ;// ...(адрес в памяти)
  RawSize              dd  0      ;// размер на диске
  RawOffsetRVA         dd  0      ;// ...(адрес на диске)
  RelocOffsetRVA       dd  0      ;//
  Reserved             dq  0      ;//
  Characteristics      dd  0      ;// флаги секции
ends                                          |
                                              V
#define IMAGE_SCN_CNT_CODE                0x00000020
#define IMAGE_SCN_CNT_INITIALIZED_DATA    0x00000040
#define IMAGE_SCN_CNT_UNINITIALIZED_DATA  0x00000080
#define IMAGE_SCN_MEM_EXECUTE             0x20000000
#define IMAGE_SCN_MEM_READ                0x40000000
#define IMAGE_SCN_MEM_WRITE               0x80000000

#define IMAGE_SCN_LNK_NRELOC_OVFL         0x01000000
#define IMAGE_SCN_MEM_DISCARDABLE         0x02000000
#define IMAGE_SCN_MEM_NOT_CACHED          0x04000000
#define IMAGE_SCN_MEM_NOT_PAGED           0x08000000
#define IMAGE_SCN_MEM_SHARED              0x10000000

C-подобный:
format  pe64 console
entry   start
include 'win64ax.inc'
include 'equates\pe64.inc'
;//------------------
.data
hFile       dd  0
findHndl    dd  0
peOffset    dd  0
seOffset    dd  0
secCount    dd  0
totalLib    dd  0
found       dd  0

align 16
wfd         WIN32_FIND_DATA
peHeader    rb  1024
;//------------------
section '.code' code executable readable
start:  sub     rsp,8

        invoke  FindFirstFile,<'*.dll',0>,wfd
        mov     [findHndl],eax
@findNextLibrary:
        or      eax,eax
        jz      @stop
        inc     [totalLib]

;// Читаем из DLL первые 1К данных
        invoke  _lopen,wfd.cFileName,OF_READ
        cmp     eax,-1
        jz      @nextStep
        mov     [hFile],eax
        invoke  _lread,rax,peHeader,1024
        invoke  _lclose,[hFile]

;// Находим указатель на РЕ-Header
        mov     edi,peHeader
        mov     esi,edi
        add     esi,3Ch
        mov     esi,[esi]
        add     edi,esi
        mov     [peOffset],edi
        cmp     word[edi],'NE'   ;// NE-file?
        jz      @nextStep

;// ECX = кол-во секций в файле, EDI = SectionTable offset
        movzx   ecx,[edi + PE_HEADER.NumberOfSection]
        add     edi,0xF8

;// Проходим по всем секциям DLL, и читаем их атрибуты
@@:     push    rdi rcx
        mov     eax,[edi + SECTION_TABLE.Characteristics]
        shr     eax,28           ;// оставить только старшие 4-бита
        cmp     eax,0x0E         ;// RWE ???
        jnz     @fuck
        inc     [found]
       cinvoke  printf,<10,' Found RWE code.  Section name: %s --> %s',0>,edi,wfd.cFileName
@fuck:  pop     rcx rdi
        add     rdi,sizeof.SECTION_TABLE   ;// переход к сл.секции..
        loop    @b

;// Все либы в текущем дире..
@nextStep:
        invoke  FindNextFile,[findHndl],wfd
        jmp     @findNextLibrary

@stop:  invoke  FindClose,[findHndl]
       cinvoke  printf,<10,' ------------------------------',\
                        10,' Total dll scan:  %d ',\
                        10,' Found counter :  %d ',0>,[totalLib],[found]
@exit: cinvoke  _getch
       cinvoke  exit,0
;//--------------------
section '.idata' import data readable
  library  msvcrt, 'msvcrt.dll',kernel32,'kernel32.dll'
  include  'api\kernel32.inc'
  include  'api\msvcrt.inc'

rweLib.png
 

Вложения

  • RweLib.zip
    2.3 КБ · Просмотры: 10
Последнее редактирование:


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