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
UdbgTest1()
{
    NTSTATUS st;
    HANDLE ExitThread, SpinThread, DebugProcess;
    CLIENT_ID ExitClientId, SpinClientId;
    DBGKM_APIMSG m;
    PDBGKM_CREATE_THREAD CreateThreadArgs;
    PDBGKM_CREATE_PROCESS CreateProcessArgs;
    PDBGKM_EXIT_THREAD ExitThreadArgs;
    PDBGKM_EXIT_PROCESS ExitProcessArgs;
    ULONG Psp;

    DbgPrint("UdbgTest1: (1)...\n");

        //
        // Verify that a process can be created with a debug
        // port.
        //

        st = NtCreateProcess(
                &DebugProcess,
                PROCESS_ALL_ACCESS,
                NULL,
                NtCurrentProcess(),
                FALSE,
                NULL,
                DebugPort,
                NULL
                );
        ASSERT(NT_SUCCESS(st));

        st = RtlCreateUserThread(
                DebugProcess,
                NULL,
                TRUE,
                0L,
                0L,
                0L,
                ThreadThatExits,
                (PVOID) STATUS_ABANDONED,
                &ExitThread,
                &ExitClientId
                );
        ASSERT(NT_SUCCESS(st));

        st = RtlCreateUserThread(
                DebugProcess,
                NULL,
                TRUE,
                0L,
                0L,
                0L,
                ThreadThatSpins,
                NULL,
                &SpinThread,
                &SpinClientId
                );
        ASSERT(NT_SUCCESS(st));

    DbgPrint("UdbgTest1: (2)...\n");

        //
        // Verify that CreateProcess Messages Arrive, and that
        // they are correct
        //

        st = NtResumeThread(SpinThread,NULL);
        ASSERT(NT_SUCCESS(st));

        st = NtReplyWaitReceivePort(
                DebugPort,
                NULL,
                NULL,
                (PPORT_MESSAGE)&m
                );
        ASSERT(NT_SUCCESS(st));
        ASSERT(m.ApiNumber == DbgKmCreateProcessApi);

        CreateThreadArgs = &m.u.CreateProcess.InitialThread;
        CreateProcessArgs = &m.u.CreateProcess;
        ASSERT( CreateThreadArgs->SubSystemKey == 0 && CreateThreadArgs->StartAddress == (PVOID)ThreadThatSpins );
        ASSERT( CreateProcessArgs->SubSystemKey == 0);

    DbgPrint("UdbgTest1: (3)...\n");

        //
        // Verify that other threads in the process are properly suspended
        //

        st = NtSuspendThread(ExitThread,&Psp);
        ASSERT(NT_SUCCESS(st) && Psp == 2);

        st = NtResumeThread(ExitThread,&Psp);
        ASSERT(NT_SUCCESS(st) && Psp == 3);

        st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m);
        ASSERT(NT_SUCCESS(st));


    DbgPrint("UdbgTest1: (4)...\n");

        //
        // Verify that CreateThread Messages Arrive, and that
        // they are correct
        //

        st = NtResumeThread(ExitThread,&Psp);
        ASSERT(NT_SUCCESS(st));

        st = NtReplyWaitReceivePort(
                DebugPort,
                NULL,
                NULL,
                (PPORT_MESSAGE)&m
                );
        ASSERT(NT_SUCCESS(st));
        ASSERT(m.ApiNumber == DbgKmCreateThreadApi);

        CreateThreadArgs = &m.u.CreateThread;
        ASSERT( CreateThreadArgs->SubSystemKey == 0 && CreateThreadArgs->StartAddress == (PVOID)ThreadThatExits );

        st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m);
        ASSERT(NT_SUCCESS(st));

    DbgPrint("UdbgTest1: (5)...\n");

        //
        // Verify that ExitThread Messages Arrive, and that
        // they are correct
        //

        st = NtReplyWaitReceivePort(
                DebugPort,
                NULL,
                NULL,
                (PPORT_MESSAGE)&m
                );
        ASSERT(NT_SUCCESS(st));
        ASSERT(m.ApiNumber == DbgKmExitThreadApi);

        ExitThreadArgs = &m.u.ExitThread;
        ASSERT( ExitThreadArgs->ExitStatus == STATUS_ABANDONED );

        st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m);
        ASSERT(NT_SUCCESS(st));

        st = NtWaitForSingleObject(ExitThread,FALSE,NULL);
        ASSERT(NT_SUCCESS(st));

    DbgPrint("UdbgTest1: (6)...\n");

        //
        // Verify that ExitThread Messages Arrive, and that
        // they are correct
        //

        st = NtTerminateProcess(DebugProcess,STATUS_REPARSE);
        ASSERT(NT_SUCCESS(st));

        st = NtReplyWaitReceivePort(
                DebugPort,
                NULL,
                NULL,
                (PPORT_MESSAGE)&m
                );
        ASSERT(NT_SUCCESS(st));
        ASSERT(m.ApiNumber == DbgKmExitThreadApi);

        ExitThreadArgs = &m.u.ExitThread;
        ASSERT( ExitThreadArgs->ExitStatus == STATUS_REPARSE );

        st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m);
        ASSERT(NT_SUCCESS(st));

    DbgPrint("UdbgTest1: (7)...\n");

        //
        // Verify that ExitProcess Messages Arrive, and that
        // they are correct
        //

        st = NtReplyWaitReceivePort(
                DebugPort,
                NULL,
                NULL,
                (PPORT_MESSAGE)&m
                );
        ASSERT(NT_SUCCESS(st));
        ASSERT(m.ApiNumber == DbgKmExitProcessApi);

        ExitProcessArgs = &m.u.ExitProcess;
        ASSERT( ExitProcessArgs->ExitStatus == STATUS_REPARSE );

        st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m);
        ASSERT(NT_SUCCESS(st));


        st = NtWaitForSingleObject(ExitThread,FALSE,NULL);
        ASSERT(NT_SUCCESS(st));

        st = NtWaitForSingleObject(DebugProcess,FALSE,NULL);
        ASSERT(NT_SUCCESS(st));

    NtClose(ExitThread);
    NtClose(SpinThread);
    NtClose(DebugProcess);

    DbgPrint("UdbgTest1: END OF TEST ***\n");

}
Beispiel #3
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 #4
0
UdbgTest2()
{
    NTSTATUS st;
    HANDLE ExceptionThread, DebugProcess;
    DBGKM_APIMSG m;
    PDBGKM_CREATE_THREAD CreateThreadArgs;
    PDBGKM_CREATE_PROCESS CreateProcessArgs;
    PDBGKM_EXIT_THREAD ExitThreadArgs;
    PDBGKM_EXIT_PROCESS ExitProcessArgs;
    PDBGKM_EXCEPTION ExceptionArgs;
    ULONG Psp;

    DbgPrint("UdbgTest2: (1)...\n");

        //
        // Verify that a process can be created with a debug
        // port.
        //

        st = NtCreateProcess(
                &DebugProcess,
                PROCESS_ALL_ACCESS,
                NULL,
                NtCurrentProcess(),
                FALSE,
                NULL,
                DebugPort,
                NULL
                );
        ASSERT(NT_SUCCESS(st));

        st = RtlCreateUserThread(
                DebugProcess,
                NULL,
                TRUE,
                0L,
                0L,
                0L,
                ThreadThatExcepts,
                (PVOID) STATUS_ABANDONED,
                &ExceptionThread,
                NULL
                );
        ASSERT(NT_SUCCESS(st));

    DbgPrint("UdbgTest2: (2)...\n");

        //
        // Verify that CreateThread Messages Arrive, and that
        // they are correct
        //

        st = NtResumeThread(ExceptionThread,NULL);
        ASSERT(NT_SUCCESS(st));

        st = NtReplyWaitReceivePort(
                DebugPort,
                NULL,
                NULL,
                (PPORT_MESSAGE)&m
                );
        ASSERT(NT_SUCCESS(st));
        ASSERT(m.ApiNumber == DbgKmCreateProcessApi);

        CreateThreadArgs = &m.u.CreateProcess.InitialThread;
        CreateProcessArgs = &m.u.CreateProcess;
        ASSERT( CreateThreadArgs->SubSystemKey == 0 && CreateThreadArgs->StartAddress == (PVOID)ThreadThatExcepts );
        ASSERT( CreateProcessArgs->SubSystemKey == 0);

        st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m);
        ASSERT(NT_SUCCESS(st));

    DbgPrint("UdbgTest2: (3)...\n");

        //
        // Verify that First Chance Exception Messages Arrive, and that
        // they are correct
        //

        st = NtReplyWaitReceivePort(
                DebugPort,
                NULL,
                NULL,
                (PPORT_MESSAGE)&m
                );
        ASSERT(NT_SUCCESS(st));
        ASSERT(m.ApiNumber == DbgKmExceptionApi);

        ExceptionArgs = &m.u.Exception;
        ASSERT( ExceptionArgs->FirstChance == TRUE );

        m.ReturnedStatus = DBG_EXCEPTION_NOT_HANDLED;

        st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m);
        ASSERT(NT_SUCCESS(st));

    DbgPrint("UdbgTest2: (4)...\n");

        //
        // Verify that First Chance Exception Messages Arrive, and that
        // they are correct
        //

        st = NtReplyWaitReceivePort(
                DebugPort,
                NULL,
                NULL,
                (PPORT_MESSAGE)&m
                );
        ASSERT(NT_SUCCESS(st));
        ASSERT(m.ApiNumber == DbgKmExceptionApi);

        ExceptionArgs = &m.u.Exception;
        ASSERT( ExceptionArgs->FirstChance == FALSE );

        m.ReturnedStatus = DBG_EXCEPTION_HANDLED;
