Внедрение dll c помощью NtCreateThread

Тема в разделе "WASM.BEGINNERS", создана пользователем PotapovPV, 28 мар 2011.

  1. PotapovPV

    PotapovPV New Member

    Публикаций:
    0
    Регистрация:
    28 мар 2011
    Сообщения:
    12
    Доброго времени суток
    Вычитал в Рихтере способ внедрения dll в адресное пространство с помощью функции CreateRemoteThread. В Windows 7 CreateRemoteThread передает управление NativeApi функции NtCreateThreadEx, которая перехватывается аналогом антивируса, в то время как NtCreateThread вызывается свободно...
    Вопрос: можно ли напрямую вызвать NtCreateThread?
    Я пытался подсоединить ntdll к проекту, и вызывать NtCreateThread напрямую, добился появления нового потока у целевого процесса в "счетчике потоков" диспетчера задач.
    Подскажите, как можно заставить созданный поток выполнять код (конкретно — LoadLibrary)? Возможно, есть какой-то способ заставить CreateRemoteThread вызывать старую функцию NtCreateThread??
    Заранее спасибо
     
  2. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.323
    вообще в Рихтере это написано... что за глупый вопрос?
     
  3. PotapovPV

    PotapovPV New Member

    Публикаций:
    0
    Регистрация:
    28 мар 2011
    Сообщения:
    12
    В Рихтере указан лишь способ заставить поток выполнять код с использованием WinAPI функции CreateRemoteThread. Каких-либо примеров, посвященных созданию потоков с помощью NativeAPI, кроме Неббета мне найти не удалось. Однако, оба примера Неббета не затрагивают создания потоков с пользовательской функцией.
    Моя просьба касалась именно NativeAPI - как передать NtCreateThread адрес выполняемой функции?
     
  4. PotapovPV

    PotapovPV New Member

    Публикаций:
    0
    Регистрация:
    28 мар 2011
    Сообщения:
    12
    Очаровательно
    Я так понимаю что для вызова LoadLibrary достаточно в контексте созданного потока выставить eip на адрес LoadLibrary? Подскажите, как ему в таком случае передавать строку с параметром. По логике, ее надо поместить в стек, однако к какому стеку будет обращаться загружаемая LoadLibrary свежесозданного потока?
     
  5. ntkernelspawn

    ntkernelspawn New Member

    Публикаций:
    0
    Регистрация:
    17 дек 2010
    Сообщения:
    61
    HANDLE hInjectThread;
    wchar_t szLibPath[MAX_PATH];
    DWORD dwLoadRes;

    LPVOID lpLibPath = ::VirtualAllocEx( hProcess, NULL, sizeof(szLibPath),MEM_COMMIT, PAGE_READWRITE );
    addressLoadLibraryW = GetProcAddress("kernel32.dll", "LoadLibraryW");

    //Validate lpLibPath
    //Validate addressLoadLibraryW

    status = NtCreateThreadEx(&hInjectThread, , , hProcess, addressLoadLibraryW, lpLibPath, FALSE, 0, 0, NULL);

    //Validate status

    while ( WaitForSingleObjectEx(hInjectThread, INFNITE, TRUE) != WAIT_OBJECT_0 );

    if ( ::GetExitCodeThread( hThread, &dwLoadRes ) ) {
    // check error in dwLoadRes
    }
    else {
    // ERROR LOADING
    }

    CloseHandle(hInjectThread);
    ::VirtualFreeEx( hProcess, lpLibPath, sizeof(szLibPath), MEM_RELEASE );
     
  6. PotapovPV

    PotapovPV New Member

    Публикаций:
    0
    Регистрация:
    28 мар 2011
    Сообщения:
    12
    Спасибо, но проблема состоит как раз в том, что бы вызвать NtCreateThread, не принимающий ни LPTHREAD_START_ROUTINE lpStartAddress, ни LPVOID lpParameter, из под семерки, а не NtCreateThreadEx.
     
  7. ASMatic

    ASMatic New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2010
    Сообщения:
    233
    PotapovPV
    вы еще тут? - бегом в гугль)
    ток сначала объясните - вот вы создаёте ветвь, что это такое в вашем понимании - Thread?
     
  8. ntkernelspawn

    ntkernelspawn New Member

    Публикаций:
    0
    Регистрация:
    17 дек 2010
    Сообщения:
    61
    PotapovPV
    https://wasm.ru/forum/viewtopic.php?id=21959
     
  9. qwe8013

    qwe8013 New Member

    Публикаций:
    0
    Регистрация:
    28 май 2009
    Сообщения:
    198
    PotapovPV
    Хотите через ntdll? Используйте RtlCreateUserThread, это удобнее.(параметры найдёте в гугле).
     
  10. PotapovPV

    PotapovPV New Member

    Публикаций:
    0
    Регистрация:
    28 мар 2011
    Сообщения:
    12
    qwe8013
    К сожалению, RtlCreateUserThread в итоге вызывает ZwCreateThreadEx, использования которого я стараюсь избежать.
    ASMatic
    Поверьте, я знаю что такое Thread. Также поверьте что я прочитал соответствующий раздел Рихтера и посвятил достаточное время гуглу.
    ntkernelspawn
    Спасибо, как-то эта тема прошла мимо меня... Будет разбирать паскаль
     
  11. ASMatic

    ASMatic New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2010
    Сообщения:
    233
    PotapovPV
    видимо я вас не понял...чем вам мешает lpStartAddressи и lpParameter в варианте с NtCreateThreadEx% он же также присутствует в NtCreateThread ток в другом виде.
     
  12. PotapovPV

    PotapovPV New Member

    Публикаций:
    0
    Регистрация:
    28 мар 2011
    Сообщения:
    12
    ASMatic
    И правда, не поняли :)
    Мне мешают не параметры, мне мешает функция NtCreateThreadEx, вызовы которой перехватываются. При этом - начиная с Висты вызов CreateRemoteThread приводит именно к вызову NtCreateThreadEx.
    NtCreateThread же в моем случае не перехватывается, поэтому вызывать надо именно ее. И названные Вами параметры передаются через стек с контекст... Вопрос как раз и состоит в том, как корректно сформировать эти самые контекст и стек. Бьюсь над проблемой уже несколько дней, но, видимо, чего-то недопонимаю - выделить стек не получается
     
  13. PotapovPV

    PotapovPV New Member

    Публикаций:
    0
    Регистрация:
    28 мар 2011
    Сообщения:
    12
    В результате вкуривания исходников win2k, Неббета и всех найденых примеров получил приведенный ниже код...
    Пытаюсь создать поток, например, в одном из процессов Google Chrome, однако при вызове NtResumeThread процесс просто падает.
    Большая просьба посмотреть и по возможности сообщить - что я забыл, или сделал неправильно

    Код (Text):
    1. #include <windows.h>
    2. #include "ntdll.h"
    3. #include "MyCreateThread.h"
    4.  
    5.  
    6.  
    7. HANDLE
    8.     APIENTRY
    9.     MyCreateRemoteThread(  
    10.                 HANDLE hProcess,   
    11.                 LPSECURITY_ATTRIBUTES lpThreadAttributes,  
    12.                 DWORD dwStackSize, 
    13.                 LPTHREAD_START_ROUTINE lpStartAddress, 
    14.                 LPVOID lpParameter,    
    15.                 DWORD dwCreationFlags, 
    16.                 LPDWORD lpThreadId
    17.                         )
    18. {
    19.  
    20.     POBJECT_ATTRIBUTES pObja;
    21.     OBJECT_ATTRIBUTES Obja;
    22.     HANDLE Handle;
    23.     CONTEXT ThreadContext;
    24.     CLIENT_ID ClientId;
    25.     ULONG i;
    26.     PUSER_STACK pStack = new USER_STACK;
    27.     NTSTATUS NtStatus;
    28.  
    29.     BaseCreateStack(hProcess, 4096, 1048576, pStack);   //значения получены экспериментально
    30.                                                         //прогоном CreateRemoteThread под WinXP
    31.                                                         //с отладчиком
    32.     BaseInitializeContext(
    33.         &ThreadContext,
    34.         lpParameter,
    35.         (PVOID)lpStartAddress,
    36.         pStack->ExpandableStackBase,
    37.         BaseContextTypeThread
    38.         );
    39.  
    40.     pObja = BaseFormatObjectAttr(&Obja, lpThreadAttributes, NULL);
    41.     NtStatus = NtCreateThread(
    42.         &Handle,
    43.         THREAD_ALL_ACCESS,
    44.         pObja,
    45.         hProcess,
    46.         &ClientId,
    47.         &ThreadContext,
    48.         pStack,
    49.         TRUE
    50.         ); 
    51.  
    52.  
    53.     InformCsrss(hProcess, Handle, ULONG (ClientId.UniqueProcess), ULONG (ClientId.UniqueThread), ClientId);
    54.  
    55.     if (!NT_SUCCESS(NtStatus)) {
    56.         NtStatus = (NTSTATUS)STATUS_NO_MEMORY;
    57.     }
    58.     else {
    59.  
    60.         if ( ARGUMENT_PRESENT(lpThreadId) ) {
    61.             *lpThreadId = HandleToUlong(ClientId.UniqueThread);
    62.         }
    63.  
    64.         if (!( dwCreationFlags & CREATE_SUSPENDED) ) {
    65.             NtResumeThread(Handle,&i);
    66.         }
    67.     }
    68.  
    69.     return Handle;
    70. }
    71.  
    72.  
    73. NTSTATUS
    74. BaseCreateStack(
    75.                 HANDLE hProcess,
    76.                 SIZE_T StackSize,
    77.                 SIZE_T MaximumStackSize,
    78.                 PUSER_STACK stack
    79.                 )
    80. {
    81.     PCH Stack;
    82.     Stack = NULL;
    83.     PULONG llong = new ULONG;
    84.     NTSTATUS NtStatus;
    85.  
    86.     StackSize = ROUND_UP( StackSize, PAGE_SIZE);
    87.  
    88.     NtStatus = NtAllocateVirtualMemory(
    89.         hProcess,
    90.         (PVOID *)&Stack,
    91.         0,
    92.         &MaximumStackSize,
    93.         MEM_RESERVE,
    94.         PAGE_READWRITE
    95.         );
    96.  
    97.     stack->ExpandableStackBottom = Stack;
    98.     stack->ExpandableStackBase = Stack + MaximumStackSize;
    99.  
    100.     Stack += MaximumStackSize - StackSize;
    101.     Stack -= PAGE_SIZE;
    102.     StackSize += PAGE_SIZE;
    103.  
    104.     NtStatus = NtAllocateVirtualMemory(
    105.         hProcess,
    106.         (PVOID *)&Stack,
    107.         0,
    108.         &StackSize,
    109.         MEM_COMMIT,
    110.         PAGE_READWRITE
    111.         );
    112.  
    113.     stack->ExpandableStackLimit = Stack;
    114.  
    115.  
    116.     SIZE_T RegionSize = PAGE_SIZE;
    117.     ULONG OldProtect;
    118.     NtStatus = NtProtectVirtualMemory(
    119.         hProcess,
    120.         (PVOID *)&Stack,
    121.         &RegionSize,
    122.         PAGE_GUARD | PAGE_READWRITE,
    123.         &OldProtect
    124.         );
    125.  
    126.     stack->ExpandableStackLimit = (PVOID)((PUCHAR)stack->ExpandableStackLimit + RegionSize);
    127.     stack->FixedStackBase = NULL;
    128.     stack->FixedStackLimit = NULL;
    129.     return NtStatus;
    130. }
    131.  
    132.  
    133.  
    134.  
    135. VOID
    136.     BaseInitializeContext (
    137.     OUT PCONTEXT Context,
    138.     IN PVOID Parameter OPTIONAL,
    139.     IN PVOID InitialPc OPTIONAL,
    140.     IN PVOID InitialSp OPTIONAL,
    141.     IN BASE_CONTEXT_TYPE ContextType
    142.     )
    143. {
    144.     Context->Eax = (ULONG)InitialPc;
    145.     Context->Ebx = (ULONG)Parameter;
    146.  
    147.     Context->SegGs = 0;
    148.     Context->SegFs = 0x38;
    149.     Context->SegEs = 0x20;
    150.     Context->SegDs = 0x20;
    151.     Context->SegSs = 0x20;
    152.     Context->SegCs = 0x18;
    153.  
    154.     Context->EFlags = 0x3000;
    155.  
    156.     Context->Esp = (ULONG) InitialSp - 4;
    157.  
    158.     HMODULE hKernel32 = LoadLibrary(L"kernel32");
    159.     DWORD procBaseThread = (DWORD)GetProcAddress(hKernel32, "BaseThreadInitThunk");
    160.  
    161.     Context->Eip = (ULONG) procBaseThread;
    162.  
    163.     Context->ContextFlags = CONTEXT_FULL;
    164.     Context->Esp -= sizeof(Parameter); // Reserve room for ret address
    165. }
    166.  
    167.  
    168.  
    169. VOID InformCsrss(HANDLE hProcess, HANDLE hThread, ULONG pid, ULONG tid, CLIENT_ID ClientId)
    170. {
    171.     struct THREAD_INFO
    172.     {
    173.         HANDLE hThread;
    174.         CLIENT_ID id;
    175.     };
    176.  
    177.     struct CSRSS_MESSAGE {
    178.         ULONG Unknown1;
    179.         ULONG Opcode;
    180.         ULONG Status;
    181.         ULONG Unknown2;
    182.     };
    183.     struct PORT_MESSAGE
    184.     {
    185.         ULONG u1;
    186.         ULONG u2;
    187.  
    188.         union
    189.         {
    190.             CLIENT_ID ClientId;
    191.             float DoNotUseThisField;
    192.         };
    193.  
    194.         ULONG MessageId;
    195.  
    196.         union
    197.         {
    198.             ULONG ClientViewSize;
    199.             ULONG CallbackId;
    200.         };
    201.     };
    202.     struct
    203.     {
    204.         PORT_MESSAGE    PortMessage;
    205.         CSRSS_MESSAGE    CsrssMessage;
    206.         THREAD_INFO        ThreadInfo;
    207.     }
    208.     csrmsg = {
    209.         {0},
    210.         {0},
    211.         {hThread, ClientId}};
    212.  
    213.     HMODULE hKernel32 = LoadLibrary(L"ntdll.dll");
    214.     DWORD procLocalAlloc = (DWORD)GetProcAddress(hKernel32, "CsrClientCallServer");
    215.  
    216.     __asm
    217.     {
    218.  
    219.         push 0x0C
    220.         push 0x10001
    221.         push NULL
    222.         lea eax, csrmsg
    223.         push eax
    224.         mov  eax, procLocalAlloc
    225.         call eax
    226.  
    227.  
    228.     }
    229. }
    230.  
    231. POBJECT_ATTRIBUTES BaseFormatObjectAttr(
    232.                                         OUT POBJECT_ATTRIBUTES ObjectAttributes,
    233.                                         IN PSECURITY_ATTRIBUTES SecurityAttributes,
    234.                                         IN PUNICODE_STRING ObjectName)
    235. {
    236.     HANDLE RootDirectory;
    237.     ULONG Attributes;
    238.     PVOID SecurityDescriptor;
    239.  
    240.     if ( ARGUMENT_PRESENT(SecurityAttributes) ||
    241.         ARGUMENT_PRESENT(ObjectName) )
    242.     {
    243.             RootDirectory = NULL;
    244.             if ( SecurityAttributes )
    245.             {
    246.                 Attributes = (SecurityAttributes->bInheritHandle ? OBJ_INHERIT : 0);
    247.                 SecurityDescriptor = SecurityAttributes->lpSecurityDescriptor;
    248.             }
    249.             else
    250.             {
    251.                 Attributes = 0;
    252.                 SecurityDescriptor = NULL;
    253.             }
    254.  
    255.             if ( ARGUMENT_PRESENT(ObjectName) ) {
    256.                 Attributes |= OBJ_OPENIF;
    257.             }
    258.             InitializeObjectAttributes(
    259.                 ObjectAttributes,
    260.                 ObjectName,
    261.                 Attributes,
    262.                 RootDirectory,
    263.                 SecurityDescriptor
    264.                 );
    265.             return ObjectAttributes;
    266.     }
    267.     else {
    268.         return NULL;
    269.     }
    270. }
     
  14. ASMatic

    ASMatic New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2010
    Сообщения:
    233
    PotapovPV
    код не рассматривал, но NtStatus видать для того чтобы его проверять.)
    пробежался бегло - не вижу как вы туда сам код треда напрвляете, поставте инт3 на входе в тред (lpStartAddress)
    и тогда резюмайте. если падает - посмотрите что по адресу lpStartAddress находиться, мож куда-то "поплыли" указатели.
     
  15. PotapovPV

    PotapovPV New Member

    Публикаций:
    0
    Регистрация:
    28 мар 2011
    Сообщения:
    12
    ASMatic
    NtStatus везде в порядке.
    Ошибку, кажется, нашел: не знаю, откуда я выкопал имя "BaseThreadInitThunk", однако свежесозданному треду, судя по исходникам винды, передается не оно, а "BaseThreadStartThunk". Именно он и передает треду код и параметры, адреса которых "прячутся" в регистрах eax и ebx
     
  16. PotapovPV

    PotapovPV New Member

    Публикаций:
    0
    Регистрация:
    28 мар 2011
    Сообщения:
    12
    Вопрос решен для Win XP