Re: Внедрение dll с помощью NtCreateThread
От: IID Россия  
Дата: 28.03.11 14:53
Оценка: +1
Здравствуйте, PotapovPV, Вы писали:

Антивирусы перехватывают гораздо глубже, в ядре. И прекрасно видят, что создаётся поток не в контексте процесса, вызывающего API. Замена WinAPI-шной функцию на Native-ную ничего не даст в плане обхода антивирусов. Но даст существенный гемморой. Нативные функции не регистрируют созданный поток в csrss. А значит бОльшая часть WinAPI будет недоступна (многие winapi функции проверяют, является ли поток win32-шным, обращаясь к csrss)
kalsarikännit
Внедрение dll с помощью NtCreateThread
От: PotapovPV  
Дата: 27.03.11 21:54
Оценка:
Доброго времени суток
Вычитал в Рихтере способ внедрения dll в адресное пространство с помощью функции CreateRemoteThread. В Windows 7 CreateRemoteThread передает управление NativeApi функции NtCreateThreadEx, которая перехватывается аналогом антивируса, в то время как NtCreateThread вызывается свободно...
Вопрос: можно ли напрямую вызвать NtCreateRemoteThread?
Я пытался подсоединить ntdll к проекту, и вызывать NtCreateRemoteThread напрямую, добился появления нового потока у целевого процесса в "счетчике потоков" диспетчера задач.
Подскажите, как можно заставить созданный поток выполнять код (конкретно — LoadLibrary)? Возможно, есть какой-то способ заставить CreateRemoteThread вызывать старую функцию NtCreateRemoteThread??
Заранее спасибо
native api ntcreateremotethread потоки
Re: Внедрение dll с помощью NtCreateThread
От: PotapovPV  
Дата: 28.03.11 08:20
Оценка:
PPV>Вопрос: можно ли напрямую вызвать NtCreateRemoteThread?
PPV>Я пытался подсоединить ntdll к проекту, и вызывать NtCreateRemoteThread напрямую, добился появления нового потока у целевого процесса в "счетчике потоков" диспетчера задач.
PPV>Подскажите, как можно заставить созданный поток выполнять код (конкретно — LoadLibrary)? Возможно, есть какой-то способ заставить CreateRemoteThread вызывать старую функцию NtCreateRemoteThread??
описАлся... Естественно — имею ввиду NtCreateThread
Насколько я понимаю, что бы вызвать LoadLibrary новым потоком, достаточно получить ее адрес и выставить EIP контекста нового потока на него? Подскажите, как, в таком случае, передать этой функции строку с параметром?
Re[2]: Внедрение dll с помощью NtCreateThread
От: _cb_  
Дата: 28.03.11 09:33
Оценка:
Здравствуйте, PotapovPV, Вы писали:

PPV>Насколько я понимаю, что бы вызвать LoadLibrary новым потоком, достаточно получить ее адрес и выставить EIP контекста нового потока на него? Подскажите, как, в таком случае, передать этой функции строку с параметром?


непонятно чо за проблемы ты решаешь? у Рихтера же полное описание есть (во всяким случает раньше было).

в качестве стартового адреса для CreateRemoteThread указываешь адрес LoadLibrary (благо он во всех процессах один и тот же). строку с именем dll пишешь в адресное пространство целевого процесса с помощью WriteProcessMemory. адрес этой строки в удаленном процессе передаешь в remote_thread_function с помощью CreateRemoteThread. еще какие-то детали нужны или осилишь дальше сам?

c SetContext и установкой eip лучше не связываться — нормально работать не будет.

если по каким-то причинам не подходит CreateRemoteThread юзай NtCreateRemoteThread.
Re[3]: Внедрение dll с помощью NtCreateThread
От: PotapovPV  
Дата: 28.03.11 19:49
Оценка:
Здравствуйте, _cb_, Вы писали:

__>непонятно чо за проблемы ты решаешь? у Рихтера же полное описание есть (во всяким случает раньше было).


Видимо, я недостаточно четко описал проблему: меня не устраивает вызов NtCreateThreadEx, который осуществляют такие функции как CreateRemoteThread и RtlCreateUserThread, задача стоит именно в вызове NtCreateThread, о чем Рихтер не упоминает.

__>если по каким-то причинам не подходит CreateRemoteThread юзай NtCreateRemoteThread.


К сожалению, о такой функции я первый раз слышу, ntdll ее не экспортирует. Где ее можно найти?
Re[2]: Внедрение dll с помощью NtCreateThread
От: PotapovPV  
Дата: 28.03.11 19:52
Оценка:
Здравствуйте, IID, Вы писали:

