как вернуться из RtlRemoteCall? пробую вызвать NtSetContextThread(-2, context) в конце вызванного кода - не восстанавливаются eax, edx, ecx Код (Text): include 'win32ax.inc' entry main .code proc main local hThread:DWORD invoke CreateThread, 0, 0, TestThread, 0, CREATE_SUSPENDED, 0 mov [hThread], eax invoke RtlRemoteCall, -1, [hThread], testcode, 1, NtSetContextThread, TRUE, TRUE invoke ResumeThread, [hThread] ret endp proc TestThread arg:DWORD invoke MessageBoxA, 0, "OK", "TestThread", 0 ret endp align 4 testcode: int3 ; for debug ;[esp+0] address of context saved by RtlRemoteCall ;[esp+4] NtSetContextThread address mov eax, [esp+4] push -2 ; GetCurrentThread() call eax int3 ; unreachable! section '.idata' import data readable writeable library kernel32,'KERNEL32.DLL',\ user32,'USER32.DLL',\ ntdll, 'NTDLL.DLL' include 'api\kernel32.inc' include 'api\user32.inc' import ntdll,\ NtSetContextThread, 'NtSetContextThread',\ RtlRemoteCall, 'RtlRemoteCall'
Есть траблы с восст. регистров на х64. Но здесь я вижу вроде х86 - GetCurrentThread возвращает псевдо хэндл -2, а вам нужен настоящий хэндл с правами THREAD_SET_CONTEXT для норм работы с натив функциями. Также вроде чтобы установить контекст тред должен быть замороженным.
GoldFinch Модель возврата из сервисов такова, что эти регистры не сохраняются, а используются при возврате(KiServiceExit(), в отличае от KiServiceExit2(), восстанавливающей полный трап-фрейм.) Используйте сервис NtContinue для восстановления контекста полностью. Текущий поток определяется локально константой (NtCurrentThread = -2).
Clerk Хм, а разве все регистры не сохраняются по [esp]? Ведь можно самому вручную восстановить. Да и вообще логичнее использовать шелкод который сам всё восстановит чем на глюко сервисы полагаться работающие через раз.
действительно, RtlRemoteCall меняет только eip и esp, так что контекст можно восстановить руками, но мне почему-то захотелось применить апи
не... чтото я не понимаю, как не трогая регистры восстановить eip и esp, если оба лежат в стеке разве что самомодификацией кода
GoldFinch Да что там восстанавливать... Упростил пример из старых закромов с исходниками для случая, когда два dword'а (оригинальный esp, за ним оригинальный eip) лежат на вершине стека: Код (Text): push eax mov eax,dword[esp+4] xchg eax,esp push dword[eax+8] mov esp,eax pop eax pop esp sub esp,4 ret
d2k9 Нисколько не через раз. Нормально возврат из сервисов быстрый посредством инструкции Sysexit, которая требует в регистрах Ecx и Edx параметры(адрес возврата и указатель на стек), регистр Eax возвращает статус. Никто не говорил что эти регистры должны сохраняться.
GoldFinch >как не трогая регистры восстановить eip и esp, если оба лежат в стеке iret для 2^6 моды d2k9 Нативные функции с псевдохендлами не работают, тред должен быть замороженным, траблы с восстановлением х64-регистров, некие "весёлости" чётко оговоренной в x64 конвенции вызовов, работающие через раз сервисы, инкрементирующийся счётчик загрузок невыгружаемых dll, сессионные рамки даже для глобальных межсессионно секций,.. Понятно, что людям свойственно ошибаться время от времени, но эта череда расхождений ужасна. Мы собираемся попросить тебя прекратить распространение дезинформации.
Sol_Ksacap IRET-фрейм является частью трап-фрейма и вынесен в контекст без изменений, спициально для возврата посредством Iretd. Тред необязательно должен быть заморожен.
Clerk Пропарсил бы наш пост до конца. Окей, в рамках ежегодного месячника инделюзионного восприятия: В первой части сообщения мы полусерьёзно предлагаем ТС воспользоваться инструкцией iret из многобитного юзермода для одновременного восстановления ss:rsp и cs:rip. (О трапфрейме ни слова не было сказано). Во второй части мы перечисляем суждения, которые считаем ошибочными. (Нет необходимости сообщать нам о том, что какие-то из них неверны – ведь именно об этом мы и говорим). Да простит нас GoldFinch за оффтоп.
Sol_Ksacap Вы утверждаете очевидные вещи. Эта структура(без смены кпл, когда стек не переключается): Код (Text): IRET_FRAME struct rEip PVOID ? rSegCs DWORD ? rEFlags DWORD ? IRET_FRAME ends Является частью контекста специально для загрузки этих регистров инструкцией Iret. Для автора это не имеет значения, так как контекст восстанавливается сразу и полнотью средствами ядра(NtContinue).
Clerk >Вы утверждаете очевидные вещи. Да, нельзя не согласится. И нам жаль, что определённый человек не может понять, о чём же мы говорим.