Добрый день. Темы по форуму изучил, но есть неопределенности. Драйвер, мне нужно запустить поток в процессе (известен PID, процесс уже давно работает) Для этого: 1. ZwOpenProcess 2. VirtualAlloc (выделяем в целевойм процессе память) 3. Пишем туда свой "шел-код" (для примера - цепочка nop ) (это все ОК) Далее по логике создания потока в Ринг3 нужно сделать CreateRemoteThread. В ядре есть функция Код (Text): NTSYSAPI NTSTATUS NTAPI ZwCreateThread( OUT PHANDLE ThreadHandle, //понятно IN ACCESS_MASK DesiredAccess, //понятно IN POBJECT_ATTRIBUTES ObjectAttributes, //понятно IN HANDLE ProcessHandle, //понятно OUT PCLIENT_ID ClientId, //понятно IN PCONTEXT ThreadContext, IN PUSER_STACK UserStack, IN BOOLEAN CreateSuspended //понятно ); Интересуют параметры IN PCONTEXT ThreadContext, IN PUSER_STACK UserStack, А точнее как их заполнить. Но предварительно мне нужно выделить память для стека? Как заполнить структуры? Читал Руссиновича и Неббета, немного неясно...
Код (Text): CONTEXT context = {CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS | CONTEXT_FLOATING_POINT}; /* set the Eip for the child process to our child function */ ZwGetContextThread(NtCurrentThread(), &context); context.Eip = (ULONG)child_entry; MEMORY_BASIC_INFORMATION mbi; ZwQueryVirtualMemory(NtCurrentProcess(), (PVOID)context.Esp, MemoryBasicInformation, &mbi, sizeof mbi, 0); USER_STACK stack = {0, 0, (PCHAR)mbi.BaseAddress + mbi.RegionSize, mbi.BaseAddress, mbi.AllocationBase}; CLIENT_ID cid; /* create thread using the modified context and stack */ ZwCreateThread(&hThread, THREAD_ALL_ACCESS, &oa, hProcess, &cid, &context, &stack, TRUE); THREAD_BASIC_INFORMATION tbi; ZwQueryInformationThread(NtCurrentThread(), ThreadBasicInformation, &tbi, sizeof tbi, 0); PNT_TIB tib = (PNT_TIB)tbi.TebBaseAddress; ZwQueryInformationThread(hThread, ThreadBasicInformation, &tbi, sizeof tbi, 0); ZwWriteVirtualMemory(hProcess, tbi.TebBaseAddress, &tib->ExceptionList, sizeof tib->ExceptionList, 0); ZwResumeThread(hThread, 0); При желании переписываешь в кернел.
Если регистрация в CSR не нужна, то более чем хватит и этого (из ntdll.dll): Код (Text): NTSTATUS RtlCreateUserThread ( IN HANDLE Process, IN PSECURITY_DESCRIPTOR ThreadSecurityDescriptor OPTIONAL, IN BOOLEAN CreateSuspended, IN ULONG ZeroBits OPTIONAL, IN SIZE_T MaximumStackSize OPTIONAL, IN SIZE_T CommittedStackSize OPTIONAL, IN PUSER_THREAD_START_ROUTINE StartAddress, IN PVOID Parameter OPTIONAL, OUT PHANDLE Thread OPTIONAL, OUT PCLIENT_ID ClientId OPTIONAL);
А для чего нужна регистрация в CSR? Всмысле если ее нет, будет ли мой поток нормально работать в юзермодном приложении? (например цикл ) for (; Sleep(1000);
Да, вполне. Без регистрации в CSR не сможешь использовать такие вещи как CreateProcess(), CreateThread(), CreateRemoteThread() и ещё что-то там, сейчас не помню уже, в общем, всё то, что через вызов CSR выполняется.
Ну как бы по регистрации потока в CSR информации вполне достаточно на форумах, так что не думаю, что с этим будут какие-то проблемы у тебя.
Погуглил, CsrClientCallServer (использую пример из Неббета номер 6.2). Но проблема в том, что я создаю поток из драйвера, а эта штука в ntdll.dll
Библиотека ntdll.dll совершенно также доступна и в ядре. Если не ошибаюсь, она всегда идёт вторым модулем в списке.
Итак, проблема - CsrClientCallServer мне дает 0хС0000008 (STATUS_INVALID_HANDLE) Делаю так: Код (Text): ZwOpenProcess(&hProcess,PROCESS_ALL_ACCESS,&oa, &cid); // получаю хендл целевого процесса .. ZwAllocateVirtualMemory(hProcess, &stack.ExpandableStackBottom, 0, &AllocSize, MEM_RESERVE, PAGE_READWRITE); ...// и другие операции со стеком и тд... status = TrueZwCreateThread(&hThread, THREAD_ALL_ACCESS, NULL, hProcess, cid, &context, &stack, TRUE); // Поток создается. Если поставить простейший цикл и последний флаг False - то поток работает. InformCsrss(hProcess, hThread, cid ); // status = TrueZwResumeThread(hThread, 0); Функция информатирования InformCsrss: Код (Text): typedef struct _BASE_CREATETHREAD_MSG { HANDLE ThreadHandle; CLIENT_ID ClientId; } BASE_CREATETHREAD_MSG, *PBASE_CREATETHREAD_MSG; typedef ULONG CSR_API_NUMBER; typedef struct _CSR_CLIENTCONNECT_MSG { IN ULONG ServerDllIndex; IN OUT PVOID ConnectionInformation; IN OUT ULONG ConnectionInformationLength; } CSR_CLIENTCONNECT_MSG, *PCSR_CLIENTCONNECT_MSG; typedef struct _BASE_CREATEPROCESS_MSG { HANDLE ProcessHandle; HANDLE ThreadHandle; CLIENT_ID ClientId; ULONG Machine; CLIENT_ID DebuggerClientId; ULONG CreationFlags; ULONG VdmBinaryType; } BASE_CREATEPROCESS_MSG, *PBASE_CREATEPROCESS_MSG; typedef struct _BASE_API_MSG { PORT_MESSAGE h; union { CSR_API_CONNECTINFO ConnectionRequest; struct { PCSR_CAPTURE_HEADER CaptureBuffer; CSR_API_NUMBER ApiNumber; ULONG ReturnValue; ULONG Reserved; union { CSR_CLIENTCONNECT_MSG ClientConnect; BASE_CREATEPROCESS_MSG CreateProcess; BASE_CREATETHREAD_MSG CreateThread; ULONG ApiMessageData[0x98]; } u; }; }; } BASE_API_MSG, *PBASE_API_MSG; VOID InformCsrss(HANDLE hProcess, HANDLE hThread, PCLIENT_ID pcid) { BASE_API_MSG BaseApiMsg; PBASE_CREATETHREAD_MSG pBaseCreateThread; RtlZeroMemory(&BaseApiMsg,sizeof(BASE_API_MSG)); pBaseCreateThread = (PBASE_CREATETHREAD_MSG)&BaseApiMsg.u.CreateThread; pBaseCreateThread->ThreadHandle = hThread; pBaseCreateThread->ClientId.UniqueProcess = pcid->UniqueProcess; pBaseCreateThread->ClientId.UniqueThread = pcid->UniqueThread; DPRINT("CsrClientCallServer %x ",CsrClientCallServer(&BaseApiMsg, 0, 0x10001, 0x0C) ); } Где копать - не понятно. Смотрел DbgPrint-ом смещение pBaseCreateThread такие же (0х28). Заполняется так же - хеднл, PID, TID. Сделал юзермодную программку CreateRemoteThread (...), отлови в олли CsrClientCallServer. Константы такие же, первые 0х28 байт непонятно что, но если их обнулить то CsrClientCallServer все равно возвращает 0. Далее в буфере по смещению 0х28 идут хендл потока, PID, TID. Почему у меня в драйвере CsrClientCallServer возвращает STATUS_INVALID_HANDLE? Я подсовываю ему hThread...
Не уверен, но мне кажется проблема в том, что переменная под хендл у тебя в а.п. ядра расположена (стек ядра), а CSR её пытается использовать в контексте своего процесса. В общем, не знаю, попробуй выделить память под хендл потока в целевом процессе и аттачься к его а.п. на время вызова CSR. Других идей пока нет.