Beispiel #1
2
pid_t fork(void)
{
 NTSTATUS nErrCode;
 CONTEXT ctxThreadContext;
 HANDLE hProcess;
 HANDLE hThread;
 INITIAL_TEB itInitialTeb;
 CLIENT_ID ciClientId;
 MEMORY_BASIC_INFORMATION mbiStackInfo;
 THREAD_BASIC_INFORMATION tbiThreadInfo;

 struct __tagcsrmsg{
  PORT_MESSAGE PortMessage;
  struct CSRSS_MESSAGE CsrssMessage;
  PROCESS_INFORMATION ProcessInformation;
  CLIENT_ID Debugger;
  ULONG CreationFlags;
  ULONG VdmInfo[2];
 } csrmsg;

 /* STEP 1: Duplicate current process */ 
 nErrCode = NtCreateProcess
 (
  &hProcess,
  PROCESS_ALL_ACCESS,
  NULL,
  NtCurrentProcess(),
  TRUE,
  0,
  0,
  0
 );

 /* failure */
 if(!NT_SUCCESS(nErrCode))
 {
  ERR("NtCreateProcess() failed with status 0x%08X\n", nErrCode);
  goto fail;
 }

 /* STEP 2: Duplicate current thread */
 /* 2.1: duplicate registers */
 ctxThreadContext.ContextFlags =
  CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS | CONTEXT_FLOATING_POINT;
 
 /* get the current thread's registers */
 nErrCode = NtGetContextThread(NtCurrentThread(), &ctxThreadContext);
 
 /* failure */
 if(!NT_SUCCESS(nErrCode))
 {
  ERR("NtGetContextThread() failed with status 0x%08X\n", nErrCode);
  goto cleanup_and_fail;
 }

 /* redirect the child process to the child_branch label (see 4.3 below) */
 ctxThreadContext.Eip = (ULONG)&&child_branch;
 
 /* 2.2: duplicate stack */
 /* get stack base and size */
 nErrCode = NtQueryVirtualMemory
 (
  NtCurrentProcess(),
  (PVOID)ctxThreadContext.Esp,
  MemoryBasicInformation,
  &mbiStackInfo,
  sizeof(mbiStackInfo),
  0
 );
 
 /* failure */
 if(!NT_SUCCESS(nErrCode))
 {
  ERR("NtQueryVirtualMemory() failed with status 0x%08X\n", nErrCode);
  goto cleanup_and_fail;
 }
 
 itInitialTeb.StackCommit = 0;
 itInitialTeb.StackReserve = 0;
 itInitialTeb.StackBase = (PVOID)((ULONG)(mbiStackInfo.BaseAddress) + mbiStackInfo.RegionSize);
 itInitialTeb.StackLimit = mbiStackInfo.BaseAddress;
 itInitialTeb.StackAllocate = mbiStackInfo.AllocationBase;
 
 /* 2.3: create duplicate thread */
 nErrCode = NtCreateThread
 (
  &hThread,
  THREAD_ALL_ACCESS,
  NULL,
  hProcess,
  (CLIENT_ID *)&ciClientId,
  &ctxThreadContext,
  &itInitialTeb,
  TRUE
 );
 
 /* failure */
 if(!NT_SUCCESS(nErrCode))
 {
  ERR("NtCreateThread() failed with status 0x%08X\n", nErrCode);
  goto cleanup_and_fail;
 }

 /* 2.4: duplicate the TEB */
 /* store the client id in the child thread's stack (see 4.3b) */
 nErrCode = NtWriteVirtualMemory
 (
  hProcess,
  &ciClientId,
  &ciClientId,
  sizeof(ciClientId),
  0
 );
 
 /* failure */
 if(!NT_SUCCESS(nErrCode))
 {
  ERR("NtWriteVirtualMemory() failed with status 0x%08X\n", nErrCode);
  goto cleanup_and_fail;
 }
 
 /* get the child thread's TEB base */
 nErrCode = NtQueryInformationThread
 (
  hThread,
  ThreadBasicInformation,
  &tbiThreadInfo,
  sizeof(tbiThreadInfo),
  0
 );
 
 /* failure */
 if(!NT_SUCCESS(nErrCode))
 {
  ERR("NtQueryInformationThread() failed with status 0x%08X\n", nErrCode);
  goto cleanup_and_fail;
 }
 
 /* copy the TEB */ 
 nErrCode = NtWriteVirtualMemory
 (
  hProcess,
  tbiThreadInfo.TebBaseAddress,
  NtCurrentTeb(),
  sizeof(TEB),
  0
 );
 
 /* failure */
 if(!NT_SUCCESS(nErrCode))
 {
  ERR("NtWriteVirtualMemory() failed with status 0x%08X\n", nErrCode);
  goto cleanup_and_fail;
 }
 
 /* STEP 3: Call Win32 subsystem */
 memset(&csrmsg, 0, sizeof(csrmsg));

 csrmsg.ProcessInformation.hProcess = hProcess;
 csrmsg.ProcessInformation.hThread = hThread;
 csrmsg.ProcessInformation.dwProcessId = (DWORD)ciClientId.UniqueProcess;
 csrmsg.ProcessInformation.dwThreadId = (DWORD)ciClientId.UniqueThread;

 nErrCode = CsrClientCallServer(&csrmsg, 0, 0x10000, 0x24);

 /* failure */
 if(!NT_SUCCESS(nErrCode))
 {
  ERR("CsrClientCallServer() failed with status 0x%08X\n", nErrCode);
  goto cleanup_and_fail;
 }
 
 /* STEP 4: Finalization */
 /* 4.1: resume thread */
 nErrCode = NtResumeThread(hThread, 0);
 
 /* 4.2: close superfluous handles */
 NtClose(hProcess);
 NtClose(hThread);
 
 /* 4.3: (parent) return the child process id */
 return ((pid_t)(ciClientId.UniqueProcess));

 /* 4.3b: (child) cleanup and return 0 */
child_branch:
 /* restore the thread and process id in the TEB */ 
 memcpy(&NtCurrentTeb()->Cid, &ciClientId, sizeof(ciClientId));
 
 /* return 0 */
 return (0);

cleanup_and_fail:
 NtTerminateProcess(hProcess, nErrCode);

fail:
 errno = __status_to_errno(nErrCode);
 return (-1);
 
}
Beispiel #2
0
ULONG
fork ()

