mirror of
https://github.com/vosen/ZLUDA.git
synced 2025-04-25 01:54:43 +00:00
702 lines
20 KiB
C++
Vendored
702 lines
20 KiB
C++
Vendored
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Module: disas.cpp (disas.exe - Detours Test Program)
|
|
//
|
|
// Microsoft Research Detours Package
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
|
|
#define DETOURS_INTERNAL
|
|
#include <detours.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
///////////////////////////////////////////////////////////////////////// ARM.
|
|
//
|
|
#ifdef DETOURS_ARM
|
|
|
|
extern "C" BYTE TestCodes[];
|
|
|
|
void DumpMemoryFragment(PBYTE pbData, ULONG cbData, ULONG cbSpace)
|
|
{
|
|
ULONG n = 0;
|
|
if (cbData >= 4) {
|
|
printf("%04x%04x ", ((PUSHORT)pbData)[0], ((PUSHORT)pbData)[1]);
|
|
n += 4;
|
|
}
|
|
else if (cbData >= 2) {
|
|
printf("%04x ", *((PUSHORT)pbData));
|
|
n += 2;
|
|
}
|
|
|
|
for (; n < cbSpace; n++) {
|
|
if (n < cbData) {
|
|
printf("%02x", pbData[n]);
|
|
}
|
|
else {
|
|
printf(" ");
|
|
}
|
|
}
|
|
if (n < cbData) {
|
|
printf(".");
|
|
}
|
|
else {
|
|
printf(" ");
|
|
}
|
|
}
|
|
|
|
inline ULONG fetch_thumb_opcode(PBYTE pbCode)
|
|
{
|
|
ULONG Opcode = *(UINT16 *)&pbCode[0];
|
|
if (Opcode >= 0xe800) {
|
|
Opcode = (Opcode << 16) | *(UINT16 *)&pbCode[2];
|
|
}
|
|
return Opcode;
|
|
}
|
|
|
|
BOOL IsTerminate(PBYTE pbSrc)
|
|
{
|
|
ULONG opcode = fetch_thumb_opcode(pbSrc);
|
|
|
|
if ((opcode & 0xff87) == 0x4700) {
|
|
// bx r
|
|
return TRUE;
|
|
}
|
|
|
|
#if 0
|
|
if ((opcode & 0xfbf08f00) == 0xf2400c00) { // movw r12,#xxxx
|
|
return TRUE;
|
|
}
|
|
|
|
if ((opcode == 0xf8dcf000) { // ldr pc,[r12]
|
|
ULONG Immediate = ((opcode2 << 12) & 0xf7000000) |
|
|
((opcode2 << 1) & 0x08000000) |
|
|
((opcode2 << 16) & 0x00ff0000) |
|
|
((opcode >> 4) & 0x0000f700) |
|
|
((opcode >> 15) & 0x00000800) |
|
|
((opcode >> 0) & 0x000000ff);
|
|
PBYTE pbTarget = *(PBYTE *)Immediate;
|
|
if (detour_is_imported(pbCode, pbTarget)) {
|
|
PBYTE pbNew = *(PBYTE *)pbTarget;
|
|
DETOUR_TRACE(("%p->%p: skipped over import table.\n", pbCode, pbNew));
|
|
return pbNew;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
#endif // DETOURS_ARM
|
|
|
|
///////////////////////////////////////////////////////////////// X86 and X64.
|
|
//
|
|
#if defined(DETOURS_X86) || defined(DETOURS_X64)
|
|
|
|
extern "C" BYTE TestCodes[];
|
|
|
|
void DumpMemoryFragment(PBYTE pbData, ULONG cbData, ULONG cbSpace)
|
|
{
|
|
ULONG n = 0;
|
|
for (; n < cbSpace; n++) {
|
|
if (n < cbData) {
|
|
printf("%02x", pbData[n]);
|
|
}
|
|
else {
|
|
printf(" ");
|
|
}
|
|
}
|
|
if (n < cbData) {
|
|
printf(".");
|
|
}
|
|
else {
|
|
printf(" ");
|
|
}
|
|
}
|
|
|
|
BOOL IsTerminate(PBYTE pbSrc)
|
|
{
|
|
if ((0xC3 == pbSrc[0] && 0x00 == pbSrc[1]) || // bx lr
|
|
0xCB == pbSrc[0] || // RETF
|
|
0xC2 == pbSrc[0] || // RET dw
|
|
0xCA == pbSrc[0] || // RETF dw
|
|
0xEB == pbSrc[0] || // JMP ob
|
|
0xE9 == pbSrc[0] || // JMP ol
|
|
0xEA == pbSrc[0]) { // JMP ol
|
|
|
|
return TRUE;
|
|
}
|
|
if (0xff == pbSrc[0] && 0x25 == pbSrc[1]) // JMP [addr]
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
#endif // DETOURS_X86 || DETOURS_X64
|
|
|
|
/////////////////////////////////////////////////////////// X86, X64, and ARM.
|
|
//
|
|
#if defined(DETOURS_X86) || defined(DETOURS_X64) || defined(DETOURS_ARM)
|
|
struct BasicBlockLink
|
|
{
|
|
public:
|
|
BasicBlockLink * m_pNext;
|
|
PBYTE m_pbEntry;
|
|
PCHAR m_pszName;
|
|
|
|
public:
|
|
BasicBlockLink(PBYTE pbEntry, PCHAR pszName = NULL)
|
|
{
|
|
m_pNext = NULL;
|
|
m_pbEntry = pbEntry;
|
|
m_pszName = pszName;
|
|
|
|
*s_ppTail = this;
|
|
s_ppTail = &m_pNext;
|
|
}
|
|
|
|
BasicBlockLink * Next()
|
|
{
|
|
return m_pNext;
|
|
}
|
|
|
|
static BasicBlockLink * GetListHead()
|
|
{
|
|
return s_pHead;
|
|
}
|
|
|
|
protected:
|
|
static BasicBlockLink * s_pHead;
|
|
static BasicBlockLink ** s_ppTail;
|
|
};
|
|
|
|
BasicBlockLink * BasicBlockLink::s_pHead = NULL;
|
|
BasicBlockLink ** BasicBlockLink::s_ppTail = &BasicBlockLink::s_pHead;
|
|
|
|
static PBYTE s_pbBegin = NULL;
|
|
static PBYTE s_pbLimit = NULL;
|
|
|
|
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;
|
|
}
|
|
|
|
BOOL CALLBACK ExportCallback(_In_opt_ PVOID pContext,
|
|
_In_ ULONG nOrdinal,
|
|
_In_opt_ LPCSTR pszName,
|
|
_In_opt_ PVOID pCode)
|
|
{
|
|
(void)pContext;
|
|
(void)nOrdinal;
|
|
(void)pCode;
|
|
|
|
(VOID) new BasicBlockLink((PBYTE)pCode, pszName ? pszName : "[NO NAME]");
|
|
return TRUE;
|
|
}
|
|
#endif // DETOURS_X86 || DETOURS_X64
|
|
|
|
//////////////////////////////////////////////////////////////////////// IA64.
|
|
//
|
|
#ifdef DETOURS_IA64
|
|
#pragma warning(disable: 4201) // ignore warning about unnamed sturcture in union.
|
|
|
|
void DumpHi(PBYTE pbData, ULONG cbData, ULONG cbSpace)
|
|
{
|
|
ULONG n = 0;
|
|
for (; n < cbSpace; n++) {
|
|
if (n < cbData) {
|
|
printf("%02x", pbData[(cbData - 1) - n]);
|
|
}
|
|
else {
|
|
printf(" ");
|
|
}
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
struct DETOUR_IA64_BUNDLE_DISASSEMBLE : public DETOUR_IA64_BUNDLE
|
|
{
|
|
public:
|
|
void SetBrx(UINT64 raw)
|
|
{
|
|
SetBrl();
|
|
SetBrlImm(raw);
|
|
}
|
|
|
|
void Dis()
|
|
{
|
|
const char szUnitNames[17] = "?aimbflx?AIMBFLX";
|
|
|
|
printf("%p: ", data);
|
|
BYTE nTemplate = GetTemplate();
|
|
BYTE nInst0 = GetInst0();
|
|
BYTE nInst1 = GetInst1();
|
|
BYTE nInst2 = GetInst2();
|
|
BYTE nUnit0 = GetUnit0();
|
|
BYTE nUnit1 = GetUnit1();
|
|
BYTE nUnit2 = GetUnit2();
|
|
if (nUnit1 == L_UNIT) { // MLX instruction
|
|
UINT64 d2 = (
|
|
// 0x0000000000fffff0
|
|
((wide[1] & 0x00fffff000000000) >> 32) |
|
|
// 0x000000ffff000000
|
|
((wide[0] & 0xffff000000000000) >> 24) |
|
|
// 0x7fffff0000000000
|
|
((wide[1] & 0x00000000007fffff) << 40) |
|
|
// 0x8000000000000000
|
|
((wide[1] & 0x0800000000000000) << 4)
|
|
);
|
|
printf("%02x %c%01x %010I64lx %c%01x %016I64lx",
|
|
nTemplate,
|
|
szUnitNames[nUnit0], nInst0, GetData0(),
|
|
szUnitNames[nUnit2], nInst2, d2);
|
|
}
|
|
else {
|
|
printf("%02x %c%01x %010I64lx %c%01x %010I64lx %c%01x %010I64lx",
|
|
nTemplate,
|
|
szUnitNames[nUnit0], nInst0, GetData0(),
|
|
szUnitNames[nUnit1], nInst1, GetData1(),
|
|
szUnitNames[nUnit2], nInst2, GetData2());
|
|
}
|
|
|
|
if (IsBrl()) {
|
|
printf(" brl %p", GetBrlTarget());
|
|
}
|
|
else if (IsMovlGp()) {
|
|
printf(" movl gp=%p", GetMovlGp());
|
|
}
|
|
if ((wide[0] & 0xfffffc000603ffff) == 0x002024000200100b &&
|
|
wide[1] == 0x0004000000203008) {
|
|
|
|
ULONG64 offset =
|
|
((wide[0] & 0x0000000001fc0000) >> 18) | // imm7b
|
|
((wide[0] & 0x000001ff00000000) >> 25) | // imm9d
|
|
((wide[0] & 0x00000000f8000000) >> 11); // imm5c
|
|
if (wide[0] & 0x0000020000000000) {
|
|
offset |= 0xffffffffffe00000;
|
|
}
|
|
printf(" imm=%016I64lx", offset);
|
|
}
|
|
printf("\n");
|
|
}
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
BOOL CALLBACK ExportCallbackIA64(_In_opt_ PVOID pContext,
|
|
_In_ ULONG nOrdinal,
|
|
_In_opt_ LPCSTR pszName,
|
|
_In_opt_ PVOID pCode)
|
|
{
|
|
(void)pContext;
|
|
(void)nOrdinal;
|
|
|
|
DETOUR_IA64_BUNDLE_DISASSEMBLE *pb = *(DETOUR_IA64_BUNDLE_DISASSEMBLE **)pCode;
|
|
DETOUR_IA64_BUNDLE temp;
|
|
|
|
if (!pb[0].Copy(&temp)) {
|
|
printf("%s:\n ", pszName ? pszName : "[NO NAME]");
|
|
pb[0].Dis();
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
#if 0
|
|
void TestBoth()
|
|
{
|
|
LPVOID pvBase = VirtualAlloc((PBYTE)0x800000000, 0x10000,
|
|
MEM_RESERVE | MEM_COMMIT,
|
|
PAGE_EXECUTE_READWRITE);
|
|
|
|
DETOUR_IA64_BUNDLE *pbBase = (DETOUR_IA64_BUNDLE *)pvBase;
|
|
DETOUR_IA64_BUNDLE *pb = pbBase;
|
|
|
|
printf("TestBoth:\n");
|
|
for (UINT64 i = 0x10; i < 0x8000000000000000; i <<= 1) {
|
|
pb->SetMovlGp(i);
|
|
if (pb->GetMovlGp() != i) {
|
|
printf("Error in MovlGp!\n");
|
|
return;
|
|
}
|
|
pb++;
|
|
|
|
pb->SetBrl(i);
|
|
if (pb->GetBrlEip() != i) {
|
|
printf("Error in Brl!\n");
|
|
return;
|
|
}
|
|
pb++;
|
|
}
|
|
|
|
for (UINT64 i = (UINT64)(INT64)-0x10; i > 0; i <<= 1) {
|
|
pb->SetMovlGp(i);
|
|
if (pb->GetMovlGp() != i) {
|
|
printf("Error in MovlGp!\n");
|
|
return;
|
|
}
|
|
pb++;
|
|
|
|
pb->SetBrl(i);
|
|
if (pb->GetBrlEip() != i) {
|
|
printf("Error in Brl!\n");
|
|
return;
|
|
}
|
|
pb++;
|
|
}
|
|
|
|
printf("u %p %p\n", pbBase, pb);
|
|
}
|
|
#endif
|
|
#endif // DETOURS_IA64
|
|
|
|
int WINAPI WinMain(HINSTANCE hinst, HINSTANCE hprev, LPSTR lpszCmdLine, int nCmdShow)
|
|
{
|
|
(void)hprev;
|
|
(void)hinst;
|
|
(void)lpszCmdLine;
|
|
(void)nCmdShow;
|
|
|
|
// Bug report, but it works here.
|
|
// 07ff8`4b783054 49ba 70b3d93a d40fb998 mov r10,98B90FD43AD9B370h
|
|
//
|
|
{
|
|
static const UCHAR mov_r10_imm64[] = {0x49, 0xba, 1, 2, 3, 4, 5, 6, 7, 8 };
|
|
|
|
PVOID const after = DetourCopyInstructionX64(0, 0, const_cast<PUCHAR>(mov_r10_imm64), 0, 0);
|
|
|
|
if (after != &mov_r10_imm64 + 1)
|
|
{
|
|
printf("mov_r10_imm64 failed, expected:%p vs. got:%p\n", &mov_r10_imm64 + 1, after);
|
|
if (IsDebuggerPresent())
|
|
{
|
|
__debugbreak();
|
|
DetourCopyInstructionX64(0, 0, const_cast<PUCHAR>(mov_r10_imm64), 0, 0);
|
|
}
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
#ifdef DETOURS_IA64
|
|
// First we check the pre-canned TestCodes from disasm.asm
|
|
//
|
|
PBYTE pbTest = *(PBYTE*)WinMain;
|
|
for (;; pbTest += 16) {
|
|
DETOUR_IA64_BUNDLE_DISASSEMBLE *pb = (DETOUR_IA64_BUNDLE_DISASSEMBLE *)pbTest;
|
|
|
|
pb->Dis();
|
|
if (pbTest[0] == 0xff) {
|
|
break;
|
|
}
|
|
DumpHi(pbTest, 16, 16);
|
|
}
|
|
|
|
#if 0
|
|
printf("\n\n");
|
|
|
|
DETOUR_IA64_BUNDLE_DISASSEMBLE *pb = (DETOUR_IA64_BUNDLE_DISASSEMBLE *)pbTest;
|
|
DETOUR_IA64_BUNDLE_DISASSEMBLE *pbBeg = pb;
|
|
DWORD dwOld;
|
|
VirtualProtect(pb, 0x2000, PAGE_EXECUTE_READWRITE, &dwOld);
|
|
printf("%p: (%d)\n", pb, sizeof(pb));
|
|
pb++;
|
|
printf("%p: (%d)\n", pb, sizeof(pb));
|
|
pb++; pb->SetBrx(0);
|
|
pb++; pb->SetBrx(0);
|
|
pb++; pb->SetBrx(0);
|
|
pb++; pb->SetBrx(0xffffffffffffffff);
|
|
pb++; pb->SetBrx(0x0fffffffffffffff);
|
|
pb++; pb->SetBrx(0x00ffffffffffffff);
|
|
pb++; pb->SetBrx(0x000fffffffffffff);
|
|
pb++; pb->SetBrx(0x0000ffffffffffff);
|
|
pb++; pb->SetBrx(0x00000fffffffffff);
|
|
pb++; pb->SetBrx(0x000000ffffffffff);
|
|
pb++; pb->SetBrx(0x0000000fffffffff);
|
|
pb++; pb->SetBrx(0x00000000ffffffff);
|
|
pb++; pb->SetBrx(0x000000000fffffff);
|
|
pb++; pb->SetBrx(0x0000000000ffffff);
|
|
pb++; pb->SetBrx(0x00000000000fffff);
|
|
pb++; pb->SetBrx(0x000000000000ffff);
|
|
pb++; pb->SetBrx(0x0000000000000fff);
|
|
pb++; pb->SetBrx(0x00000000000000ff);
|
|
pb++; pb->SetBrx(0x000000000000000f);
|
|
pb++; pb->SetBrx(0x0000000000000000);
|
|
pb++; pb->SetBrx(0xffffffffffffffff);
|
|
pb++; pb->SetBrx(0xffffffffffffffff);
|
|
pb->SetInst0(0xff);
|
|
pb->SetData0(0xffffffffffffffff);
|
|
printf("%p:\n", pb);
|
|
DETOUR_IA64_BUNDLE_DISASSEMBLE *pbEnd = pb;
|
|
for (pb = pbBeg; pb < pbEnd; pb++) {
|
|
printf(" %p: ", pb);
|
|
DumpHi((BYTE*)pb, 16, 16);
|
|
}
|
|
#endif
|
|
|
|
#if 1
|
|
{
|
|
// Then we check all of the code we can find in user32.dll
|
|
//
|
|
printf("\n");
|
|
HINSTANCE hInst = LoadLibraryA("user32.dll");
|
|
printf("Loaded: user32.dll: %p\n", hInst);
|
|
|
|
PBYTE pbEntry = (PBYTE)DetourGetEntryPoint(hInst);
|
|
printf("Entry: %p\n", pbEntry);
|
|
ExportCallbackIA64(NULL, 0, "[Entry]", pbEntry);
|
|
DetourEnumerateExports(hInst, NULL, ExportCallbackIA64);
|
|
}
|
|
|
|
{
|
|
// Then we check all of the code we can find in opengl32.dll
|
|
//
|
|
printf("\n");
|
|
HINSTANCE hInst = LoadLibraryA("opengl32.dll");
|
|
printf("Loaded: opengl32.dll: %p\n", hInst);
|
|
|
|
PBYTE pbEntry = (PBYTE)DetourGetEntryPoint(hInst);
|
|
printf("Entry: %p\n", pbEntry);
|
|
ExportCallbackIA64(NULL, 0, "[Entry]", pbEntry);
|
|
DetourEnumerateExports(hInst, NULL, ExportCallbackIA64);
|
|
}
|
|
|
|
printf("\n");
|
|
for (HINSTANCE hInst = NULL; (hInst = DetourEnumerateModules(hInst)) != NULL;) {
|
|
CHAR szModuleName[512];
|
|
GetModuleFileNameA(hInst, szModuleName,
|
|
sizeof(szModuleName)/sizeof(szModuleName[0]));
|
|
printf("%p : %s\n", hInst, szModuleName);
|
|
DetourEnumerateExports(hInst, NULL, ExportCallbackIA64);
|
|
}
|
|
|
|
printf("\n");
|
|
#endif
|
|
#if 0
|
|
TestBoth();
|
|
#endif
|
|
#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("%08lx ", (ULONG)(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("%08lx ", (ULONG)(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 = LoadLibraryA("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
|
|
// Create an output buffer and fill it with debugbreaks.
|
|
//
|
|
PBYTE pbBuffer
|
|
= (PBYTE)VirtualAlloc(NULL, 0x400, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE);
|
|
for (PBYTE pbOut = pbBuffer; pbOut < pbBuffer + 0x400;) {
|
|
*pbOut++ = 0xfe;
|
|
*pbOut++ = 0xde;
|
|
}
|
|
PBYTE pbDst = pbBuffer;
|
|
PVOID pvDstPool = (PVOID)(pbBuffer + 0x400);
|
|
|
|
// First we check the pre-canned TestCodes from disasm.asm
|
|
//
|
|
PBYTE pbBegin = (PBYTE)DetourCodeFromPointer(TestCodes, NULL);
|
|
printf("%p: (TestCodes %p) => %p\n", pbBegin, TestCodes, pbBuffer);
|
|
for (PBYTE pbSrc = pbBegin;;) {
|
|
if (pbSrc[0] != 0xfe && pbSrc[1] != 0xde) { // BREAK
|
|
printf("%08x ", pbSrc - pbBegin);
|
|
DumpMemoryFragment(pbSrc, 8, 8);
|
|
printf("\n");
|
|
printf("failed on last.\n");
|
|
return 1;
|
|
}
|
|
pbSrc += 2;
|
|
*pbDst++ = 0xfe;
|
|
*pbDst++ = 0xde;
|
|
|
|
if ((pbSrc[0] == 0x00 && pbSrc[1] == 0xbf) && // NOP
|
|
(pbSrc[2] != 0xfe && pbSrc[3] != 0xde)) { // BREAK
|
|
// Skip over a single NOP so we can test alignment.
|
|
pbSrc += 2;
|
|
}
|
|
|
|
if ((pbSrc[0] == 0x00 && pbSrc[1] == 0xbf) && // NOP
|
|
(pbSrc[2] != 0xfe && pbSrc[3] != 0xde)) { // BREAK
|
|
// If there is a second NOP, then we insert alignment.
|
|
pbSrc += 2;
|
|
*pbDst++ = 0x00;
|
|
*pbDst++ = 0xbf;
|
|
}
|
|
|
|
|
|
LONG lExtra = 0;
|
|
PVOID pbTarget = NULL;
|
|
PBYTE pbNext = (PBYTE)DetourCopyInstruction(pbDst, &pvDstPool, pbSrc, &pbTarget, &lExtra);
|
|
|
|
LONG cbTest = (LONG)(pbNext - pbSrc);
|
|
|
|
printf("%08x ", pbSrc - pbBegin);
|
|
DumpMemoryFragment(pbSrc, cbTest, 4);
|
|
printf("[%8p] ", pbTarget);
|
|
DumpMemoryFragment(pbDst, cbTest + lExtra, 16);
|
|
printf("\n");
|
|
|
|
if (pbSrc[cbTest] != 0xfe || pbSrc[cbTest+1] != 0xde) {
|
|
printf("%p: failed! (pbSrc[n]=%02x, pbSrc[n+1]=%02x\n",
|
|
pbSrc,
|
|
pbSrc[cbTest], pbSrc[cbTest+1]);
|
|
__debugbreak();
|
|
pbNext = (PBYTE)DetourCopyInstruction(pbDst, &pvDstPool, pbSrc, &pbTarget, &lExtra);
|
|
cbTest = (LONG)(pbNext - pbSrc);
|
|
return 1;
|
|
}
|
|
|
|
pbDst += cbTest + lExtra;
|
|
pbSrc += cbTest;
|
|
|
|
if (pbSrc[0] == 0xfe && pbSrc[1] == 0xde &&
|
|
pbSrc[2] == 0xfe && pbSrc[3] == 0xde) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
// Then we check all of the code we can find in user32.dll
|
|
//
|
|
HINSTANCE hInst = LoadLibraryA("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_ARM
|
|
|
|
return 0;
|
|
}
|
|
//
|
|
///////////////////////////////////////////////////////////////// End of File.
|