Пример #1
0
BOOL MapNewExecutableRegionInProcess(
		IN HANDLE TargetProcessHandle,
		IN HANDLE TargetThreadHandle,
		IN LPVOID NewExecutableRawImage)
{
	PROCESS_INFORMATION       BasicInformation;
	PIMAGE_SECTION_HEADER     SectionHeader;
	PIMAGE_DOS_HEADER         DosHeader;
	PIMAGE_NT_HEADERS         NtHeader64;
	DWORD_PTR                 dwImageBase;
	NtUnmapViewOfSection      pNtUnmapViewOfSection;
	LPVOID                    pImageBase;
	SIZE_T                    dwBytesWritten;
	SIZE_T                    dwBytesRead;
	int                       Count;
	PCONTEXT                  ThreadContext;
	BOOL                      Success = FALSE;

	DosHeader = (PIMAGE_DOS_HEADER)NewExecutableRawImage;
	if (DosHeader->e_magic == IMAGE_DOS_SIGNATURE)
	{
		NtHeader64 = (PIMAGE_NT_HEADERS64)((DWORD)NewExecutableRawImage + DosHeader->e_lfanew);
		if (NtHeader64->Signature == IMAGE_NT_SIGNATURE)
		{
			RtlZeroMemory(&BasicInformation, sizeof(PROCESS_INFORMATION));
			ThreadContext = (PCONTEXT)VirtualAlloc(NULL, sizeof(ThreadContext) + 4, MEM_COMMIT, PAGE_READWRITE);
			ThreadContext = (PCONTEXT)Align((DWORD)ThreadContext, 4);
			ThreadContext->ContextFlags = CONTEXT_FULL;
			if (GetThreadContext(TargetThreadHandle, ThreadContext)) //used to be LPCONTEXT(ThreadContext)
			{
				ReadProcessMemory(TargetProcessHandle, (LPCVOID)(ThreadContext->Rdx + 16), &dwImageBase, sizeof(DWORD_PTR), &dwBytesRead);

				pNtUnmapViewOfSection = (NtUnmapViewOfSection)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtUnmapViewOfSection");
				if (pNtUnmapViewOfSection)
					pNtUnmapViewOfSection(TargetProcessHandle, (PVOID)dwImageBase);

				pImageBase = VirtualAllocEx(TargetProcessHandle, (LPVOID)NtHeader64->OptionalHeader.ImageBase, NtHeader64->OptionalHeader.SizeOfImage, 0x3000, PAGE_EXECUTE_READWRITE);
				if (pImageBase)
				{
					WriteProcessMemory(TargetProcessHandle, pImageBase, (LPCVOID)NewExecutableRawImage, NtHeader64->OptionalHeader.SizeOfHeaders, &dwBytesWritten);
					SectionHeader = IMAGE_FIRST_SECTION(NtHeader64);
					for (Count = 0; Count < NtHeader64->FileHeader.NumberOfSections; Count++)
					{
						WriteProcessMemory(TargetProcessHandle, (LPVOID)((DWORD_PTR)pImageBase + SectionHeader->VirtualAddress), (LPVOID)((DWORD_PTR)NewExecutableRawImage + SectionHeader->PointerToRawData), SectionHeader->SizeOfRawData, &dwBytesWritten);
						SectionHeader++;
					}
					WriteProcessMemory(TargetProcessHandle, (LPVOID)(ThreadContext->Rdx + 16), (LPVOID)&NtHeader64->OptionalHeader.ImageBase, sizeof(DWORD_PTR), &dwBytesWritten);
					ThreadContext->Rcx = (DWORD_PTR)pImageBase + NtHeader64->OptionalHeader.AddressOfEntryPoint;
					SetThreadContext(TargetThreadHandle, (LPCONTEXT)ThreadContext);
					ResumeThread(TargetThreadHandle);
					Success = TRUE;
				}
				else
					TerminateProcess(TargetProcessHandle, 0);
				//VirtualFree(ThreadContext, 0, MEM_RELEASE);
			}
		}
	}

	return Success;
}
Пример #2
0
bool changeContextToUndoRecoving(HANDLE thread, CONTEXT* c){
	Q_UNUSED(c);
	return SetThreadContext(thread, &lastRecoveredContext);
}
Пример #3
0
//-------------------------------------------------------------------------
static void ProcessThreadIPs(HANDLE hThread, UINT pos, UINT action)
{
    // If the thread suspended in the overwritten area,
    // move IP to the proper address.

    CONTEXT c;
#ifdef _M_X64
    DWORD64 *pIP = &c.Rip;
#else
    DWORD   *pIP = &c.Eip;
#endif
    UINT count;

    c.ContextFlags = CONTEXT_CONTROL;
    if (!GetThreadContext(hThread, &c))
        return;

    if (pos == ALL_HOOKS_POS)
    {
        pos = 0;
        count = g_hooks.size;
    }
    else
    {
        count = pos + 1;
    }

    for (; pos < count; ++pos)
    {
        PHOOK_ENTRY pHook = &g_hooks.pItems[pos];
        BOOL        enable;
        DWORD_PTR   ip;

        switch (action)
        {
        case ACTION_DISABLE:
            enable = FALSE;
            break;

        case ACTION_ENABLE:
            enable = TRUE;
            break;

        case ACTION_APPLY_QUEUED:
            enable = pHook->queueEnable;
            break;
        }
        if (pHook->isEnabled == enable)
            continue;

        if (enable)
            ip = FindNewIP(pHook, *pIP);
        else
            ip = FindOldIP(pHook, *pIP);

        if (ip != 0)
        {
            *pIP = ip;
            SetThreadContext(hThread, &c);
        }
    }
}
Пример #4
0
static int r_debug_native_reg_write (RDebug *dbg, int type, const ut8* buf, int size) {

	// XXX use switch or so
	if (type == R_REG_TYPE_DRX) {
#if __i386__ || __x86_64__
#if __KFBSD__
		return (0 == ptrace (PT_SETDBREGS, dbg->pid,
			(caddr_t)buf, sizeof (struct dbreg)));
#elif __linux__
		return linux_reg_write (dbg, type, buf, size);
#elif __APPLE__
		if (1) return false; //disable until fixed ?? know why this
		return xnu_reg_write (dbg, type, buf, size);
#else
		//eprintf ("TODO: No support for write DRX registers\n");
		#if __WINDOWS__
		int tid = dbg->tid;
		int pid = dbg->pid;
		BOOL ret;
		HANDLE thread;
		CONTEXT ctx __attribute__((aligned (16)));
		memcpy (&ctx, buf, sizeof (CONTEXT));
		ctx.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
		thread = w32_open_thread (pid, tid);
		ret=SetThreadContext (thread, &ctx)? true: false;
		CloseHandle(thread);
		return ret;
		#endif
		return false;
#endif
#else // i386/x86-64
		return false;
#endif
	} else
	if (type == R_REG_TYPE_GPR) {
#if __WINDOWS__ && !__CYGWIN__
		BOOL ret;
		CONTEXT ctx __attribute__((aligned (16)));
		memcpy (&ctx, buf, sizeof (CONTEXT));
		ctx.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
	//	eprintf ("EFLAGS =%x\n", ctx.EFlags);
		HANDLE thread = w32_open_thread (dbg->pid, dbg->tid);
		ret = SetThreadContext (thread, &ctx)? true: false;
		CloseHandle (thread);
		return ret;
#elif __linux__
		return linux_reg_write (dbg, type, buf, size);
#elif __sun || __NetBSD__ || __KFBSD__ || __OpenBSD__
		int ret = ptrace (PTRACE_SETREGS, dbg->pid,
			(void*)(size_t)buf, sizeof (R_DEBUG_REG_T));
		if (sizeof (R_DEBUG_REG_T) < size)
			size = sizeof (R_DEBUG_REG_T);
		return (ret != 0) ? false: true;
#elif __APPLE__
		return xnu_reg_write (dbg, type, buf, size);
#else
#warning r_debug_native_reg_write not implemented
#endif
	} //else eprintf ("TODO: reg_write_non-gpr (%d)\n", type);
	return false;
}
Пример #5
0
LONG WINAPI DetourTransactionCommitEx(PVOID **pppFailedPointer)
{
    if (pppFailedPointer != NULL) {
        // Used to get the last error.
        *pppFailedPointer = s_ppPendingError;
    }
    if (s_nPendingThreadId != (LONG)GetCurrentThreadId()) {
        return ERROR_INVALID_OPERATION;
    }

    // If any of the pending operations failed, then we abort the whole transaction.
    if (s_nPendingError != NO_ERROR) {
        DETOUR_BREAK();
        DetourTransactionAbort();
        return s_nPendingError;
    }

    // Common variables.
    DetourOperation *o;
    DetourThread *t;

    // Insert or remove each of the detours.
    for (o = s_pPendingOperations; o != NULL; o = o->pNext) {
        if (o->fIsRemove) {
            PBYTE pbSrc = o->pTrampoline->rbCode;
            LONG cbCopy = 0;
            for (; cbCopy < o->pTrampoline->cbTarget;) {
                LONG lExtra = 0;
                pbSrc = (PBYTE)DetourCopyInstructionEx(o->pbTarget + cbCopy,
                                                       pbSrc, NULL, &lExtra);
                if (lExtra != 0) {
                    break;  // Abort if offset doesn't fit.
                }
                cbCopy = (LONG)(pbSrc - o->pTrampoline->rbCode);
            }
            if (cbCopy != o->pTrampoline->cbTarget) { // Count came out different!
                // This is a drastic error as the backward copy should never fail.
                s_nPendingError = ERROR_INVALID_DATA;
                s_ppPendingError = (PVOID*)o->ppbPointer;
                DETOUR_BREAK();
            }
#ifdef DETOURS_IA64
#error Feature not supported in this release.
#else // DETOURS_IA64
            *o->ppbPointer = o->pbTarget;
#endif
        }
        else {
            DETOUR_TRACE(("detours: pbTramp =%p, pbRemain=%p, pbDetour=%p, cbTarget=%d\n",
                          o->pTrampoline,
                          o->pTrampoline->pbRemain,
                          o->pTrampoline->pbDetour,
                          o->pTrampoline->cbTarget));

            DETOUR_TRACE(("detours: pbTarget=%p: "
                          "%02x %02x %02x %02x "
                          "%02x %02x %02x %02x "
                          "%02x %02x %02x %02x [before]\n",
                          o->pbTarget,
                          o->pbTarget[0], o->pbTarget[1], o->pbTarget[2], o->pbTarget[3],
                          o->pbTarget[4], o->pbTarget[5], o->pbTarget[6], o->pbTarget[7],
                          o->pbTarget[8], o->pbTarget[9], o->pbTarget[10], o->pbTarget[11]));

#ifdef DETOURS_IA64
#error Feature not supported in this release.


#endif // DETOURS_IA64

#ifdef DETOURS_X64
#error Feature not supported in this release.



#endif // DETOURS_X64

#ifdef DETOURS_X86
            PBYTE pbCode = detour_gen_jmp_immediate(o->pbTarget, o->pTrampoline->pbDetour);
            pbCode = detour_gen_brk(pbCode, o->pTrampoline->pbRemain);
            *o->ppbPointer = o->pTrampoline->rbCode;
#endif // DETOURS_X86

            DETOUR_TRACE(("detours: pbTarget=%p: "
                          "%02x %02x %02x %02x "
                          "%02x %02x %02x %02x "
                          "%02x %02x %02x %02x [after]\n",
                          o->pbTarget,
                          o->pbTarget[0], o->pbTarget[1], o->pbTarget[2], o->pbTarget[3],
                          o->pbTarget[4], o->pbTarget[5], o->pbTarget[6], o->pbTarget[7],
                          o->pbTarget[8], o->pbTarget[9], o->pbTarget[10], o->pbTarget[11]));

            DETOUR_TRACE(("detours: pbTramp =%p: "
                          "%02x %02x %02x %02x "
                          "%02x %02x %02x %02x "
                          "%02x %02x %02x %02x\n",
                          o->pTrampoline,
                          o->pTrampoline->rbCode[0], o->pTrampoline->rbCode[1],
                          o->pTrampoline->rbCode[2], o->pTrampoline->rbCode[3],
                          o->pTrampoline->rbCode[4], o->pTrampoline->rbCode[5],
                          o->pTrampoline->rbCode[6], o->pTrampoline->rbCode[7],
                          o->pTrampoline->rbCode[8], o->pTrampoline->rbCode[9],
                          o->pTrampoline->rbCode[10], o->pTrampoline->rbCode[11]));

#ifdef DETOURS_IA64
#error Feature not supported in this release.




























#endif // DETOURS_IA64
        }
    }

    // Update any suspended threads.
    for (t = s_pPendingThreads; t != NULL; t = t->pNext) {
        CONTEXT cxt;
        cxt.ContextFlags = CONTEXT_CONTROL;

#undef DETOURS_EIP
#undef DETOURS_EIP_TYPE

#ifdef DETOURS_X86
#define DETOURS_EIP         Eip
#define DETOURS_EIP_TYPE    DWORD
#endif // DETOURS_X86

#ifdef DETOURS_X64
#error Feature not supported in this release.

#endif // DETOURS_X64

#ifdef DETOURS_IA64
#error Feature not supported in this release.

#endif // DETOURS_IA64

        if (GetThreadContext(t->hThread, &cxt)) {
            for (DetourOperation *o = s_pPendingOperations; o != NULL; o = o->pNext) {
                if (o->fIsRemove) {
                    if (cxt.DETOURS_EIP >= (DETOURS_EIP_TYPE)(ULONG_PTR)o->pTrampoline &&
                            cxt.DETOURS_EIP < (DETOURS_EIP_TYPE)(ULONG_PTR)o->pTrampoline + sizeof(o->pTrampoline)) {

                        cxt.DETOURS_EIP -= (DETOURS_EIP_TYPE)(ULONG_PTR)o->pTrampoline;
                        cxt.DETOURS_EIP += (DETOURS_EIP_TYPE)(ULONG_PTR)o->pbTarget;

                        SetThreadContext(t->hThread, &cxt);
                    }
                }
                else {
                    if (cxt.DETOURS_EIP >= (DETOURS_EIP_TYPE)(ULONG_PTR)o->pbTarget &&
                            cxt.DETOURS_EIP < ((DETOURS_EIP_TYPE)(ULONG_PTR)o->pbTarget +
                                               o->pTrampoline->cbTarget)) {

                        cxt.DETOURS_EIP -= (DETOURS_EIP_TYPE)(ULONG_PTR)o->pbTarget;
                        cxt.DETOURS_EIP += (DETOURS_EIP_TYPE)(ULONG_PTR)o->pTrampoline;

                        SetThreadContext(t->hThread, &cxt);
                    }
                }
            }
        }
#undef DETOURS_EIP
    }

    // Restore all of the page permissions and flush the icache.
    HANDLE hProcess = GetCurrentProcess();
    for (o = s_pPendingOperations; o != NULL;) {
        // We don't care if this fails, because the code is still accessible.
        DWORD dwOld;
        VirtualProtect(o->pbTarget, o->pTrampoline->cbTarget, o->dwPerm, &dwOld);
        FlushInstructionCache(hProcess, o->pbTarget, o->pTrampoline->cbTarget);

        if (o->fIsRemove && o->pTrampoline) {
            detour_free_trampoline(o->pTrampoline);
            o->pTrampoline = NULL;
        }

        DetourOperation *n = o->pNext;
        delete o;
        o = n;
    }
    s_pPendingOperations = NULL;

    // Make sure the trampoline pages are no longer writable.
    detour_runnable_trampoline_regions();

    // Resume any suspended threads.
    for (t = s_pPendingThreads; t != NULL;) {
        // There is nothing we can do if this fails.
        ResumeThread(t->hThread);

        DetourThread *n = t->pNext;
        delete t;
        t = n;
    }
    s_pPendingThreads = NULL;
    s_nPendingThreadId = 0;

    if (pppFailedPointer != NULL) {
        *pppFailedPointer = s_ppPendingError;
    }

    return s_nPendingError;
}
Пример #6
0
int main(int argc,char **argv)
{
    parseArgs(argc, argv);

    SIZE_T bW = 0, bR = 0;
    char *exeInput = (char *)malloc(MAX_PATH);
    char *dllInput = (char *)malloc(MAX_PATH);
    char *wdrInput = (char *)malloc(MAX_PATH);

    memset(exeInput,0,MAX_PATH);
    memset(dllInput,0,MAX_PATH);
    memset(wdrInput,0,MAX_PATH);

    if (opMode == OPMODE_LIST)
    {
        listProcesses(stringToMatch);
        return 0;
    }
    else if(opMode == OPMODE_INJECT)
    {
        if (globalDll == NULL)
        {
            printf(" [dll] > ");
            fgets(dllInput,MAX_PATH,stdin);
        }
        else
        {
            strcpy(dllInput,globalDll);
        }
        injectIntoProcess(globalInject,dllInput);
        return 0;
    }

    if (globalTest)
    {
        strcpy(exeInput,"test.exe");
        strcpy(dllInput,"shackle.dll");
        strcpy(wdrInput,"c:\\projects\\elegurawolfe\\");
    }
    else if(globalExeName == NULL || globalWorkingDirectory == NULL || globalDll == NULL)
    {
        // printf("* SOMETHING MISSING %08x%08x%08x\n", (unsigned long )globalExeName, (unsigned long )globalWorkingDirectory, (unsigned long )globalDll);
        printf(" [exe] > ");
        fgets(exeInput,MAX_PATH,stdin);
        if (globalDll == NULL)
        {
            printf(" [dll] > ");
            fgets(dllInput,MAX_PATH,stdin);
        }
        else
        {
            strcpy(dllInput,globalDll);
        }
        printf(" [wdr] > ");
        fgets(wdrInput,MAX_PATH,stdin);

        chomp(exeInput);
        chomp(dllInput);
        chomp(wdrInput);
    }
    else
    {
        strcpy(exeInput,globalExeName);
        strcpy(dllInput,globalDll);
        strcpy(wdrInput,globalWorkingDirectory);
    }

    if (exists(exeInput) == 0)
    {
        printf(" [FAIL-EXE] %s does not exist\n",exeInput);
        return 0;
    }

    if(exists(dllInput) == 0)
    {
        printf(" [FAIL-DLL] %s does not exist\n",dllInput);
        return 0;
    }

    PROCESS_INFORMATION pi;
    STARTUPINFO si;

    memset (&pi,0,sizeof(PROCESS_INFORMATION));
    memset (&si, 0, sizeof (STARTUPINFO));
    si.cb = sizeof(si);

    HANDLE hNtDll = LoadLibrary("ntdll.dll");
    NtQueryInformationProcess = (_NtQueryInformationProcess )(GetProcAddress( (HMODULE )hNtDll, "NtQueryInformationProcess"));
    HANDLE hKernel = LoadLibrary("kernel32.dll");
    LPVOID addrLoadLibrary = GetProcAddress( (HMODULE )hKernel, "LoadLibraryA");

    BOOL derp = CreateProcess(exeInput, exeInput, NULL, NULL, FALSE, CREATE_SUSPENDED + CREATE_NEW_CONSOLE, NULL, wdrInput, &si, &pi);
    if (derp == NULL)
    {
        char *errorMessage;
        FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER +
                       FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError (), 0,
                       (char *) &errorMessage, 1, NULL);
        printf (" [FAIL] %s", errorMessage);
        return 0;
    }

    HANDLE hProcess = pi.hProcess;
    HANDLE hThread = pi.hThread;

    globalPid = pi.dwProcessId;
    printf(" * [INFO] new process id is %d\n",pi.dwProcessId);