IID>Здравствуйте, PotapovPV, Вы писали:


IID>Антивирусы перехватывают гораздо глубже, в ядре. И прекрасно видят, что создаётся поток не в контексте процесса, вызывающего API. Замена WinAPI-шной функцию на Native-ную ничего не даст в плане обхода антивирусов. Но даст существенный гемморой. Нативные функции не регистрируют созданный поток в csrss. А значит бОльшая часть WinAPI будет недоступна (многие winapi функции проверяют, является ли поток win32-шным, обращаясь к csrss)


Собственно, я недаром написал "аналог антивируса": у меня простенький стенд, на котором перехватывается вызов NtCreateThreadEx и у меня стоит задача вызвать NtCreateThread. Очевидно, что реальный антивирусы действуют глубже.
Касательно регистрации потока в csrss есть пример у Неббета, однако, хотелось бы найти где-нибудь некоторое количество теории по этому поводу...
Можно ли где-нибудь найти пример создания контекста потока?
Re[4]: Внедрение dll с помощью NtCreateThread
От: _cb_  
Дата: 29.03.11 06:06
Оценка:
Здравствуйте, PotapovPV, Вы писали:

PPV>Видимо, я недостаточно четко описал проблему: меня не устраивает вызов NtCreateThreadEx, который осуществляют такие функции как CreateRemoteThread и RtlCreateUserThread, задача стоит именно в вызове NtCreateThread, о чем Рихтер не упоминает.


я уже давно это все не исследовал и чо и как сейчас сделано точно не знаю, но думаю что даже если ты будешь вызывать NtCreateThread, то этот метод все равно в конечном итоге вызовет NtCreateThreadEx.

__>>если по каким-то причинам не подходит CreateRemoteThread юзай NtCreateRemoteThread.

PPV>К сожалению, о такой функции я первый раз слышу, ntdll ее не экспортирует. Где ее можно найти?

ты сам про нее написал в исходном посте. на сколько я понимаю сейчас такой функции уже не существует, вроде бы она была в каких-то старых осях.

я не знаю какую именно задачу ты пытаешься решить, но может забить на все эти CreateRemoteThread и прописать свою dll в AppInitDlls?

если очень хочется поэкспериментировать с созданием удаленных потоков, то можешь попробовать заставить работать вариант с SetThreadContext. но там достаточно много возни, в том числе и с поддержкой x64. плюс есть предположение что метод ненадежный и может обвалить целевой процесс: http://blog.not-a-kernel-guy.com/2010/05/04/812
Re[5]: Внедрение dll с помощью NtCreateThread
От: ononim  
Дата: 29.03.11 10:34
Оценка:
PPV>>Видимо, я недостаточно четко описал проблему: меня не устраивает вызов NtCreateThreadEx, который осуществляют такие функции как CreateRemoteThread и RtlCreateUserThread, задача стоит именно в вызове NtCreateThread, о чем Рихтер не упоминает.
__>я уже давно это все не исследовал и чо и как сейчас сделано точно не знаю, но думаю что даже если ты будешь вызывать NtCreateThread, то этот метод все равно в конечном итоге вызовет NtCreateThreadEx.
Вообщето, как ни странно, скорее будет наоборот

__>>>если по каким-то причинам не подходит CreateRemoteThread юзай NtCreateRemoteThread.

PPV>>К сожалению, о такой функции я первый раз слышу, ntdll ее не экспортирует. Где ее можно найти?
__>ты сам про нее написал в исходном посте. на сколько я понимаю сейчас такой функции уже не существует, вроде бы она была в каких-то старых осях.
Не было таких.
Как много веселых ребят, и все делают велосипед...
Re[6]: Внедрение dll с помощью NtCreateThread
От: _cb_  
Дата: 29.03.11 11:07
Оценка:
Здравствуйте, ononim, Вы писали:

O>Вообщето, как ни странно, скорее будет наоборот


может и так... согласен что это выглядит странно...

__>>ты сам про нее написал в исходном посте. на сколько я понимаю сейчас такой функции уже не существует, вроде бы она была в каких-то старых осях.

O>Не было таких.

ok.
Re[6]: Внедрение dll с помощью NtCreateThread
От: PotapovPV  
Дата: 29.03.11 11:11
Оценка:
Здравствуйте, ononim, Вы писали:

O>Вообщето, как ни странно, скорее будет наоборот

Они не вызывают друг друга... Они независимы.
Однако, до Vista вызывается NtCreateThread, а начиная с Vista — NtCreateThreadEx

