RtlCreateUserThread vs CreateRemoteThread

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

  1. klzlk

    klzlk New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2011
    Сообщения:
    449
    984259h
    Что по вашему произойдёт при выполнении инструкции Ret, если в стеке 0, Arg ?
     
  2. klzlk

    klzlk New Member

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

    984259h New Member

    Публикаций:
    0
    Регистрация:
    25 авг 2007
    Сообщения:
    194
    klzlk
    Что по вашему произойдёт при выполнении инструкции Ret, если в стеке 0, Arg ?
    Ничего хорошего в стеке должен быть адрес (eip) возврата который кладется в стек когда выполняется инструкция call
     
  4. 984259h

    984259h New Member

    Публикаций:
    0
    Регистрация:
    25 авг 2007
    Сообщения:
    194
    Меня сейчас интересует один вопрос почему приложение падает с этим кодом ?

    Код (Text):
    1. DWORD WINAPI MyRemoteThread(LPVOID lpParam)
    2. {
    3.    
    4.     return 0;        
    5. }
    Код (Text):
    1.          
    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 thread
    7.                  DWORD CommittedStackSize = SysInfo.uPageSize;
    8.                  DWORD MaximumStackSize = SysInfo.uAllocationGranularity;
    9.                  // allocate reserve memory onto stack
    10.                  PVOID pStack = NULL;
    11.                  NtStatus = NtAllocateVirtualMemory(hProcess,&pStack,0,&MaximumStackSize,MEM_RESERVE,PAGE_READWRITE);
    12.                  if (NT_SUCCESS(NtStatus))
    13.                  {
    14.                      // fill TEB
    15.                      INITIAL_TEB InitialTeb;
    16.                      InitialTeb.OldInitialTeb.OldStackBase = NULL;
    17.                      InitialTeb.OldInitialTeb.OldStackLimit = NULL;
    18.                      InitialTeb.StackAllocationBase = pStack;
    19.                      InitialTeb.StackBase = (PVOID)((DWORD)pStack + MaximumStackSize);
    20.                      pStack = (PVOID) ((DWORD)pStack + MaximumStackSize - CommittedStackSize);                   
    21.                      BOOLEAN GuardPage;
    22.                      if (MaximumStackSize > CommittedStackSize)
    23.                      {
    24.                         pStack = (PVOID) ((DWORD)pStack - SysInfo.uPageSize);
    25.                         CommittedStackSize =  CommittedStackSize + SysInfo.uPageSize;
    26.                         GuardPage = TRUE;
    27.                      }
    28.                      else
    29.                      {
    30.                         GuardPage = FALSE;  
    31.                      }
    32.                      // allocate committ memory onto stack
    33.                      NtStatus = NtAllocateVirtualMemory(hProcess,&pStack,0,&CommittedStackSize,MEM_COMMIT,PAGE_READWRITE);
    34.                      if (NT_SUCCESS(NtStatus))
    35.                      {
    36.                         InitialTeb.StackLimit = pStack;
    37.                         // if page guarded
    38.                         if (GuardPage)
    39.                         {
    40.                             ULONG OldProtect;
    41.                             DWORD RegionSize =  SysInfo.uPageSize;
    42.                             NtStatus = NtProtectVirtualMemory(hProcess,&pStack,&RegionSize,PAGE_GUARD | PAGE_READWRITE,&OldProtect);
    43.                             if (NT_SUCCESS(NtStatus))
    44.                             {
    45.                                InitialTeb.StackLimit = (PVOID)((DWORD)InitialTeb.StackLimit - RegionSize);
    46.                                // Create an initial context for the new thread.
    47.                                CONTEXT ThreadContext;
    48.                                ThreadContext.Eax = 0L;
    49.                                ThreadContext.Ebx = 1L;    
    50.                                ThreadContext.Ecx = 2L;
    51.                                ThreadContext.Edx = 3L;
    52.                                ThreadContext.Esi = 4L;
    53.                                ThreadContext.Edi = 5L;
    54.                                ThreadContext.Ebp = 0L;
    55.                                ThreadContext.SegGs = 0;
    56.                                ThreadContext.SegFs = 0x38;      // KGDT_R3_TEB
    57.                                ThreadContext.SegEs = 0x20;      // KGDT_R3_DATA;
    58.                                ThreadContext.SegDs = 0x20;      // KGDT_R3_DATA;
    59.                                ThreadContext.SegSs = 0x20;      // KGDT_R3_DATA;
    60.                                ThreadContext.SegCs = 0x18;      // KGDT_R3_CODE;
    61.                                ThreadContext.EFlags = 0x200L;   // force interrupts on, clear all else.
    62.                                ThreadContext.Esp = (DWORD)InitialTeb.StackBase;
    63.                                ThreadContext.Eip = (ULONG)MyRemoteThread;  // thread function
    64.                                ThreadContext.ContextFlags = CONTEXT_FULL;
    65.                                ThreadContext.Esp -= sizeof(pSelfBaseAddress);  // Parametr size to stack
    66.                                NtStatus = NtWriteVirtualMemory(hProcess,(PVOID)ThreadContext.Esp,(PVOID)&pSelfBaseAddress,sizeof(pSelfBaseAddress),NULL);
    67.                                if (NT_SUCCESS(NtStatus))
    68.                                {
    69.                                   ThreadContext.Esp -= sizeof(pSelfBaseAddress);   // Reserve room for ret
    70.                                   HANDLE hRemoteThread;
    71.                                   CLIENT_ID ThreadClientId;
    72.                                   NtStatus = NtCreateThread(&hRemoteThread,THREAD_ALL_ACCESS,&ObjectAttributes,hProcess,&ThreadClientId,&ThreadContext,&InitialTeb,TRUE);
    73.                                   if (NT_SUCCESS(NtStatus))
    74.                                   {
    75.                                      BASE_API_MSG BaseApiMsg;
    76.                                      MyZeroMemory(&BaseApiMsg,sizeof(BASE_API_MSG),0);
    77.                                      PBASE_CREATETHREAD_MSG pBaseCreateThread = (PBASE_CREATETHREAD_MSG)&BaseApiMsg.u.BaseCreateThread;
    78.                                      pBaseCreateThread->hThread = hRemoteThread;
    79.                                      pBaseCreateThread->ClientId = ThreadClientId;
    80.                                      // inform client server subsystem of new thread in process
    81.                                      NtStatus = CsrClientCallServer((PCSR_API_MSG)&BaseApiMsg,0,0x10001,0x0C);
    82.                                      if (NT_SUCCESS(NtStatus))
    83.                                      {
    84.                                         NtResumeThread(hRemoteThread,NULL);
    85.                                      }
    86.                                      NtClose(hRemoteThread);
    87.                                   }
    88.                                }
    89.                             }
    90.                          }
    91.                      }
    92.                  }
    93.               }
    а с этим не падает
    Код (Text):
    1.          HANDLE hRem;
    2.          NtStatus = RtlCreateUserThread(hProcess,NULL,FALSE,0,NULL,NULL,MyRemoteThread,pSelfBaseAddress,&hRem,NULL);
    3.                  // или CreateRemoteThread
     
  5. klzlk

    klzlk New Member

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

    Call выполняется в стабе для пользовательских тредов(BaseThreadStart()):
    Код (Text):
    1. {
    2.     try {
    3.         if ( NtCurrentTeb()->NtTib.Version == OS2_VERSION ) {
    4.             if ( !BaseRunningInServerProcess ) {
    5.                 CsrNewThread();
    6.                 }
    7.             }
    8.         ExitThread((lpStartAddress)(lpParameter));
    9.         }
    10.     except(UnhandledExceptionFilter( GetExceptionInformation() )) {
    11.         if ( !BaseRunningInServerProcess ) {
    12.             ExitProcess(GetExceptionCode());
    13.             }
    14.         else {
    15.             ExitThread(GetExceptionCode());
    16.             }
    17.         }
    18. }
    В нэйтивных никаких стабов нет, стартап процедура непосредственно задаётся. И Ret в таком стеке передаст управление на 0:0, там память не выделена и #AV.
     
  6. 984259h

    984259h New Member

    Публикаций:
    0
    Регистрация:
    25 авг 2007
    Сообщения:
    194
    klzlk
    честно говоря в Вашем ответе решения не понял может у Вас есть пример, обертка на NtCreateThread только что бы стек и context были заполнены вручную без использования RtlpCreateStak и RtlInitializeContext. Хочется разобраться что в коде не правильно сделано.
     
  7. 984259h

    984259h New Member

    Публикаций:
    0
    Регистрация:
    25 авг 2007
    Сообщения:
    194
    klzlk
    так что нужно что бы в стеке было что бы после ret передало управление на нужный нам адрес ???
     
  8. klzlk

    klzlk New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2011
    Сообщения:
    449
    984259h
    Ясно что необходим адрес возврата. Вам полезно посмотреть сурс функи RtlRemoteCall().
     
  9. 984259h

    984259h New Member

    Публикаций:
    0
    Регистрация:
    25 авг 2007
    Сообщения:
    194
    klzlk
    так проще будет что бы удаленный поток вызвал какую нить фу-ю завершения (самого себя завершил что бы лишний раз не дергать RtlRemoteCall что повлечет за собой NtWriteVirtualMemory) что я и делал например находил адрес фу-и exitthread в этом потоке только почему то был облом так и не понял почему.
    я смотрел исходник ее там реализовано через получение и установку контекста.
     
  10. klzlk

    klzlk New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2011
    Сообщения:
    449
    984259h
    Легальный способ заполнить стек - использовать NtWriteVM. Да и права доступа одинаковы, как для записи, так и для аллокаций. А стек нужен полюбому - для доставки стартап апк. Можно без апк запилить(VF), но смысла я не вижу.
    И вообще что это за проблема с адресом возврата, зачем он нужен. Передайте управление на ExitThread/RtlExitUserThread(), либо вручную завершите.
     
  11. 984259h

    984259h New Member

    Публикаций:
    0
    Регистрация:
    25 авг 2007
    Сообщения:
    194
    klzlk
    у меня в удаленном потоке крутится цикл но в случае неудачи поток должен завершится без креша процесса вот с самого начала поставил фу-ю my_api.pExitThread(0) на ней вылетает код (Unhandled exception) не могу понять почему ...
     
  12. ASMatic

    ASMatic New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2010
    Сообщения:
    233
    984259h
    вы б уже давно почитале http://wasm.ru/forum/viewtopic.php?id=32181, законектились дебагером, поставили бряк и пронаблюдали чо там ваш кодез натворил = быстрей, не?)
     
  13. 984259h

    984259h New Member

    Публикаций:
    0
    Регистрация:
    25 авг 2007
    Сообщения:
    194
    ASMatic
    я это как раз и делал но ...
    происходит вызов my_api.pExitThread(0);
    далее
    вылетает на
    в адресе (ebp+73h) не выделенная память
     
  14. ASMatic

    ASMatic New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2010
    Сообщения:
    233
    7708F381 - этот модуль в иду и смотрим откуда адрес узялсо то
     
  15. 984259h

    984259h New Member

    Публикаций:
    0
    Регистрация:
    25 авг 2007
    Сообщения:
    194
    ASMatic
    тут уже ситуация поинтересней я по хешам восстановил адреса апишек и сверил их с полученными адресами функцией GetProccAddress все сошлись с апишками в моей структуре (my_api) помимо адреса ExitThread вот почему и был провал блин не заметил все же адреса помимо одного и тот который нужен.
     
  16. klzlk

    klzlk New Member

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

    984259h New Member

    Публикаций:
    0
    Регистрация:
    25 авг 2007
    Сообщения:
    194
    Все равно всем спасибо