#if ARCHI == 64
    BOOL wow64 = FALSE;
    IsWow64Process(hProcess,&wow64);

    if (wow64 == TRUE)
    {
        IsDll64Bit(globalDll);
        printf(" [WARN] injecting into wow64 ");
    }
#endif

    printf(" [INFO] process handle is %08x\n",(unsigned long )hProcess);

    PROCESS_BASIC_INFORMATION pib;
    PEB_ARCHI globalPEB;

    NtQueryInformationProcess (hProcess, 0, (PVOID )(&pib), sizeof (pib),& bW);
    printf(" [INFO] pib.PebBaseAddress = 0x%x (size of field is %d)\n", pib.PebBaseAddress, sizeof(pib.PebBaseAddress));

    ReadProcessMemory (hProcess, pib.PebBaseAddress, &globalPEB, sizeof (globalPEB), &bR);
    if (bR != sizeof (globalPEB))
    {
        char *errorMessage;
        FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER +
                       FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError (), 0,
                       (char *) &errorMessage, 1, NULL);
        printf (" [FAIL] %s", errorMessage);
        return 0;
    }

    printf(" [INFO] peb.ImageBaseAddress = %p\n", globalPEB.ImageBaseAddress);

    UINT_PTR entryPoint = guessExecutableEntryPoint (hProcess, globalPEB.ImageBaseAddress);
    printf(" [INFO] entryPoint = 0x%8x\n", entryPoint);

    char oldEntryChars[2];
    DWORD oldProtect = 0;
    DWORD discardProtect = 0;

    VirtualProtectEx(hProcess,(LPVOID )entryPoint,1, PAGE_READWRITE, &oldProtect);
    ReadProcessMemory(hProcess,(LPCVOID )entryPoint,(char *)oldEntryChars,2,&bR);
    printf(" [INFO] old entry is %02x %02x\n", (unsigned char )oldEntryChars[0],(unsigned char )oldEntryChars[1]);
    printf(" [INFO] writing...\n");

    WriteProcessMemory(hProcess,(LPVOID )entryPoint,"\xEB\xFE",2,&bW);
    VirtualProtectEx(hProcess,(LPVOID )entryPoint,1,oldProtect,&discardProtect);

    char newEntryChars[2];

    ReadProcessMemory(hProcess,(LPCVOID )entryPoint,(char *)newEntryChars,2,&bR);
    if (newEntryChars[0] == '\xEB' && newEntryChars[1] == '\xFE')
    {
        printf(" [INFO] new entry is %02x %02x\n", (unsigned char )newEntryChars[0],(unsigned char )newEntryChars[1]);
    }
    else
    {
        printf(" [INFO] new entry is %02x %02x, something's wrong\n", (unsigned char )newEntryChars[0],(unsigned char )newEntryChars[1]);
        return 0;
    }

    CONTEXT context;
    context.ContextFlags = CONTEXT_FULL;

    GetThreadContext (hThread, &context);
    context.PC_REG = entryPoint;
    SetThreadContext(hThread,&context);
    ResumeThread(pi.hThread);

    LPVOID remoteMemory = VirtualAllocEx(hProcess,NULL,strlen(dllInput) + 1,MEM_COMMIT + MEM_RESERVE, PAGE_READWRITE);
    WriteProcessMemory(hProcess,(LPVOID )remoteMemory,dllInput,strlen(dllInput) + 1,&bW);

    printf(" [INFO] trying to create a remote thread at %08x\n",(unsigned long )addrLoadLibrary);

    char *dllOutput = (char *)malloc(MAX_PATH);
    memset(dllOutput,0,MAX_PATH);
    ReadProcessMemory(hProcess,(LPCVOID )remoteMemory,dllOutput,MAX_PATH,&bR);
    printf(" [INFO] confirming process has cave with \"%s\"\n",dllOutput);
    free(dllOutput);

    if(globalWait)
    {
        printf(" [WAIT] press any key to create remote thread...\n");
        getc(stdin);
    }

    HANDLE threadId = CreateRemoteThread(hProcess,NULL,0,(LPTHREAD_START_ROUTINE )addrLoadLibrary,remoteMemory,NULL,NULL);
    if (threadId == NULL)
    {
        printf(" [INFO] could not create remote thread\n");
        return 0;
    }
    else
    {
        WaitForSingleObject(threadId, INFINITE);   //this waits untill thread thread has finished
        // VirtualFree(remoteMemory, 0, MEM_RELEASE); //free myFunc memory
        CloseHandle(threadId);
        // CloseHandle(hProcess);
    }

    int i = globalCooldown;
    for (; i > 0; i--)
    {
        printf(" [INFO] waiting %d seconds\n",i);
        Sleep(1000);
    }

    printf(" [INFO] restoring entrypoint...\n");
    SuspendThread(pi.hThread);

    VirtualProtectEx(hProcess,(LPVOID )entryPoint,1, PAGE_READWRITE, &oldProtect);
    i = WriteProcessMemory(hProcess,(LPVOID )entryPoint,(char *)&oldEntryChars,2,&bW);
    if (i == 0)
    {
        char *errorMessage;
        FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER +
                       FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError (), 0,
                       (char *) &errorMessage, 1, NULL);
        printf (" [FAIL] %s", errorMessage);
        return 0;
    }
    ReadProcessMemory(hProcess,(LPCVOID )entryPoint,(char *)newEntryChars,2,&bR);
    VirtualProtectEx(hProcess,(LPVOID )entryPoint,1, oldProtect, &discardProtect);
    printf(" [INFO] entry restored to %02x %02x\n", (unsigned char )newEntryChars[0],(unsigned char )newEntryChars[1]);
    GetThreadContext (hThread, &context);
    context.PC_REG = entryPoint;
    SetThreadContext(hThread,&context);
    ResumeThread(pi.hThread);

    printf(" [INFO] bye!");
    free(exeInput);
    free(dllInput);
    free(wdrInput);

    return 0;
}
Пример #7
0
DWORD ThreadHijackInjection(HANDLE hProcess, PCHAR dllName){
	
	DWORD CurrentPid = GetProcessId(hProcess);
	DWORD dwInjectionThread;
	HANDLE hThread;

	// We are going to just get a handle to a thread in the process, any thread.
	HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
	THREADENTRY32 te;

	if (h != INVALID_HANDLE_VALUE) {
		te.dwSize = sizeof(te);
		if (Thread32First(h, &te)) {
			do {
				if (te.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + sizeof(te.th32OwnerProcessID)) {
					if(te.th32OwnerProcessID == CurrentPid){
						dwInjectionThread = te.th32ThreadID;
					}
				}
				te.dwSize = sizeof(te);
			} while (Thread32Next(h, &te));
		}
		CloseHandle(h);
	}

	// Suspend that thread.
	hThread = OpenThread(THREAD_INJECT_PERMISSIONS, FALSE, te.th32ThreadID);
	SuspendThread(hThread);

	// Get its context, so we know where to return to after redirecting logic flow.
	CONTEXT context;
	context.ContextFlags = CONTEXT_FULL;
	GetThreadContext(hThread, &context);

	DWORD_PTR *returnPointer;

#ifdef _WIN64
	returnPointer = &context.Rip;
	#define PLACEHOLDER 0xDEADBEEFDEADBEEF
#else
	returnPointer = &context.Eip;
	#define PLACEHOLDER 0xDEADBEEF
#endif

	// Make a buffer for the PIC
	PVOID picBuf = malloc(GetLoaderPicSize());

	// Have the pic copied into that buffer.
	GetLoaderPic(picBuf, GetProcAddress(GetModuleHandleA("Kernel32.dll"),"LoadLibraryA"), dllName, (DWORD)(strlen(dllName)+1));

	// Replace deadbeef (return address) in the pic with a pointer to the thread's current position.
	for(DWORD i=0; i < GetLoaderPicSize() - sizeof(PVOID);i++){
		DWORD_PTR *deadbeef = (DWORD_PTR*)((DWORD_PTR)picBuf + i);
		if(*deadbeef == PLACEHOLDER){
			*deadbeef = *returnPointer;
			break;
		}
	}

	// Create a code cave in the target process.
	LPVOID cave = VirtualAllocEx(hProcess, 0, GetLoaderPicSize(), MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);

	// Copy over the pic
	WriteProcessMemory(hProcess, cave, picBuf, GetLoaderPicSize(), NULL);

	// Redirect execution flow.
	*returnPointer = (DWORD_PTR)cave;
	SetThreadContext(hThread,&context);
	ResumeThread(hThread);

	return 1;
}
bool WINAPI CreateMemoryProcess(
								LPVOID lpImage,
								char* pPath
								)
{
	// Variables for Process Forking
	/////////////////////////////////////////////////////////////////
	DWORD                lWritten;
	DWORD                lImageSize;
	DWORD                lImageBase;
	DWORD                lImageHeaderSize;
	DWORD                lFirstSection;
	DWORD                lJumpSize = 0;
	DWORD                lSectionCount;
	DWORD                lSectionSize;
	DWORD                lPreviousProtection;

	LPVOID                  lpImageMemory;

    IMAGE_DOS_HEADER        dsDosHeader;
    IMAGE_NT_HEADERS        ntNtHeader;
    IMAGE_SECTION_HEADER    shSections[512 * 2];

    PROCESS_INFORMATION     piProcessInformation;
    STARTUPINFO             suStartUpInformation;
    CONTEXT                 cContext;
	DWORD					lProccessBaseAdress;
	DWORD					lProccessImageSize;

	char*                   pProcessName;
	bool					bIsNewProccessName = false;
	bool					bReturnValue = false;
    /////////////////////////////////////////////////////////////////
    // End Variable Definition
	
	if(strlen(pPath) == 0)
	{
		// No process name is set. Trying to fork this process
		pProcessName = new char[MAX_PATH];
		ZeroMemory(pProcessName, MAX_PATH);
		bIsNewProccessName = true;

#ifdef CPDEBUG
			printf("Trying to fork same process file\n");
#endif
		// Get the file name for the dummy process
		if(GetModuleFileName(NULL, pProcessName, MAX_PATH) == 0)
		{
#ifdef CPDEBUG
			printf("Error: Can't recive GetModuleFileName() from proccess.\n");
#endif
			delete [] pProcessName;
			return bReturnValue;
		}
	}
	else
	{
		pProcessName = pPath;
	}
    
#ifdef CPDEBUG
	printf("Using %s for injection\n", pProcessName);
#endif

    // Grab the DOS Headers
    memcpy(&dsDosHeader, lpImage, sizeof(dsDosHeader));
    if(dsDosHeader.e_magic != IMAGE_DOS_SIGNATURE)
    {
#ifdef CPDEBUG
		printf("Error: File DOS header wrong\n");
#endif
		if(bIsNewProccessName)
			delete [] pProcessName;
        return false;
    }

    // Grab NT Headers
	memcpy(&ntNtHeader, (LPVOID)((DWORD)lpImage + dsDosHeader.e_lfanew), sizeof(ntNtHeader));
    if(ntNtHeader.Signature != IMAGE_NT_SIGNATURE)
    {
#ifdef CPDEBUG
		printf("Error: No NT Signature finded.\n");
#endif
		if(bIsNewProccessName)
			delete [] pProcessName;
        return false;
    }

    // Get Size and Image Base
	lImageBase = ntNtHeader.OptionalHeader.ImageBase;
	lImageSize = ntNtHeader.OptionalHeader.SizeOfImage;
    lImageHeaderSize = ntNtHeader.OptionalHeader.SizeOfHeaders;
#ifdef CPDEBUG
		printf("New image base = %X\n", lImageBase);
		printf("New image size = %d\n", lImageSize);
		printf("New image header size = %d\n", lImageHeaderSize);
#endif

    // Allocate memory for image
    lpImageMemory = new LPVOID[lImageSize];
    ZeroMemory(lpImageMemory, lImageSize);

    lFirstSection = (DWORD)(((DWORD)lpImage + dsDosHeader.e_lfanew) + sizeof(IMAGE_NT_HEADERS));
    
    memcpy(shSections, (LPVOID)(lFirstSection), sizeof(IMAGE_SECTION_HEADER) * ntNtHeader.FileHeader.NumberOfSections);
#ifdef CPDEBUG
		printf("%d header sections founded\n", ntNtHeader.FileHeader.NumberOfSections);
#endif
	memcpy(lpImageMemory, lpImage, lImageHeaderSize);

    // Get Section Alignment
    if((ntNtHeader.OptionalHeader.SizeOfHeaders % ntNtHeader.OptionalHeader.SectionAlignment) == 0)
    {
        lJumpSize = ntNtHeader.OptionalHeader.SizeOfHeaders;
    }
    else
    {
        lJumpSize = ntNtHeader.OptionalHeader.SizeOfHeaders / ntNtHeader.OptionalHeader.SectionAlignment;
        lJumpSize += 1;
        lJumpSize *= ntNtHeader.OptionalHeader.SectionAlignment;
    }

    LPVOID lpImageMemoryDummy = (LPVOID)((DWORD)lpImageMemory + lJumpSize);

    // Copy Sections To Buffer
    for(lSectionCount = 0; lSectionCount < ntNtHeader.FileHeader.NumberOfSections; lSectionCount++)
    {
        lJumpSize = 0;
        lSectionSize = shSections[lSectionCount].SizeOfRawData;
        
        memcpy(lpImageMemoryDummy, (LPVOID)((DWORD)lpImage + shSections[lSectionCount].PointerToRawData), lSectionSize);

        if((shSections[lSectionCount].Misc.VirtualSize % ntNtHeader.OptionalHeader.SectionAlignment) == 0)
        {
            lJumpSize = shSections[lSectionCount].Misc.VirtualSize;
        }
        else
        {
            lJumpSize  = shSections[lSectionCount].Misc.VirtualSize / ntNtHeader.OptionalHeader.SectionAlignment;
            lJumpSize += 1;
            lJumpSize *= ntNtHeader.OptionalHeader.SectionAlignment;
        }

        lpImageMemoryDummy = (LPVOID)((DWORD)lpImageMemoryDummy + lJumpSize);
    }

    ZeroMemory(&suStartUpInformation, sizeof(STARTUPINFO));
    ZeroMemory(&piProcessInformation, sizeof(PROCESS_INFORMATION));
    ZeroMemory(&cContext, sizeof(CONTEXT));

    suStartUpInformation.cb = sizeof(suStartUpInformation);

    // Create Process
    if(CreateProcess(
					NULL,
					pProcessName,
					NULL,
					NULL,
					false,
					CREATE_SUSPENDED,
					NULL,
					NULL,
					&suStartUpInformation,
					&piProcessInformation
					))
    {
#ifdef CPDEBUG
			printf("Proccess suspended\n");
#endif
        cContext.ContextFlags = CONTEXT_FULL;
		if(!GetThreadContext(piProcessInformation.hThread,&cContext))
		{
#ifdef CPDEBUG
			printf("Fail to get context of suspended proccess.\n");
#endif
			TerminateProcess(piProcessInformation.hProcess, 0);
			if(bIsNewProccessName)
				delete [] pProcessName;
            delete [] lpImageMemory;
            return false;
			return true;
		}

		DWORD *pEbxInfo = (DWORD *)cContext.Ebx;
		DWORD read;
		ReadProcessMemory(
							piProcessInformation.hProcess, 
							&pEbxInfo[2], 
							(LPVOID)&lProccessBaseAdress, 
							sizeof(DWORD), 
							&read
							);

		DWORD curAddr = lProccessBaseAdress;
		MEMORY_BASIC_INFORMATION memInfo;
		while(VirtualQueryEx(
								piProcessInformation.hProcess, 
								(LPVOID)curAddr, 
								&memInfo, 
								sizeof(memInfo))
							)
		{
			if(memInfo.State == MEM_FREE)
				break;
			curAddr += memInfo.RegionSize;
		}
		lProccessImageSize = (DWORD)curAddr - (DWORD)lProccessBaseAdress;

#ifdef CPDEBUG
		printf("Current image base adress = %X\n", lProccessBaseAdress);
		printf("Current image size = %d\n", lProccessImageSize);
#endif

        // Check image base and image size
        if(lImageBase == lProccessBaseAdress && lImageSize <= lProccessImageSize)
        {
			// we can load new image to same place
#ifdef CPDEBUG
		printf("Using same image place\n");
#endif
            VirtualProtectEx(
								piProcessInformation.hProcess,
								(LPVOID)lImageBase,
								lImageSize,
								PAGE_EXECUTE_READWRITE,
								(DWORD*)&lPreviousProtection
							);
        }
        else
        {
			// We can't use same place, allocate memory for it.
#ifdef CPDEBUG
			printf("Allocation place for new image\n");
#endif
            if(NtUnmapViewOfSection(
										piProcessInformation.hProcess,
										(LPVOID)lProccessBaseAdress
									) == 0)
			{
#ifdef CPDEBUG
					printf("Old section unmaped\n");
#endif
					LPVOID lpIsAllocated = VirtualAllocEx(
											piProcessInformation.hProcess,
											(LPVOID)lImageBase,
											lImageSize,
											MEM_COMMIT | MEM_RESERVE,
											PAGE_EXECUTE_READWRITE
									);
					if(lpIsAllocated)
					{
#ifdef CPDEBUG
						printf("Memory allocated successful\n");
#endif
					}
					else
					{
#ifdef CPDEBUG
						printf("Error: Can't allocated\n");
#endif
					}
			}
			else
			{
#ifdef CPDEBUG
				printf("Error: Can't unmap old section\n");
#endif
			}
        }

        // Write Image to Process
        if(WriteProcessMemory(
								piProcessInformation.hProcess,
								(LPVOID)lImageBase,
								lpImageMemory,
								lImageSize,
								(DWORD*)&lWritten
							))
        {
            bReturnValue = true;
#ifdef CPDEBUG
		printf("New image writen\n");
#endif
        }
		else
		{
#ifdef CPDEBUG
			printf("Error: New image written error.\n");
#endif
		}

        // Set Image Base
        if(WriteProcessMemory(
								piProcessInformation.hProcess,
								(LPVOID)((DWORD)cContext.Ebx + 8),
								&lImageBase,
								4,
								(DWORD*)&lWritten)
							)
        {
#ifdef CPDEBUG
			printf("Updated init point\n");
#endif
        }
		else
		{
			bReturnValue = false;
#ifdef CPDEBUG
			printf("Error: Can't update init point\n");
#endif
		}

        if(!bReturnValue)
        {
#ifdef CPDEBUG
			printf("Error: Error during image rewriting. Exit.\n");
#endif
			TerminateProcess(piProcessInformation.hProcess, 0);
			if(bIsNewProccessName)
				delete [] pProcessName;
            delete [] lpImageMemory;
            return false;
        }

        // Set the new entry point
        cContext.Eax = lImageBase + ntNtHeader.OptionalHeader.AddressOfEntryPoint;
        
        SetThreadContext(
						piProcessInformation.hThread,
						&cContext
						);

		if(lImageBase == lProccessBaseAdress && lImageSize <= lProccessImageSize)
		{
#ifdef CPDEBUG
			printf("Returning old protection for new image.\n");
#endif
            VirtualProtectEx(
								piProcessInformation.hProcess,
								(LPVOID)lImageBase,
								lImageSize,
								lPreviousProtection,
								0
								);
		}
        // Resume the process
        ResumeThread(piProcessInformation.hThread);
    }
	else
	{
#ifdef CPDEBUG
		printf("Error: Can't start %s\n", pProcessName);
#endif
		return false;
	}

	if(bIsNewProccessName)
		delete [] pProcessName;
    delete [] lpImageMemory;

	if(bReturnValue)
	{
#ifdef CPDEBUG
			printf("Successful injected. No errors during doing this.\n");
#endif
	}

    return bReturnValue;
}
Пример #9
0
TARGET_ADDRESS nub_setup_function_call 
  (NUB nub, 
   NUBTHREAD thread,
   TARGET_ADDRESS function, 
   NUBINT arg_count,
   TARGET_ADDRESS *args,
   NUBHANDLE *context_cookie)
{
  LPDBGPROCESS        process = (LPDBGPROCESS) nub;
  LPDBGTHREAD         threadC = (LPDBGTHREAD) thread;
  CONTEXT             context;
  THREAD_MEMORY       *saved_thread 
                       = (THREAD_MEMORY*) malloc (sizeof(THREAD_MEMORY));
  BOOL                status;
  DWORD               stack_position;
  DWORD               original_IP;
  DWORD               i = 0;
  BOOL                write_status;
  DWORD               bytes_written;
  TARGET_ADDRESS      address_to_break;

  // suspend_thread(threadC);

  // Now get context information. We need to know the return address
  // for our frame-to-be, and also the stack pointer + frame pointer
  // as is.

  context.ContextFlags = CONTEXT_FULL;

  status = get_thread_context(process, threadC, &context);

  dylan_debugger_message("nub_setup_function_call: Thread Context: %= : %=",
			 threadC->ThreadHandle, status);
  dylan_debugger_message("Esp: %=  Eip: %=",
			 context.Esp,
			 context.Eip);

  //print_context("Context pulled from thread state", &context);

  // Now remember everything about the debug state of this thread.

  saved_thread->ThreadState = threadC->ThreadState;
  saved_thread->WaitingForDebugger = threadC->WaitingForDebugger;
  saved_thread->SingleStepping = threadC->SingleStepping;
  saved_thread->NeedsBreakpointReplacement 
     = threadC->NeedsBreakpointReplacement;
  saved_thread->BreakpointToReplace = threadC->BreakpointToReplace;
  saved_thread->StoppedState = threadC->StoppedState;
  saved_thread->LastReceivedEvent = threadC->LastReceivedEvent;
  saved_thread->NubCodeOfLastEvent = threadC->NubCodeOfLastEvent;
  saved_thread->ThreadContext = context;

  // Allocate enough space on the stack to hold the arguments to the
  // remote function, and the return address.

  stack_position = 
     (DWORD) nub_allocate_stack_space
       (nub, 
        thread,
        ((DWORD) (arg_count + 1)) * sizeof(DWORD));

  if (stack_position == 0x0) {
    debugger_error("Serious Error: Failed to allocate stack in Spy call on Thread %=",
		   (TARGET_ADDRESS)threadC->ThreadHandle,
		   (TARGET_ADDRESS)NULL);
    // Internal error
    return(NULL);
  }

  // And get ready for the remote call. If the thread was stopped at a
  // breakpoint, we need to override that, because we are going to alter
  // the instruction pointer.

  if (saved_thread->NeedsBreakpointReplacement) {
    LPDEBUG_POINT breakpoint = saved_thread->BreakpointToReplace;
    drop_breakpoint(process, breakpoint);
    threadC->NeedsBreakpointReplacement = FALSE;
    if (!(saved_thread->SingleStepping)) {
      context.EFlags = context.EFlags & 0xFFFFFEFF;
    }
    // And resume those threads that will have been suspended.
    // resume_all_except(process, thread);
  }

  if (!status) {
    // Internal nub error.
    return (NULL);
  }

  //print_context("Context being saved", &(saved_thread->ThreadContext));

  // Grab the return address so that the access path chappies can set a
  // breakpoint on it to clean up the stack.

  address_to_break = (TARGET_ADDRESS) context.Eip;
  original_IP = context.Eip;

  // DIY stack frame!!!!
  // We are using the C calling convention to bring about our remote
  // call. At the point of call, the new stack frame must have all the
  // arguments pushed, followed by the return address.

  context.Esp = stack_position;

  // And make the instruction pointer point to our function.

  context.Eip = (DWORD) function;

  // The stack should now be fooling this thread into thinking that
  // it has to execute our remote function, which it will go off and do
  // as soon as the application resumes. But we have to set the context.

  status = SetThreadContext (threadC->ThreadHandle, &context);

  if (!status) {
    // Internal nub error.
    return(NULL);
  }

  // print_context("Context set back to thread", &context);
  // Push the return address - ie, the next instruction that was going
  // to be executed, before we started messing about...

  write_status =
    ValidatedWriteProcessMemory 
      (process->ProcessHandle,
       (LPVOID) stack_position,
       (LPVOID) &(original_IP),
       sizeof(TARGET_ADDRESS),
       &bytes_written);

  stack_position += sizeof(TARGET_ADDRESS);

  if ((!write_status) || (bytes_written != sizeof(TARGET_ADDRESS))) {
    // Internal nub error.
    return (NULL);
  }

  // Push the argument array.

  for (i = 0; i < (DWORD) arg_count; i++) {

    write_status =
      ValidatedWriteProcessMemory 
        (process->ProcessHandle,
         (LPVOID) stack_position,
         (LPVOID) &(args[i]),
         sizeof(TARGET_ADDRESS),
         &bytes_written);

    if ((!write_status) || (bytes_written != sizeof(TARGET_ADDRESS))) {
      // Internal nub error.
      return (NULL);
    }
    else {
      //printf ("Wrote the argument %x at %x.\n", args[i], stack_position);
    }
    stack_position += sizeof(TARGET_ADDRESS);
  }


  //print_context("Context set back to thread", &context);

  (*context_cookie) = (NUBHANDLE) saved_thread;
  //resume_thread(threadC);
  return (address_to_break);
}
Пример #10
0
/// <summary>
/// Set native thread context
/// </summary>
/// <param name="hThread">Thread handle.</param>
/// <param name="ctx">Thread context</param>
/// <returns>Status code</returns>
NTSTATUS Native::SetThreadContextT( HANDLE hThread, _CONTEXT64& ctx )
{
    LastNtStatus( STATUS_SUCCESS );
    SetThreadContext( hThread, reinterpret_cast<PCONTEXT>(&ctx) );
    return LastNtStatus();
}
Пример #11
0
int r3dSetDataBreakpoint( void* address, r3dDataBreakpointByteLen byteLen, int condition )
{
#ifndef FINAL_BUILD
	g_BreakPointThreads.Clear();

	HANDLE hThreadSnap = INVALID_HANDLE_VALUE; 
	THREADENTRY32 te32;

	// Take a snapshot of all running threads  
	hThreadSnap = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 ); 
	if( hThreadSnap == INVALID_HANDLE_VALUE ) 
		return 0;

	// Fill in the size of the structure before using it. 
	te32.dwSize = sizeof(THREADENTRY32 ); 

	// Retrieve information about the first thread,
	// and exit if unsuccessful
	if( !Thread32First( hThreadSnap, &te32 ) ) 
	{
		return 0;
	}

	DWORD currProcessID = GetCurrentProcessId();

	// Now walk the thread list of the system,
	// and display information about each thread
	// associated with the specified process
	do 
	{ 
		if( te32.th32OwnerProcessID == currProcessID )
		{
			g_BreakPointThreads.PushBack( te32.th32ThreadID );
		}
	} while( Thread32Next(hThreadSnap, &te32 ) );

	//  Don't forget to clean up the snapshot object.
	CloseHandle( hThreadSnap );

	//------------------------------------------------------------------------

	int currentThreadId = GetCurrentThreadId();

	for( int i = 0; i < (int)g_BreakPointThreads.Count(); i ++ )
	{
		CONTEXT cxt;

		int threadId = g_BreakPointThreads[ i ];

		HANDLE threadHandle = OpenThread( THREAD_ALL_ACCESS, FALSE, threadId );

		if( threadHandle == INVALID_HANDLE_VALUE )
			return 0;

		if( threadId != currentThreadId )
			SuspendThread( threadHandle );

		int len = 0;

		switch( byteLen )
		{
		case R3D_DATABREAKPOINT_1_BYTE: len = 0; break;
		case R3D_DATABREAKPOINT_2_BYTES: len = 1; break;
		case R3D_DATABREAKPOINT_4_BYTES: len = 3; break;
		default: r3d_assert(false); // invalid length
		}

		// The only registers we care about are the debug registers
		cxt.ContextFlags = CONTEXT_DEBUG_REGISTERS;

		// Read the register values
		if( !GetThreadContext(threadHandle, &cxt) )
		{
			CloseHandle( threadHandle );
			return 0;
		}

		// Find an available hardware register
		int index = 0;
		for( index = 0; index < 4; ++index )
		{
			if( ( cxt.Dr7 & ( 1 << ( index * 2 ) ) ) == 0 )
				break;
		}

		r3d_assert( index < 4 ); // All hardware breakpoint registers are already being used

		switch ( index )
		{
		case 0: cxt.Dr0 = (DWORD) address; break;
		case 1: cxt.Dr1 = (DWORD) address; break;
		case 2: cxt.Dr2 = (DWORD) address; break;
		case 3: cxt.Dr3 = (DWORD) address; break;
		default: assert(false); // m_index has bogus value
		}

		SetBits(cxt.Dr7, 16 + (index*4), 2, condition);
		SetBits(cxt.Dr7, 18 + (index*4), 2, len);
		SetBits(cxt.Dr7, index*2,        1, 1);

		// Write out the new debug registers

		int failed = 0;

		if ( !SetThreadContext(threadHandle, &cxt) )
			failed = 1;


		if( threadId != currentThreadId )
			ResumeThread( threadHandle );

		CloseHandle( threadHandle );

		if( failed )
			return 0;
	}
