mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
256 lines
7.1 KiB
256 lines
7.1 KiB
#include "master.hxx"
|
|
#pragma hdrstop
|
|
|
|
#define IMPOSSIBLE_ACCESS_LENGTH 0xFFFFFFFF
|
|
|
|
#define X86_FLAG_BIT_VM 0x0200
|
|
|
|
#define X86_OPCODE_ADDRESS_SIZE_PREFIX 0x67
|
|
#define X86_OPCODE_LOCK_PREFIX 0xF0
|
|
#define X86_OPCODE_OPERAND_SIZE_PREFIX 0x66
|
|
#define X86_OPCODE_CS_SEGMENT_PREFIX 0x2E
|
|
#define X86_OPCODE_DS_SEGMENT_PREFIX 0x3E
|
|
#define X86_OPCODE_ES_SEGMENT_PREFIX 0x26
|
|
#define X86_OPCODE_FS_SEGMENT_PREFIX 0x64
|
|
#define X86_OPCODE_GS_SEGMENT_PREFIX 0x65
|
|
#define X86_OPCODE_SS_SEGMENT_PREFIX 0x36
|
|
|
|
#define X86_OPCODE_REPE_PREFIX 0xF2
|
|
#define X86_OPCODE_REPNE_PREFIX 0xF3
|
|
|
|
#define X86_OPCODE_EXTENSION_PREFIX 0x0F
|
|
|
|
typedef struct
|
|
{
|
|
DWORD bmaskOpcodeMeaningfulBits;
|
|
DWORD bmpOpcode;
|
|
DWORD bmaskOpcodeAccessTypeBit;
|
|
ULONG cbDefaultLength;
|
|
LPSTR pszOpcodeName;
|
|
} X86_OPCODE_ENTRY;
|
|
|
|
static X86_OPCODE_ENTRY OriginalOpcodeList[]=
|
|
{
|
|
{ 0xFF, 0xD7, 0x00, 1, "XLAT" },
|
|
{ 0xFF, 0xFF, 0x00, 4, "CALL or JMP indirect via mem" },
|
|
|
|
{ 0xFE, 0x8A, 0x01, 1, "MOV mem to reg" },
|
|
{ 0xFE, 0x88, 0x01, 1, "MOV reg to mem" },
|
|
{ 0xFE, 0xC6, 0x01, 1, "MOV imm to mem" },
|
|
{ 0xFE, 0xA0, 0x01, 1, "MOV mem to acc" },
|
|
{ 0xFE, 0xA2, 0x01, 1, "MOV acc to mem" },
|
|
|
|
{ 0xFE, 0x86, 0x01, 1, "XCHG mem with reg" },
|
|
|
|
{ 0xFE, 0xF7, 0x01, 1, "INC/DEC mem" },
|
|
{ 0xFE, 0xF6, 0x01, 1, "NOT/NEG mem" },
|
|
|
|
{ 0xFE, 0x38, 0x01, 1, "CMP mem with reg" },
|
|
{ 0xFE, 0x3A, 0x01, 1, "CMP reg with mem" },
|
|
|
|
{ 0xFE, 0x84, 0x01, 1, "TEST mem and reg" },
|
|
{ 0xFE, 0xF6, 0x01, 1, "TEST/IMUL imm and mem" },
|
|
|
|
{ 0xFE, 0xD0, 0x01, 1, "Rotate or Shift by 1" },
|
|
{ 0xFE, 0xD2, 0x01, 1, "Rotate or Shift by cl" },
|
|
{ 0xFE, 0xC0, 0x01, 1, "Rotate or Shift by imm" },
|
|
|
|
{ 0xFE, 0xC0, 0x01, 1, "Rotate or Shift by imm" },
|
|
|
|
{ 0xFE, 0xA6, 0x01, 1, "CMPS" },
|
|
{ 0xFE, 0xAC, 0x01, 1, "LODS" },
|
|
{ 0xFE, 0xA4, 0x01, 1, "MOVS" },
|
|
{ 0xFE, 0xAE, 0x01, 1, "SCAS" },
|
|
{ 0xFE, 0xAA, 0x01, 1, "STOS" },
|
|
|
|
{ 0xFC, 0x80, 0x01, 1, "<intop> imm to mem" },
|
|
{ 0xFC, 0x80, 0x01, 1, "CMP imm with mem" },
|
|
|
|
{ 0xC6, 0x02, 0x01, 1, "<intop> mem to reg" },
|
|
{ 0xC6, 0x00, 0x01, 1, "<intop> reg to mem" },
|
|
|
|
{ 0x00, 0x00, 0x00, 0, "Sentinel" }
|
|
};
|
|
|
|
static X86_OPCODE_ENTRY ExtendedOpcodeList[]=
|
|
{
|
|
{ 0xFF, 0xAF, 0x00, 4, "IMUL reg w/ mem" },
|
|
{ 0xFF, 0xA4, 0x00, 4, "SHLD [mem],imm" },
|
|
{ 0xFF, 0xAC, 0x00, 4, "SHRD [mem],imm" },
|
|
{ 0xFF, 0xA5, 0x00, 4, "SHLD [mem],CL" },
|
|
{ 0xFF, 0xAD, 0x00, 4, "SHRD [mem],CL" },
|
|
{ 0xFF, 0xBA, 0x00, 4, "BTx [mem],imm" },
|
|
{ 0xFF, 0xA3, 0x00, 4, "BTx [mem],reg" },
|
|
{ 0xFF, 0xBC, 0x00, 4, "BSF [mem],imm" },
|
|
{ 0xFF, 0xBD, 0x00, 4, "BSR [mem],imm" },
|
|
|
|
{ 0xFE, 0xB6, 0x01, IMPOSSIBLE_ACCESS_LENGTH, "MOVZX assume: mem to reg" },
|
|
{ 0xFE, 0xBE, 0x01, IMPOSSIBLE_ACCESS_LENGTH, "MOVSX assume: mem to reg" },
|
|
|
|
{ 0xFE, 0xC0, 0x01, 1, "XADD [mem],reg" },
|
|
{ 0xFE, 0xB0, 0x01, 1, "CMPXCHG [mem],reg" },
|
|
|
|
{ 0xF0, 0x90, 0x00, 1, "SETcccc = Set byte on cccc" },
|
|
|
|
{ 0x00, 0x00, 0x00, 0, "Sentinel" }
|
|
};
|
|
|
|
|
|
BOOLEAN
|
|
X86_CalculateOpcodeAccessLength
|
|
(
|
|
IN HANDLE hProcess,
|
|
IN HANDLE hThread,
|
|
IN OUT PULONG pcbAccessLength,
|
|
IN OUT LPSTR *ppszDescription
|
|
)
|
|
{
|
|
BYTE Opcode;
|
|
CONTEXT Context;
|
|
BOOL fOperandSizeToggle=FALSE;
|
|
BOOL fByteAccess=FALSE;
|
|
DWORD cbRead;
|
|
BOOL fOpcodeIsPrefix;
|
|
int idxOpcode;
|
|
X86_OPCODE_ENTRY *OpcodeList = OriginalOpcodeList;
|
|
|
|
if ( pcbAccessLength == NULL )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
*pcbAccessLength = 1;
|
|
|
|
Context.ContextFlags = CONTEXT_FULL;
|
|
|
|
if ( !GetThreadContext( hThread, &Context ) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
for (;;Context.Eip++)
|
|
{
|
|
if ( !ReadProcessMemory( hProcess,
|
|
(PVOID)Context.Eip,
|
|
&Opcode,
|
|
sizeof( BYTE ),
|
|
&cbRead )
|
|
|| cbRead != sizeof(BYTE) )
|
|
{
|
|
return( FALSE );
|
|
}
|
|
|
|
fOpcodeIsPrefix = TRUE;
|
|
|
|
switch ( Opcode )
|
|
{
|
|
case X86_OPCODE_OPERAND_SIZE_PREFIX:
|
|
fOperandSizeToggle = TRUE;
|
|
break;
|
|
case X86_OPCODE_EXTENSION_PREFIX:
|
|
OpcodeList = ExtendedOpcodeList;
|
|
break;
|
|
case X86_OPCODE_LOCK_PREFIX:
|
|
case X86_OPCODE_ADDRESS_SIZE_PREFIX:
|
|
case X86_OPCODE_CS_SEGMENT_PREFIX:
|
|
case X86_OPCODE_DS_SEGMENT_PREFIX:
|
|
case X86_OPCODE_ES_SEGMENT_PREFIX:
|
|
case X86_OPCODE_FS_SEGMENT_PREFIX:
|
|
case X86_OPCODE_GS_SEGMENT_PREFIX:
|
|
case X86_OPCODE_SS_SEGMENT_PREFIX:
|
|
case X86_OPCODE_REPE_PREFIX:
|
|
case X86_OPCODE_REPNE_PREFIX:
|
|
break;
|
|
default:
|
|
fOpcodeIsPrefix = FALSE;
|
|
}
|
|
|
|
if ( !fOpcodeIsPrefix )
|
|
{
|
|
for ( idxOpcode = 0;
|
|
OpcodeList[ idxOpcode ].bmaskOpcodeMeaningfulBits != 0;
|
|
idxOpcode ++ )
|
|
{
|
|
if ( ( Opcode & OpcodeList[ idxOpcode ].bmaskOpcodeMeaningfulBits ) ==
|
|
OpcodeList[ idxOpcode ].bmpOpcode )
|
|
{
|
|
if ( Debug>1 )
|
|
{
|
|
DebugPrintf( "Opcode 0x%02X is %s\n",
|
|
Opcode,
|
|
OpcodeList[ idxOpcode ].pszOpcodeName );
|
|
}
|
|
|
|
if ( ARGUMENT_PRESENT( ppszDescription ) )
|
|
{
|
|
*ppszDescription = OpcodeList[ idxOpcode ].pszOpcodeName;
|
|
}
|
|
|
|
*pcbAccessLength = OpcodeList[ idxOpcode ].cbDefaultLength;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( OpcodeList[ idxOpcode ].bmaskOpcodeMeaningfulBits == 0 )
|
|
{
|
|
if ( OpcodeList != ExtendedOpcodeList )
|
|
{
|
|
DebugPrintf( "Unknown opcode: 0x%02X\n", Opcode );
|
|
}
|
|
else
|
|
{
|
|
DebugPrintf( "Unknown two-byte opcode: 0x0F 0x%02X\n", Opcode );
|
|
}
|
|
|
|
if ( Debug>0 )
|
|
{
|
|
DebugBreak();
|
|
}
|
|
|
|
return( FALSE );
|
|
}
|
|
|
|
if ( Opcode & OpcodeList[ idxOpcode ].bmaskOpcodeAccessTypeBit )
|
|
{
|
|
/*
|
|
BOGUS - For some reason, the VM bit is set. That can't be right.
|
|
|
|
if ( Context.EFlags & X86_FLAG_BIT_VM )
|
|
{
|
|
*pcbAccessLength = fModeToggle ? 4 : 2;
|
|
}
|
|
else
|
|
{
|
|
*pcbAccessLength = fModeToggle ? 2 : 4;
|
|
}
|
|
*/
|
|
|
|
*pcbAccessLength = ( fOperandSizeToggle ? 2 : 4 );
|
|
|
|
//
|
|
// Some operations (MOVZX, MOVSX) have differenly sized source
|
|
// and destination operands. These are flagged with the impossible
|
|
// access length.
|
|
//
|
|
|
|
if ( OpcodeList[ idxOpcode ].cbDefaultLength == IMPOSSIBLE_ACCESS_LENGTH )
|
|
{
|
|
ASSERT(( *pcbAccessLength % 2 ) == 0 );
|
|
|
|
*pcbAccessLength >>= 1;
|
|
}
|
|
|
|
if ( Debug>1 )
|
|
{
|
|
DebugPrintf( "Opcode %02X is a %d-byte access.\n",
|
|
Opcode,
|
|
*pcbAccessLength );
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
return( TRUE );
|
|
}
|