keng Опубликовано 9 октября, 2016 Поделиться Опубликовано 9 октября, 2016 Буду краток. Имеется игра, хочется с ней сделать N. С определенным модулем. Получаю base address модуля, получаю его же размер. Делаю OpenProcess с правами на все (sic!), дальше хочу в свой процесс скопировать весь модуль целиком. По шагам: 0. VirtualAlloc, *размер_модуля*, COMMIT, RWE 1. VirtualProtectEx, pID, *базовый_адрес_модуля*, *размер_модуля*, RO 2. RPM, pID, *базовый_адрес_модуля*, *адрес из п.0*, *размер_модуля* Падаю уже на п. 0 - ERROR_INVALID_ADDRESS. Отладчиком смотрел - адрес валиден. RPM падает с ERROR_PARTIAL_COPY. Если копировать не весь модуль, а только кусочек (проверял на 64 байтах) - все в порядке. Размер модуля верен, pID тоже. На другом процессе этот же код молча отрабатывает. Вопрос - что еще придумать? Взываю к @gmz и @Xipho Вот еще пара скриншотов: 1 Ссылка на комментарий Поделиться на другие сайты Поделиться
Garik66 Опубликовано 9 октября, 2016 Поделиться Опубликовано 9 октября, 2016 1 минуту назад, keng сказал: Взываю к @gmz Все дороги ведут к gmz. Я тоже часто обращаюсь либо к нему, либо к MasterGH. Ссылка на комментарий Поделиться на другие сайты Поделиться
Xipho Опубликовано 9 октября, 2016 Поделиться Опубликовано 9 октября, 2016 6 минут назад, keng сказал: 0. VirtualAlloc, *размер_модуля*, COMMIT, RWE VirtualAllocEx со ссылкой на свой модуль не пробовал? 2 минуты назад, Garik66 сказал: Все дороги ведут к gmz. Я тоже часто обращаюсь либо к нему, либо к MasterGH. Вот щас обидел, да. Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 9 октября, 2016 Автор Поделиться Опубликовано 9 октября, 2016 4 minutes ago, Xipho said: VirtualAllocEx со ссылкой на свой модуль не пробовал? Вот щас обидел, да. Не-не-не, я в *свой* процесс копирую модуль извне. Или это очередная фича, а не баг? PS: Пришло в голову, что головной exe-модуль нельзя просто так весь ставить в RO, попробовал RWE - теперь VirtualProtectEx отдает ERROR_NO_ACCESS. Само собой, все запускается от админа и бла-бла-бла. PPS: ERROR_NOACCESS - мой косяк, неправильно dwOldProtect передавал. Все еще ERROR_INVALID_ADDRESS. Ссылка на комментарий Поделиться на другие сайты Поделиться
Garik66 Опубликовано 9 октября, 2016 Поделиться Опубликовано 9 октября, 2016 2 минуты назад, Xipho сказал: VirtualAllocEx со ссылкой на свой модуль не пробовал? Вот щас обидел, да. И конечно к Xipho - но это уже по умолчанию, как само собой разумеющееся. Ссылка на комментарий Поделиться на другие сайты Поделиться
Xipho Опубликовано 9 октября, 2016 Поделиться Опубликовано 9 октября, 2016 7 минут назад, keng сказал: PS: Пришло в голову, что головной exe-модуль нельзя просто так весь ставить в RO, попробовал RWE - теперь VirtualProtectEx отдает ERROR_NO_ACCESS. Само собой, все запускается от админа и бла-бла-бла. PPS: ERROR_NOACCESS - мой косяк, неправильно dwOldProtect передавал. Все еще ERROR_INVALID_ADDRESS. Завтра бы в обед, если будет время, обсудить кусок кода. Интересный момент получается. 6 минут назад, Garik66 сказал: И конечно к Xipho - но это уже по умолчанию, как само собой разумеющееся. Да-да-да... )) Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 9 октября, 2016 Автор Поделиться Опубликовано 9 октября, 2016 1 minute ago, Xipho said: Завтра бы в обед, если будет время, обсудить кусок кода. Интересный момент получается. Да-да-да... )) Вот я сам и офигеваю сижу, вроде бы до этого не сталкивался с подобным. В качестве костыля - читать кусками, но это бред, учитывая то что OpenProcess мне все права перед этим выдает. Ссылка на комментарий Поделиться на другие сайты Поделиться
Dino Опубликовано 10 октября, 2016 Поделиться Опубликовано 10 октября, 2016 Проблема скорее не в VirualProtectEx, а в том что ты в рабочем модуле попадаешь на зарезервированный кусок памяти ( MEM_RESERVE и только) на что ReadProcessMemory дает пинка под зад, но ведь ее нельзя за это осуждать, как бы ты повел на ее месте? Советую скопировать модуль по частям, то есть заголовки, секции и прочая лабуда Более простой и костыльный вариант это проверять каждую страницу памяти подопытного при помощи VirtualQueryEx и все что является MEM_COMMIT - копировать Я так полагаю ты дампер пишешь, тогда не буду предлагать вариант с CreateFile. 1 Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 10 октября, 2016 Автор Поделиться Опубликовано 10 октября, 2016 3 hours ago, Dino said: Проблема скорее не в VirualProtectEx, а в том что ты в рабочем модуле попадаешь на зарезервированный кусок памяти ( MEM_RESERVE и только) на что ReadProcessMemory дает пинка под зад, но ведь ее нельзя за это осуждать, как бы ты повел на ее месте? Советую скопировать модуль по частям, то есть заголовки, секции и прочая лабуда Более простой и костыльный вариант это проверять каждую страницу памяти подопытного при помощи VirtualQueryEx и все что является MEM_COMMIT - копировать Я так полагаю ты дампер пишешь, тогда не буду предлагать вариант с CreateFile. Вариант, конечно, да и смещения будет просто пересчитать, но меня больше интересует, нафига так сделали. Т.е. лично мне впервые такое в игре попадается. Ночью еще подумалось, что это могут быть господа репакеры, но не понимаю смысла в подобном "антидампе" в игре. 1 Ссылка на комментарий Поделиться на другие сайты Поделиться
gmz Опубликовано 10 октября, 2016 Поделиться Опубликовано 10 октября, 2016 пхах получается между хидером и 1 секцией есть дыра в 0x1000? значит там пакер какой то? а размер модуля из SizeOfImage? покажи еще скрин секций из cffexplorer 1 Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 10 октября, 2016 Автор Поделиться Опубликовано 10 октября, 2016 54 minutes ago, gmz said: пхах получается между хидером и 1 секцией есть дыра в 0x1000? значит там пакер какой то? а размер модуля из SizeOfImage? покажи еще скрин секций из cffexplorer Размер - 0х1AA000, точнее посмотрю уже дома - на маке сложновато. Пакер, кстати, тоже надо бы проверить - я все больше грешу на репакеров. Ссылка на комментарий Поделиться на другие сайты Поделиться
Dino Опубликовано 10 октября, 2016 Поделиться Опубликовано 10 октября, 2016 (изменено) а размер модуля из SizeOfImage? покажи еще скрин секций из cffexplorer с Sizeofimage все в порядке он учитывает эту зарезервированную область Изменено 10 октября, 2016 пользователем Dino Ссылка на комментарий Поделиться на другие сайты Поделиться
Dino Опубликовано 10 октября, 2016 Поделиться Опубликовано 10 октября, 2016 (изменено) Если предположить что загрузчик для каждой области резервирует память отдельно, то это все объясняется тем что адреса должны быть кратны 64кб, именно поэтому дистанция между заголовками и секциями 0xf000. Но это не точно Изменено 10 октября, 2016 пользователем Dino Ссылка на комментарий Поделиться на другие сайты Поделиться
gmz Опубликовано 10 октября, 2016 Поделиться Опубликовано 10 октября, 2016 3 часа назад, Dino сказал: сли предположить что загрузчик для каждой области резервирует память отдельно, то это все объясняется тем что адреса должны быть кратны 64кб, именно поэтому дистанция между заголовками и секциями 0xf000. Но это не точно в норм PE 4к выравнивание Ссылка на комментарий Поделиться на другие сайты Поделиться
Dino Опубликовано 10 октября, 2016 Поделиться Опубликовано 10 октября, 2016 48 минуты назад, gmz сказал: в норм PE 4к выравнивание Адрес при резервировании должен быть выровнен на 64к, а 4к это размер страницы при ее выделении Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 10 октября, 2016 Автор Поделиться Опубликовано 10 октября, 2016 Короче, пакера нет, но там Mono. Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 10 октября, 2016 Автор Поделиться Опубликовано 10 октября, 2016 Используя тайную технику костылирования, я на скорую руку набросал вот это: Spoiler proc GetBadPages uses ebx edx ecx edi,lpModule,lpOpt locals pID dd ? pHandle dd ? pMbi MEMORY_BASIC_INFORMATION ? rgnSize dd ? endAddr dd ? endl mov eax, [lpModule] mov eax, [eax + MODULEENTRY32.th32ProcessID] ; eax = Process ID mov [pID], eax invoke OpenProcess, PROCESS_QUERY_INFORMATION, 0, [pID] .if eax = 0 jmp .ERROR .endif mov [pHandle], eax ; Save opened process handle ; mov ebx, [lpModule] mov ecx, [ebx + MODULEENTRY32.modBaseAddr] ; ecx = Module Base Address mov [endAddr], ecx mov ebx, [ebx + MODULEENTRY32.modBaseSize] ; ebx = Module Base Size, in bytes add [endAddr], ebx ; endAddr = Module Base Address + Module Base Size .LOOP: push ecx ; Saving MBA lea edx, [pMbi] ; edx = address of MEMORY_BASIC_INFORMATION struct invoke VirtualQueryEx, [pHandle], ecx, edx, sizeof.MEMORY_BASIC_INFORMATION ; Trying to get info about the 1-st region .if eax = 0 jmp .ERROR .endif lea edx, [pMbi] mov eax, [edx + MEMORY_BASIC_INFORMATION.RegionSize] ; Getting region size, in bytes .if eax = 0 ; If it's zero - quit, we've got no access for some reason jmp .ERROR .endif mov [rgnSize], eax ; Saving current region size mov eax, [edx + MEMORY_BASIC_INFORMATION.State] ; Getting region state .if eax = MEM_RESERVE ; If it's MEM_RESERVE - BAM! Need to save dat mov eax, [lpOpt] lea eax, [eax + OPTION.ModuleBadPageList] .if dword [eax] = 0 ; The module's bad page list is empty pop ecx ; Restoring current region address mov [eax], ecx ; Saving it into buffer mov ebx, [rgnSize] mov [eax + 4], ebx ; Saving current region size next to it's address push ecx ; Saving ecx back to stack .else ; The module's bad page list is NOT empty pop ecx mov ebx,ecx ; Saving current region address to ebx push ecx mov ecx,OPTION_BAD_PAGES_BUF_SZ @@: .if dword [eax] = 0 ; If we've got an empty space mov [eax], ebx mov ebx, [rgnSize] mov [eax + 4], ebx jmp @f ; Save addr and size and exit .else ; Keep searching sub ecx, 8 ; 8 - 2 DWORDS, for addr and size .if ecx = 0 ; Reached the limit? jmp .ERROR .endif add eax, 8 ; Moving buffer 8 bytes forward jmp @b ; Back to trying .endif .endif .endif @@: pop ecx add ecx, [rgnSize] ; Increasing Module Base Address by current region size .if ecx >= [endAddr] ; Check if we have reached the limit jmp .EXIT .endif jmp .LOOP ; exit xor eax, eax ; Setting eax to zero - all fine .ERROR: dec eax jmp .RET .EXIT: .if [pHandle] <> 0 ; Have we opened the handle? invoke CloseHandle, [pHandle] ; Trying to close .if eax = 0 dec eax .endif .endif .RET: ret endp Кто хочет - читайте код и комментарии, я это в основном для себя оставил. Завтра, возможно, доделаю адекватное чтение, учитывая найденный мусор. PS: Надо будет поиграться с rep lodsd. Ссылка на комментарий Поделиться на другие сайты Поделиться
Рекомендуемые сообщения