#endif
	return 1;
}
Пример #12
0
STATUS 
DbgThreadSetBreakpoint(
	IN PHWBREAKDATA BreakpointData
	)
{
	HANDLE hThread;
	DWORD dwDebugRegister;
	CONTEXT	ctxThreadContext = {0};
	ERRORINFO err;
	CHAR szBreakType[20] = {'\0'};
	ctxThreadContext.ContextFlags = CONTEXT_DEBUG_REGISTERS;

	/* Open thread with desired access */
	hThread = OpenThread( THREAD_SET_CONTEXT | THREAD_GET_CONTEXT | THREAD_SUSPEND_RESUME , 
		                   FALSE, 
						   BreakpointData->dwThreadId);
	if ( hThread == NULL )
	{
		REPORT_ERROR("OpenThread()", &err);
		/* Set the Error Flag to proper value */
		BreakpointData->dwStatus = DR_BREAK_ERROR_UNK; 
		return PWNYPOT_STATUS_INTERNAL_ERROR;
	}

	/* Is thread already suspend ? */
	if ( BreakpointData->dwThreadStatus != THREAD_ALREADY_SUSPEND )
	{
		/* Suspend thread for getting/setting thread context in a safe manner */
		if ( SuspendThread(hThread) == -1 )
		{
			REPORT_ERROR("SuspendThread()",&err);
			BreakpointData->dwStatus = DR_BREAK_ERROR_UNK;
			return PWNYPOT_STATUS_INTERNAL_ERROR;

		}
	}
	
	/* Get thread current context */
	if ( !GetThreadContext(hThread,&ctxThreadContext) )
	{
		REPORT_ERROR("GetThreadContext()",&err);
		BreakpointData->dwStatus = DR_BREAK_ERROR_UNK;
		return PWNYPOT_STATUS_INTERNAL_ERROR;
	}
	
	/* check if Dr(n) is busy with another Hardware Breakpoint? */
	if ( !IsBitSet(ctxThreadContext.Dr7,0) || !IsBitSet(ctxThreadContext.Dr7,1) )
	{
		/* Set the Debug Register */
		dwDebugRegister = 0;
		/* Set the breakpoint address */
		ctxThreadContext.Dr0 = (DWORD)BreakpointData->Address;
		/* Set Dr(n) state as a busy register, it can be use for removing specific breakpoint */
		BreakpointData->dwDrBusyRemove = dwDebugRegister;

	} else if ( !IsBitSet(ctxThreadContext.Dr7,2) || !IsBitSet(ctxThreadContext.Dr7,3) )
	{
		dwDebugRegister = 1;
		ctxThreadContext.Dr1 = (DWORD)BreakpointData->Address;
		BreakpointData->dwDrBusyRemove = dwDebugRegister;

	} else if ( !IsBitSet(ctxThreadContext.Dr7,4) || !IsBitSet(ctxThreadContext.Dr7,5) )
	{
		dwDebugRegister = 2;
		ctxThreadContext.Dr2 = (DWORD)BreakpointData->Address;
		BreakpointData->dwDrBusyRemove = dwDebugRegister;

	} else if ( !IsBitSet(ctxThreadContext.Dr7,6) || !IsBitSet(ctxThreadContext.Dr7,7) )
	{
		dwDebugRegister = 3;
		ctxThreadContext.Dr3 = (DWORD)BreakpointData->Address;
		BreakpointData->dwDrBusyRemove = dwDebugRegister;

	} else 
	{
		/* All Debug Registers are busy */
		BreakpointData->dwStatus = DR_ALL_BUSY;
		return PWNYPOT_STATUS_GENERAL_FAIL;
	}

	/* Set the proper bit in Dr7 for used Debug Register and Breakpoint type */
	ctxThreadContext.Dr7 |= 1 << (dwDebugRegister * 2);
	ctxThreadContext.Dr7 |= BreakpointData->dwCondition << ((dwDebugRegister * 4) + 16);
	ctxThreadContext.Dr7 |= 1 << ((dwDebugRegister * 4) + 18);

	/* Enable the Breakpoint for thread by setting the thread context */
	if ( !SetThreadContext(hThread,&ctxThreadContext) )
	{
		REPORT_ERROR("GetThreadContext()",&err);
		BreakpointData->dwStatus = DR_BREAK_ERROR_UNK;
		return PWNYPOT_STATUS_INTERNAL_ERROR;
	}

	BreakpointData->dwStatus = DR_BREAK_SET;
	switch ( BreakpointData->dwCondition )
	{
	case HW_ACCESS:
		strncpy( szBreakType, HW_ACCESS_STR, 20);
		break;
	case HW_EXECUTE:
		strncpy( szBreakType, HW_EXECUTE_STR, 20);
		break;
	case HW_WRITE:
		strncpy( szBreakType, HW_WRITE_STR, 20);
		break;
	}

	DEBUG_PRINTF(LDBG, NULL, "Breakpoint On | TID : %p - Dr%d - Len : %d - Condition : %s!\n", BreakpointData->dwThreadId , dwDebugRegister, BreakpointData->dwSize , szBreakType);
	
	/* Resume the thread if it was not in suspend state at creation time */
	if ( BreakpointData->dwThreadStatus != THREAD_ALREADY_SUSPEND )
		ResumeThread(hThread);
	return PWNYPOT_STATUS_SUCCESS;
}
Пример #13
0
void clear_application_breakpoint (LPDBGPROCESS process, DWORD address)
{
  LPDEBUG_POINT this_debug_point, last_debug_point;
  LPDBGTHREAD   this_thread;

  if (!process->ExitingProcess) {

  dylan_debugger_message("clear_application_breakpoint %=", address, 0);

  this_debug_point = process->DebugPointList;
  this_thread = process->ThreadList;
  last_debug_point = NULL;

  while (this_debug_point != NULL) {

    if ((this_debug_point->DebugPointType == DBG_POINT_BREAKPOINT) &&
        (this_debug_point->u.Breakpoint.Type == APPLICATION_BREAKPOINT) &&
        (this_debug_point->u.Breakpoint.Address == address)) {

      // Lift out the breakpoint.

      lift_breakpoint(process, this_debug_point);

      // One or more threads might actually be stopped at this breakpoint.
      // If so, they must be stopped from writing it back into the
      // process.

      this_thread = process->ThreadList;
      while (this_thread != NULL) {
        CONTEXT  context;
        if (this_thread->NeedsBreakpointReplacement) {

          // This thread is waiting at a breakpoint. If that breakpoint
          // is the one we're removing now, we have to hack its state.

          if (this_thread->BreakpointToReplace == this_debug_point) {

            dylan_debugger_message("Thread no longer needs breakpoint replacement %= %=",
                                   this_thread->ThreadHandle, address);

            this_thread->NeedsBreakpointReplacement = FALSE;

            // The thread will have been put into single-step mode in order
            // to recover from the breakpoint. But it might also be in
            // single-step mode anyway! If it isn't, take it out of
            // single-step mode.

            if (!(this_thread->SingleStepping)) {
              context.ContextFlags = CONTEXT_CONTROL;
              get_thread_context(process, this_thread, &context);
              context.EFlags = context.EFlags & 0xFFFFFEFF;
              SetThreadContext(this_thread->ThreadHandle, &context);
              // resume_all_except(process, this_thread);
            }
          }
        }
        this_thread = this_thread->Next;
      }

      // Delete the descriptor from the list.

      if (last_debug_point == NULL) {
        // This shouldn't happen, but we might as well handle it.
        (process->DebugPointList) = this_debug_point->Next;
        free(this_debug_point);
        this_debug_point = (process->DebugPointList);
      }
      else {
        last_debug_point->Next = this_debug_point->Next;
        free(this_debug_point);
        this_debug_point = (last_debug_point->Next);
      }

    }
    else {
        last_debug_point = this_debug_point;
        this_debug_point = this_debug_point->Next;
    }
  }
  }
}
Пример #14
0
/* PIC inject for win8/8.1 */
BOOL pic_inject(void *mpara, LPCWSTR dll_name)
{
    BOOL		exitCode = FALSE;
    CONTEXT		context;
    DWORD_PTR	*returnPointer;
    DWORD_PTR	i;
    PVOID		picBuf;
    LPVOID		funcBuff;
    SIZE_T		cbSize;
    char		dllName[VALUE_LEN+1];
    HMODULE		hNtdll;
    PROCESS_INFORMATION pi = *(LPPROCESS_INFORMATION)mpara;
    _NtAllocateVirtualMemory TrueNtAllocateVirtualMemory = NULL;
    _NtWriteVirtualMemory	 TrueNtWriteVirtualMemory	 = NULL;
    _NtFreeVirtualMemory	 TrueNtFreeVirtualMemory	 = NULL;
    _NtResumeThread			 TrueNtResumeThread			 = NULL;
    hNtdll = GetModuleHandleW(L"ntdll.dll");
    if (!hNtdll)
    {
        return exitCode;
    }
    TrueNtAllocateVirtualMemory = (_NtAllocateVirtualMemory)GetProcAddress(hNtdll, "NtAllocateVirtualMemory");
    TrueNtWriteVirtualMemory = (_NtWriteVirtualMemory)GetProcAddress(hNtdll, "NtWriteVirtualMemory");
    TrueNtFreeVirtualMemory = (_NtFreeVirtualMemory)GetProcAddress(hNtdll, "NtFreeVirtualMemory");
    TrueNtResumeThread = (_NtResumeThread)GetProcAddress(hNtdll, "NtResumeThread");
    if ( !(TrueNtAllocateVirtualMemory &&
           TrueNtWriteVirtualMemory    &&
           TrueNtFreeVirtualMemory     &&
           TrueNtResumeThread)
       )
    {
        return exitCode;
    }
    if ( !WideCharToMultiByte(CP_ACP, 0,dll_name,(int)((wcslen(dll_name)+1)*sizeof(WCHAR)), \
                              dllName, VALUE_LEN,"" , NULL)
       )
    {
        return exitCode;
    }
    /* Get its context, so we know where to return to after redirecting logic flow. */
    context.ContextFlags = CONTEXT_FULL;
    GetThreadContext(pi.hThread, &context);
#ifdef _WIN64
    returnPointer = &context.Rip;
#define PLACEHOLDER 0xDEADBEEFDEADBEEF
#else
    returnPointer = &context.Eip;
#define PLACEHOLDER 0xDEADBEEF
#endif
    cbSize = GetLoaderPicSize();
    /* Make a buffer for the PIC */
    picBuf = SYS_MALLOC(cbSize);
    if ( !picBuf )
    {
        return exitCode;
    }
#ifdef _LOGDEBUG
    logmsg("cbSize = %lu\n",cbSize);
#endif
    /* Have the pic copied into that buffer. */
    GetLoaderPic(picBuf, GetProcAddress(GetModuleHandleA("Kernel32.dll"),"LoadLibraryA"), \
                 dllName, (DWORD_PTR)(strlen(dllName)+1));
    /* Replace deadbeef (return address) in the pic with a pointer to the thread's current position. */
    for(i=0; i < cbSize - sizeof(PVOID); i++)
    {
        DWORD_PTR *deadbeef = (DWORD_PTR*)((DWORD_PTR)picBuf + i);
        if(*deadbeef == PLACEHOLDER) {
            *deadbeef = *returnPointer;
            break;
        }
    }

    /* Create a code funcBuff in the target process. */
    funcBuff = VirtualAllocEx(pi.hProcess, 0, cbSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    WriteProcessMemory(pi.hProcess, funcBuff, picBuf, cbSize, NULL);
    *returnPointer = (DWORD_PTR)funcBuff;
    exitCode = SetThreadContext(pi.hThread,&context);
    TrueNtResumeThread(pi.hThread,NULL);
    SYS_FREE(picBuf);
    cbSize = 0;
    TrueNtFreeVirtualMemory(pi.hProcess,funcBuff,&cbSize,MEM_RELEASE);
    return exitCode;
}
Пример #15
0
  virtual void WritePatch() override
  {
    hadesmem::detail::AcquireSRWLock const lock(
      &GetSrwLock(), hadesmem::detail::SRWLockType::Exclusive);

    auto& veh_hooks = GetVehHooks();

    HADESMEM_DETAIL_ASSERT(veh_hooks.find(target_) == std::end(veh_hooks));
    veh_hooks[target_] = this;

    auto const veh_cleanup_hook = [&]()
    {
      auto const veh_hooks_removed = veh_hooks.erase(target_);
      (void)veh_hooks_removed;
      HADESMEM_DETAIL_ASSERT(veh_hooks_removed);
    };
    auto scope_veh_cleanup_hook =
      hadesmem::detail::MakeScopeWarden(veh_cleanup_hook);

    HADESMEM_DETAIL_TRACE_A("Setting DR hook.");

    auto& dr_hooks = GetDrHooks();
    auto const thread_id = ::GetCurrentThreadId();
    HADESMEM_DETAIL_ASSERT(dr_hooks.find(thread_id) == std::end(dr_hooks));

    Thread const thread(thread_id);
    auto context = GetThreadContext(thread, CONTEXT_DEBUG_REGISTERS);

    std::uint32_t dr_index = static_cast<std::uint32_t>(-1);
    for (std::uint32_t i = 0; i < 4; ++i)
    {
      // Check whether the DR is available according to the control register
      bool const control_available = !(context.Dr7 & (1ULL << (i * 2)));
      // Check whether the DR is zero. Pobably not actually necessary, but
      // it's a nice additional sanity check. This may require a
      // user-controlable flag in future though if the code being hooked is
      // 'hostile'.
      bool const dr_available = !(&context.Dr0)[i];
      if (control_available && dr_available)
      {
        dr_index = i;
        break;
      }
    }

    if (dr_index == static_cast<std::uint32_t>(-1))
    {
      HADESMEM_DETAIL_THROW_EXCEPTION(
        Error{} << ErrorString{"No free debug registers."});
    }

    dr_hooks[ ::GetCurrentThreadId()] = dr_index;

    auto const dr_cleanup_hook = [&]()
    {
      auto const dr_hooks_removed = dr_hooks.erase(::GetCurrentThreadId());
      (void)dr_hooks_removed;
      HADESMEM_DETAIL_ASSERT(dr_hooks_removed);
    };
    auto scope_dr_cleanup_hook =
      hadesmem::detail::MakeScopeWarden(dr_cleanup_hook);

    (&context.Dr0)[dr_index] = reinterpret_cast<std::uintptr_t>(target_);
    // Set appropriate L0-L3 flag
    context.Dr7 |= static_cast<std::uintptr_t>(1ULL << (dr_index * 2));
    // Set appropriate RW0-RW3 field (Execution)
    std::uintptr_t break_type = 0;
    context.Dr7 |= (break_type << (16 + 4 * dr_index));
    // Set appropriate LEN0-LEN3 field (1 byte)
    std::uintptr_t break_len = 0;
    context.Dr7 |= (break_len << (18 + 4 * dr_index));
    // Set LE flag
    std::uintptr_t local_enable = 1 << 8;
    context.Dr7 |= local_enable;

    SetThreadContext(thread, context);

    scope_veh_cleanup_hook.Dismiss();
    scope_dr_cleanup_hook.Dismiss();
  }
Пример #16
0
TARGET_ADDRESS nub_allocate_stack_space
  (NUB nub,
   NUBTHREAD nubthread,
   NUBINT byte_count)
{
  LPDBGPROCESS                   process = (LPDBGPROCESS) nub;
  LPDBGTHREAD                    thread = (LPDBGTHREAD) nubthread;
  NUBINT                         code;
  DWORD                          count = (DWORD) byte_count;
  CONTEXT                        context;
  CONTEXT                        context_as_was;
  BOOL                           status_get_context, 
                                 status_set_context, 
                                 status_write,
                                 status_read;
  ALLOCATOR_INSTRUCTION_SEQUENCE instruction_sequence;
  ALLOCATOR_INSTRUCTION_SEQUENCE saved_stack_memory;
  DWORD                          SP;
  DWORD                          IP;
  DWORD                          instruction_position;
  DWORD                          bytes_written,
                                 bytes_read;
  DWORD                          expected_bp_address;
  BOOL                           spy_has_returned = FALSE;
  int                            second_chance_counter = 0;

  // Get the context for the thread.

  context.ContextFlags = CONTEXT_FULL;
  status_get_context =  get_thread_context(process, thread, &context);

  dylan_debugger_message("nub_allocate_stack_space: Thread Context before: %= : %=",
			 thread->ThreadHandle, status_get_context);
  dylan_debugger_message("Esp: %=  Eip: %=",
			 context.Esp,
			 context.Eip);

  context_as_was = context;

  if (thread->NeedsBreakpointReplacement)
    context.EFlags = context.EFlags & 0xFFFFFEFF;

  // Fill in the instruction sequence SUB ESP, <count>; INT 3

  instruction_sequence.Nop1 = 0x90;
  instruction_sequence.Nop2 = 0x90;
  instruction_sequence.SubInstruction = 0x81;
  instruction_sequence.SpecifyEsp = 0xEC;
  instruction_sequence.Immediate32 = count;
  instruction_sequence.BreakInstruction = 0xCC;

  SP = context.Esp;
  IP = context.Eip;

  // Write the instruction sequence onto the stack. The number of words we
  // are writing is small enough that this should work on both NT and
  // 95.

//context.Esp -= sizeof(ALLOCATOR_INSTRUCTION_SEQUENCE);
  instruction_position = context.Esp;
  context.Eip = instruction_position;

  // Save the data that was there originally. As a precaution, we will
  // re-write this back again if we have to abort the whole procedure.

  status_read =
     ReadProcessMemory
         (process->ProcessHandle,
          (LPCVOID) instruction_position,
          (LPVOID) &saved_stack_memory,
          sizeof(ALLOCATOR_INSTRUCTION_SEQUENCE),
          &bytes_read);

  // Out with the old, in with the new...

  status_write =
     ValidatedWriteProcessMemory 
         (process->ProcessHandle,
          (LPVOID) instruction_position,
          (LPVOID) &instruction_sequence,
          sizeof(ALLOCATOR_INSTRUCTION_SEQUENCE),
          &bytes_written);

  // Flush the instruction cache because we have written a segment of
  // code.

  FlushInstructionCache(process->ProcessHandle,
                        (LPCVOID) instruction_position,
                        sizeof(ALLOCATOR_INSTRUCTION_SEQUENCE));

  // Set the context of the thread so that it will execute the SUB instruction
  // and then return control to the debugger.

  status_set_context = SetThreadContext(thread->ThreadHandle, &context);

  if (!status_set_context) {
    status_write =
       ValidatedWriteProcessMemory 
           (process->ProcessHandle,
            (LPVOID) instruction_position,
            (LPVOID) &saved_stack_memory,
            sizeof(ALLOCATOR_INSTRUCTION_SEQUENCE),
            &bytes_written);
    SetThreadContext(thread->ThreadHandle, &context_as_was); // Just in case
    return(NULL);
  }

  // Remember the address at which we expect the breakpoint.

  expected_bp_address = instruction_position + 8;

  // Let the thread execute the fragment of code. Hopefully, that will give
  // us space on the stack that Windows 95 won't crap all over.

  suspend_all(process);
  process->ThreadRunningSpy = thread;
  thread->AddressOfSpyBreakpoint = expected_bp_address;

  // Explicitly continue all threads to release frozen threads;
  // they are all suspended at this point so won't be put back
  // into execution

  nub_threads_continue(nub);

  // Now do what it takes to put this Spy running Thread alone into execution

  execute_thread(thread);

  wait_for_stop_reason_internal
     (process, TRUE, 30000, &code, STOP_REASON_WAIT_SPY);

  if (code == SPY_RETURN_DBG_EVENT) {
    // Resume the suspended threads.
    resume_all_except(process, thread);

    // Write back the stack data that we crapped all over.
    status_write =
       ValidatedWriteProcessMemory 
           (process->ProcessHandle,
            (LPVOID) instruction_position,
            (LPVOID) &saved_stack_memory,
            sizeof(ALLOCATOR_INSTRUCTION_SEQUENCE),
            &bytes_written);

    // Get the context again. This should have ESP correctly set.
    status_get_context = GetThreadContext(thread->ThreadHandle, &context);

    dylan_debugger_message("nub_allocate_stack_space: Thread Context after: %= : %=",
			   thread->ThreadHandle, status_get_context);
    dylan_debugger_message("Esp: %=  Eip: %=",
			   context.Esp,
			   context.Eip);


    return((TARGET_ADDRESS) (context.Esp));
  }
  else {
    resume_all_except(process, thread);
    status_write =
       ValidatedWriteProcessMemory 
           (process->ProcessHandle,
            (LPVOID) instruction_position,
            (LPVOID) &saved_stack_memory,
            sizeof(ALLOCATOR_INSTRUCTION_SEQUENCE),
            &bytes_written);
    SetThreadContext(thread->ThreadHandle, &context_as_was);
    nub_debug_message("Error: Micro Spy call failed on Thread %=, code: %=",
		      (TARGET_ADDRESS)thread->ThreadHandle,
		      (TARGET_ADDRESS)code);
    return (NULL);
  }
  // Resume the suspended threads.
  resume_all_except(process, thread);

  // Write back the stack data that we crapped all over.

  status_write =
     ValidatedWriteProcessMemory 
         (process->ProcessHandle,
          (LPVOID) instruction_position,
          (LPVOID) &saved_stack_memory,
          sizeof(ALLOCATOR_INSTRUCTION_SEQUENCE),
          &bytes_written);

  // Get the context again. This should have ESP correctly set.
  status_get_context = GetThreadContext(thread->ThreadHandle, &context);

  return((TARGET_ADDRESS) (context.Esp));
}
Пример #17
0
bool DebugFrontend::StartProcessAndRunToEntry(LPCSTR exeFileName, LPSTR commandLine, LPCSTR directory, PROCESS_INFORMATION& processInfo)
{

    STARTUPINFO startUpInfo = { 0 };
    startUpInfo.cb = sizeof(startUpInfo);

    ExeInfo info;
    if (!GetExeInfo(exeFileName, info) || info.entryPoint == 0)
    {
        MessageEvent("Error: The entry point for the application could not be located", MessageType_Error);
        return false;
    }

    if (!info.i386)
    {
        MessageEvent("Error: Debugging 64-bit applications is not supported", MessageType_Error);
        return false;
    }

    DWORD flags = DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS;

    if (!CreateProcess(NULL, commandLine, NULL, NULL, TRUE, flags, NULL, directory, &startUpInfo, &processInfo))
    {
        OutputError(GetLastError());
        return false;
    }

    // Running to the entry point currently doesn't work for managed applications, so
    // just start it up.

    if (!info.managed)
    {

        unsigned long entryPoint = info.entryPoint;

        BYTE breakPointData;
        bool done = false;
        
        while (!done)
        {

            DEBUG_EVENT debugEvent;
            WaitForDebugEvent(&debugEvent, INFINITE);

            DWORD continueStatus = DBG_EXCEPTION_NOT_HANDLED;

            if (debugEvent.dwDebugEventCode == EXCEPTION_DEBUG_EVENT)
            {
                if (debugEvent.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP ||
                    debugEvent.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT)
                {

                    CONTEXT context;
                    context.ContextFlags = CONTEXT_FULL;

                    GetThreadContext(processInfo.hThread, &context);

                    if (context.Eip == entryPoint + 1)
                    {

                        // Restore the original code bytes.
                        SetBreakpoint(processInfo.hProcess, (LPVOID)entryPoint, false, &breakPointData);
                        done = true;

                        // Backup the instruction pointer so that we execute the original instruction.
                        --context.Eip;
                        SetThreadContext(processInfo.hThread, &context);

                        // Suspend the thread before we continue the debug event so that the program
                        // doesn't continue to run.
                        SuspendThread(processInfo.hThread);

                    }

                    continueStatus = DBG_CONTINUE;

                }
            }
            else if (debugEvent.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
            {
                done = true;
            }
            else if (debugEvent.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT)
            {
            
                // Offset the entry point by the load address of the process.
                entryPoint += reinterpret_cast<size_t>(debugEvent.u.CreateProcessInfo.lpBaseOfImage);

                // Write a break point at the entry point of the application so that we
                // will stop when we reach that point.
                SetBreakpoint(processInfo.hProcess, reinterpret_cast<void*>(entryPoint), true, &breakPointData);

                CloseHandle(debugEvent.u.CreateProcessInfo.hFile);

            }
            else if (debugEvent.dwDebugEventCode == LOAD_DLL_DEBUG_EVENT)
            {
                CloseHandle(debugEvent.u.LoadDll.hFile);
            }

            ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, continueStatus);
        
        }

    }

    DebugActiveProcessStop(processInfo.dwProcessId);
    return true;

}
Пример #18
0
void _debug_rstr_context(CONTEXT* __context__,kernel_pthread_t *__pthread_ptr__){
   CONTEXT __local_context__;
   __context__->ContextFlags=PTHREAD_CONTEXT_DUMP;
   memcpy(&__local_context__,__context__,sizeof(CONTEXT));
   SetThreadContext(__pthread_ptr__->tcb->hTask, &__local_context__);
}
Пример #19
0
bool
clear_break_point(
	_In_ ch_param* param,
	_In_ DWORD_PTR address,
	_In_ unsigned char opcode,
	_In_ bool reset_eip
	)
{
	_ASSERTE(NULL != param);
	_ASSERTE(0 != address);
	_ASSERTE(NULL != opcode);
	if (NULL == param || 0 == address || NULL == opcode) return false;

	SIZE_T cb_rw = 0;
	unsigned char temp = 0;
	BOOL ret = ReadProcessMemory(
		param->hproc,
		(LPCVOID)address,
		&temp,
		sizeof(unsigned char),
		&cb_rw
		);

	if (TRUE != ret || cb_rw != sizeof(unsigned char))
	{
		log(
			"ReadProcessMemory( hprocess = 0x%08x, address = 0x%p ), gle = %u",
			param->hproc,
			address,
			GetLastError()
			);
		return false;
	}

	if (temp != BREAK_OPCODE)
	{
		log(
			"hprocess = 0x%08x, address = 0x%p, opcode = 0x%02x (not BREAK_OPCODE!)",
			param->hproc,
			address,
			temp
			);
		return false;
	}

	MEMORY_BASIC_INFORMATION mbi = { 0 };
	if (0 == VirtualQueryEx(
		param->hproc,
		(LPCVOID)address,
		&mbi,
		sizeof(mbi)))
	{
		log(
			"VirtualQueryEx( hprocess = 0x%08x, address = 0x%p ), gle = %u",
			param->hproc,
			address,
			GetLastError()
			);
		return false;
	}

	if (TRUE != VirtualProtectEx(
		param->hproc,
		mbi.BaseAddress,
		mbi.RegionSize,
		PAGE_EXECUTE_READWRITE,
		&mbi.Protect))
	{
		log(
			"VirtualProtectEx( hprocess = 0x%08x, address = 0x%p, size = %u, PAGE_EXECUTE_READWRITE ) gle = %u",
			param->hproc,
			mbi.BaseAddress,
			mbi.RegionSize,
			GetLastError()
			);
		return false;
	}

	do
	{
		ret = WriteProcessMemory(
			param->hproc,
			(LPVOID)address,
			&opcode,
			sizeof(unsigned char),
			&cb_rw);
		if (TRUE != ret || cb_rw != sizeof(unsigned char))
		{
			log(
				"WriteProcessMemory( hprocess = 0x%08x, address = 0x%p ), gle = %u",
				param->hproc,
				address,
				GetLastError()
				);

				ret = FALSE;
			break;
		}

		if (TRUE != FlushInstructionCache(param->hproc, (LPCVOID)address, sizeof(unsigned char)))
		{
			log(
				"WriteProcessMemory( hprocess = 0x%08x, address = 0x%p ), gle = %u",
				param->hproc,
				address,
				GetLastError()
				);
		}
	} while (false);

	VirtualProtectEx(param->hproc, mbi.BaseAddress, mbi.RegionSize, mbi.Protect, &mbi.Protect);

	if (true == reset_eip)
	{
		_ASSERTE(NULL != param->hthread);
		if (NULL != param->hthread)
		{
#if defined(_AMD64_)
			param->context.Rip--;
#elif defined(_X86_)
			param->context.Eip--;
#else
#error !!unsupported architecture!!
#endif			
			if (TRUE != SetThreadContext(param->hthread, &param->context))
			{
				log(
					"SetThreadContext(hthread=0x%08x), gle = %u",
					param->hthread,
					GetLastError()
					);
			}
		}
	}

	return (TRUE == ret) ? true : false;
}
/* Function to setup remote process that waits for this process to
   exit and then deletes its executable.  */
static int SelfDelete()
{
  STARTUPINFO si;
  PROCESS_INFORMATION pi;
  ZeroMemory(&si, sizeof(si));
  si.cb = sizeof(si);

  /* Create a process using the explorer executable but suspend it
     immediately.  */
  if(CreateProcess(0, _T("explorer.exe"), 0, 0, 0,
                   (CREATE_SUSPENDED | IDLE_PRIORITY_CLASS),
                   0, 0, &si, &pi))
    {
    /* Structure to store code and data to copy to remote process.  */
    SelfDeleteRemoteCode code;

    DWORD oldProtect;
    CONTEXT context;
    DWORD entryPoint;

    /* Setup pointers to kernel functions for the remote code to call.  */
    code.fnWaitForSingleObject  = WaitForSingleObject;
    code.fnCloseHandle          = CloseHandle;
    code.fnDeleteFile           = DeleteFile;
    code.fnSleep                = Sleep;
    code.fnExitProcess          = ExitProcess;
    code.fnGetLastError         = GetLastError;

    /* Give the remote process a copy of our own process handle.  */
    DuplicateHandle(GetCurrentProcess(), GetCurrentProcess(),
                    pi.hProcess, &code.hParent, 0, FALSE, 0);

    /* Store the file name of this process's executable.  */
    GetModuleFileName(0, code.szFileName, MAX_PATH);

    /* Store the binary code to execute remotely.  */
    memcpy(code.opCodes, SelfDeleteRemoteThread, SELF_DELETE_CODESIZE);

    /* Allocate some space on process's stack and place our
       SelfDeleteRemoteCode structure there.  Then set the instruction
       pointer to this location and let the process resume.  */
    context.ContextFlags = (CONTEXT_INTEGER | CONTEXT_CONTROL);
    GetThreadContext(pi.hThread, &context);

    /* Allocate space on stack that is aligned to cache-line boundary.  */
    entryPoint = (context.Esp - sizeof(SelfDeleteRemoteCode)) & ~0x1F;

    /* Place a pointer to the structure at the bottom-of-stack.  This
       pointer is located in such a way that it becomes the
       SelfDeleteRemoteThread's first argument.  */
    code.Arg0 = (SelfDeleteRemoteCode*)entryPoint;

    /* Set dummy return address for remote thread.  It will never return.  */
    context.Esp = entryPoint - 4;

    /* Set remote thread to execute the opCodes we copy to the process.  */
    context.Eip = entryPoint + (((char*)&code.opCodes) - ((char*)&code));

    /* Copy the code and data to the remote process entry point.  */
    VirtualProtectEx(pi.hProcess, (PVOID)entryPoint, sizeof(code),
                     PAGE_EXECUTE_READWRITE, &oldProtect);
    WriteProcessMemory(pi.hProcess, (PVOID)entryPoint, &code, sizeof(code), 0);

    /* Make sure the new code will be loaded.  */
    FlushInstructionCache(pi.hProcess, (PVOID)entryPoint, sizeof(code));

    /* Set the remote thread to execute at our entry point.  */
    SetThreadContext(pi.hThread, &context);

    /* Let the remote process continue.  It will block until this
       process exits.  */
    ResumeThread(pi.hThread);
    CloseHandle(pi.hThread);
    CloseHandle(pi.hProcess);
    return 1;
    }

  return 0;
}
Пример #21
0
/*
 * Set the register state of the supplied thread
 *
 * req: TLV_TYPE_THREAD_HANDLE - The thread to set
 * req: TLV_TYPE_REGISTER x N  - The registers to set
 */
DWORD request_sys_process_thread_set_regs(Remote *remote, Packet *packet)
{
	Packet *response = packet_create_response(packet);
	HANDLE thread;
	DWORD result = ERROR_SUCCESS;

	do
	{
		if ((thread = (HANDLE)packet_get_tlv_value_uint(packet, 
				TLV_TYPE_THREAD_HANDLE)))
		{
			CONTEXT context;
			DWORD index = 0;
			Tlv reg;

			memset(&context, 0, sizeof(context));

			// Get the current thread register state
			context.ContextFlags = CONTEXT_FULL;

			if (!GetThreadContext(thread, &context))
			{
				result = GetLastError();
				break;
			}

			// Enumerate through all of the register we're setting
			while (packet_enum_tlv(packet, index++, TLV_TYPE_REGISTER, 
					&reg) == ERROR_SUCCESS)
			{
				LPCSTR name;
				ULONG value;
				Tlv nameTlv, valueTlv;

				// Get the group's entries
				if ((packet_get_tlv_group_entry(packet, &reg, 
						TLV_TYPE_REGISTER_NAME, &nameTlv) != ERROR_SUCCESS) ||
				    (packet_get_tlv_group_entry(packet, &reg,
						TLV_TYPE_REGISTER_VALUE_32, &valueTlv) != ERROR_SUCCESS))
					continue;
				
				// Validate them
				if ((packet_is_tlv_null_terminated(packet, 
						&nameTlv) != ERROR_SUCCESS) ||
				    (valueTlv.header.length < sizeof(ULONG)))
					continue;
				
				// Stash them
				name  = (LPCSTR)nameTlv.buffer;
				value = ntohl(*(PULONG)valueTlv.buffer);

				// Set this register's value
				set_thread_register_value(&context, name, value);
			}

			// Update the thread's context
			if (!SetThreadContext(thread, &context))
			{
				result = GetLastError();
				break;
			}
		}
		else
			result = ERROR_INVALID_PARAMETER;

	} while (0);

	packet_transmit_response(result, remote, response);

	return ERROR_SUCCESS;
}
/* this thread assists with the returns from simulated interrupts
   
   ideally, the interrupthandler would just assume the state right before the
   interrupt, but this is not possible given the x86 and nt, so the interrupt
   handling thread has to suspend itself, and let some other thread manipulate
   its state while it is suspended. 
   
   when this thread runs, interrupts will be disabled, so we reenable them
   once it is finished.
   */
DWORD WINAPI interrupt_return_assist(LPVOID ptr) {
  signal_queue_t *sq;
  int scount, rcount;
  int success = FALSE;
  CONTEXT context;

  if (DEBUG)
    kprintf("IRA:starting ...\n");

  for(;;) {
    /* wait politely until we are needed */
    WaitOnObject(cleanup);

    if (DEBUG)
      kprintf("IRA:woken up ...\n");
	
    WaitOnObject(mutex);

    {
      success = FALSE;
      sq = signalq;
      signalq = signalq->next;
      assert(signalq == NULL);

      /* wait for the system thread to enter a "safe" state */
      while(readytoreturn != TRUE)
	SwitchToThread();

      while(success != TRUE) {

	scount = SuspendThread(sq->threadid);
	memset(&context, 0, sizeof(CONTEXT));

#ifdef WINCE
	context.ContextFlags = CONTEXT_FULL;
#else
	context.ContextFlags = 
     CONTEXT_FULL | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS 
                  | CONTEXT_CONTROL;
#endif

	AbortOnError(GetThreadContext(system_thread, &context));

	if (DEBUG)
	  kprintf("IRA:system thread is at 0x%x.\n", EIP);
	if((EIP >= loopforever_start_address && 
	    EIP <= loopforever_end_address)) {
	  if (DEBUG)
	    kprintf("IRA:enabling interrupts.\n");
	  interrupt_level = ENABLED;

	  AbortOnError(SetThreadContext(sq->threadid, sq->context));

	  rcount = ResumeThread(sq->threadid);

	  if (DEBUG)
	    kprintf("IRA:Interrupt return assist scount %d rcount %d\n", 
		   scount, rcount);

	  assert(rcount >= scount + 1);
	  success = TRUE;
	} 
	else {
	  ResumeThread(system_thread);
	  ReleaseMutex(mutex);
	  SwitchToThread();
	  WaitOnObject(mutex);
	}
      }
    } 
    ReleaseMutex(mutex);
    free(sq);
  }

  /* never reached */
  return 0;
}
Пример #23
0
int
pthread_cancel (pthread_t thread)
     /*
      * ------------------------------------------------------
      * DOCPUBLIC
      *      This function requests cancellation of 'thread'.
      *
      * PARAMETERS
      *      thread
      *              reference to an instance of pthread_t
      *
      *
      * DESCRIPTION
      *      This function requests cancellation of 'thread'.
      *      NOTE: cancellation is asynchronous; use pthread_join to
      *                wait for termination of 'thread' if necessary.
      *
      * RESULTS
      *              0               successfully requested cancellation,
      *              ESRCH           no thread found corresponding to 'thread',
      *              ENOMEM          implicit self thread create failed.
      * ------------------------------------------------------
      */
{
  int result;
  int cancel_self;
  pthread_t self;

  /* This is the proper way to test thread validity. */
  result = pthread_kill(thread, 0);
  if (0 != result)
    {
      return result;
    }

  if ((self = pthread_self()) == NULL)
    {
      return ENOMEM;
    };

  /*
   * FIXME!!
   *
   * Can a thread cancel itself?
   *
   * The standard doesn't
   * specify an error to be returned if the target
   * thread is itself.
   *
   * If it may, then we need to ensure that a thread can't
   * deadlock itself trying to cancel itself asyncronously
   * (pthread_cancel is required to be an async-cancel
   * safe function).
   */
  cancel_self = pthread_equal(thread, self);

  /*
   * Lock for async-cancel safety.
   */
  (void) pthread_mutex_lock(&thread->cancelLock);

  if (thread->cancelType == PTHREAD_CANCEL_ASYNCHRONOUS
      && thread->cancelState == PTHREAD_CANCEL_ENABLE
      && thread->state < PThreadStateCanceling )
    {
      if (cancel_self)
        {
          thread->state = PThreadStateCanceling;
          thread->cancelState = PTHREAD_CANCEL_DISABLE;

          (void) pthread_mutex_unlock(&thread->cancelLock);
          ptw32_throw(PTW32_EPS_CANCEL);

          /* Never reached */
        }
      else
        {
          HANDLE threadH = thread->threadH;

          SuspendThread(threadH);

          if (WaitForSingleObject(threadH, 0) == WAIT_TIMEOUT )
            {
              CONTEXT context;

              thread->state = PThreadStateCanceling;
              thread->cancelState = PTHREAD_CANCEL_DISABLE;
              context.ContextFlags = CONTEXT_CONTROL;
              GetThreadContext(threadH, &context);
              PTW32_PROGCTR(context) = (DWORD) ptw32_cancel_self;
              SetThreadContext(threadH, &context);
              (void) pthread_mutex_unlock(&thread->cancelLock);
              ResumeThread(threadH);
            }
        }
    }
  else
    {
      /*
       * Set for deferred cancellation.
       */
      if ( thread->state >= PThreadStateCanceling
           || !SetEvent (thread->cancelEvent))
        {
          result = ESRCH;
        }

      (void) pthread_mutex_unlock(&thread->cancelLock);
    }

  return (result);
}
/* 
 * Send an interrupt to the system thread: adjust its stack to call
 * the appropriate interrupt handler with the specified argument. the
 * "type" argument identifies interrupt-specific processing which must
 * be done, in particular, what we should do if interrupts are
 * disabled or the system thread is in a non-preemptable state
 * (e.g. executing a system library function). clock interrupts are
 * dropped, network interrupts are deferred. this function replaces
 * code which used to be common to clock_poll and network_poll.
*/
void send_interrupt(int type, void* arg) {
  CONTEXT context;
  int safe_to_proceed = 0;
  int drop_interrupt = 0;
  interrupt_queue_t* interrupt_info = NULL;

  for (;;) {
    WaitOnObject(mutex);

    /* need to protect this code: we only activate the interrupt if interrupts
       are actually enabled, but we also need to ensure they are not disabled
       after we test -- so we suspend the system thread first.
       */
    SuspendThread(system_thread);
    memset(&context, 0, sizeof(CONTEXT));
#ifdef WINCE
    context.ContextFlags = CONTEXT_FULL;
#else
    context.ContextFlags = 
      CONTEXT_FULL | CONTEXT_FLOATING_POINT | CONTEXT_DEBUG_REGISTERS 
                   | CONTEXT_CONTROL;
#endif
    /* Warning: a printf here makes the system lock */

    AbortOnError(GetThreadContext(system_thread, &context));

    /* find interrupt description in the interrupt queue */
    interrupt_info = interrupt_queue;
    while (interrupt_info!=NULL && interrupt_info->type!=type)
      interrupt_info = interrupt_info->next;
    
    if (interrupt_info == NULL) {
      /* 
       * we couldn't find the interrupt with type "type" so we crash the
       * sistem.
      */

      kprintf("An interrupt of the unregistered type %d was received.\n",
	     type);
      AbortOnCondition(1,"Crashing.");
    } else {
      /*
       * interrupt-type-specific processing: can we interrupt now? If we 
       * ended up interrupting the process at a time when it is in some non-minithread-safe
       * Windows library, then defer or drop the interrupt.
       */
      switch (interrupt_info->property){
      case INTERRUPT_DROP:
	if (interrupt_level == DISABLED
	    || (EIP < start_address)
	    || (EIP > end_address)) {
	  drop_interrupt = 1;
	}
	else
	  safe_to_proceed = 1;
	break;
      case INTERRUPT_DEFER:
	if (interrupt_level == ENABLED 
	    && (EIP >= start_address)
	    && (EIP <= end_address)) {
	  interrupt_level = DISABLED;
	  safe_to_proceed = 1;
	}
	break;
      default:
	break;
      }
    } 
     
    if (safe_to_proceed == 1)
      break;
    else {
      ResumeThread(system_thread);
      ReleaseMutex(mutex);
      if (DEBUG) {
	switch (interrupt_info->property) {
	case INTERRUPT_DROP:
	  kprintf("Interrupt of type %d dropped, eip = 0x%x.\n", 
		 interrupt_info->type, EIP);
	  break;
	case INTERRUPT_DEFER:
	  kprintf("Interrupt of type %d deffered, eip = 0x%x.\n", 
		 interrupt_info->type, EIP);
	  break;
	}
      }
    }

    if (drop_interrupt == 1)
      return;
    else
      SwitchToThread();
  }

  /* now fix the system thread's stack so it runs run_user_handler */
  {
#ifdef _M_AMD64
        __int64 stack;
#else
    int stack;
#endif

    if (DEBUG) {
      kprintf("Interrupts are enabled, system thread pc = 0x%x\n", EIP);
      kprintf("Adjusting system thread context ...\n");
    }

    /* set the interrupt number */
    /* arg->intnumber = ++intnumber; */
    stack = ESP;	/* Esp == extended stack pointer */

    /* safe to do a printf because other thread is stunned in user code */
    if (DEBUG)
      kprintf("Suspended system thread, adjusting stack, sp = 0x%x\n", stack);

    stack -= (sizeof(CONTEXT) + 64); /* 64 is slop */
        /* This alignment is necessary on x64 systems, otherwise it will crash
         * with error code 998.
         */
        stack += 64 - (stack % 64); /* align to a 64-byte boundary */
    memcpy((int *) stack, &context, sizeof(CONTEXT));
    EIP = receive_interrupt;
    REG1 = stack; /*pointer to context*/    
    REG2 = type; /*type, second argument */
#ifndef WINCE
#ifdef _M_AMD64
        context.R8 = (__int64) arg;
        /* space to store registers */
        stack -= sizeof(int *) * 5;
        /* used in debugging the ra */
        *(__int64 *) stack = 0xdeadbeefcafebabe;
#else
    /* for x86 put arg pointer on the stack since only two 
       parameters can be passed in registers.
    */
    stack-=sizeof(void*);
    *((int*)stack)=(int) arg;
    stack-=sizeof(void*); 
#endif
#else
    /* for ARM put the third argument in R2 */
    context.R2 = (int) arg;
#endif
    ESP = stack;
    
    AbortOnError(SetThreadContext(system_thread, &context));

    AbortOnError(GetThreadContext(system_thread, &context));
    
    ResumeThread(system_thread);
  }
  ReleaseMutex(mutex);
}
Пример #25
0
void InjectDLL64( LPPROCESS_INFORMATION ppi )
{
  CONTEXT context;
  DWORD   len;
  LPVOID  mem;
  DWORD64 LLW;
  union
  {
    PBYTE    pB;
    PDWORD64 pL;
  } ip;
  #define CODESIZE 92
  static BYTE code[CODESIZE+TSIZE(MAX_PATH)] = {
	0,0,0,0,0,0,0,0,	   // original rip
	0,0,0,0,0,0,0,0,	   // LoadLibraryW
	0x9C,			   // pushfq
	0x50,			   // push  rax
	0x51,			   // push  rcx
	0x52,			   // push  rdx
	0x53,			   // push  rbx
	0x55,			   // push  rbp
	0x56,			   // push  rsi
	0x57,			   // push  rdi
	0x41,0x50,		   // push  r8
	0x41,0x51,		   // push  r9
	0x41,0x52,		   // push  r10
	0x41,0x53,		   // push  r11
	0x41,0x54,		   // push  r12
	0x41,0x55,		   // push  r13
	0x41,0x56,		   // push  r14
	0x41,0x57,		   // push  r15
	0x48,0x83,0xEC,0x28,	   // sub   rsp, 40
	0x48,0x8D,0x0D,41,0,0,0,   // lea   ecx, L"path\to\errout64.dll"
	0xFF,0x15,-49,-1,-1,-1,    // call  LoadLibraryW
	0x48,0x83,0xC4,0x28,	   // add   rsp, 40
	0x41,0x5F,		   // pop   r15
	0x41,0x5E,		   // pop   r14
	0x41,0x5D,		   // pop   r13
	0x41,0x5C,		   // pop   r12
	0x41,0x5B,		   // pop   r11
	0x41,0x5A,		   // pop   r10
	0x41,0x59,		   // pop   r9
	0x41,0x58,		   // pop   r8
	0x5F,			   // pop   rdi
	0x5E,			   // pop   rsi
	0x5D,			   // pop   rbp
	0x5B,			   // pop   rbx
	0x5A,			   // pop   rdx
	0x59,			   // pop   rcx
	0x58,			   // pop   rax
	0x9D,			   // popfq
	0xFF,0x25,-91,-1,-1,-1,    // jmp   original Rip
	0,			   // dword alignment for LLW, fwiw
  };

  len = TSIZE(lstrlen( hDllName ) + 1);
  if (len > TSIZE(MAX_PATH))
    return;
  CopyMemory( code + CODESIZE, hDllName, len );
  len += CODESIZE;

  context.ContextFlags = CONTEXT_CONTROL;
  GetThreadContext( ppi->hThread, &context );
  mem = VirtualAllocEx( ppi->hProcess, NULL, len, MEM_COMMIT,
			PAGE_EXECUTE_READWRITE );
  LLW = (DWORD64)LoadLibraryW;

  ip.pB = code;

  *ip.pL++ = context.Rip;
  *ip.pL++ = LLW;

  WriteProcessMemory( ppi->hProcess, mem, code, len, NULL );
  FlushInstructionCache( ppi->hProcess, mem, len );
  context.Rip = (DWORD64)mem + 16;
  SetThreadContext( ppi->hThread, &context );
}
Пример #26
0
/**
 * Sets a data watch for the given address.
 *
 * @address The location to watch.
 * @size The size of the memory block address points to. Can be 1, 2 or 4 bytes.
 * @when Determines when to trigger the break point (write or read/write).
 */
void DataBreakpoint::Set(void* address, int size, Condition when)
{
  if (_register_index != -1)
    throw std::runtime_error("Watch point already set. Use clear() before setting a new one.");

  switch (size)
  {
    case 1:
      size = 0;
      break;
    case 2:
      size = 1;
      break;
    case 4:
      size = 3;
      break;
    default:
      throw std::runtime_error("Invalid data length for watch point specified.");
  }

  HANDLE currentThread = GetCurrentThread();

  // Set up the thread context for this watch point.
  CONTEXT context;
  context.ContextFlags = CONTEXT_DEBUG_REGISTERS;

  // Read the register values
  if (!GetThreadContext(currentThread, &context))
    throw std::runtime_error("Failed getting the current thread context.");

  // Find an available hardware register.
  for (_register_index = 0; _register_index < 4; ++_register_index)
  {
    if ((context.Dr7 & (REGISTER_TYPE)(1 << (2 * _register_index))) == 0)
		  break;
  }
  if (_register_index >= 4)
    throw std::runtime_error("Could not find a free hardware register.");

  switch (_register_index)
  {
    case 0:
      context.Dr0 = (REGISTER_TYPE)address;
      break;
    case 1:
      context.Dr1 = (REGISTER_TYPE)address;
      break;
    case 2:
      context.Dr2 = (REGISTER_TYPE)address;
      break;
    case 3:
      context.Dr3 = (REGISTER_TYPE)address;
      break;
  }

  SetBits(context.Dr7, 16 + (4 * _register_index), 2, when);
  SetBits(context.Dr7, 18 + (4 * _register_index), 2, size);
  SetBits(context.Dr7, 2 * _register_index, 1, 1);

  if (!SetThreadContext(currentThread, &context))
    throw std::runtime_error("Could not set modified thread context for the watch point.");
}
Пример #27
0
bool DebuggingLoop()
{
	DEBUG_EVENT DebugEvent;
	CONTEXT ctxThreadContext;
	DWORD dwDebugState = NULL;

	PTCHAR sTemp = (PTCHAR)malloc(255 * sizeof(TCHAR));
	szTempSym = (PCHAR)malloc(MAX_SYM_NAME);

	ctxThreadContext.ContextFlags = CONTEXT_FULL;
	
	while(bDebugging)
	{
		if(!WaitForDebugEvent(&DebugEvent,INFINITE))
		{
			free(sTemp);
			free(szTempSym);
			return false;
		}

		switch(DebugEvent.dwDebugEventCode)
		{
		case LOAD_DLL_DEBUG_EVENT:
			{
				SymRefreshModuleList(piProcInfo.hProcess);
				dwDebugState = DBG_CONTINUE;
				break;
			}
		case CREATE_PROCESS_DEBUG_EVENT:
			{
				if(!bSymInit)
					bSymInit = SymInitialize(piProcInfo.hProcess,NULL,FALSE);
				dwDebugState = DBG_CONTINUE;
				break;
			}
		case CREATE_THREAD_DEBUG_EVENT:
			{
				HANDLE hThread = OpenThread(THREAD_ALL_ACCESS,false,DebugEvent.dwThreadId);
				GetThreadContext(hThread,&ctxThreadContext);
				ctxThreadContext.EFlags |= 0x100;
				SetThreadContext(hThread,&ctxThreadContext);

				dwDebugState = DBG_CONTINUE;
				break;
			}
		case EXIT_PROCESS_DEBUG_EVENT:
			{
				bDebugging = false;
				dwDebugState = DBG_CONTINUE;
				break;
			}
		case EXCEPTION_DEBUG_EVENT:
			{
				switch(DebugEvent.u.Exception.ExceptionRecord.ExceptionCode)
				{
				case EXCEPTION_BREAKPOINT:
					{
						dwDebugState = DBG_CONTINUE;
						break;
					}
				case EXCEPTION_SINGLE_STEP:
					{	
						HANDLE hThread = OpenThread(THREAD_ALL_ACCESS,false,DebugEvent.dwThreadId);
						GetThreadContext(hThread,&ctxThreadContext);
						InsertInfo((DWORD)DebugEvent.u.Exception.ExceptionRecord.ExceptionAddress,DebugEvent.dwThreadId,sTemp);
						ctxThreadContext.EFlags |= 0x100;
						SetThreadContext(hThread,&ctxThreadContext);
						dwDebugState = DBG_CONTINUE;
						break;
					}
				default:
					dwDebugState = DBG_EXCEPTION_NOT_HANDLED;
				}
				break;
			}
		default:
			dwDebugState = DBG_EXCEPTION_NOT_HANDLED;
		}
		ContinueDebugEvent(DebugEvent.dwProcessId,DebugEvent.dwThreadId,dwDebugState);
	}
	free(sTemp);
	free(szTempSym);
	return false;
}
Пример #28
0
static void
arm_set_thread_context (win32_thread_info *th, DEBUG_EVENT* current_event)
{
  SetThreadContext (th->h, &th->context);
}
BOOL GetSetThreadContext_Injection()
{
#ifdef _WIN64
	return TRUE; //TODO implement this on x64
#else
	TCHAR lpApplicationName[] = _T("C:\\Windows\\System32\\svchost.exe");
	TCHAR lpApplicationName2[] = _T("C:\\masm32\\examples\\dialogs_later\\basic\\basicdlg.exe");
	BOOL bResult = FALSE;

	STARTUPINFO StartupInfo;
	PROCESS_INFORMATION ProcessInfo;

	PCONTEXT pContext = NULL;
	HANDLE hFile = INVALID_HANDLE_VALUE;

	SecureZeroMemory(&StartupInfo, sizeof(STARTUPINFO));
	SecureZeroMemory(&ProcessInfo, sizeof(PPROCESS_INFORMATION));

	do { /* not a loop */

		// Create the hollowed process in suspended mode
		if (!CreateProcess(lpApplicationName, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &StartupInfo, &ProcessInfo)) {
			print_last_error(_T("CreateProcess"));
			break;
		}

		// Allocate space for context structure	
		LPVOID pTargetImageBase = NULL;

		pContext = PCONTEXT(VirtualAlloc(NULL, sizeof(CONTEXT), MEM_COMMIT, PAGE_READWRITE));
		if (pContext == NULL) {
			print_last_error(_T("VirtualAlloc"));
			break;
		}

		// Get the thread context of target
		pContext->ContextFlags = CONTEXT_FULL;
		if (!GetThreadContext(ProcessInfo.hThread, pContext)) {
			print_last_error(_T("GetThreadContext"));	
			break;
		}

		// Read the image base address of target
		ReadProcessMemory(ProcessInfo.hProcess, LPCVOID(pContext->Ebx + 8), pTargetImageBase, 4, NULL);

		// Opening source image
		hFile = CreateFile(lpApplicationName2, GENERIC_READ, NULL, NULL, OPEN_ALWAYS, NULL, NULL);
		if (hFile == INVALID_HANDLE_VALUE)
		{
			print_last_error(_T("CreateFile"));
			break;
		}

		// Reading the file
		DWORD dwSize = GetFileSize(hFile, 0);
		DWORD dwBytesRead;
		PBYTE pBuffer = static_cast<PBYTE>(MALLOC(dwSize));

		if (pBuffer == NULL) {
			print_last_error(_T("HeapAlloc"));
			break;
		}
		else {

			SecureZeroMemory(pBuffer, dwSize);

			ReadFile(hFile, pBuffer, dwSize, &dwBytesRead, 0);
			PIMAGE_SECTION_HEADER pImageSectionHeader;

			PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pBuffer;
			if (pDosHeader->e_magic == IMAGE_DOS_SIGNATURE)
			{
				PIMAGE_NT_HEADERS32 pNTHeaders = PIMAGE_NT_HEADERS(DWORD(pBuffer) + pDosHeader->e_lfanew);
				if (pNTHeaders->Signature == IMAGE_NT_SIGNATURE)
				{

					if (DWORD(pTargetImageBase) == pNTHeaders->OptionalHeader.ImageBase)
					{
						pNtUnmapViewOfSection NtUnmapViewOfSection;
						NtUnmapViewOfSection = (pNtUnmapViewOfSection)(GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtUnmapViewOfSection"));
						NtUnmapViewOfSection(ProcessInfo.hProcess, pTargetImageBase);
					}

					LPVOID pImageBase;

					pImageBase = VirtualAllocEx(ProcessInfo.hProcess, LPVOID(pNTHeaders->OptionalHeader.ImageBase),
						pNTHeaders->OptionalHeader.SizeOfImage,
						MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

					if (pImageBase == NULL) {
						print_last_error(_T("VirtualAllocEx"));
						break;
					}
					else {

						WriteProcessMemory(ProcessInfo.hProcess, pImageBase, pBuffer, pNTHeaders->OptionalHeader.SizeOfHeaders, NULL);
						for (int Count = 0; Count < pNTHeaders->FileHeader.NumberOfSections; Count++)
						{
							pImageSectionHeader = PIMAGE_SECTION_HEADER(DWORD(pBuffer) + pDosHeader->e_lfanew + 248 + (Count * 40));
							WriteProcessMemory(ProcessInfo.hProcess, LPVOID(DWORD(pImageBase) + pImageSectionHeader->VirtualAddress),
								LPVOID(DWORD(pBuffer) + pImageSectionHeader->PointerToRawData), pImageSectionHeader->SizeOfRawData, NULL);
						}
						WriteProcessMemory(ProcessInfo.hProcess, LPVOID(pContext->Ebx + 8), LPVOID(&pNTHeaders->OptionalHeader.ImageBase), 4, NULL);
						pContext->Eax = DWORD(pImageBase) + pNTHeaders->OptionalHeader.AddressOfEntryPoint;
						SetThreadContext(ProcessInfo.hThread, LPCONTEXT(pContext));

						LONG dwRet;

						dwRet = ResumeThread(ProcessInfo.hThread);
						bResult = (dwRet != -1);
					}
				}
			}

			FREE(pBuffer);
		}

	} while (FALSE); /* not a loop */

	/* Cleanup */
	if (ProcessInfo.hThread) CloseHandle(ProcessInfo.hThread);
	if (ProcessInfo.hProcess) CloseHandle(ProcessInfo.hProcess);
	if (pContext) VirtualFree(pContext, 0, MEM_RELEASE);
	if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile);

	return bResult;
#endif
}
Пример #30
0
BOOL MapNewExecutableRegionInProcess(
		IN HANDLE TargetProcessHandle,
		IN HANDLE TargetThreadHandle,
		IN LPVOID NewExecutableRawImage)
{
	PROCESS_BASIC_INFORMATION BasicInformation;
	PIMAGE_SECTION_HEADER     SectionHeader;
	PIMAGE_DOS_HEADER         DosHeader;
	PIMAGE_NT_HEADERS         NtHeader;
	PMINI_PEB                 ProcessPeb;
	NTSTATUS                  (NTAPI *NtUnmapViewOfSection)(HANDLE, LPVOID) = NULL;
	NTSTATUS                  (NTAPI *NtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, LPVOID, ULONG, PULONG) = NULL;
	NTSTATUS                  Status;
	CONTEXT                   ThreadContext;
	LPVOID                    OldEntryPoint = NULL;
	LPVOID                    TargetImageBase = NULL;
	ULONG                     SectionIndex = 0;
	ULONG                     SizeOfBasicInformation;
	BOOL                      Success = FALSE;


	//
	// Error checking? Bah.
	//
	DosHeader = (PIMAGE_DOS_HEADER)NewExecutableRawImage;
	NtHeader  = (PIMAGE_NT_HEADERS)((PCHAR)NewExecutableRawImage + DosHeader->e_lfanew);

	do
	{
		//
		// Get the old entry point address by inspecting eax of the current
		// thread (which should be BaseProcessStart).  Eax holds the address
		// of the entry point for the executable when the process is created
		// suspended.
		//
		ZeroMemory(
				&ThreadContext,
				sizeof(ThreadContext));

		ThreadContext.ContextFlags = CONTEXT_INTEGER;

		if (!GetThreadContext(
					TargetThreadHandle,
					&ThreadContext))
		{
			break;
		}

		OldEntryPoint = (LPVOID) NtHeader->OptionalHeader.ImageBase;

		//
		// Unmap the old executable region in the child process to avoid
		// conflicts
		//
		NtUnmapViewOfSection = (NTSTATUS (NTAPI *)(HANDLE, LPVOID))GetProcAddress(
				GetModuleHandle(
					TEXT("NTDLL")),
				"NtUnmapViewOfSection");

		NtUnmapViewOfSection(TargetProcessHandle, OldEntryPoint);

		//
		// Change the entry point address to the new executable's entry point
		//
		ThreadContext.Eax = NtHeader->OptionalHeader.AddressOfEntryPoint +
			NtHeader->OptionalHeader.ImageBase;

		if (!SetThreadContext(
					TargetThreadHandle,
					&ThreadContext))
			break;

		//
		// Allocate storage for the new executable in the child process
		//
		if (!(TargetImageBase = VirtualAllocEx(
						TargetProcessHandle,
						(LPVOID)NtHeader->OptionalHeader.ImageBase,
						NtHeader->OptionalHeader.SizeOfImage,
						MEM_COMMIT | MEM_RESERVE,
						PAGE_EXECUTE_READWRITE)))
			break;

		//
		// Update the executable's image base address in the PEB...
		//
		NtQueryInformationProcess = (NTSTATUS (NTAPI *)(HANDLE, PROCESSINFOCLASS, LPVOID, ULONG, PULONG))GetProcAddress(
				GetModuleHandle(
					TEXT("NTDLL")),
				"NtQueryInformationProcess");

		if (NtQueryInformationProcess(
					TargetProcessHandle,
					ProcessBasicInformation,
					&BasicInformation,
					sizeof(BasicInformation),
					&SizeOfBasicInformation) != ERROR_SUCCESS)
			break;

		ProcessPeb = BasicInformation.PebBaseAddress;

		if (!WriteProcessMemory(
					TargetProcessHandle,
					(LPVOID)&ProcessPeb->ImageBaseAddress,
					(LPVOID)&NtHeader->OptionalHeader.ImageBase,
					sizeof(LPVOID),
					NULL))
			break;

		//
		// Copy the image headers and all of the section contents
		//
		if (!WriteProcessMemory(
					TargetProcessHandle,
					TargetImageBase,
					NewExecutableRawImage,
					NtHeader->OptionalHeader.SizeOfHeaders,
					NULL))
			break;

		Success = TRUE;
		for (SectionIndex = 0,
				SectionHeader = IMAGE_FIRST_SECTION(NtHeader);
				SectionIndex < NtHeader->FileHeader.NumberOfSections;
				SectionIndex++)
		{
			//
			// Skip uninitialized data
			//
			if ((!SectionHeader[SectionIndex].SizeOfRawData) ||
					(SectionHeader[SectionIndex].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA))
				continue;

			if (!WriteProcessMemory(
						TargetProcessHandle,
						(LPVOID)((PCHAR)TargetImageBase +
							SectionHeader[SectionIndex].VirtualAddress),
						(LPVOID)((PCHAR)NewExecutableRawImage +
							SectionHeader[SectionIndex].PointerToRawData),
						SectionHeader[SectionIndex].SizeOfRawData,
						NULL))
			{
				Success = FALSE;
				break;
			}
		}

	} while (0);

	return Success;
}