RtlCreateUserThread vs CreateRemoteThread

Тема в разделе "WASM.WIN32", создана пользователем 984259h, 2 июл 2011.

  1. 984259h

    984259h New Member

    Публикаций:
    0
    Регистрация:
    25 авг 2007
    Сообщения:
    194
    Какая принципиальная разница между RtlCreateUserThread и CreateRemoteThread.
    Вопрос состоит в том что есть машина на ней XP SP3 неком процессе создаю функцией CreateRemoteThread удаленный поток все ок.
    Потом создаю этот же поток функцией RtlCreateUserThread процесс начинает есть 50% процессорного времени и еще 50% есть csrss ? Может при RtlCreateUserThread надо делать уведомление ?
    В то время на Viste и Seven обе функции (RtlCreateUserThread и CreateRemoteThread ) отрабатывают нормально
     
  2. 984259h

    984259h New Member

    Публикаций:
    0
    Регистрация:
    25 авг 2007
    Сообщения:
    194
    вот исходник с винды правда 2000
    Код (Text):
    1. HANDLE
    2. APIENTRY
    3. CreateRemoteThread(
    4.     HANDLE hProcess,
    5.     LPSECURITY_ATTRIBUTES lpThreadAttributes,
    6.     DWORD dwStackSize,
    7.     LPTHREAD_START_ROUTINE lpStartAddress,
    8.     LPVOID lpParameter,
    9.     DWORD dwCreationFlags,
    10.     LPDWORD lpThreadId
    11.     )
    12.  
    13. /*++
    14.  
    15. Routine Description:
    16.  
    17.     A thread object can be created to execute within the address space of the
    18.     another process using CreateRemoteThread.
    19.  
    20.     Creating a thread causes a new thread of execution to begin in the address
    21.     space of the current process. The thread has access to all objects opened
    22.     by the process.
    23.  
    24.     The thread begins executing at the address specified by the StartAddress
    25.     parameter. If the thread returns from this procedure, the results are
    26.     un-specified.
    27.  
    28.     The thread remains in the system until it has terminated and
    29.     all handles to the thread
    30.     have been closed through a call to CloseHandle.
    31.  
    32.     When a thread terminates, it attains a state of signaled satisfying all
    33.     waits on the object.
    34.  
    35.     In addition to the STANDARD_RIGHTS_REQUIRED access flags, the following
    36.     object type specific access flags are valid for thread objects:
    37.  
    38.         - THREAD_QUERY_INFORMATION - This access is required to read
    39.           certain information from the thread object.
    40.  
    41.         - SYNCHRONIZE - This access is required to wait on a thread
    42.           object.
    43.  
    44.         - THREAD_GET_CONTEXT - This access is required to read the
    45.           context of a thread using GetThreadContext.
    46.  
    47.         - THREAD_SET_CONTEXT - This access is required to write the
    48.           context of a thread using SetThreadContext.
    49.  
    50.         - THREAD_SUSPEND_RESUME - This access is required to suspend or
    51.           resume a thread using SuspendThread or ResumeThread.
    52.  
    53.         - THREAD_ALL_ACCESS - This set of access flags specifies all of
    54.           the possible access flags for a thread object.
    55.  
    56. Arguments:
    57.  
    58.     hProcess - Supplies the handle to the process in which the thread is
    59.         to be create in.
    60.  
    61.     lpThreadAttributes - An optional parameter that may be used to specify
    62.         the attributes of the new thread.  If the parameter is not
    63.         specified, then the thread is created without a security
    64.         descriptor, and the resulting handle is not inherited on process
    65.         creation.
    66.  
    67.     dwStackSize - Supplies the size in bytes of the stack for the new thread.
    68.         A value of zero specifies that the thread's stack size should be
    69.         the same size as the stack size of the first thread in the process.
    70.         This size is specified in the application's executable file.
    71.  
    72.     lpStartAddress - Supplies the starting address of the new thread.  The
    73.         address is logically a procedure that never returns and that
    74.         accepts a single 32-bit pointer argument.
    75.  
    76.     lpParameter - Supplies a single parameter value passed to the thread.
    77.  
    78.     dwCreationFlags - Supplies additional flags that control the creation
    79.         of the thread.
    80.  
    81.         dwCreationFlags Flags:
    82.  
    83.         CREATE_SUSPENDED - The thread is created in a suspended state.
    84.             The creator can resume this thread using ResumeThread.
    85.             Until this is done, the thread will not begin execution.
    86.  
    87.     lpThreadId - Returns the thread identifier of the thread.  The
    88.         thread ID is valid until the thread terminates.
    89.  
    90. Return Value:
    91.  
    92.     NON-NULL - Returns a handle to the new thread.  The handle has full
    93.         access to the new thread and may be used in any API that
    94.         requires a handle to a thread object.
    95.  
    96.     NULL - The operation failed. Extended error status is available
    97.         using GetLastError.
    98.  
    99. --*/
    100.  
    101. {
    102.     NTSTATUS Status;
    103.     OBJECT_ATTRIBUTES Obja;
    104.     POBJECT_ATTRIBUTES pObja;
    105.     HANDLE Handle;
    106.     CONTEXT ThreadContext;
    107.     INITIAL_TEB InitialTeb;
    108.     CLIENT_ID ClientId;
    109.     ULONG i;
    110.  
    111. #if !defined(BUILD_WOW6432)
    112.     BASE_API_MSG m;
    113.     PBASE_CREATETHREAD_MSG a = (PBASE_CREATETHREAD_MSG)&m.u.CreateThread;
    114. #endif
    115.  
    116. #if defined(WX86) || defined(_AXP64_)
    117.     BOOL bWx86 = FALSE;
    118.     HANDLE Wx86Info;
    119.     PWX86TIB Wx86Tib;
    120. #endif
    121.  
    122.  
    123.  
    124.     //
    125.     // Allocate a stack for this thread in the address space of the target
    126.     // process.
    127.     //
    128.  
    129.     Status = BaseCreateStack(
    130.                 hProcess,
    131.                 dwStackSize,
    132.                 0L,
    133.                 &InitialTeb
    134.                 );
    135.  
    136.     if ( !NT_SUCCESS(Status) ) {
    137.         BaseSetLastNTError(Status);
    138.         return NULL;
    139.         }
    140.  
    141.     //
    142.     // Create an initial context for the new thread.
    143.     //
    144.  
    145.     BaseInitializeContext(
    146.         &ThreadContext,
    147.         lpParameter,
    148.         (PVOID)lpStartAddress,
    149.         InitialTeb.StackBase,
    150.         BaseContextTypeThread
    151.         );
    152.  
    153.     pObja = BaseFormatObjectAttributes(&Obja,lpThreadAttributes,NULL);
    154.  
    155.  
    156.     Status = NtCreateThread(
    157.                 &Handle,
    158.                 THREAD_ALL_ACCESS,
    159.                 pObja,
    160.                 hProcess,
    161.                 &ClientId,
    162.                 &ThreadContext,
    163.                 &InitialTeb,
    164.                 TRUE
    165.                 );
    166.     if (!NT_SUCCESS(Status)) {
    167.         BaseFreeThreadStack(hProcess,NULL, &InitialTeb);
    168.         BaseSetLastNTError(Status);
    169.         return NULL;
    170.         }
    171.  
    172.  
    173.  
    174.     try {
    175.  
    176.  
    177. #if defined(WX86) || defined(_AXP64_)
    178.  
    179.         //
    180.         // Check the Target Processes to see if this is a Wx86 process
    181.         //
    182.         Status = NtQueryInformationProcess(hProcess,
    183.                                            ProcessWx86Information,
    184.                                            &Wx86Info,
    185.                                            sizeof(Wx86Info),
    186.                                            NULL
    187.                                            );
    188.         if (!NT_SUCCESS(Status)) {
    189.             leave;
    190.             }
    191.  
    192.         Wx86Tib = (PWX86TIB)NtCurrentTeb()->Vdm;
    193.  
    194.         //
    195.         // if Wx86 process, setup for emulation
    196.         //
    197.         if ((ULONG_PTR)Wx86Info == sizeof(WX86TIB)) {
    198.  
    199.             //
    200.             // create a WX86Tib and initialize it's Teb->Vdm.
    201.             //
    202.             Status = BaseCreateWx86Tib(hProcess,
    203.                                        Handle,
    204.                                        (ULONG)((ULONG_PTR)lpStartAddress),
    205.                                        dwStackSize,
    206.                                        0L,
    207.                                        (Wx86Tib &&
    208.                                         Wx86Tib->Size == sizeof(WX86TIB) &&
    209.                                         Wx86Tib->EmulateInitialPc)
    210.                                        );
    211.             if (!NT_SUCCESS(Status)) {
    212.                 leave;
    213.                 }
    214.  
    215.             bWx86 = TRUE;
    216.  
    217.             }
    218.         else if (Wx86Tib && Wx86Tib->EmulateInitialPc) {
    219.  
    220.             //
    221.             // if not Wx86 process, and caller wants to call x86 code in that
    222.             // process, fail the call.
    223.             //
    224.             Status = STATUS_ACCESS_DENIED;
    225.             leave;
    226.  
    227.             }
    228.  
    229. #endif  // WX86
    230.  
    231.  
    232.         //
    233.         // Call the Windows server to let it know about the
    234.         // process.
    235.         //
    236.         if ( !BaseRunningInServerProcess ) {
    237.  
    238. #if defined(BUILD_WOW6432)
    239.             Status = CsrBasepCreateThread(Handle,
    240.                                           ClientId
    241.                                           );
    242. #else
    243.             a->ThreadHandle = Handle;
    244.             a->ClientId = ClientId;
    245.             CsrClientCallServer( (PCSR_API_MSG)&m,
    246.                                  NULL,
    247.                                  CSR_MAKE_API_NUMBER( BASESRV_SERVERDLL_INDEX,
    248.                                                       BasepCreateThread
    249.                                                     ),
    250.                                  sizeof( *a )
    251.                                );
    252.  
    253.             Status = m.ReturnValue;
    254. #endif
    255.         }
    256.  
    257.         else {
    258.             if (hProcess != NtCurrentProcess()) {
    259.                 CSRREMOTEPROCPROC ProcAddress;
    260.                 ProcAddress = (CSRREMOTEPROCPROC)GetProcAddress(
    261.                                                     GetModuleHandleA("csrsrv"),
    262.                                                     "CsrCreateRemoteThread"
    263.                                                     );
    264.                 if (ProcAddress) {
    265.                     Status = (ProcAddress)(Handle, &ClientId);
    266.                     }
    267.                 }
    268.             }
    269.  
    270.  
    271.         if (!NT_SUCCESS(Status)) {
    272.             Status = (NTSTATUS)STATUS_NO_MEMORY;
    273.             }
    274.         else {
    275.  
    276.             if ( ARGUMENT_PRESENT(lpThreadId) ) {
    277.                 *lpThreadId = HandleToUlong(ClientId.UniqueThread);
    278.                 }
    279.  
    280.             if (!( dwCreationFlags & CREATE_SUSPENDED) ) {
    281.                 NtResumeThread(Handle,&i);
    282.                 }
    283.             }
    284.  
    285.         }
    286.     finally {
    287.         if (!NT_SUCCESS(Status)) {
    288.             BaseFreeThreadStack(hProcess,
    289.                                 Handle,
    290.                                 &InitialTeb
    291.                                 );
    292.  
    293.             NtTerminateThread(Handle, Status);
    294.             NtClose(Handle);
    295.             BaseSetLastNTError(Status);
    296.             Handle = NULL;
    297.             }
    298.         }
    299.  
    300.  
    301.     return Handle;
    302.  
    303. }
    и собственно RtlCreateUserThread
    Код (Text):
    1. NTSTATUS
    2. RtlCreateUserThread(
    3.     IN HANDLE Process,
    4.     IN PSECURITY_DESCRIPTOR ThreadSecurityDescriptor OPTIONAL,
    5.     IN BOOLEAN CreateSuspended,
    6.     IN ULONG ZeroBits OPTIONAL,
    7.     IN SIZE_T MaximumStackSize OPTIONAL,
    8.     IN SIZE_T CommittedStackSize OPTIONAL,
    9.     IN PUSER_THREAD_START_ROUTINE StartAddress,
    10.     IN PVOID Parameter OPTIONAL,
    11.     OUT PHANDLE Thread OPTIONAL,
    12.     OUT PCLIENT_ID ClientId OPTIONAL
    13.     )
    14.  
    15. /*++
    16.  
    17. Routine Description:
    18.  
    19.     This function creates a user mode thread in a user process.  The caller
    20.     specifies the attributes of the new thread.  A handle to the thread, along
    21.     with its Client Id are returned to the caller.
    22.  
    23. Arguments:
    24.  
    25.     Process - Handle to the target process in which to create the new thread.
    26.  
    27.     ThreadSecurityDescriptor - An optional pointer to the Security Descriptor
    28.         give to the new thread.
    29.  
    30.     CreateSuspended - A boolean parameter that specifies whether or not the new
    31.         thread is to be created suspended or not.  If TRUE, the new thread
    32.         will be created with an initial suspend count of 1.  If FALSE then
    33.         the new thread will be ready to run when this call returns.
    34.  
    35.     ZeroBits - This parameter is passed to the virtual memory manager
    36.         when the stack is allocated.  Stacks are always allocated with the
    37.         MEM_TOP_DOWN allocation attribute.
    38.  
    39.     MaximumStackSize - This is the maximum size of the stack.  This size
    40.         will be rounded up to the next highest page boundary.  If zero is
    41.         specified, then the default size will be 64K bytes.
    42.  
    43.     CommittedStackSize - This is the initial committed size of the stack.  This
    44.         size is rounded up to the next highest page boundary and then an
    45.         additional page is added for the guard page.  The resulting size
    46.         will then be commited and the guard page protection initialized
    47.         for the last committed page in the stack.
    48.  
    49.     StartAddress - The initial starting address of the thread.
    50.  
    51.     Parameter - An optional pointer to a 32-bit pointer parameter that is
    52.         passed as a single argument to the procedure at the start address
    53.         location.
    54.  
    55.     Thread - An optional pointer that, if specified, points to a variable that
    56.         will receive the handle of the new thread.
    57.  
    58.     ClientId - An optional pointer that, if specified, points to a variable
    59.         that will receive the Client Id of the new thread.
    60.  
    61. Return Value:
    62.  
    63.     TBS
    64.  
    65. --*/
    66.  
    67. {
    68.     NTSTATUS Status;
    69.     CONTEXT ThreadContext;
    70.     OBJECT_ATTRIBUTES ObjectAttributes;
    71.     INITIAL_TEB InitialTeb;
    72.     HANDLE ThreadHandle;
    73.     CLIENT_ID ThreadClientId;
    74.  
    75.     //
    76.     // Allocate a stack for this thread in the address space of the target
    77.     // process.
    78.     //
    79.  
    80.     Status = RtlpCreateStack( Process,
    81.                               MaximumStackSize,
    82.                               CommittedStackSize,
    83.                               ZeroBits,
    84.                               &InitialTeb
    85.                             );
    86.     if ( !NT_SUCCESS( Status ) ) {
    87.         return( Status );
    88.         }
    89.  
    90.     //
    91.     // Create an initial context for the new thread.
    92.     //
    93.  
    94.  
    95.     RtlInitializeContext( Process,
    96.                           &ThreadContext,
    97.                           Parameter,
    98.                           (PVOID)StartAddress,
    99.                           InitialTeb.StackBase
    100.                         );
    101.  
    102.     //
    103.     // Now create a thread in the target process.  The new thread will
    104.     // not have a name and its handle will not be inherited by other
    105.     // processes.
    106.     //
    107.  
    108.     InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL,
    109.                                 ThreadSecurityDescriptor );
    110.     Status = ZwCreateThread( &ThreadHandle,
    111.                              THREAD_ALL_ACCESS,
    112.                              &ObjectAttributes,
    113.                              Process,
    114.                              &ThreadClientId,
    115.                              &ThreadContext,
    116.                              &InitialTeb,
    117.                              CreateSuspended
    118.                            );
    119.     if (!NT_SUCCESS( Status )) {
    120. #if DBG
    121.         DbgPrint( "NTRTL: RtlCreateUserThread Failed. NtCreateThread Status == %X\n",
    122.                   Status );
    123. #endif // DBG
    124.         RtlpFreeStack( Process, &InitialTeb );
    125.         }
    126.     else {
    127.         if (ARGUMENT_PRESENT( Thread )) {
    128.             *Thread = ThreadHandle;
    129.             }
    130.  
    131.         if (ARGUMENT_PRESENT( ClientId )) {
    132.             *ClientId = ThreadClientId;
    133.             }
    134.  
    135.         }
    136.  
    137.     //
    138.     // Return status
    139.     //
    140.  
    141.     return( Status );
    142. }
    может были какие то изменения начиная с ХР ?
     
  3. klzlk

    klzlk New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2011
    Сообщения:
    449
    Csrss тратит время на обработку сообщений с порта исключений, которые циклически возникают в созданном потоке.
     
  4. 984259h

    984259h New Member

    Публикаций:
    0
    Регистрация:
    25 авг 2007
    Сообщения:
    194
    klzlk
    так на xp нужно делать уведомление о потоке CsrClientCallServer...
    если да то почему не нужно его делать на висте и севен я же на всех осях (xp,висте,севен) запускаю в одном сеансе ...
     
  5. klzlk

    klzlk New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2011
    Сообщения:
    449
    984259h
    Фолт у вас там рекурсивно возникает(и хэндлится диспетчером исключений в csrss, там сервер порта исключений, который все юзермодные фолты хэндлит). Возможно в других версиях системы содержимое к примеру стека отличается(помню что нэйтивный тред не получает на стеке аргумент, да и без того стопяцот причин может быть). Без отладчика ничего не будет. Бог не может писать на васме.
     
  6. 984259h

    984259h New Member

    Публикаций:
    0
    Регистрация:
    25 авг 2007
    Сообщения:
    194
    klzlk
    И так у меня получается следующая ситуация
    CreateRemoteThread работает на все осях (хр, висте и севен)
    RtlCreateUserThread только на ВИСТЕ и СЕВЕН
    На ХР она грузит проц ? (почему ?) было бы хорошо пройтись отладчиком но как ? то есть я делаю инжект всего РЕ образа (не длл) ? полностью пишу код по смещенной базе потом делаю поток на функцию которая по хешам находит все нужные мне апишки (короче базонезависимый код)
    Реверсил kernel32 из XP там CreateRemoteThread --> NtCreateThread + CsrClientCallServer.
    В висте и севен там след ситуация:
    Kernel32 там CreateRemoteThread-> через (MinWin х3рня с api-ms-win-core-XXX-l1-1-0.dll прогруженая apisetschema.dll) опускается на kernelbase.dll.
    то есть
    Kernel32 --> CreateRemoteThread ==> kernelbase.dll --> CreateRemoteThread --> CreateRemoteThreadEx --> NtCreateThreadEx + CsrClientCallServer. аналогично и
    Kernel32 --> CreateRemoteThreadEx ==> kernelbase.dll --> CreateRemoteThreadEx --> NtCreateThreadEx + CsrClientCallServer.
    в Ntdll.dll там RtlCreateUserThread --> RtlCreateUserThreadEx --> NtCreateThreadEx.
    Меня начали смущать сомнения на счет уведомления CsrClientCallServer.
    в инжектированном потоке используется WaitForSingleObject и WaitForMultipleObjects но в след. топике http://www.wasm.ru/forum/viewtopic.php?id=28243
    z0mailbox говорит что без CsrClientCallServer будут косяки ... какая то аномалия
     
  7. klzlk

    klzlk New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2011
    Сообщения:
    449
    984259h
    Зачем вам использовать винапи с нэйтивными тредами ?
    Если используете нэйтив, то и ждать следует должным образом - посредством сервисов(NtWaitForSingleObject etc.). Винапи содержат много лишнего функционала.

    Суспендите процесс(все потоки, аля F12) и смотрите где висит ваш тред.
     
  8. qqqqqq

    qqqqqq New Member

    Публикаций:
    0
    Регистрация:
    4 июл 2011
    Сообщения:
    14
    Давно была та же хрень, уж не помню как решил, помню только, что уведомление не надо делать. С какими параметрами делаешь BaseCreateStack и BaseInitializeContext?
     
  9. 984259h

    984259h New Member

    Публикаций:
    0
    Регистрация:
    25 авг 2007
    Сообщения:
    194
    klzlk
    Инжект сделан полностью на нетиве !!!!!!!!!!!
    а тот поток который инжектируется реализован на WINAPI !!!!
     
  10. 984259h

    984259h New Member

    Публикаций:
    0
    Регистрация:
    25 авг 2007
    Сообщения:
    194
    qqqqqq
    Сегодня попробую использовать полностью NtCreateThread то есть полностью выделю память под стек инициализирую контекст ну конечно теб ) пожже отпишу
     
  11. klzlk

    klzlk New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2011
    Сообщения:
    449
    984259h
    Ну и зачем это нужно, если есть винапи ?
    Нэйтив это не круто, это гемор, к которому следует прибегать если не достаточно винапи функционала.
     
  12. qqqqqq

    qqqqqq New Member

    Публикаций:
    0
    Регистрация:
    4 июл 2011
    Сообщения:
    14
    <erased>
     
  13. klzlk

    klzlk New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2011
    Сообщения:
    449
    qqqqqq
    Отладчик в руки и дебажить. Привыкли всё нахоляву.
     
  14. 984259h

    984259h New Member

    Публикаций:
    0
    Регистрация:
    25 авг 2007
    Сообщения:
    194
    qqqqqq
    Взял все и исходников винды .
    все полностью сделал c NtCreateThread создаю поток замороженный потом делаю уведомление CsrClientCallServer (возвращает в ошибку 0xC0000001 STATUS_UNSUCCESSFUL) потом восстанавливаю выполнения потока. Если проигнорить CsrClientCallServer то на семерке и висте работает на XP та самая хрень ...
     
  15. qqqqqq

    qqqqqq New Member

    Публикаций:
    0
    Регистрация:
    4 июл 2011
    Сообщения:
    14
    ...а надо взять и переделать чтоб работало :)

    1. BaseCreateStack:
    - ImageStackSize:=$8000;
    - делаешь стек Stack:=VirtualAllocEx(hProcess,0,ImageStackSize,{MEM_RESERVE or }MEM_COMMIT,Page_Execute_ReadWrite);
    - инициализируешь TEB
    OldStackBase:=Nil; OldStackLimit:=Nil;
    StackAllocationBase:=Stack;
    StackBase:=Stack+ImageStackSize;
    StackLimit:=Stack;

    2. BaseInitializeContext
    Eax:=InitialPc; Ebx:=0;
    SegGs:=0; SegFs:=56; SegEs:=32; SegDs:=32; SegSs:=32; SegCs:=24;
    EFlags:=$3000; //IOPL=3
    Eip:=InitialPc;
    ContextFlags:=CONTEXT_FULL;
    Esp:=InitialSp{-4}; //раскоменть 4, если передаешь потоку параметры
     
  16. 984259h

    984259h New Member

    Публикаций:
    0
    Регистрация:
    25 авг 2007
    Сообщения:
    194
    qqqqqq
    я это все сделал !!! примерно так
    Код (Text):
    1.               // Create stack size for remote process
    2.               SYSTEM_BASIC_INFORMATION SysInfo;
    3.               NtStatus = NtQuerySystemInformation(SystemBasicInformation,&SysInfo,sizeof(SysInfo),NULL);
    4.               if (NT_SUCCESS(NtStatus))
    5.               {
    6.                  // default stack size of remote process
    7.                  DWORD CommittedStackSize = SysInfo.uPageSize;
    8.                  DWORD MaximumStackSize = SysInfo.uAllocationGranularity;
    9.                  if ( CommittedStackSize >= MaximumStackSize )  MaximumStackSize = ROUND_UP(CommittedStackSize, (1024*1024));
    10.                  CommittedStackSize = ROUND_UP(CommittedStackSize,SysInfo.uPageSize );
    11.                  MaximumStackSize = ROUND_UP(MaximumStackSize,SysInfo.uAllocationGranularity);
    12.                  // allocate max memory onto stack
    13.                  PVOID pStack = NULL;
    14.                  NtStatus = NtAllocateVirtualMemory(hProcess,&pStack,0,&MaximumStackSize,MEM_RESERVE,PAGE_READWRITE);
    15.                  if (NT_SUCCESS(NtStatus))
    16.                  {
    17.                      // fill TEB
    18.                      INITIAL_TEB InitialTeb;
    19.                          InitialTeb.OldInitialTeb.OldStackBase = NULL;
    20.                          InitialTeb.OldInitialTeb.OldStackLimit = NULL;
    21.                          InitialTeb.StackAllocationBase = pStack;
    22.                          InitialTeb.StackBase = (PVOID)((DWORD)pStack + MaximumStackSize);
    23.                      pStack = (PVOID) ((DWORD)pStack + MaximumStackSize - CommittedStackSize);
    24.                      BOOLEAN GuardPage;
    25.                      if (MaximumStackSize > CommittedStackSize)
    26.                      {
    27.                         pStack = (PVOID) ((DWORD)pStack - SysInfo.uPageSize);
    28.                         CommittedStackSize =  CommittedStackSize + SysInfo.uPageSize;
    29.                         GuardPage = TRUE;
    30.                      }
    31.                      else
    32.                      {
    33.                        GuardPage = FALSE;  
    34.                      }
    35.                      // allocate committed memory onto stack
    36.                      NtStatus = NtAllocateVirtualMemory(hProcess,&pStack,0,&CommittedStackSize,MEM_COMMIT,PAGE_READWRITE);
    37.                      if (NT_SUCCESS(NtStatus))
    38.                      {
    39.                         InitialTeb.StackLimit = pStack;
    40.                         // if page guarded
    41.                         if (GuardPage)
    42.                         {
    43.                             ULONG OldProtect;
    44.                             DWORD RegionSize =  SysInfo.uPageSize;
    45.                             NtStatus = NtProtectVirtualMemory(hProcess,&pStack,&RegionSize,PAGE_GUARD | PAGE_READWRITE,&OldProtect);
    46.                             if (NT_SUCCESS(NtStatus))
    47.                             {
    48.                                InitialTeb.StackLimit = (PVOID)((DWORD)InitialTeb.StackLimit - RegionSize);
    49.                                // Create an initial context for the new thread.
    50.                                CONTEXT ThreadContext;
    51.                                   ThreadContext.Eax = 0L;
    52.                                   ThreadContext.Ebx = 1L;
    53.                                   ThreadContext.Ecx = 2L;
    54.                                   ThreadContext.Edx = 3L;
    55.                                   ThreadContext.Esi = 4L;
    56.                                   ThreadContext.Edi = 5L;
    57.                                   ThreadContext.Ebp = 0L;
    58.  
    59.                                   ThreadContext.SegGs = 0;
    60.                                   ThreadContext.SegFs = 0x38;      // KGDT_R3_TEB
    61.                                   ThreadContext.SegEs = 0x20;      // KGDT_R3_DATA;
    62.                                   ThreadContext.SegDs = 0x20;      // KGDT_R3_DATA;
    63.                                   ThreadContext.SegSs = 0x20;      // KGDT_R3_DATA;
    64.                                   ThreadContext.SegCs = 0x18;      // KGDT_R3_CODE;
    65.                                   ThreadContext.EFlags = 0x200L;   // force interrupts on, clear all else.
    66.                                  
    67.                                   ThreadContext.Esp = (DWORD)InitialTeb.StackBase;
    68.                                   ThreadContext.Eip = (ULONG)pFunction;
    69.  
    70.                                   ThreadContext.ContextFlags = CONTEXT_CONTROL|CONTEXT_INTEGER|CONTEXT_SEGMENTS;
    71.  
    72.                                   ThreadContext.Esp -= sizeof(pSelfBaseAddress);
    73.                                   NtWriteVirtualMemory(hProcess,(PVOID)ThreadContext.Esp,(PVOID)&pSelfBaseAddress,sizeof(pSelfBaseAddress),NULL);
    74.                                   ThreadContext.Esp -= sizeof(pSelfBaseAddress);   // Reserve room for ret address
    75.  
    76.                                   InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL,NULL);
    77.  
    78.                                   HANDLE hRemoteThread;
    79.                                   CLIENT_ID ThreadClientId;
    80.                                   NtStatus = NtCreateThread(&hRemoteThread,THREAD_ALL_ACCESS,&ObjectAttributes,hProcess,&ThreadClientId,&ThreadContext,&InitialTeb,TRUE);
    81.                                   if (NT_SUCCESS(NtStatus))
    82.                                   {
    83.  
    84.                                          CSRMSG csrmsg = { {0}, {0}, {hProcess,hRemoteThread,(DWORD)ThreadClientId.UniqueProcess,(DWORD)ThreadClientId.UniqueThread}, {0}, 0, {0} };
    85.                                          NtStatus = CsrClientCallServer(&csrmsg,0,0x10001,0x0C);
    86. // NtStatus CsrClientCallServer  SASTUS_UNSUCCESSFUL  (0xC0000001)
    87.            
    88.                                          NtResumeThread(hRemoteThread,NULL);
    89.                                          
    90.                                   }
    91.                             }
    92.                          }
    93.                      }
    94.                  }
    95.               }
    где pFunction стартовый адрес поточной функции а pSelfBaseAddress параметр к ней
     
  17. qqqqqq

    qqqqqq New Member

    Публикаций:
    0
    Регистрация:
    4 июл 2011
    Сообщения:
    14
    984259h
    Куча лишнего кода, у меня сначала тоже так было - это "классическая инициализация по учебнику". Во-первых NtQuerySystemInformation нафиг нужно, бери MaximumStackSize равным именно 8000h. Во вторых, CommittedStackSize у тебя должно быть равным 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 committed memory onto stack
    NtStatus = NtAllocateVirtualMemory(hProcess,&pStack,0,&CommittedStackSize,MEM_COMMIT,PAGE_READWRITE);
    ------------------------------------
    просто не нужен, вызывай AllocateVirtualMemory только 1 раз и сразу выделяй память без резервирования. В-третьих, также выкинь GuardPage и NtProtectVirtualMemory - использование этого ничего не дает. И потом, почему ты после правильной инициализации ThreadContext.Esp = (DWORD)InitialTeb.StackBase делаешь ThreadContext.Esp -= sizeof(pSelfBaseAddress)? Что вообще такое NtWriteVirtualMemory? Это ты пишешь "тело" потока? Так это надо делать в самом начале перед созданием потока.

    И последнее, у меня все прекрасно работает без уведомления Csr и без создания спящего потока, т.е. не нужно ResumeThread.
    И самое последнее - по-моему тормоза в полтинник процессорных ресурсов были всязаны именно с неравенством CommittedStackSize и MaximumStackSize. Должно быть CommittedStackSize=MaximumStackSize=8000h
     
  18. ASMatic

    ASMatic New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2010
    Сообщения:
    233
    qqqqqq&984259h
    объясните мне, будьте добры - зачем вот эти все иниты стека, уведомления csrss и т.п. когда этот же код, только "правильней" находится в библиотеке kernel32.dll?
     
  19. 984259h

    984259h New Member

    Публикаций:
    0
    Регистрация:
    25 авг 2007
    Сообщения:
    194
    qqqqqq
    это наблюдается даже если просто юзать RtlCreateUserThread в том то и дело что сначала думал что процессорные тормоза из-за то того что не делаю уведомление ...
     
  20. klzlk

    klzlk New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2011
    Сообщения:
    449
    984259h
    Поздравляю, вы изобрели велосипед :lol: