Bug 1240977 - DLL interceptor improvements for Windows 10 x64 ntdll APIs; r=ehsan

This commit is contained in:
Aaron Klotz 2016-01-20 10:44:17 -07:00
Родитель d0a5f2f401
Коммит 096c338869
1 изменённых файлов: 74 добавлений и 0 удалений

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

@ -468,6 +468,69 @@ protected:
int mMaxHooks;
int mCurHooks;
// rex bits
static const BYTE kMaskHighNibble = 0xF0;
static const BYTE kRexOpcode = 0x40;
static const BYTE kMaskRexW = 0x08;
static const BYTE kMaskRexR = 0x04;
static const BYTE kMaskRexX = 0x02;
static const BYTE kMaskRexB = 0x01;
// mod r/m bits
static const BYTE kRegFieldShift = 3;
static const BYTE kMaskMod = 0xC0;
static const BYTE kMaskReg = 0x38;
static const BYTE kMaskRm = 0x07;
static const BYTE kRmNeedSib = 0x04;
static const BYTE kModReg = 0xC0;
static const BYTE kModDisp32 = 0x80;
static const BYTE kModDisp8 = 0x40;
static const BYTE kModNoRegDisp = 0x00;
static const BYTE kRmNoRegDispDisp32 = 0x05;
// sib bits
static const BYTE kMaskSibScale = 0xC0;
static const BYTE kMaskSibIndex = 0x38;
static const BYTE kMaskSibBase = 0x07;
static const BYTE kSibBaseEbp = 0x05;
int CountModRmSib(const BYTE *aModRm, BYTE* aSubOpcode)
{
if (!aModRm) {
return -1;
}
int numBytes = 1; // Start with 1 for mod r/m byte itself
switch (*aModRm & kMaskMod) {
case kModReg:
return numBytes;
case kModDisp8:
numBytes += 1;
break;
case kModDisp32:
numBytes += 4;
break;
case kModNoRegDisp:
if ((*aModRm & kMaskRm) == kRmNoRegDispDisp32 ||
((*aModRm & kMaskRm) == kRmNeedSib &&
(*(aModRm + 1) & kMaskSibBase) == kSibBaseEbp)) {
numBytes += 4;
}
break;
default:
// This should not be reachable
MOZ_ASSERT_UNREACHABLE("Impossible value for modr/m byte mod bits");
return -1;
}
if ((*aModRm & kMaskRm) == kRmNeedSib) {
// SIB byte
numBytes += 1;
}
if (aSubOpcode) {
*aSubOpcode = (*aModRm & kMaskReg) >> kRegFieldShift;
}
return numBytes;
}
#if defined(_M_X64)
// To patch for JMP and JE
@ -775,6 +838,17 @@ protected:
} else if (origBytes[nBytes] == 0x33) {
// xor r32, r/m32
nBytes += 2;
} else if (origBytes[nBytes] == 0xf6) {
// test r/m8, imm8 (used by ntdll on Windows 10 x64)
// (no flags are affected by near jmp since there is no task switch,
// so it is ok for a jmp to be written immediately after a test)
BYTE subOpcode = 0;
int nModRmSibBytes = CountModRmSib(&origBytes[nBytes + 1], &subOpcode);
if (nModRmSibBytes < 0 || subOpcode != 0) {
// Unsupported
return;
}
nBytes += 2 + nModRmSibBytes;
} else if (origBytes[nBytes] == 0xc3) {
// ret
nBytes++;