Beispiel #1
0
int TestDetourCopyInstruction(PBYTE pbSrcInstruction, PCHAR pszFunction)
{
    PBYTE pbSrc = pbSrcInstruction;
    ULONG nIns = 0;

    if (pszFunction) {
        printf("%s:\n", pszFunction);
    }
    for (; nIns < 4096; nIns++) {
        BYTE rbDst[128];
        PVOID pbDstPool = (PVOID)(rbDst + sizeof(rbDst));
        LONG lExtra = 0;
        PVOID pbTarget = NULL;
        ULONG cbStep = (ULONG)((PBYTE)DetourCopyInstruction(rbDst, &pbDstPool, pbSrc,
                                                            &pbTarget, &lExtra) - pbSrc);

        printf("    %p:", pbSrc);
        DumpMemoryFragment(rbDst, cbStep, 10);
        printf(" ");
        DumpMemoryFragment(rbDst, cbStep, 10);
        if (pbTarget) {
            if (pbTarget == DETOUR_INSTRUCTION_TARGET_DYNAMIC) {
                printf("  Dynamic\n");
            }
            else {
                printf(" %p%c\n", pbTarget,
                       (pbTarget >= s_pbBegin && pbTarget < s_pbLimit) ? ' ' : '!');
            }
        }
        else {
            printf("\n");
        }

        if (pbTarget && pbTarget != DETOUR_INSTRUCTION_TARGET_DYNAMIC) {
            if (pbTarget > pbSrc &&
                pbTarget >= s_pbBegin &&
                pbTarget < s_pbLimit
               ) {
                (void) new BasicBlockLink((PBYTE)pbTarget, NULL);
            }
        }

        if (IsTerminate(pbSrc)) {
            break;
        }

        pbSrc += cbStep;
    }
    return nIns;
}
Beispiel #2
0
static VOID Decode(PBYTE pbCode, LONG nInst)
{
	PBYTE pbSrc = pbCode;
	PBYTE pbEnd;
	PBYTE pbTarget;
	for (LONG n = 0; n < nInst; n++) {
		pbTarget = NULL;
		pbEnd = (PBYTE)DetourCopyInstruction(NULL, NULL, (PVOID)pbSrc, (PVOID*)&pbTarget, NULL);
		//Dump(pbSrc, (int)(pbEnd - pbSrc), pbTarget);
		pbSrc = pbEnd;

		if (pbTarget != NULL) {
			break;
		}
	}
}
Beispiel #3
0
int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hprev, LPSTR lpszCmdLine, int nCmdShow)
{
    (void)hprev;
    (void)hinst;
    (void)lpszCmdLine;
    (void)nCmdShow;

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































































































#endif // DETOURS_IA64

#if defined(DETOURS_X64) || defined(DETOURS_X86)
    // First we check the pre-canned TestCodes from disasm.asm
    //
    PBYTE pbBegin = (PBYTE)DetourCodeFromPointer(TestCodes, NULL);
    printf("%p:\n", pbBegin);
    for (PBYTE pbTest = pbBegin;;) {
        if (pbTest[0] != 0xcc) {    // int 3
            printf("%08x  ", pbTest - pbBegin);
            DumpMemoryFragment(pbTest, 8, 8);
            printf("\n");
            printf("failed on last.\n");
            return 1;
        }
        pbTest++;

        if (pbTest[0] == 0x70 || pbTest[0] == 0x71) {
            printf("[%p]:\n", pbTest);
        }
        BYTE rbDst[128];
        PVOID pbDstPool = (PVOID)(rbDst + sizeof(rbDst));
        LONG lExtra = 0;
        PVOID pbTarget = NULL;
        PBYTE pbNext = (PBYTE)DetourCopyInstruction(rbDst, &pbDstPool, pbTest,
                                                    &pbTarget, &lExtra);

        LONG cbTest = (LONG)(pbNext - pbTest);

        printf("%08x  ", pbTest - pbBegin);
        DumpMemoryFragment(pbTest, cbTest, 12);
        printf("[%16p] ", pbTarget);
        DumpMemoryFragment(rbDst, cbTest + lExtra, 11);
        printf("\n");

        if (pbTest[cbTest] != 0xcc) {
            printf("failed!\n");
            return 1;
        }

        pbTest += cbTest;

        if (pbTest[0] == 0xcc && pbTest[1] == 0xcc) {
            break;
        }
    }

#if 0
    // Then we check all of the code we can find in user32.dll
    //
    HINSTANCE hInst = LoadLibrary("user32.dll");
    printf("Loaded: user32.dll: %p\n", hInst);

    s_pbBegin = (PBYTE)hInst;
    s_pbLimit = s_pbBegin + DetourGetModuleSize(hInst);

    PBYTE pbEntry = DetourGetEntryPoint(hInst);
    (VOID) new BasicBlockLink(pbEntry, "user32.dll");

    DetourEnumerateExports(hInst, NULL, ExportCallback);

    ULONG nIns = 0;
    for (BasicBlockLink *pLink = BasicBlockLink::GetListHead();
         pLink; pLink = pLink->Next()) {

        nIns += TestDetourCopyInstruction(pLink->m_pbEntry, pLink->m_pszName);
        if (nIns > 100000) {
            break;
        }
    }
    printf("Disassembled %d instructions.\n", nIns);
#endif
#endif // DETOURS_X86 || DETOURS_X64

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

































































































#endif // DETOURS_ARM

    return 0;
}
LONG WINAPI DetourAttachEx(PVOID *ppPointer,
                           PVOID pDetour,
                           PDETOUR_TRAMPOLINE *ppRealTrampoline,
                           PVOID *ppRealTarget,
                           PVOID *ppRealDetour)
{
    LONG error = NO_ERROR;

    if (ppRealTrampoline != NULL) {
        *ppRealTrampoline = NULL;
    }
    if (ppRealTarget != NULL) {
        *ppRealTarget = NULL;
    }
    if (ppRealDetour != NULL) {
        *ppRealDetour = NULL;
    }

    if (s_nPendingThreadId != (LONG)GetCurrentThreadId()) {
        DETOUR_TRACE(("transaction conflict with thread id=%d\n", s_nPendingThreadId));
        return ERROR_INVALID_OPERATION;
    }

    // If any of the pending operations failed, then we don't need to do this.
    if (s_nPendingError != NO_ERROR) {
        DETOUR_TRACE(("pending transaction error=%d\n", s_nPendingError));
        return s_nPendingError;
    }

    if (ppPointer == NULL) {
        DETOUR_TRACE(("ppPointer is null\n"));
        return ERROR_INVALID_HANDLE;
    }
    if (*ppPointer == NULL) {
        error = ERROR_INVALID_HANDLE;
        s_nPendingError = error;
        s_ppPendingError = ppPointer;
        DETOUR_TRACE(("*ppPointer is null (ppPointer=%p)\n", ppPointer));
        DETOUR_BREAK();
        return error;
    }

    PBYTE pbTarget = (PBYTE)*ppPointer;
    PDETOUR_TRAMPOLINE pTrampoline = NULL;
    DetourOperation *o = NULL;

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










#else // DETOURS_IA64
    pbTarget = (PBYTE)DetourCodeFromPointer(pbTarget, NULL);
    pDetour = DetourCodeFromPointer(pDetour, NULL);
#endif // !DETOURS_IA64

    // Don't follow a jump if its destination is the target function.
    // This happens when the detour does nothing other than call the target.
    if (pDetour == (PVOID)pbTarget) {
        if (s_fIgnoreTooSmall) {
            goto stop;
        }
        else {
            DETOUR_BREAK();
            goto fail;
        }
    }

    if (ppRealTarget != NULL) {
        *ppRealTarget = pbTarget;
    }
    if (ppRealDetour != NULL) {
        *ppRealDetour = pDetour;
    }

    o = new DetourOperation;
    if (o == NULL) {
        error = ERROR_NOT_ENOUGH_MEMORY;
      fail:
        s_nPendingError = error;
        DETOUR_BREAK();
      stop:
        if (pTrampoline != NULL) {
            detour_free_trampoline(pTrampoline);
            pTrampoline = NULL;
            if (ppRealTrampoline != NULL) {
                *ppRealTrampoline = NULL;
            }
        }
        if (o != NULL) {
            delete o;
            o = NULL;
        }
        s_ppPendingError = ppPointer;
        return error;
    }

    pTrampoline = detour_alloc_trampoline(pbTarget);
    if (pTrampoline == NULL) {
        error = ERROR_NOT_ENOUGH_MEMORY;
        DETOUR_BREAK();
        goto fail;
    }

    if (ppRealTrampoline != NULL) {
        *ppRealTrampoline = pTrampoline;
    }

    DETOUR_TRACE(("detours: pbTramp=%p, pDetour=%p\n", pTrampoline, pDetour));

    memset(pTrampoline->rAlign, 0, sizeof(pTrampoline->rAlign));

    // Determine the number of movable target instructions.
    PBYTE pbSrc = pbTarget;
    PBYTE pbTrampoline = pTrampoline->rbCode;
    PBYTE pbPool = pbTrampoline + sizeof(pTrampoline->rbCode);
    ULONG cbTarget = 0;
    ULONG cbJump = SIZE_OF_JMP;
    ULONG nAlign = 0;

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


























#endif

    while (cbTarget < cbJump) {
        PBYTE pbOp = pbSrc;
        LONG lExtra = 0;

        DETOUR_TRACE((" DetourCopyInstruction(%p,%p)\n",
                      pbTrampoline, pbSrc));
        pbSrc = (PBYTE)
            DetourCopyInstruction(pbTrampoline, (PVOID*)&pbPool, pbSrc, NULL, &lExtra);
        DETOUR_TRACE((" DetourCopyInstruction() = %p (%d bytes)\n",
                      pbSrc, (int)(pbSrc - pbOp)));
        pbTrampoline += (pbSrc - pbOp) + lExtra;
        cbTarget = (LONG)(pbSrc - pbTarget);
        pTrampoline->rAlign[nAlign].obTarget = cbTarget;
        pTrampoline->rAlign[nAlign].obTrampoline = pbTrampoline - pTrampoline->rbCode;

        if (detour_does_code_end_function(pbOp)) {
            break;
        }
    }

    // Consume, but don't duplicate padding if it is needed and available.
    while (cbTarget < cbJump) {
        LONG cFiller = detour_is_code_filler(pbSrc);
        if (cFiller == 0) {
            break;
        }

        pbSrc += cFiller;
        cbTarget = (LONG)(pbSrc - pbTarget);
    }

#if DETOUR_DEBUG
    {
        DETOUR_TRACE((" detours: rAlign ["));
        LONG n = 0;
        for (n = 0; n < ARRAYSIZE(pTrampoline->rAlign); n++) {
            if (pTrampoline->rAlign[n].obTarget == 0 &&
                pTrampoline->rAlign[n].obTrampoline == 0) {
                break;
            }
            DETOUR_TRACE((" %d/%d",
                          pTrampoline->rAlign[n].obTarget,
                          pTrampoline->rAlign[n].obTrampoline
                          ));

        }
        DETOUR_TRACE((" ]\n"));
    }
#endif

    if (cbTarget < cbJump || nAlign > ARRAYSIZE(pTrampoline->rAlign)) {
        // Too few instructions.

        error = ERROR_INVALID_BLOCK;
        if (s_fIgnoreTooSmall) {
            goto stop;
        }
        else {
            DETOUR_BREAK();
            goto fail;
        }
    }

    if (pbTrampoline > pbPool) {
        __debugbreak();
    }

#if 0 // [GalenH]
    if (cbTarget < pbTrampoline - pTrampoline->rbCode) {
        __debugbreak();
    }
#endif

    pTrampoline->cbCode = (BYTE)(pbTrampoline - pTrampoline->rbCode);
    pTrampoline->cbRestore = (BYTE)cbTarget;
    CopyMemory(pTrampoline->rbRestore, pbTarget, cbTarget);

#if !defined(DETOURS_IA64)
    if (cbTarget > sizeof(pTrampoline->rbCode) - cbJump) {
        // Too many instructions.
        error = ERROR_INVALID_HANDLE;
        DETOUR_BREAK();
        goto fail;
    }
#endif // !DETOURS_IA64

    pTrampoline->pbRemain = pbTarget + cbTarget;
    pTrampoline->pbDetour = (PBYTE)pDetour;

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




































#endif // DETOURS_IA64

    pbTrampoline = pTrampoline->rbCode + pTrampoline->cbCode;
#ifdef DETOURS_X64
#error Feature not supported in this release.

#endif // DETOURS_X64

#ifdef DETOURS_X86
    pbTrampoline = detour_gen_jmp_immediate(pbTrampoline, pTrampoline->pbRemain);
    pbTrampoline = detour_gen_brk(pbTrampoline, pbPool);
#endif // DETOURS_X86

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

#endif // DETOURS_ARM

    DWORD dwOld = 0;
    if (!VirtualProtect(pbTarget, cbTarget, PAGE_EXECUTE_READWRITE, &dwOld)) {
        error = GetLastError();
        DETOUR_BREAK();
        goto fail;
    }

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

    o->fIsRemove = FALSE;
    o->ppbPointer = (PBYTE*)ppPointer;
    o->pTrampoline = pTrampoline;
    o->pbTarget = pbTarget;
    o->dwPerm = dwOld;
    o->pNext = s_pPendingOperations;
    s_pPendingOperations = o;

    return NO_ERROR;
}