Передаётся родительским тредом, определён в статическом импорте, определяется динамически и вообще не понятно о чём вопрос.
klzlk Что по вашему произойдёт при выполнении инструкции Ret, если в стеке 0, Arg ? Ничего хорошего в стеке должен быть адрес (eip) возврата который кладется в стек когда выполняется инструкция call
Меня сейчас интересует один вопрос почему приложение падает с этим кодом ? Code (Text): DWORD WINAPI MyRemoteThread(LPVOID lpParam) { return 0; } Code (Text): SYSTEM_BASIC_INFORMATION SysInfo; NtStatus = NtQuerySystemInformation(SystemBasicInformation,&SysInfo,sizeof(SysInfo),NULL); if (NT_SUCCESS(NtStatus)) { // default stack size of remote thread DWORD CommittedStackSize = SysInfo.uPageSize; DWORD MaximumStackSize = SysInfo.uAllocationGranularity; // allocate reserve memory onto stack PVOID pStack = NULL; NtStatus = NtAllocateVirtualMemory(hProcess,&pStack,0,&MaximumStackSize,MEM_RESERVE,PAGE_READWRITE); if (NT_SUCCESS(NtStatus)) { // fill TEB INITIAL_TEB InitialTeb; InitialTeb.OldInitialTeb.OldStackBase = NULL; InitialTeb.OldInitialTeb.OldStackLimit = NULL; InitialTeb.StackAllocationBase = pStack; InitialTeb.StackBase = (PVOID)((DWORD)pStack + MaximumStackSize); pStack = (PVOID) ((DWORD)pStack + MaximumStackSize - CommittedStackSize); BOOLEAN GuardPage; if (MaximumStackSize > CommittedStackSize) { pStack = (PVOID) ((DWORD)pStack - SysInfo.uPageSize); CommittedStackSize = CommittedStackSize + SysInfo.uPageSize; GuardPage = TRUE; } else { GuardPage = FALSE; } // allocate committ memory onto stack NtStatus = NtAllocateVirtualMemory(hProcess,&pStack,0,&CommittedStackSize,MEM_COMMIT,PAGE_READWRITE); if (NT_SUCCESS(NtStatus)) { InitialTeb.StackLimit = pStack; // if page guarded if (GuardPage) { ULONG OldProtect; DWORD RegionSize = SysInfo.uPageSize; NtStatus = NtProtectVirtualMemory(hProcess,&pStack,&RegionSize,PAGE_GUARD | PAGE_READWRITE,&OldProtect); if (NT_SUCCESS(NtStatus)) { InitialTeb.StackLimit = (PVOID)((DWORD)InitialTeb.StackLimit - RegionSize); // Create an initial context for the new thread. CONTEXT ThreadContext; ThreadContext.Eax = 0L; ThreadContext.Ebx = 1L; ThreadContext.Ecx = 2L; ThreadContext.Edx = 3L; ThreadContext.Esi = 4L; ThreadContext.Edi = 5L; ThreadContext.Ebp = 0L; ThreadContext.SegGs = 0; ThreadContext.SegFs = 0x38; // KGDT_R3_TEB ThreadContext.SegEs = 0x20; // KGDT_R3_DATA; ThreadContext.SegDs = 0x20; // KGDT_R3_DATA; ThreadContext.SegSs = 0x20; // KGDT_R3_DATA; ThreadContext.SegCs = 0x18; // KGDT_R3_CODE; ThreadContext.EFlags = 0x200L; // force interrupts on, clear all else. ThreadContext.Esp = (DWORD)InitialTeb.StackBase; ThreadContext.Eip = (ULONG)MyRemoteThread; // thread function ThreadContext.ContextFlags = CONTEXT_FULL; ThreadContext.Esp -= sizeof(pSelfBaseAddress); // Parametr size to stack NtStatus = NtWriteVirtualMemory(hProcess,(PVOID)ThreadContext.Esp,(PVOID)&pSelfBaseAddress,sizeof(pSelfBaseAddress),NULL); if (NT_SUCCESS(NtStatus)) { ThreadContext.Esp -= sizeof(pSelfBaseAddress); // Reserve room for ret HANDLE hRemoteThread; CLIENT_ID ThreadClientId; NtStatus = NtCreateThread(&hRemoteThread,THREAD_ALL_ACCESS,&ObjectAttributes,hProcess,&ThreadClientId,&ThreadContext,&InitialTeb,TRUE); if (NT_SUCCESS(NtStatus)) { BASE_API_MSG BaseApiMsg; MyZeroMemory(&BaseApiMsg,sizeof(BASE_API_MSG),0); PBASE_CREATETHREAD_MSG pBaseCreateThread = (PBASE_CREATETHREAD_MSG)&BaseApiMsg.u.BaseCreateThread; pBaseCreateThread->hThread = hRemoteThread; pBaseCreateThread->ClientId = ThreadClientId; // inform client server subsystem of new thread in process NtStatus = CsrClientCallServer((PCSR_API_MSG)&BaseApiMsg,0,0x10001,0x0C); if (NT_SUCCESS(NtStatus)) { NtResumeThread(hRemoteThread,NULL); } NtClose(hRemoteThread); } } } } } } } а с этим не падает Code (Text): HANDLE hRem; NtStatus = RtlCreateUserThread(hProcess,NULL,FALSE,0,NULL,NULL,MyRemoteThread,pSelfBaseAddress,&hRem,NULL); // или CreateRemoteThread
984259h Call выполняется в стабе для пользовательских тредов(BaseThreadStart()): Code (Text): { try { if ( NtCurrentTeb()->NtTib.Version == OS2_VERSION ) { if ( !BaseRunningInServerProcess ) { CsrNewThread(); } } ExitThread((lpStartAddress)(lpParameter)); } except(UnhandledExceptionFilter( GetExceptionInformation() )) { if ( !BaseRunningInServerProcess ) { ExitProcess(GetExceptionCode()); } else { ExitThread(GetExceptionCode()); } } } В нэйтивных никаких стабов нет, стартап процедура непосредственно задаётся. И Ret в таком стеке передаст управление на 0:0, там память не выделена и #AV.
klzlk честно говоря в Вашем ответе решения не понял может у Вас есть пример, обертка на NtCreateThread только что бы стек и context были заполнены вручную без использования RtlpCreateStak и RtlInitializeContext. Хочется разобраться что в коде не правильно сделано.
klzlk так проще будет что бы удаленный поток вызвал какую нить фу-ю завершения (самого себя завершил что бы лишний раз не дергать RtlRemoteCall что повлечет за собой NtWriteVirtualMemory) что я и делал например находил адрес фу-и exitthread в этом потоке только почему то был облом так и не понял почему. я смотрел исходник ее там реализовано через получение и установку контекста.
984259h Легальный способ заполнить стек - использовать NtWriteVM. Да и права доступа одинаковы, как для записи, так и для аллокаций. А стек нужен полюбому - для доставки стартап апк. Можно без апк запилить(VF), но смысла я не вижу. И вообще что это за проблема с адресом возврата, зачем он нужен. Передайте управление на ExitThread/RtlExitUserThread(), либо вручную завершите.
klzlk у меня в удаленном потоке крутится цикл но в случае неудачи поток должен завершится без креша процесса вот с самого начала поставил фу-ю my_api.pExitThread(0) на ней вылетает код (Unhandled exception) не могу понять почему ...
984259h вы б уже давно почитале http://wasm.ru/forum/viewtopic.php?id=32181, законектились дебагером, поставили бряк и пронаблюдали чо там ваш кодез натворил = быстрей, не?)
ASMatic я это как раз и делал но ... происходит вызов my_api.pExitThread(0); далее вылетает на в адресе (ebp+73h) не выделенная память
ASMatic тут уже ситуация поинтересней я по хешам восстановил адреса апишек и сверил их с полученными адресами функцией GetProccAddress все сошлись с апишками в моей структуре (my_api) помимо адреса ExitThread вот почему и был провал блин не заметил все же адреса помимо одного и тот который нужен.
984259h Вам было бы проще описать чётко задачу, тогда возможно и запилить приличный код. А гадать над вашими приватными кодесами нет смысла.