__>>>>если по каким-то причинам не подходит CreateRemoteThread юзай NtCreateRemoteThread.

PPV>>>К сожалению, о такой функции я первый раз слышу, ntdll ее не экспортирует. Где ее можно найти?
__>>ты сам про нее написал в исходном посте. на сколько я понимаю сейчас такой функции уже не существует, вроде бы она была в каких-то старых осях.
O>Не было таких.

Верно. В исходном посте я опечатался.

Нигде не найду найти информацию по созданию контекста процесса
Re[7]: Внедрение dll с помощью NtCreateThread
От: ononim  
Дата: 29.03.11 11:23
Оценка:
PPV>Верно. В исходном посте я опечатался.
PPV>Нигде не найду найти информацию по созданию контекста процесса
неужели у когото еще нету стыренных исходников винды?
Как много веселых ребят, и все делают велосипед...
Re: Внедрение dll с помощью NtCreateThread
От: PotapovPV  
Дата: 04.04.11 20:25
Оценка:
В результате вкуривания исходников win2k, Неббета и всех найденых примеров получил приведенный ниже код...
Пытаюсь создать поток, например, в одном из процессов Google Chrome, однако при вызове NtResumeThread процесс просто падает.
Большая просьба посмотреть и по возможности сообщить — что я забыл, или сделал неправильно

#include <windows.h>
#include "ntdll.h"
#include "MyCreateThread.h"



HANDLE
    APIENTRY
    MyCreateRemoteThread(    
                HANDLE hProcess,    
                LPSECURITY_ATTRIBUTES lpThreadAttributes,    
                DWORD dwStackSize,    
                LPTHREAD_START_ROUTINE lpStartAddress,    
                LPVOID lpParameter,        
                DWORD dwCreationFlags,    
                LPDWORD lpThreadId
                        )
{

    POBJECT_ATTRIBUTES pObja;
    OBJECT_ATTRIBUTES Obja;
    HANDLE Handle;
    CONTEXT ThreadContext;
    CLIENT_ID ClientId;
    ULONG i;
    PUSER_STACK pStack = new USER_STACK;
    NTSTATUS NtStatus;

    BaseCreateStack(hProcess, 4096, 1048576, pStack);    //значения получены экспериментально
                                                        //прогоном CreateRemoteThread под WinXP
                                                        //с отладчиком
    BaseInitializeContext(
        &ThreadContext,
        lpParameter,
        (PVOID)lpStartAddress,
        pStack->ExpandableStackBase,
        BaseContextTypeThread
        );

    pObja = BaseFormatObjectAttr(&Obja, lpThreadAttributes, NULL);
    NtStatus = NtCreateThread(
        &Handle,
        THREAD_ALL_ACCESS,
        pObja,
        hProcess,
        &ClientId,
        &ThreadContext,
        pStack,
        TRUE
        );    


    InformCsrss(hProcess, Handle, ULONG (ClientId.UniqueProcess), ULONG (ClientId.UniqueThread), ClientId);

    if (!NT_SUCCESS(NtStatus)) {
        NtStatus = (NTSTATUS)STATUS_NO_MEMORY;
    }
    else {

        if ( ARGUMENT_PRESENT(lpThreadId) ) {
            *lpThreadId = HandleToUlong(ClientId.UniqueThread);
        }

        if (!( dwCreationFlags & CREATE_SUSPENDED) ) {
            NtResumeThread(Handle,&i);
        }
    }

    return Handle;
}


NTSTATUS
BaseCreateStack(
                HANDLE hProcess,
                SIZE_T StackSize,
                SIZE_T MaximumStackSize,
                PUSER_STACK stack
                )
{
    PCH Stack;
    Stack = NULL;
    PULONG llong = new ULONG;
    NTSTATUS NtStatus;

    StackSize = ROUND_UP( StackSize, PAGE_SIZE);

    NtStatus = NtAllocateVirtualMemory(
        hProcess,
        (PVOID *)&Stack,
        0,
        &MaximumStackSize,
        MEM_RESERVE,
        PAGE_READWRITE
        );

    stack->ExpandableStackBottom = Stack;
    stack->ExpandableStackBase = Stack + MaximumStackSize;

    Stack += MaximumStackSize - StackSize;
    Stack -= PAGE_SIZE;
    StackSize += PAGE_SIZE;

    NtStatus = NtAllocateVirtualMemory(
        hProcess,
        (PVOID *)&Stack,
        0,
        &StackSize,
        MEM_COMMIT,
        PAGE_READWRITE
        );

    stack->ExpandableStackLimit = Stack;


    SIZE_T RegionSize = PAGE_SIZE;
    ULONG OldProtect;
    NtStatus = NtProtectVirtualMemory(
        hProcess,
        (PVOID *)&Stack,
        &RegionSize,
        PAGE_GUARD | PAGE_READWRITE,
        &OldProtect
        );

    stack->ExpandableStackLimit = (PVOID)((PUCHAR)stack->ExpandableStackLimit + RegionSize);
    stack->FixedStackBase = NULL;
    stack->FixedStackLimit = NULL;
    return NtStatus;
}