skip4:
        st = NtTerminateProcess(DebugProcess,STATUS_REPARSE);
        ASSERT(NT_SUCCESS(st));

        st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m);
        ASSERT(NT_SUCCESS(st));

        st = NtReplyWaitReceivePort(
                DebugPort,
                NULL,
                NULL,
                (PPORT_MESSAGE)&m
                );
        ASSERT(NT_SUCCESS(st));
        ASSERT(m.ApiNumber == DbgKmExitThreadApi);

        ExitThreadArgs = &m.u.ExitThread;
        ASSERT( ExitThreadArgs->ExitStatus == STATUS_REPARSE );

        st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m);
        ASSERT(NT_SUCCESS(st));

    DbgPrint("UdbgTest2: (5)...\n");

        //
        // Verify that ExitProcess Messages Arrive, and that
        // they are correct
        //

        st = NtReplyWaitReceivePort(
                DebugPort,
                NULL,
                NULL,
                (PPORT_MESSAGE)&m
                );
        ASSERT(NT_SUCCESS(st));
        ASSERT(m.ApiNumber == DbgKmExitProcessApi);

        ExitProcessArgs = &m.u.ExitProcess;
        ASSERT( ExitProcessArgs->ExitStatus == STATUS_REPARSE );

        st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m);
        ASSERT(NT_SUCCESS(st));


        st = NtWaitForSingleObject(ExceptionThread,FALSE,NULL);
        ASSERT(NT_SUCCESS(st));

        st = NtWaitForSingleObject(DebugProcess,FALSE,NULL);
        ASSERT(NT_SUCCESS(st));

    NtClose(ExceptionThread);
    NtClose(DebugProcess);

    DbgPrint("UdbgTest2: END OF TEST ***\n");
}