Пишу, значит, я RunPE шеллкод, тестирую на примерах к FASM - всё ок - запускает экзешник от имени другого процесса. Но вот попадается мне простой блокнот (х86) и мой RunPE уже не в состоянии его запустить. А дело в том, что блокнот имеет ImageBase=0x01000000 и не имеет релоков. В то же время в чужом процессе, от имени которого я пытаюсь запустить блокнот с помощью инжекта, эта область памяти помечена как RESERVED и MEM_MAPPED. Значит мне надо как-то закрыть этот MAP файл в чужом процессе, но как? ZwUnmapViewOfSection вываливается с ошибкой 0xC0000045 (STATUS_INVALID_PAGE_PROTECTION ) и не помогает - все равно страница содержит флаг MEM_MAPPED. Проверяю так: Код (C): if (VirtualQueryEx(processInfo.hProcess, (LPCVOID)pHdrs->OptionalHeader.ImageBase, &memInfo, sizeof(memInfo))) { if (memInfo.Type == MEM_MAPPED) { fncs.pNtUnmapViewOfSection(processInfo.hProcess, memInfo.BaseAddress); } VirtualQueryEx(processInfo.hProcess, (LPCVOID)pHdrs->OptionalHeader.ImageBase, &memInfo, sizeof(memInfo)); if (memInfo.Type == MEM_MAPPED) { puts("OXOXO"); } } Например, я пытаюсь винжектить блокнот в интернет эксплорер. Блокнот (ImageBase=0x01000000), а у ИЕ есть релоки. Например, ИЕ загрузился (ImageBase=0x0930000). Исполняемый файл ИЕ загружается с нормальными правами чтения/записи. Но! Участок памяти, куда надо отправить блокнот имеет свойство PAGE_NOACCESS (было при аллокации), MEM_MAPPED и MEM_RESERVE ! Пытаюсь освободить кусок зарезервированной памяти, сначала получаю базовый адрес участка памяти, а затем отправляю его на VirtualFreeEx, но функция возвращает ошибку 0x57 (ERROR_INVALID_PARAMETER) Код (Text): if (VirtualQueryEx(processInfo.hProcess, (LPCVOID)pHdrs->OptionalHeader.ImageBase, &memInfo, sizeof(memInfo))) { if (memInfo.Type == MEM_MAPPED) { DWORD dwOldProtect = 0; printf("BASE: %X\r\n", (DWORD)memInfo.BaseAddress); printf("ALLOCATION BASE: %X\r\n", (DWORD)memInfo.AllocationBase); printf("TYPE: %X\r\n", memInfo.Type); printf("ALLOCATION PROTECT: %X\r\n", memInfo.AllocationProtect); printf("PROTECT: %X\r\n", memInfo.Protect); printf("STATE: %X\r\n", memInfo.State); printf("Y:%X\r\n", (DWORD)fncs.pVirtualFreeEx(processInfo.hProcess, (LPVOID)memInfo.AllocationBase, 0x0, MEM_RELEASE)); printf("=%X\r\n", GetLastError()); printf("X:%X\r\n", (DWORD)fncs.pVirtualAllocEx(processInfo.hProcess, (LPVOID)memInfo.AllocationBase, 0x10000, MEM_COMMIT, PAGE_EXECUTE_READWRITE)); printf("%X\r\n", VirtualProtectEx(processInfo.hProcess, (LPVOID)memInfo.BaseAddress, memInfo.RegionSize, PAGE_EXECUTE_WRITECOPY, &dwOldProtect)); printf("%X\r\n", GetLastError());
H3aVyH0Rs3, wrk В этом сервисе данный статусный код отсутствует, он может быть в старших версиях, на них сурков нет. Какая версия системы ? И где семпл ? А есчо это всё через нэйтив делается, какие есчо винапи. И пойми что разные статусные коды отображаются на один винапи код ошибки: generr.c Так не разберёшся, нужно статусные коды знать нэйтив. А в общем ты пытаешься древний примитив реализовать тут его уже все переписали, тупо отмапить от фикс базы и вручную настроить формат. Если с такими простыми траблами разобраться не можешь - пошёл по форумам дамаг сюда, то куда тебе писать загрузчики, вначале архитектуру изучи и узнай где искать решение что бы по форумам не ходить)
Windows 8.1 x64 и Windows 10 x64 А не одно и то же? Я всмысле не знаю различия в чем заключаются между NtReadVirtualMemory и ReadProcessMemory. --- Сообщение объединено, 11 июн 2021 --- Вопрос не в том - выполнить это как RunPE или LoadPE. Вопрос как освободить область памяти (релоков нет, другая не подходит), чтобы я мог туда закинуть образ EXE и работать с ним, хоть от своего процесса, хоть чужой суспендить.
H3aVyH0Rs3, > Windows 8.1 x64 и Windows 10 x64 Открывай идой ядерный сервис смотри где там этот статусный код. > А не одно и то же? Выше я уже говорил почему. > Вопрос не в том - выполнить это как RunPE или LoadPE. Это очевидно, может возьми готовое это любая малварь использует если поискать то можно накопать тысячи однотипных сурков. А есчо может у тебя авер блочит, сейчас защита такое сделать не даст. Тем более в 10-ке.
Может я и тупой, но... > Это очевидно, может возьми готовое это любая малварь использует если поискать то можно накопать тысячи однотипных сурков. Все сорцы, которые я накопал (RunPE) - максимум освобождают образ оригинального файла (если базы совпадают), никаким освобождением других областей памяти там и не пахнет. > А есчо может у тебя авер блочит, сейчас защита такое сделать не даст. Нет авера, ни на 8.1 ни на 10ке. Странно, что защита распространяется на определенные области памяти, а на чтение/запись памяти в чужом процессе не распространяется и на чтение контекста не распространяется. В любом случае благодарю за помощь.
H3aVyH0Rs3, Никакой помощи небыло лишь критика. Задача не решена. Почему резервная область не освобождается, может ты не верные параметры задаёшь сервисные.
Говорю ж - область памяти особенная. Как память может быть одновременно MEM_MAPPED, RESERVED и PAGE_NOACCESS? По-моему это шизофазия какае-то.
H3aVyH0Rs3, Резервная область с не выделенной памятью, эти два атрибута обычны и понятны. Но вот почему не файловая проекция, должно быть MEM_IMAGE ?? Может ты сам там что то перемапил(ты ведь грузишь из памяти соотв. отображение не файловой секции), покажи семпл.
Как создаешь процесс? Что если создать в SUSPENDED состоянии, выделить нужный блок памяти через VirtualAllocEx по нужному адресу. Впоследствии этот блок можно будет использовать. Насчет невозможности размапить отображение, есть флаг: Код (Text): #define SEC_NO_CHANGE 0x00400000 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.
Так и делаю, но VirtualAllocEx вылетает с ошибкой, потому что блок памяти уже занят вот этим зарезервированным MEM_MAPPED и RESERVED.
Thetrik, > SEC_NO_CHANGE Это используется ядром гуя для блокировки проекции, те не файлова секция отображается два раза, изменения в не файловой секции это своего рода зеркало, межпроцессный обмен. Изменение по данным в первом процессе приводит к таким же изменениям в другой проекции. Это не работает для файловых секций. Как может быть спроецирован образ блокнота не как файловая проекция ?? Если атрибут стоит sec_no_ch,то как юзер загрузчик настроит образ ?? Учитывая что раньше никто таких проблем не видел и что тс нуби тупо скопипастил код не понимая ничего, вполне вероятно что там этот кодес с проекциями может делать что угодно. С sec_no_ch была такая техника - выделялась область потоком гуя, затем он останавливался и таким образoм область нелья было удалить. Код (Text): ; Indy, Great ; 2009 virustech.org ; NtGdiExtEscape ; NtGdiGetSpoolMessage ; NtGdiSetBitmapBits ; NtGdiPolyDraw ; NtGdiDrawEscape ; NtGdiCheckBitmapBits ; ... .686 .model flat, stdcall option casemap :none include \masm32\include\ntdll.inc includelib \masm32\lib\ntdll.lib include \masm32\include\user32.inc includelib \masm32\lib\user32.lib .data RegionAddress PVOID 0 SynchLock BOOLEAN FALSE RaiseLock BOOLEAN FALSE .code ThreadStartupRoutine proc UserParameter:PVOID ; Цикл ожидания выделения памяти в первом треде. WaitLock: cmp SynchLock,FALSE je WaitLock mov RaiseLock,FALSE xor ecx,ecx mov eax,1085H ; NtGdiEnumFontChunk push ecx push ecx push ecx push RegionAddress push ecx push PAGE_SIZE push ecx push ecx mov edx,esp Int 2EH lea esp,[esp + 4*8] mov RaiseLock,TRUE jmp WaitLock ThreadStartupRoutine endp BREAKERR macro .if Eax != STATUS_INVALID_PAGE_PROTECTION int 3 ; Ошибка. .endif endm Entry proc Local ClientId:CLIENT_ID Local ThreadHandle:HANDLE Local RegionSize:ULONG Local OldProtect:ULONG invoke RtlCreateUserThread, NtCurrentProcess, NULL, FALSE, 0, 0, 0, addr ThreadStartupRoutine, 0, addr ThreadHandle, addr ClientId Synch: mov RegionSize,PAGE_SIZE mov RegionAddress,0 invoke ZwAllocateVirtualMemory, NtCurrentProcess, addr RegionAddress, 0, addr RegionSize, MEM_COMMIT, PAGE_READONLY ; Тред вызывающий теневой сервис выводим из ожидания. mov SynchLock,TRUE ; Останавливаем тред исполняющий теневой сервис. invoke ZwSuspendThread, ThreadHandle, NULL ; Попытка освобождения памяти. ; В случае успеха сервис возвратит STATUS_INVALID_PAGE_PROTECTION. invoke ZwFreeVirtualMemory, NtCurrentProcess, addr RegionAddress, addr RegionSize, MEM_RELEASE test eax,eax mov SynchLock,FALSE jnz Raise ; Выводим тред из спящего состояния и выполняем цикл захвата. invoke ZwResumeThread, ThreadHandle, NULL jmp Synch Raise: BREAKERR ; Теперь запамять захвачена. Для разлочивания её следует вывести тред ; из спящего состояния, после чего дождаться возвращения его из сервиса. ; - Попытка освобождения памяти закончится неудачей. invoke ZwFreeVirtualMemory, NtCurrentProcess, addr RegionAddress, addr RegionSize, MEM_RELEASE BREAKERR ; - Изменить атрибуты доступа региона не удастся. invoke ZwProtectVirtualMemory, NtCurrentProcess, addr RegionAddress, addr RegionSize, PAGE_READONLY, addr OldProtect BREAKERR ; Выводим тред из спящего состояния. invoke ZwResumeThread, ThreadHandle, NULL ; Ожидаем разлочивание региона. @@: cmp RaiseLock,FALSE je @b ; Освобождаем регион. invoke ZwFreeVirtualMemory, NtCurrentProcess, addr RegionAddress, addr RegionSize, MEM_RELEASE int 3 ret Call MessageBox ; imp Entry endp end Entry