VOID
    BaseInitializeContext (
    OUT PCONTEXT Context,
    IN PVOID Parameter OPTIONAL,
    IN PVOID InitialPc OPTIONAL,
    IN PVOID InitialSp OPTIONAL,
    IN BASE_CONTEXT_TYPE ContextType
    )
{
    Context->Eax = (ULONG)InitialPc;
    Context->Ebx = (ULONG)Parameter;

    Context->SegGs = 0;
    Context->SegFs = 0x38;
    Context->SegEs = 0x20;
    Context->SegDs = 0x20;
    Context->SegSs = 0x20;
    Context->SegCs = 0x18;

    Context->EFlags = 0x3000;

    Context->Esp = (ULONG) InitialSp - 4;

    HMODULE hKernel32 = LoadLibrary(L"kernel32");
    DWORD procBaseThread = (DWORD)GetProcAddress(hKernel32, "BaseThreadInitThunk");

    Context->Eip = (ULONG) procBaseThread;

    Context->ContextFlags = CONTEXT_FULL;
    Context->Esp -= sizeof(Parameter); // Reserve room for ret address
}



VOID InformCsrss(HANDLE hProcess, HANDLE hThread, ULONG pid, ULONG tid, CLIENT_ID ClientId)
{
    struct THREAD_INFO
    {
        HANDLE hThread;
        CLIENT_ID id;
    };

    struct CSRSS_MESSAGE {
        ULONG Unknown1;
        ULONG Opcode;
        ULONG Status;
        ULONG Unknown2;
    };
    struct PORT_MESSAGE
    {
        ULONG u1;
        ULONG u2;

        union
        {
            CLIENT_ID ClientId;
            float DoNotUseThisField;
        };

        ULONG MessageId;

        union
        {
            ULONG ClientViewSize;
            ULONG CallbackId;
        };
    };
    struct
    {
        PORT_MESSAGE    PortMessage;
        CSRSS_MESSAGE    CsrssMessage;
        THREAD_INFO        ThreadInfo;
    }
    csrmsg = {
        {0},
        {0},
        {hThread, ClientId}};

    HMODULE hKernel32 = LoadLibrary(L"ntdll.dll");
    DWORD procLocalAlloc = (DWORD)GetProcAddress(hKernel32, "CsrClientCallServer");

    __asm
    {

        push 0x0C
        push 0x10001
        push NULL
        lea eax, csrmsg
        push eax
        mov  eax, procLocalAlloc
        call eax


    }
}

POBJECT_ATTRIBUTES BaseFormatObjectAttr(
                                        OUT POBJECT_ATTRIBUTES ObjectAttributes,
                                        IN PSECURITY_ATTRIBUTES SecurityAttributes,
                                        IN PUNICODE_STRING ObjectName)
{
    HANDLE RootDirectory;
    ULONG Attributes;
    PVOID SecurityDescriptor;

    if ( ARGUMENT_PRESENT(SecurityAttributes) ||
        ARGUMENT_PRESENT(ObjectName) ) 
    {
            RootDirectory = NULL;
            if ( SecurityAttributes ) 
            {
                Attributes = (SecurityAttributes->bInheritHandle ? OBJ_INHERIT : 0);
                SecurityDescriptor = SecurityAttributes->lpSecurityDescriptor;
            }
            else 
            {
                Attributes = 0;
                SecurityDescriptor = NULL;
            }

            if ( ARGUMENT_PRESENT(ObjectName) ) {
                Attributes |= OBJ_OPENIF;
            }
            InitializeObjectAttributes(
                ObjectAttributes,
                ObjectName,
                Attributes,
                RootDirectory,
                SecurityDescriptor
                );
            return ObjectAttributes;
    }
    else {
        return NULL;
    }
}
Re[2]: Внедрение dll с помощью NtCreateThread
От: ononim  
Дата: 04.04.11 20:28
Оценка:
стек падения процесса-жертвы неплохо бы увидеть
Как много веселых ребят, и все делают велосипед...
Re[3]: Внедрение dll с помощью NtCreateThread
От: PotapovPV  
Дата: 04.04.11 20:54
Оценка:
Здравствуйте, ononim, Вы писали:

O>стек падения процесса-жертвы неплохо бы увидеть


Я тесно общаюсь с дебаггерами всего лишь около месяца, поэтому не слишком силен в теории.
Подскажите, пожалуйста, метод получения стека процесса на момент падения
Re[4]: Внедрение dll с помощью NtCreateThread
От: ononim  
Дата: 04.04.11 21:00
Оценка:
O>>стек падения процесса-жертвы неплохо бы увидеть
PPV>Я тесно общаюсь с дебаггерами всего лишь около месяца, поэтому не слишком силен в теории.
PPV>Подскажите, пожалуйста, метод получения стека процесса на момент падения
Да какая тут теория.. Аттачите(F6) windbg к работающему процессу который в дальнейшем упадет, и когда он упадет — (вы это увидите) — пишете kv ffff
Как много веселых ребят, и все делают велосипед...
Re[5]: Внедрение dll с помощью NtCreateThread
От: PotapovPV  
Дата: 05.04.11 06:50
Оценка:
Здравствуйте, ononim, Вы писали:
O>Да какая тут теория.. Аттачите(F6) windbg к работающему процессу который в дальнейшем упадет, и когда он упадет — (вы это увидите) — пишете kv ffff

После падения получаем:
Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000000 ebx=01060000 ecx=00008000 edx=00000000 esi=cccccccc edi=cccccccc
eip=00000000 esp=03fb0000 ebp=cccccccc iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=0038  gs=0000             efl=00010246
00000000 ??              ???
0:005> kv ffff
  Memory  ChildEBP RetAddr  Args to Child              
WARNING: Frame IP not in any known module. Following frames may be wrong.
          cccccccc 00000000 00000000 00000000 00000000 0x0

Я неверно формирую контекст потока?
Re[6]: Внедрение dll с помощью NtCreateThread
От: ononim  
Дата: 05.04.11 07:42
Оценка:
PPV>Здравствуйте, ononim, Вы писали:
O>>Да какая тут теория.. Аттачите(F6) windbg к работающему процессу который в дальнейшем упадет, и когда он упадет — (вы это увидите) — пишете kv ffff
PPV>После падения получаем:
PPV>
PPV>Access violation - code c0000005 (first chance)
PPV>First chance exceptions are reported before any exception handling.
PPV>This exception may be expected and handled.
PPV>eax=00000000 ebx=01060000 ecx=00008000 edx=00000000 esi=cccccccc edi=cccccccc
PPV>eip=00000000 esp=03fb0000 ebp=cccccccc iopl=0         nv up ei pl zr na pe nc
PPV>cs=001b  ss=0023  ds=0023  es=0023  fs=0038  gs=0000             efl=00010246
PPV>00000000 ??              ???
PPV>0:005> kv ffff
PPV>  Memory  ChildEBP RetAddr  Args to Child              
PPV>WARNING: Frame IP not in any known module. Following frames may be wrong.
PPV>          cccccccc 00000000 00000000 00000000 00000000 0x0
PPV>

PPV>Я неверно формирую контекст потока?
Похоже на то. Кстати еще советую изучить как работает BaseThreadInitThunk — вполне возможно что ее поведение поменялось с тех пор как сорсы винды были сперты. К примеру (чисто гипотетически) может ей надо еще контекст на стек ложить.
Вобщем сделайте еще так — заатачьтесь windbg к процессу, поставьте бряк на BaseThreadInitThunk и посмотрите что произойдет когда BaseThreadInitThunk придет для вашего потока (если придет)
Как много веселых ребят, и все делают велосипед...
Re[7]: Внедрение dll с помощью NtCreateThread
От: PotapovPV  
Дата: 05.04.11 22:05
Оценка:
Здравствуйте, ononim, Вы писали:
O>Похоже на то. Кстати еще советую изучить как работает BaseThreadInitThunk — вполне возможно что ее поведение поменялось с тех пор как сорсы винды были сперты. К примеру (чисто гипотетически) может ей надо еще контекст на стек ложить.
Кажется, Ошибка в том, что я что-то перепутал именно с функцией: ума не приложу откуда я вынул этот BaseThreadInitThunk. Исходники винды говорят о BaseThreadStartThunk, которую я сейчас и пытаюсь найти...
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.