Backed out 5 changesets (bug 951827) for causing bug 975820.

Backed out changeset 16b840c2de31 (bug 951827)
Backed out changeset 8fb155711dfe (bug 951827)
Backed out changeset 1109dba48e6b (bug 951827)
Backed out changeset 236ed76eea8b (bug 951827)
Backed out changeset 96cf7c13a8cb (bug 951827)
This commit is contained in:
Ryan VanderMeulen 2014-02-24 14:52:14 -05:00
Родитель bf210fa5d2
Коммит 12d0416fc6
3 изменённых файлов: 39 добавлений и 248 удалений

Просмотреть файл

@ -614,8 +614,7 @@ DllBlocklist_Initialize()
ReentrancySentinel::InitializeStatics();
// Use a shared hook since other software may also hook this API (bug 951827)
bool ok = NtDllIntercept.AddSharedHook("LdrLoadDll", reinterpret_cast<intptr_t>(patched_LdrLoadDll), (void**) &stub_LdrLoadDll);
bool ok = NtDllIntercept.AddHook("LdrLoadDll", reinterpret_cast<intptr_t>(patched_LdrLoadDll), (void**) &stub_LdrLoadDll);
if (!ok) {
sBlocklistInitFailed = true;

Просмотреть файл

@ -41,13 +41,8 @@
* 1. Save first N bytes of OrigFunction to trampoline, where N is a
* number of bytes >= 5 that are instruction aligned.
*
* 2. (Usually) Replace first 5 bytes of OrigFunction with a jump to the hook
* 2. Replace first 5 bytes of OrigFunction with a jump to the Hook
* function.
* (Special "shared" mode) Replace first 6 bytes of OrigFunction with an
* indirect jump to the hook function. "Shared" means that other software
* also tries to hook the same function. The indirect jump uses an absolute
* address, which allows us to coexist with other hooks that don't know how
* to relocate our 5-byte PC-relative jump.
*
* 3. After N bytes of the trampoline, add a jump to OrigFunction+N to
* continue original program flow.
@ -81,8 +76,6 @@ class WindowsDllNopSpacePatcher
byteptr_t mPatchedFns[maxPatchedFns];
int mPatchedFnsLen;
static const uint16_t opTrampolineShortJump = 0xf9eb;
public:
WindowsDllNopSpacePatcher()
: mModule(0)
@ -96,11 +89,6 @@ public:
for (int i = 0; i < mPatchedFnsLen; i++) {
byteptr_t fn = mPatchedFns[i];
// If other code has changed this function, it is not safe to modify.
if (*((uint16_t*)fn) != opTrampolineShortJump) {
continue;
}
// Ensure we can write to the code.
DWORD op;
if (!VirtualProtectEx(GetCurrentProcess(), fn, 2, PAGE_EXECUTE_READWRITE, &op)) {
@ -202,7 +190,7 @@ public:
*origFunc = fn + 2;
// Short jump up into our long jump.
*((uint16_t*)(fn)) = opTrampolineShortJump; // jmp $-5
*((uint16_t*)(fn)) = 0xf9eb; // jmp $-5
// I think this routine is safe without this, but it can't hurt.
FlushInstructionCache(GetCurrentProcess(),
@ -224,12 +212,6 @@ class WindowsDllDetourPatcher
{
typedef unsigned char *byteptr_t;
public:
enum JumpType
{
JUMP_DONTCARE,
JUMP_ABSOLUTE
};
WindowsDllDetourPatcher()
: mModule(0), mHookPage(0), mMaxHooks(0), mCurHooks(0)
{
@ -247,28 +229,7 @@ public:
#else
#error "Unknown processor type"
#endif
Trampoline *tramp = (Trampoline*)p;
byteptr_t origBytes = (byteptr_t)tramp->origFunction;
// If CreateTrampoline failed, we may have an empty trampoline.
if (!origBytes) {
continue;
}
// If other code has changed this function, it is not safe to modify.
#if defined(_M_IX86)
if (tramp->jumpType != JUMP_ABSOLUTE &&
*origBytes != opTrampolineRelativeJump) {
continue;
}
#elif defined(_M_X64)
if (*((uint16_t*)origBytes) != opTrampolineRegLoad) {
continue;
}
#else
#error "Unknown processor type"
#endif
byteptr_t origBytes = *((byteptr_t *)p);
// ensure we can modify the original code
DWORD op;
if (!VirtualProtectEx(GetCurrentProcess(), origBytes, nBytes, PAGE_EXECUTE_READWRITE, &op)) {
@ -277,14 +238,9 @@ public:
}
// Remove the hook by making the original function jump directly
// in the trampoline.
intptr_t dest = (intptr_t)(&tramp->code[0]);
intptr_t dest = (intptr_t)(p + sizeof(void *));
#if defined(_M_IX86)
if (tramp->jumpType == JUMP_ABSOLUTE) {
// Absolute jumps on x86 are done indirectly via tramp->jumpTarget
tramp->jumpTarget = dest;
} else {
*((intptr_t*)(origBytes+1)) = dest - (intptr_t)(origBytes+5); // target displacement
}
*((intptr_t*)(origBytes+1)) = dest - (intptr_t)(origBytes+5); // target displacement
#elif defined(_M_X64)
*((intptr_t*)(origBytes+2)) = dest;
#else
@ -339,7 +295,7 @@ public:
mModule = 0;
}
bool AddHook(const char *pname, intptr_t hookDest, JumpType jumpType, void **origFunc)
bool AddHook(const char *pname, intptr_t hookDest, void **origFunc)
{
if (!mModule)
return false;
@ -350,7 +306,7 @@ public:
return false;
}
CreateTrampoline(pAddr, hookDest, jumpType, origFunc);
CreateTrampoline(pAddr, hookDest, origFunc);
if (!*origFunc) {
//printf ("CreateTrampoline failed\n");
return false;
@ -362,35 +318,19 @@ public:
protected:
const static int kPageSize = 4096;
const static int kHookSize = 128;
const static int kCodeSize = 100;
const static uint8_t opTrampolineRelativeJump = 0xe9;
const static uint16_t opTrampolineIndirectJump = 0x25ff;
const static uint16_t opTrampolineRegLoad = 0xbb49;
HMODULE mModule;
byteptr_t mHookPage;
int mMaxHooks;
int mCurHooks;
struct Trampoline
{
void *origFunction;
JumpType jumpType;
intptr_t jumpTarget;
uint8_t code[kCodeSize];
};
static_assert(sizeof(Trampoline) <= kHookSize, "Trampolines too big");
void CreateTrampoline(void *origFunction,
intptr_t dest,
JumpType jumpType,
void **outTramp)
{
*outTramp = nullptr;
Trampoline *tramp = FindTrampolineSpace();
byteptr_t tramp = FindTrampolineSpace();
if (!tramp)
return;
@ -400,9 +340,7 @@ protected:
int pJmp32 = -1;
#if defined(_M_IX86)
const int bytesNeeded = (jumpType == JUMP_ABSOLUTE) ? 6 : 5;
while (nBytes < bytesNeeded) {
while (nBytes < 5) {
// Understand some simple instructions that might be found in a
// prologue; we might need to extend this as necessary.
//
@ -446,22 +384,10 @@ protected:
} else if (origBytes[nBytes] == 0x6A) {
// PUSH imm8
nBytes += 2;
} else if (origBytes[nBytes] == 0xa1) {
// MOV EAX, dword ptr [m32]
nBytes += 5;
} else if (origBytes[nBytes] == 0xe9) {
pJmp32 = nBytes;
// jmp 32bit offset
nBytes += 5;
} else if (origBytes[nBytes] == 0xf6 &&
origBytes[nBytes+1] == 0x05) {
// TEST byte ptr [m32], imm8
nBytes += 7;
} else if (origBytes[nBytes] == 0xff &&
origBytes[nBytes+1] == 0x25) {
// JMP dword ptr [m32]
// This is an indirect absolute jump; don't set pJmp32
nBytes += 6;
} else {
//printf ("Unknown x86 instruction byte 0x%02x, aborting trampoline\n", origBytes[nBytes]);
return;
@ -613,18 +539,17 @@ protected:
#error "Unknown processor type"
#endif
if (nBytes > kCodeSize) {
if (nBytes > 100) {
//printf ("Too big!");
return;
}
// We keep the address of the original function in the first bytes of
// the trampoline buffer
tramp->origFunction = origFunction;
tramp->jumpType = jumpType;
tramp->jumpTarget = dest;
*((void **)tramp) = origFunction;
tramp += sizeof(void *);
memcpy(&tramp->code[0], origFunction, nBytes);
memcpy(tramp, origFunction, nBytes);
// OrigFunction+N, the target of the trampoline
byteptr_t trampDest = origBytes + nBytes;
@ -634,36 +559,38 @@ protected:
// Jump directly to the original target of the jump instead of jumping to the
// original function.
// Adjust jump target displacement to jump location in the trampoline.
*((intptr_t*)(&tramp->code[pJmp32+1])) += origBytes - &tramp->code[0];
*((intptr_t*)(tramp+pJmp32+1)) += origBytes - tramp;
} else {
tramp->code[nBytes] = opTrampolineRelativeJump; // jmp
*((intptr_t*)(&tramp->code[nBytes+1])) = (intptr_t)trampDest - (intptr_t)(&tramp->code[nBytes+5]); // target displacement
tramp[nBytes] = 0xE9; // jmp
*((intptr_t*)(tramp+nBytes+1)) = (intptr_t)trampDest - (intptr_t)(tramp+nBytes+5); // target displacement
}
#elif defined(_M_X64)
// If JMP32 opcode found, we don't insert to trampoline jump
if (pJmp32 >= 0) {
// mov r11, address
*((uint16_t*)(&tramp->code[pJmp32])) = opTrampolineRegLoad;
*((intptr_t*)(&tramp->code[pJmp32+2])) = (intptr_t)directJmpAddr;
tramp[pJmp32] = 0x49;
tramp[pJmp32+1] = 0xbb;
*((intptr_t*)(tramp+pJmp32+2)) = (intptr_t)directJmpAddr;
// jmp r11
tramp->code[pJmp32+10] = 0x41;
tramp->code[pJmp32+11] = 0xff;
tramp->code[pJmp32+12] = 0xe3;
tramp[pJmp32+10] = 0x41;
tramp[pJmp32+11] = 0xff;
tramp[pJmp32+12] = 0xe3;
} else {
// mov r11, address
*((uint16_t*)(&tramp->code[nBytes])) = opTrampolineRegLoad;
*((intptr_t*)(&tramp->code[nBytes+2])) = (intptr_t)trampDest;
tramp[nBytes] = 0x49;
tramp[nBytes+1] = 0xbb;
*((intptr_t*)(tramp+nBytes+2)) = (intptr_t)trampDest;
// jmp r11
tramp->code[nBytes+10] = 0x41;
tramp->code[nBytes+11] = 0xff;
tramp->code[nBytes+12] = 0xe3;
tramp[nBytes+10] = 0x41;
tramp[nBytes+11] = 0xff;
tramp[nBytes+12] = 0xe3;
}
#endif
// The trampoline is now valid.
*outTramp = &tramp->code[0];
*outTramp = tramp;
// ensure we can modify the original code
DWORD op;
@ -674,18 +601,13 @@ protected:
#if defined(_M_IX86)
// now modify the original bytes
if (jumpType == JUMP_ABSOLUTE) {
// Indirect jump with absolute address of pointer
// jmp dword ptr [&tramp->jumpTarget]
*((uint16_t*)(origBytes)) = opTrampolineIndirectJump;
*((intptr_t*)(origBytes+2)) = (intptr_t)&tramp->jumpTarget;
} else {
origBytes[0] = opTrampolineRelativeJump; // jmp rel32
*((intptr_t*)(origBytes+1)) = dest - (intptr_t)(origBytes+5); // target displacement
}
origBytes[0] = 0xE9; // jmp
*((intptr_t*)(origBytes+1)) = dest - (intptr_t)(origBytes+5); // target displacement
#elif defined(_M_X64)
// mov r11, address
*((uint16_t*)(origBytes)) = opTrampolineRegLoad;
origBytes[0] = 0x49;
origBytes[1] = 0xbb;
*((intptr_t*)(origBytes+2)) = dest;
// jmp r11
@ -698,16 +620,16 @@ protected:
VirtualProtectEx(GetCurrentProcess(), origFunction, nBytes, op, &op);
}
Trampoline* FindTrampolineSpace()
byteptr_t FindTrampolineSpace()
{
if (mCurHooks >= mMaxHooks)
return nullptr;
return 0;
byteptr_t p = mHookPage + mCurHooks*kHookSize;
mCurHooks++;
return (Trampoline*)p;
return p;
}
};
@ -717,7 +639,6 @@ class WindowsDllInterceptor
{
internal::WindowsDllNopSpacePatcher mNopSpacePatcher;
internal::WindowsDllDetourPatcher mDetourPatcher;
typedef internal::WindowsDllDetourPatcher::JumpType JumpType;
const char *mModuleName;
int mNHooks;
@ -765,32 +686,10 @@ public:
mDetourPatcher.Init(mModuleName, mNHooks);
}
bool rv = mDetourPatcher.AddHook(pname, hookDest, JumpType::JUMP_DONTCARE,
origFunc);
bool rv = mDetourPatcher.AddHook(pname, hookDest, origFunc);
// printf("detourPatcher returned %d\n", rv);
return rv;
}
bool AddSharedHook(const char *pname, intptr_t hookDest, void **origFunc)
{
if (!mModuleName) {
return false;
}
// Skip the nop-space patcher and use only the detour patcher. Nop-space
// patches use relative jumps, which are not safe to share.
if (!mDetourPatcher.Initialized()) {
mDetourPatcher.Init(mModuleName, mNHooks);
}
bool rv = mDetourPatcher.AddHook(pname, hookDest, JumpType::JUMP_ABSOLUTE,
origFunc);
return rv;
}
};
} // namespace mozilla

Просмотреть файл

@ -38,31 +38,6 @@ patched_rotatePayload(payload p)
return orig_rotatePayload(p);
}
__declspec(noinline) bool AlwaysTrue(int, int, int, int, int, int) {
// Dummy function that makes the caller recognizable by the detour patcher
return true;
}
extern "C" __declspec(dllexport) __declspec(noinline) uint32_t SetBits(uint32_t x)
{
if (AlwaysTrue(1, 2, 3, 4, 5, 6)) {
return x | 0x11;
}
return 0;
}
static uint32_t (*orig_SetBits_early)(uint32_t);
static uint32_t patched_SetBits_early(uint32_t x)
{
return orig_SetBits_early(x) | 0x2200;
}
static uint32_t (*orig_SetBits_late)(uint32_t);
static uint32_t patched_SetBits_late(uint32_t x)
{
return orig_SetBits_late(x) | 0x330000;
}
bool TestHook(const char *dll, const char *func)
{
void *orig_func;
@ -82,25 +57,6 @@ bool TestHook(const char *dll, const char *func)
}
}
bool TestSharedHook(const char *dll, const char *func)
{
void *orig_func;
bool successful = false;
{
WindowsDllInterceptor TestIntercept;
TestIntercept.Init(dll);
successful = TestIntercept.AddSharedHook(func, 0, &orig_func);
}
if (successful) {
printf("TEST-PASS | WindowsDllInterceptor | Could hook (shared) %s from %s\n", func, dll);
return true;
} else {
printf("TEST-UNEXPECTED-FAIL | WindowsDllInterceptor | Failed to hook (shared) %s from %s\n", func, dll);
return false;
}
}
int main()
{
payload initial = { 0x12345678, 0xfc4e9d31, 0x87654321 };
@ -156,66 +112,6 @@ int main()
return 1;
}
#ifdef _M_IX86
// The x64 detour patcher does understand the assembly code of SetBits.
// We only need these shared hook tests on x86 anyway, because shared hooks
// are the same as regular hooks on x64.
// Despite the noinline annotation, the compiler may try to re-use the
// return value of SetBits(0). Force it to call the function every time.
uint32_t (*volatile SetBitsVolatile)(uint32_t) = SetBits;
{
WindowsDllInterceptor ExeInterceptEarly;
ExeInterceptEarly.Init("TestDllInterceptor.exe");
if (ExeInterceptEarly.AddSharedHook("SetBits", reinterpret_cast<intptr_t>(patched_SetBits_early), (void**) &orig_SetBits_early)) {
printf("TEST-PASS | WindowsDllInterceptor | Early hook added\n");
} else {
printf("TEST-UNEXPECTED-FAIL | WindowsDllInterceptor | Failed to add early hook\n");
return 1;
}
if (SetBitsVolatile(0) == 0x2211) {
printf("TEST-PASS | WindowsDllInterceptor | Early hook was called\n");
} else {
printf("TEST-UNEXPECTED-FAIL | WindowsDllInterceptor | Early hook was not called\n");
return 1;
}
{
WindowsDllInterceptor ExeInterceptLate;
ExeInterceptLate.Init("TestDllInterceptor.exe");
if (ExeInterceptLate.AddHook("SetBits", reinterpret_cast<intptr_t>(patched_SetBits_late), (void**) &orig_SetBits_late)) {
printf("TEST-PASS | WindowsDllInterceptor | Late hook added\n");
} else {
printf("TEST-UNEXPECTED-FAIL | WindowsDllInterceptor | Failed to add late hook\n");
return 1;
}
if (SetBitsVolatile(0) == 0x332211) {
printf("TEST-PASS | WindowsDllInterceptor | Late hook was called\n");
} else {
printf("TEST-UNEXPECTED-FAIL | WindowsDllInterceptor | Late hook was not called\n");
return 1;
}
}
if (SetBitsVolatile(0) == 0x2211) {
printf("TEST-PASS | WindowsDllInterceptor | Late hook was unregistered\n");
} else {
printf("TEST-UNEXPECTED-FAIL | WindowsDllInterceptor | Late hook was not unregistered\n");
return 1;
}
}
if (SetBitsVolatile(0) == 0x11) {
printf("TEST-PASS | WindowsDllInterceptor | Early hook was unregistered\n");
} else {
printf("TEST-UNEXPECTED-FAIL | WindowsDllInterceptor | Early hook was not unregistered\n");
return 1;
}
#endif
if (TestHook("user32.dll", "GetWindowInfo") &&
#ifdef _WIN64
TestHook("user32.dll", "SetWindowLongPtrA") &&
@ -242,9 +138,6 @@ int main()
TestHook("kernel32.dll", "VirtualAlloc") &&
TestHook("kernel32.dll", "MapViewOfFile") &&
TestHook("gdi32.dll", "CreateDIBSection") &&
#endif
#ifdef _M_IX86 // Shared hooks are the same as regular hooks on x64
TestSharedHook("ntdll.dll", "LdrLoadDll") &&
#endif
TestHook("ntdll.dll", "LdrLoadDll")) {
printf("TEST-PASS | WindowsDllInterceptor | all checks passed\n");