{
    LONG i;
    PULONG Foo;
    NTSTATUS status;
    HANDLE CurrentProcessHandle;
    HANDLE ProcessHandle;
    CONTEXT ThreadContext;
    CLIENT_ID Cid1;
    HANDLE Thread1;
    LARGE_INTEGER DelayTime;
    INITIAL_TEB Teb;

    CurrentProcessHandle = NtCurrentProcess();
    DbgPrint("creating new process\n");

    status = NtCreateProcess(
                 &ProcessHandle,
                 PROCESS_ALL_ACCESS, //DesiredAccess,
                 NULL, //ObjectAttributes,
                 CurrentProcessHandle, //ParentProcess
                 TRUE, //InheritObjectTable,
                 NULL, //SectionHandle
                 NULL, //DebugPort OPTIONAL,
                 NULL  //ExceptionPort OPTIONAL
             );

    DbgPrint("status from create process %lx\n",status);

    if (!NT_SUCCESS(status)) {
        return 0;
    }
    ThreadContext.ContextFlags = CONTEXT_FULL;

    status = NtGetContextThread (NtCurrentThread(), &ThreadContext);

    DbgPrint("status from get context %lx\n",status);

    if (status == 0) {

#ifdef i386
        ThreadContext.Eax = 0x7777;
        ThreadContext.Esp -= 0x18;
        Foo = (PULONG)ThreadContext.Esp;
        DbgPrint("stack value is %lx\n",*Foo);
#endif

#ifdef MIPS
        ThreadContext.IntV0 = 0x7777;
#endif

        status = NtCreateThread(
                     &Thread1,
                     THREAD_ALL_ACCESS,
                     NULL,
                     ProcessHandle,
                     &Cid1,
                     &ThreadContext,
                     &Teb,
                     FALSE
                 );

//        DelayTime.HighPart = -1;
//        DelayTime.LowPart = 0;
//        NtDelayExecution (FALSE, &DelayTime);

        return 0;
    } else {

        ProcessNumber += ProcessNumber;
        return ProcessNumber;

    }

}
Beispiel #3
0
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
    void *(*start_routine)(void*), void *arg)
{
 HANDLE hThread;
 OBJECT_ATTRIBUTES oaThreadAttrs;
 CLIENT_ID ciId;
 CONTEXT cxThreadContext;
 INITIAL_TEB itInitialTeb;
 BOOLEAN fSuspended;
 ULONG nOldPageProtection;
 NTSTATUS nErrCode;

 /* initialize generic object attributes */
 oaThreadAttrs.Length = sizeof(OBJECT_ATTRIBUTES);
 oaThreadAttrs.RootDirectory = NULL;
 oaThreadAttrs.ObjectName = NULL;
 oaThreadAttrs.Attributes = 0;
 oaThreadAttrs.SecurityDescriptor = NULL;
 oaThreadAttrs.SecurityQualityOfService = NULL;

 /* initialize thread attributes */
 fSuspended = FALSE; /* FIXME? really needed? can we hardcode this to FALSE? */

 /* stack attributes */
 FIXME("stack size defaulted to 0x100000 - thread attributes ignored");

 /* stack reserve size */
 itInitialTeb.StackReserve = 0x100000;

 /* stack commit size */
 itInitialTeb.StackCommit = itInitialTeb.StackReserve - PAGE_SIZE;

 /* guard page */
 itInitialTeb.StackCommit += PAGE_SIZE;

 /* reserve stack */
 itInitialTeb.StackAllocate = NULL;

 nErrCode = NtAllocateVirtualMemory
 (
  NtCurrentProcess(),
  &itInitialTeb.StackAllocate,
  0,
  &itInitialTeb.StackReserve,
  MEM_RESERVE,
  PAGE_READWRITE
 );

 if(!NT_SUCCESS(nErrCode))
 {
  return (__status_to_errno(nErrCode)); /* FIXME? TODO? pthread specific error codes? */
 }

 itInitialTeb.StackBase = (PVOID)((ULONG)itInitialTeb.StackAllocate + itInitialTeb.StackReserve);
 itInitialTeb.StackLimit = (PVOID)((ULONG)itInitialTeb.StackBase - itInitialTeb.StackCommit);

 /* commit stack */
 nErrCode = NtAllocateVirtualMemory
 (
  NtCurrentProcess(),
  &itInitialTeb.StackLimit,
  0,
  &itInitialTeb.StackCommit,
  MEM_COMMIT,
  PAGE_READWRITE
 );

 if(!NT_SUCCESS(nErrCode))
 {
  NtFreeVirtualMemory
  (
   NtCurrentProcess(),
   itInitialTeb.StackAllocate,
   &itInitialTeb.StackReserve,
   MEM_RELEASE
  );

  return (__status_to_errno(nErrCode));
 }

 /* protect guard page */
 nErrCode = NtProtectVirtualMemory
 (
  NtCurrentProcess(),
  itInitialTeb.StackLimit,
  PAGE_SIZE,
  PAGE_GUARD | PAGE_READWRITE,
  &nOldPageProtection
 );

 if(!NT_SUCCESS(nErrCode))
 {
  NtFreeVirtualMemory
  (
   NtCurrentProcess(),
   itInitialTeb.StackAllocate,
   &itInitialTeb.StackReserve,
   MEM_RELEASE
  );

  return (__status_to_errno(nErrCode));
 }

 /* initialize thread registers */

//#ifdef __i386__
 memset(&cxThreadContext, 0, sizeof(CONTEXT));
 cxThreadContext.Eip = (LONG)__threadentry;
 cxThreadContext.SegGs = USER_DS;
 cxThreadContext.SegFs = TEB_SELECTOR;
 cxThreadContext.SegEs = USER_DS;
 cxThreadContext.SegDs = USER_DS;
 cxThreadContext.SegCs = USER_CS;
 cxThreadContext.SegSs = USER_DS;
 cxThreadContext.Esp = (ULONG)itInitialTeb.StackBase - 12;
 cxThreadContext.EFlags = (1<<1) + (1<<9);

 /* initialize call stack */
 *((PULONG)((ULONG)itInitialTeb.StackBase - 4)) = (ULONG)arg; /* thread argument */
 *((PULONG)((ULONG)itInitialTeb.StackBase - 8)) = (ULONG)start_routine; /* thread start routine */
 *((PULONG)((ULONG)itInitialTeb.StackBase - 12)) = 0xDEADBEEF; /* "shouldn't see me" */
//#else
//#error Unsupported architecture
//#endif

 INFO("about to create new thread - start routine at %#x, argument %#x", start_routine, arg);

 /* create thread */
 nErrCode = NtCreateThread
 (
  &hThread,
  THREAD_ALL_ACCESS,
  &oaThreadAttrs,
  NtCurrentProcess(),
  &ciId,
  &cxThreadContext,
  &itInitialTeb,
  fSuspended
 );

 if(!NT_SUCCESS(nErrCode))
 {
  NtFreeVirtualMemory
  (
   NtCurrentProcess(),
   itInitialTeb.StackAllocate,
   &itInitialTeb.StackReserve,
   MEM_RELEASE
  );

  return (__status_to_errno(nErrCode));
 }

 /* FIXME? should we return the thread handle or the thread id? */
 if(thread != 0)
  *thread = (pthread_t)&ciId.UniqueThread; /* for the moment, we return the id */

 return (0);

}