Траблы в RunPE

Тема в разделе "WASM.WIN32", создана пользователем H3aVyH0Rs3, 10 июн 2021.

Метки:
  1. H3aVyH0Rs3

    H3aVyH0Rs3 New Member

    Публикаций:
    0
    Регистрация:
    10 июн 2021
    Сообщения:
    6
    Пишу, значит, я RunPE шеллкод, тестирую на примерах к FASM - всё ок - запускает экзешник от имени другого процесса. Но вот попадается мне простой блокнот (х86) и мой RunPE уже не в состоянии его запустить. А дело в том, что блокнот имеет ImageBase=0x01000000 и не имеет релоков. В то же время в чужом процессе, от имени которого я пытаюсь запустить блокнот с помощью инжекта, эта область памяти помечена как RESERVED и MEM_MAPPED. Значит мне надо как-то закрыть этот MAP файл в чужом процессе, но как? ZwUnmapViewOfSection вываливается с ошибкой 0xC0000045 (STATUS_INVALID_PAGE_PROTECTION
    ) и не помогает - все равно страница содержит флаг MEM_MAPPED. Проверяю так:
    Код (C):
    1.       if (VirtualQueryEx(processInfo.hProcess, (LPCVOID)pHdrs->OptionalHeader.ImageBase, &memInfo, sizeof(memInfo))) {
    2.         if (memInfo.Type == MEM_MAPPED) {
    3.           fncs.pNtUnmapViewOfSection(processInfo.hProcess, memInfo.BaseAddress);
    4.         }
    5.         VirtualQueryEx(processInfo.hProcess, (LPCVOID)pHdrs->OptionalHeader.ImageBase, &memInfo, sizeof(memInfo));
    6.         if (memInfo.Type == MEM_MAPPED) {
    7.           puts("OXOXO");
    8.         }
    9.       }
    Например, я пытаюсь винжектить блокнот в интернет эксплорер. Блокнот (ImageBase=0x01000000), а у ИЕ есть релоки. Например, ИЕ загрузился (ImageBase=0x0930000). Исполняемый файл ИЕ загружается с нормальными правами чтения/записи. Но! Участок памяти, куда надо отправить блокнот имеет свойство PAGE_NOACCESS (было при аллокации), MEM_MAPPED и MEM_RESERVE !

    [​IMG]

    Пытаюсь освободить кусок зарезервированной памяти, сначала получаю базовый адрес участка памяти, а затем отправляю его на VirtualFreeEx, но функция возвращает ошибку 0x57 (ERROR_INVALID_PARAMETER)
    Код (Text):
    1.       if (VirtualQueryEx(processInfo.hProcess, (LPCVOID)pHdrs->OptionalHeader.ImageBase, &memInfo, sizeof(memInfo))) {
    2.         if (memInfo.Type == MEM_MAPPED) {
    3.           DWORD dwOldProtect = 0;
    4.           printf("BASE: %X\r\n", (DWORD)memInfo.BaseAddress);
    5.           printf("ALLOCATION BASE: %X\r\n", (DWORD)memInfo.AllocationBase);
    6.           printf("TYPE: %X\r\n", memInfo.Type);
    7.           printf("ALLOCATION PROTECT: %X\r\n", memInfo.AllocationProtect);
    8.           printf("PROTECT: %X\r\n", memInfo.Protect);
    9.           printf("STATE: %X\r\n", memInfo.State);
    10.           printf("Y:%X\r\n", (DWORD)fncs.pVirtualFreeEx(processInfo.hProcess, (LPVOID)memInfo.AllocationBase, 0x0, MEM_RELEASE));
    11.           printf("=%X\r\n", GetLastError());
    12.           printf("X:%X\r\n", (DWORD)fncs.pVirtualAllocEx(processInfo.hProcess, (LPVOID)memInfo.AllocationBase, 0x10000, MEM_COMMIT, PAGE_EXECUTE_READWRITE));
    13.           printf("%X\r\n", VirtualProtectEx(processInfo.hProcess, (LPVOID)memInfo.BaseAddress, memInfo.RegionSize, PAGE_EXECUTE_WRITECOPY, &dwOldProtect));
    14.           printf("%X\r\n", GetLastError());
    15.  
     
  2. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    H3aVyH0Rs3,

    wrk

    В этом сервисе данный статусный код отсутствует, он может быть в старших версиях, на них сурков нет. Какая версия системы ?

    И где семпл ?

    А есчо это всё через нэйтив делается, какие есчо винапи.

    И пойми что разные статусные коды отображаются на один винапи код ошибки:

    generr.c

    Так не разберёшся, нужно статусные коды знать нэйтив.

    А в общем ты пытаешься древний примитив реализовать тут его уже все переписали, тупо отмапить от фикс базы и вручную настроить формат. Если с такими простыми траблами разобраться не можешь - пошёл по форумам дамаг сюда, то куда тебе писать загрузчики, вначале архитектуру изучи и узнай где искать решение что бы по форумам не ходить)
     
  3. H3aVyH0Rs3

    H3aVyH0Rs3 New Member

    Публикаций:
    0
    Регистрация:
    10 июн 2021
    Сообщения:
    6
    Windows 8.1 x64 и Windows 10 x64

    А не одно и то же? Я всмысле не знаю различия в чем заключаются между NtReadVirtualMemory и ReadProcessMemory.
    --- Сообщение объединено, 11 июн 2021 ---
    Вопрос не в том - выполнить это как RunPE или LoadPE. Вопрос как освободить область памяти (релоков нет, другая не подходит), чтобы я мог туда закинуть образ EXE и работать с ним, хоть от своего процесса, хоть чужой суспендить.
     
  4. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    H3aVyH0Rs3,

    > Windows 8.1 x64 и Windows 10 x64

    Открывай идой ядерный сервис смотри где там этот статусный код.

    > А не одно и то же?

    Выше я уже говорил почему.

    > Вопрос не в том - выполнить это как RunPE или LoadPE.

    Это очевидно, может возьми готовое это любая малварь использует если поискать то можно накопать тысячи однотипных сурков. А есчо может у тебя авер блочит, сейчас защита такое сделать не даст. Тем более в 10-ке.
     
    H3aVyH0Rs3 нравится это.
  5. H3aVyH0Rs3

    H3aVyH0Rs3 New Member

    Публикаций:
    0
    Регистрация:
    10 июн 2021
    Сообщения:
    6
    Может я и тупой, но...
    > Это очевидно, может возьми готовое это любая малварь использует если поискать то можно накопать тысячи однотипных сурков.
    Все сорцы, которые я накопал (RunPE) - максимум освобождают образ оригинального файла (если базы совпадают), никаким освобождением других областей памяти там и не пахнет.
    > А есчо может у тебя авер блочит, сейчас защита такое сделать не даст.
    Нет авера, ни на 8.1 ни на 10ке. Странно, что защита распространяется на определенные области памяти, а на чтение/запись памяти в чужом процессе не распространяется и на чтение контекста не распространяется.
    В любом случае благодарю за помощь.
     
  6. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    H3aVyH0Rs3,

    Никакой помощи небыло лишь критика. Задача не решена. Почему резервная область не освобождается, может ты не верные параметры задаёшь сервисные.
     
  7. H3aVyH0Rs3

    H3aVyH0Rs3 New Member

    Публикаций:
    0
    Регистрация:
    10 июн 2021
    Сообщения:
    6
    Говорю ж - область памяти особенная. Как память может быть одновременно MEM_MAPPED, RESERVED и PAGE_NOACCESS? По-моему это шизофазия какае-то.
     
  8. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    H3aVyH0Rs3,

    Резервная область с не выделенной памятью, эти два атрибута обычны и понятны. Но вот почему не файловая проекция, должно быть MEM_IMAGE ??

    Может ты сам там что то перемапил(ты ведь грузишь из памяти соотв. отображение не файловой секции), покажи семпл.
     
  9. Thetrik

    Thetrik UA6527P

    Публикаций:
    0
    Регистрация:
    25 июл 2011
    Сообщения:
    861
    Как создаешь процесс? Что если создать в SUSPENDED состоянии, выделить нужный блок памяти через VirtualAllocEx по нужному адресу. Впоследствии этот блок можно будет использовать.
    Насчет невозможности размапить отображение, есть флаг:
    Код (Text):
    1. #define SEC_NO_CHANGE 0x00400000
    2.  
    3. SEC_NO_CHANGE - Once the file is mapped, the protection cannot be changed nor can the view be unmapped. The view is unmapped when the process is deleted. Cannot be used with SEC_IMAGE.
     
    H3aVyH0Rs3 нравится это.
  10. H3aVyH0Rs3

    H3aVyH0Rs3 New Member

    Публикаций:
    0
    Регистрация:
    10 июн 2021
    Сообщения:
    6
    Так и делаю, но VirtualAllocEx вылетает с ошибкой, потому что блок памяти уже занят вот этим зарезервированным MEM_MAPPED и RESERVED.
     
  11. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    Thetrik,

    > SEC_NO_CHANGE

    Это используется ядром гуя для блокировки проекции, те не файлова секция отображается два раза, изменения в не файловой секции это своего рода зеркало, межпроцессный обмен. Изменение по данным в первом процессе приводит к таким же изменениям в другой проекции. Это не работает для файловых секций. Как может быть спроецирован образ блокнота не как файловая проекция ??

    Если атрибут стоит sec_no_ch,то как юзер загрузчик настроит образ ??

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

    С sec_no_ch была такая техника - выделялась область потоком гуя, затем он останавливался и таким образoм область нелья было удалить.

    Код (Text):
    1. ; Indy, Great
    2. ; 2009 virustech.org
    3.  
    4. ; NtGdiExtEscape
    5. ; NtGdiGetSpoolMessage
    6. ; NtGdiSetBitmapBits
    7. ; NtGdiPolyDraw
    8. ; NtGdiDrawEscape
    9. ; NtGdiCheckBitmapBits
    10. ; ...
    11.  
    12.     .686
    13.     .model flat, stdcall
    14.     option casemap :none
    15.    
    16.     include \masm32\include\ntdll.inc
    17.     includelib \masm32\lib\ntdll.lib
    18.        
    19.     include \masm32\include\user32.inc
    20.     includelib \masm32\lib\user32.lib
    21.    
    22. .data
    23. RegionAddress    PVOID 0
    24. SynchLock        BOOLEAN FALSE
    25. RaiseLock        BOOLEAN FALSE
    26.  
    27. .code
    28. ThreadStartupRoutine proc UserParameter:PVOID
    29. ; Цикл ожидания выделения памяти в первом треде.
    30. WaitLock:
    31.     cmp SynchLock,FALSE
    32.     je WaitLock
    33.     mov RaiseLock,FALSE
    34.     xor ecx,ecx
    35.     mov eax,1085H    ; NtGdiEnumFontChunk
    36.     push ecx
    37.     push ecx
    38.     push ecx
    39.     push RegionAddress
    40.     push ecx
    41.     push PAGE_SIZE
    42.     push ecx
    43.     push ecx
    44.     mov edx,esp
    45.     Int 2EH
    46.     lea esp,[esp + 4*8]
    47.     mov RaiseLock,TRUE
    48.     jmp WaitLock
    49. ThreadStartupRoutine endp
    50.  
    51. BREAKERR macro
    52.     .if Eax != STATUS_INVALID_PAGE_PROTECTION
    53.     int 3    ; Ошибка.
    54.     .endif
    55. endm
    56.  
    57. Entry proc
    58. Local ClientId:CLIENT_ID
    59. Local ThreadHandle:HANDLE
    60. Local RegionSize:ULONG
    61. Local OldProtect:ULONG
    62.     invoke RtlCreateUserThread, NtCurrentProcess, NULL, FALSE, 0, 0, 0, addr ThreadStartupRoutine, 0, addr ThreadHandle, addr ClientId
    63. Synch:
    64.     mov RegionSize,PAGE_SIZE
    65.     mov RegionAddress,0
    66.     invoke ZwAllocateVirtualMemory, NtCurrentProcess, addr RegionAddress, 0, addr RegionSize, MEM_COMMIT, PAGE_READONLY
    67. ; Тред вызывающий теневой сервис выводим из ожидания.
    68.     mov SynchLock,TRUE
    69. ; Останавливаем тред исполняющий теневой сервис.
    70.     invoke ZwSuspendThread, ThreadHandle, NULL
    71. ; Попытка освобождения памяти.
    72. ; В случае успеха сервис возвратит STATUS_INVALID_PAGE_PROTECTION.
    73.     invoke ZwFreeVirtualMemory, NtCurrentProcess, addr RegionAddress, addr RegionSize, MEM_RELEASE
    74.     test eax,eax
    75.     mov SynchLock,FALSE
    76.     jnz Raise
    77. ; Выводим тред из спящего состояния и выполняем цикл захвата.
    78.     invoke ZwResumeThread, ThreadHandle, NULL
    79.     jmp Synch
    80. Raise:
    81.     BREAKERR
    82. ; Теперь запамять захвачена. Для разлочивания её следует вывести тред
    83. ; из спящего состояния, после чего дождаться возвращения его из сервиса.
    84. ; - Попытка освобождения памяти закончится неудачей.
    85.     invoke ZwFreeVirtualMemory, NtCurrentProcess, addr RegionAddress, addr RegionSize, MEM_RELEASE
    86.     BREAKERR
    87. ; - Изменить атрибуты доступа региона не удастся.
    88.     invoke ZwProtectVirtualMemory, NtCurrentProcess, addr RegionAddress, addr RegionSize, PAGE_READONLY, addr OldProtect
    89.     BREAKERR
    90. ; Выводим тред из спящего состояния.
    91.     invoke ZwResumeThread, ThreadHandle, NULL
    92. ; Ожидаем разлочивание региона.
    93. @@:
    94.     cmp RaiseLock,FALSE
    95.     je @b
    96. ; Освобождаем регион.
    97.     invoke ZwFreeVirtualMemory, NtCurrentProcess, addr RegionAddress, addr RegionSize, MEM_RELEASE
    98.     int 3
    99.     ret
    100.     Call MessageBox    ; imp
    101. Entry endp
    102. end Entry
     
    Последнее редактирование: 13 июн 2021