parse86.c


The file parse86.c has been added to perform the parsing of Intel x86 instructions. Thirteen functions are provided by this file:

  • transferInstruction–Calls the transfer function for the operand at the source

  • transferData–Transfers the data associated with the referenced operand

  • transferDataPrefix–Transfers prefix data for operands 66 and 67

  • adjustData–Adjusts for operands with relative offset

  • noTransferOp–Dummy function for operations without transfers

  • transferOp0F–Transfer function for operation 0f

  • transferOp66–Transfer function for operation 66

  • transferOp67–Transfer function for operation 67

  • transferOpF6–Transfer function for operation f6

  • transferOpF7–Transfer function for operation f7

  • transferOpFF–Transfer function for operation ff

  • getNextInstruction–Gets more bytes to parse into an x86 instruction

  • isJump–Checks for all types of jump instructions

  // parse86 // Copyright Ric Vieler, 2006 // disassembler for getx86Instruction #if _WIN32_WINNT >= 0x0500 #define NDIS50 1 #else #define NDIS40 1 #endif #define BINARY_COMPATIBLE 0 #ifdef __cplusplus extern "C" { #endif #include <ndis.h> #include <ntddk.h> #include "ghost.h" #include "injectManager.h" #ifdef __cplusplus } #endif #include "parse86.h" #pragma code_seg("PAGE") #pragma optimize( "", off ) // for X86INSTRUCTION struct #pragma pack(1) typedef struct _X86_16BIT_INSTRUCTION {  BOOL operandIs16;  BOOL addressIs16;  PBYTE* jumpAddress;  LONG* extra; } X86_16BIT_INSTRUCTION; // forward declaration for XFER_FUNCTION struct _X86INSTRUCTION; typedef struct _X86INSTRUCTION* PX86INSTRUCTION; typedef PBYTE (*XFER_FUNCTION)(X86_16BIT_INSTRUCTION* op16Ptr, PX86INSTRUCTION opPtr, PBYTE destination, PBYTE source); typedef struct _X86INSTRUCTION {  ULONG opcode : 8;  ULONG size : 3;  ULONG size16 : 3;  ULONG modeOffset : 3;  LONG relOffset : 3;  ULONG flagMask : 4;  XFER_FUNCTION pXferFunction; } X86INSTRUCTION; // flags for flagMask enum {  DYNAMIC_FLAG = 0x1u,  ADDRESS_FLAG = 0x2u,  NOENLARGE_FLAG = 0x4u,  SIB_FLAG = 0x10u,  NOTSIB_FLAG = 0x0fu, }; #pragma pack() BYTE regMemMode[256] = {  0,0,0,0,0x11,4,0,0,0,0,0,0,0x11,4,0,0, // 00 - 0f  0,0,0,0,0x11,4,0,0,0,0,0,0,0x11,4,0,0, // 10 - 1f  0,0,0,0,0x11,4,0,0,0,0,0,0,0x11,4,0,0, // 20 - 2f  0,0,0,0,0x11,4,0,0,0,0,0,0,0x11,4,0,0, // 30 - 3f  1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1, // 40 - 4f  1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1, // 50 - 5f  1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1, // 60 - 6f  1,1,1,1,2,1,1,1,1,1,1,1,2,1,1,1, // 70 - 7f  4,4,4,4,5,4,4,4,4,4,4,4,5,4,4,4, // 80 - 8f  4,4,4,4,5,4,4,4,4,4,4,4,5,4,4,4, // 90 - 9f  4,4,4,4,5,4,4,4,4,4,4,4,5,4,4,4, // a0 - af  4,4,4,4,5,4,4,4,4,4,4,4,5,4,4,4, // b0 - bf  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // c0 - cf  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // d0 - df  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // e0 - ef  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 // f0 - ff }; // prototypes for X86INSTRUCTION PBYTE transferData( X86_16BIT_INSTRUCTION* op16Ptr, X86INSTRUCTION* opPtr, PBYTE destination, PBYTE source ); PBYTE transferDataPrefix( X86_16BIT_INSTRUCTION* op16Ptr, X86INSTRUCTION* opPtr, PBYTE destination, PBYTE source ); PBYTE adjustData( X86_16BIT_INSTRUCTION* op16Ptr, PBYTE destination, PBYTE source, LONG bytes, LONG targetOffset ); PBYTE noTransferOp( X86_16BIT_INSTRUCTION* op16Ptr, X86INSTRUCTION* opPtr, PBYTE destination, PBYTE source ); PBYTE transferOp0F( X86_16BIT_INSTRUCTION* op16Ptr, X86INSTRUCTION* opPtr, PBYTE destination, PBYTE source ); PBYTE transferOp66( X86_16BIT_INSTRUCTION* op16Ptr, X86INSTRUCTION* opPtr, PBYTE destination, PBYTE source ); PBYTE transferOp67( X86_16BIT_INSTRUCTION* op16Ptr, X86INSTRUCTION* opPtr, PBYTE destination, PBYTE source ); PBYTE transferOpF6( X86_16BIT_INSTRUCTION* op16Ptr, X86INSTRUCTION* opPtr, PBYTE destination, PBYTE source ); PBYTE transferOpF7( X86_16BIT_INSTRUCTION* op16Ptr, X86INSTRUCTION* opPtr, PBYTE destination, PBYTE source ); PBYTE transferOpFF( X86_16BIT_INSTRUCTION* op16Ptr, X86INSTRUCTION* opPtr, PBYTE destination, PBYTE source ); // follows opcode in X86INSTRUCTION #define transfer1 1, 1, 0, 0, 0, transferData #define transfer1Dynamic 1, 1, 0, 0, DYNAMIC_FLAG, transferData #define transfer2 2, 2, 0, 0, 0, transferData #define transfer2Jump   2, 2, 0, 1, 0, transferData #define transfer2NoJump 2, 2, 0, 1, NOENLARGE_FLAG, transferData #define transfer2Dynamic 2, 2, 0, 0, DYNAMIC_FLAG, transferData #define transfer3 3, 3, 0, 0, 0, transferData #define transfer3Dynamic 3, 3, 0, 0, DYNAMIC_FLAG, transferData #define transfer3Or5 5, 3, 0, 0, 0, transferData #define transfer3Or5Target 5, 3, 0, 1, 0, transferData #define transfer5Or7Dynamic 7, 5, 0, 0, DYNAMIC_FLAG, transferData #define transfer3Or5Address 5, 3, 0, 0, ADDRESS_FLAG, transferData #define transfer4 4, 4, 0, 0, 0, transferData #define transfer5 5, 5, 0, 0, 0, transferData #define transfer7 7, 7, 0, 0, 0, transferData #define transfer2Mod 2, 2, 1, 0, 0, transferData #define transfer2Mod1 3, 3, 1, 0, 0, transferData #define transfer2ModOperand 6, 4, 1, 0, 0, transferData #define transfer3Mod 3, 3, 2, 0, 0, transferData #define transferPrefix 1, 1, 0, 0, 0, transferDataPrefix #define transfer0F 1, 1, 0, 0, 0, transferOp0F #define transfer66 1, 1, 0, 0, 0, transferOp66 #define transfer67 1, 1, 0, 0, 0, transferOp67 #define transferF6 0, 0, 0, 0, 0, transferOpF6 #define transferF7 0, 0, 0, 0, 0, transferOpF7 #define transferFF 0, 0, 0, 0, 0, transferOpFF #define noTransfer 1, 1, 0, 0, 0, noTransferOp #define lastEntry 0, 0, 0, 0, 0, NULL // intel op codes and disassembly parameters X86INSTRUCTION instructionMap[257] = {  { 0x00, transfer2Mod },  { 0x01, transfer2Mod },  { 0x02, transfer2Mod },  { 0x03, transfer2Mod },  { 0x04, transfer2 },  { 0x05, transfer3Or5 },  { 0x06, transfer1 },  { 0x07, transfer1 },  { 0x08, transfer2Mod },  { 0x09, transfer2Mod },  { 0x0A, transfer2Mod },  { 0x0B, transfer2Mod },  { 0x0C, transfer2 },  { 0x0D, transfer3Or5 },  { 0x0E, transfer1 },  { 0x0F, transfer0F },  { 0x10, transfer2Mod },  { 0x11, transfer2Mod },  { 0x12, transfer2Mod },  { 0x13, transfer2Mod },  { 0x14, transfer2 },  { 0x15, transfer3Or5 },  { 0x16, transfer1 },  { 0x17, transfer1 },  { 0x18, transfer2Mod },  { 0x19, transfer2Mod },  { 0x1A, transfer2Mod },  { 0x1B, transfer2Mod },  { 0x1C, transfer2 },  { 0x1D, transfer3Or5 },  { 0x1E, transfer1 },  { 0x1F, transfer1 },  { 0x20, transfer2Mod },  { 0x21, transfer2Mod },  { 0x22, transfer2Mod },  { 0x23, transfer2Mod },  { 0x24, transfer2 },  { 0x25, transfer3Or5 },  { 0x26, transferPrefix },  { 0x27, transfer1 },  { 0x28, transfer2Mod },  { 0x29, transfer2Mod },  { 0x2A, transfer2Mod },  { 0x2B, transfer2Mod },  { 0x2C, transfer2 },  { 0x2D, transfer3Or5 },  { 0x2E, transferPrefix },  { 0x2F, transfer1 },  { 0x30, transfer2Mod },  { 0x31, transfer2Mod },  { 0x32, transfer2Mod },  { 0x33, transfer2Mod },  { 0x34, transfer2 },  { 0x35, transfer3Or5 },  { 0x36, transferPrefix },  { 0x37, transfer1 },  { 0x38, transfer2Mod },  { 0x39, transfer2Mod },  { 0x3A, transfer2Mod },  { 0x3B, transfer2Mod },  { 0x3C, transfer2 },  { 0x3D, transfer3Or5 },  { 0x3E, transferPrefix },  { 0x3F, transfer1 },  { 0x40, transfer1 },  { 0x41, transfer1 },  { 0x42, transfer1 },  { 0x43, transfer1 },  { 0x44, transfer1 },  { 0x45, transfer1 },  { 0x46, transfer1 },  { 0x47, transfer1 },  { 0x48, transfer1 },  { 0x49, transfer1 },  { 0x4A, transfer1 },  { 0x4B, transfer1 },  { 0x4C, transfer1 },  { 0x4D, transfer1 },  { 0x4E, transfer1 },  { 0x4F, transfer1 },  { 0x50, transfer1 },  { 0x51, transfer1 },  { 0x52, transfer1 },  { 0x53, transfer1 },  { 0x54, transfer1 },  { 0x55, transfer1 },  { 0x56, transfer1 },  { 0x57, transfer1 },  { 0x58, transfer1 },  { 0x59, transfer1 },  { 0x5A, transfer1 },  { 0x5B, transfer1 },  { 0x5C, transfer1 },  { 0x5D, transfer1 },  { 0x5E, transfer1 },  { 0x5F, transfer1 },  { 0x60, transfer1 },  { 0x61, transfer1 },  { 0x62, transfer2Mod },  { 0x63, transfer2Mod },  { 0x64, transferPrefix },  { 0x65, transferPrefix },  { 0x66, transfer66 },  { 0x67, transfer67 },  { 0x68, transfer3Or5 },  { 0x69, transfer2ModOperand },  { 0x6A, transfer2 },  { 0x6B, transfer2Mod1 },  { 0x6C, transfer1 },  { 0x6D, transfer1 },  { 0x6E, transfer1 },  { 0x6F, transfer1 },  { 0x70, transfer2Jump },  { 0x71, transfer2Jump },  { 0x72, transfer2Jump },  { 0x73, transfer2Jump },  { 0x74, transfer2Jump },  { 0x75, transfer2Jump },  { 0x76, transfer2Jump },  { 0x77, transfer2Jump },  { 0x78, transfer2Jump },  { 0x79, transfer2Jump },  { 0x7A, transfer2Jump },  { 0x7B, transfer2Jump },  { 0x7C, transfer2Jump },  { 0x7D, transfer2Jump },  { 0x7E, transfer2Jump },  { 0x7F, transfer2Jump },  { 0x80, transfer2Mod1 },  { 0x81, transfer2ModOperand },  { 0x82, transfer2 },  { 0x83, transfer2Mod1 },  { 0x84, transfer2Mod },  { 0x85, transfer2Mod },  { 0x86, transfer2Mod },  { 0x87, transfer2Mod },  { 0x88, transfer2Mod },  { 0x89, transfer2Mod },  { 0x8A, transfer2Mod },  { 0x8B, transfer2Mod },  { 0x8C, transfer2Mod },  { 0x8D, transfer2Mod },  { 0x8E, transfer2Mod },  { 0x8F, transfer2Mod },  { 0x90, transfer1 },  { 0x91, transfer1 },  { 0x92, transfer1 },  { 0x93, transfer1 },  { 0x94, transfer1 },  { 0x95, transfer1 },  { 0x96, transfer1 },  { 0x97, transfer1 },  { 0x98, transfer1 },  { 0x99, transfer1 },  { 0x9A, transfer5Or7Dynamic },  { 0x9B, transfer1 },  { 0x9C, transfer1 },  { 0x9D, transfer1 },  { 0x9E, transfer1 },  { 0x9F, transfer1 },  { 0xA0, transfer3Or5Address },  { 0xA1, transfer3Or5Address },  { 0xA2, transfer3Or5Address },  { 0xA3, transfer3Or5Address },  { 0xA4, transfer1 },  { 0xA5, transfer1 },  { 0xA6, transfer1 },  { 0xA7, transfer1 },  { 0xA8, transfer2 },  { 0xA9, transfer3Or5 },  { 0xAA, transfer1 },  { 0xAB, transfer1 },  { 0xAC, transfer1 },  { 0xAD, transfer1 },  { 0xAE, transfer1 },  { 0xAF, transfer1 },  { 0xB0, transfer2 },  { 0xB1, transfer2 },  { 0xB2, transfer2 },  { 0xB3, transfer2 },  { 0xB4, transfer2 },  { 0xB5, transfer2 },  { 0xB6, transfer2 },  { 0xB7, transfer2 },  { 0xB8, transfer3Or5 },  { 0xB9, transfer3Or5 },  { 0xBA, transfer3Or5 },  { 0xBB, transfer3Or5 },  { 0xBC, transfer3Or5 },  { 0xBD, transfer3Or5 },  { 0xBE, transfer3Or5 },  { 0xBF, transfer3Or5 },  { 0xC0, transfer2Mod1 },  { 0xC1, transfer2Mod1 },  { 0xC2, transfer3 },  { 0xC3, transfer1 },  { 0xC4, transfer2Mod },  { 0xC5, transfer2Mod },  { 0xC6, transfer2Mod1 },  { 0xC7, transfer2ModOperand },  { 0xC8, transfer4 },  { 0xC9, transfer1 },  { 0xCA, transfer3Dynamic },  { 0xCB, transfer1Dynamic },  { 0xCC, transfer1Dynamic },  { 0xCD, transfer2Dynamic },  { 0xCE, transfer1Dynamic },  { 0xCF, transfer1Dynamic },  { 0xD0, transfer2Mod },  { 0xD1, transfer2Mod },  { 0xD2, transfer2Mod },  { 0xD3, transfer2Mod },  { 0xD4, transfer2 },  { 0xD5, transfer2 },  { 0xD6, noTransfer },  { 0xD7, transfer1 },  { 0xD8, transfer2Mod },  { 0xD9, transfer2Mod },  { 0xDA, transfer2Mod },  { 0xDB, transfer2Mod },  { 0xDC, transfer2Mod },  { 0xDD, transfer2Mod },  { 0xDE, transfer2Mod },  { 0xDF, transfer2Mod },  { 0xE0, transfer2NoJump },  { 0xE1, transfer2NoJump },  { 0xE2, transfer2NoJump },  { 0xE3, transfer2Jump },  { 0xE4, transfer2 },  { 0xE5, transfer2 },  { 0xE6, transfer2 },  { 0xE7, transfer2 },  { 0xE8, transfer3Or5Target },  { 0xE9, transfer3Or5Target },  { 0xEA, transfer5Or7Dynamic },  { 0xEB, transfer2Jump },  { 0xEC, transfer1 },  { 0xED, transfer1 },  { 0xEE, transfer1 },  { 0xEF, transfer1 },  { 0xF0, transferPrefix },  { 0xF1, noTransfer },  { 0xF2, transferPrefix },  { 0xF3, transferPrefix },  { 0xF4, transfer1 },  { 0xF5, transfer1 },  { 0xF6, transferF6 },  { 0xF7, transferF7 },  { 0xF8, transfer1 },  { 0xF9, transfer1 },  { 0xFA, transfer1 },  { 0xFB, transfer1 },  { 0xFC, transfer1 },  { 0xFD, transfer1 },  { 0xFE, transfer2Mod },  { 0xFF, transferFF },  { 0x00, lastEntry } }; // intel extended op codes and disassembly parameters X86INSTRUCTION extendedInstructionMap[257] = {  { 0x00, transfer2Mod },  { 0x01, transfer2Mod },  { 0x02, transfer2Mod },  { 0x03, transfer2Mod },  { 0x04, noTransfer },  { 0x05, noTransfer },  { 0x06, transfer2 },  { 0x07, noTransfer },  { 0x08, transfer2 },  { 0x09, transfer2 },  { 0x0A, noTransfer },  { 0x0B, transfer2 },  { 0x0C, noTransfer },  { 0x0D, noTransfer },  { 0x0E, noTransfer },  { 0x0F, noTransfer },  { 0x10, noTransfer },  { 0x11, noTransfer },  { 0x12, noTransfer },  { 0x13, noTransfer },  { 0x14, noTransfer },  { 0x15, noTransfer },  { 0x16, noTransfer },  { 0x17, noTransfer },  { 0x18, noTransfer },  { 0x19, noTransfer },  { 0x1A, noTransfer },  { 0x1B, noTransfer },  { 0x1C, noTransfer },  { 0x1D, noTransfer },  { 0x1E, noTransfer },  { 0x1F, noTransfer },  { 0x20, transfer2Mod },  { 0x21, transfer2Mod },  { 0x22, transfer2Mod },  { 0x23, transfer2Mod },  { 0x24, noTransfer },  { 0x25, noTransfer },  { 0x26, noTransfer },  { 0x27, noTransfer },  { 0x28, noTransfer },  { 0x29, noTransfer },  { 0x2A, noTransfer },  { 0x2B, noTransfer },  { 0x2C, noTransfer },  { 0x2D, noTransfer },  { 0x2E, noTransfer },  { 0x2F, noTransfer },  { 0x30, transfer2 },  { 0x31, transfer2 },  { 0x32, transfer2 },  { 0x33, transfer2 },  { 0x34, transfer2 },  { 0x35, transfer2 },  { 0x36, noTransfer },  { 0x37, noTransfer },  { 0x38, noTransfer },  { 0x39, noTransfer },  { 0x3A, noTransfer },  { 0x3B, noTransfer },  { 0x3C, noTransfer },  { 0x3D, noTransfer },  { 0x3E, noTransfer },  { 0x3F, noTransfer },  { 0x40, transfer2Mod },  { 0x41, transfer2Mod },  { 0x42, transfer2Mod },  { 0x43, transfer2Mod },  { 0x44, transfer2Mod },  { 0x45, transfer2Mod },  { 0x46, transfer2Mod },  { 0x47, transfer2Mod },  { 0x48, transfer2Mod },  { 0x49, transfer2Mod },  { 0x4A, transfer2Mod },  { 0x4B, transfer2Mod },  { 0x4C, transfer2Mod },  { 0x4D, transfer2Mod },  { 0x4E, transfer2Mod },  { 0x4F, transfer2Mod },  { 0x50, noTransfer },  { 0x51, noTransfer },  { 0x52, noTransfer },  { 0x53, noTransfer },  { 0x54, noTransfer },  { 0x55, noTransfer },  { 0x56, noTransfer },  { 0x57, noTransfer },  { 0x58, noTransfer },  { 0x59, noTransfer },  { 0x5A, noTransfer },  { 0x5B, noTransfer },  { 0x5C, noTransfer },  { 0x5D, noTransfer },  { 0x5E, noTransfer },  { 0x5F, noTransfer },  { 0x60, transfer2Mod },  { 0x61, noTransfer },  { 0x62, transfer2Mod },  { 0x63, transfer2Mod },  { 0x64, transfer2Mod },  { 0x65, transfer2Mod },  { 0x66, transfer2Mod },  { 0x67, transfer2Mod },  { 0x68, transfer2Mod },  { 0x69, transfer2Mod },  { 0x6A, transfer2Mod },  { 0x6B, transfer2Mod },  { 0x6C, noTransfer },  { 0x6D, noTransfer },  { 0x6E, transfer2Mod },  { 0x6F, transfer2Mod },  { 0x70, noTransfer },  { 0x71, transfer2Mod1 },  { 0x72, transfer2Mod1 },  { 0x73, transfer2Mod1 },  { 0x74, transfer2Mod },  { 0x75, transfer2Mod },  { 0x76, transfer2Mod },  { 0x77, transfer2 },  { 0x78, noTransfer },  { 0x79, noTransfer },  { 0x7A, noTransfer },  { 0x7B, noTransfer },  { 0x7C, noTransfer },  { 0x7D, noTransfer },  { 0x7E, transfer2Mod },  { 0x7F, transfer2Mod },  { 0x80, transfer3Or5Target },  { 0x81, transfer3Or5Target },  { 0x82, transfer3Or5Target },  { 0x83, transfer3Or5Target },  { 0x84, transfer3Or5Target },  { 0x85, transfer3Or5Target },  { 0x86, transfer3Or5Target },  { 0x87, transfer3Or5Target },  { 0x88, transfer3Or5Target },  { 0x89, transfer3Or5Target },  { 0x8A, transfer3Or5Target },  { 0x8B, transfer3Or5Target },  { 0x8C, transfer3Or5Target },  { 0x8D, transfer3Or5Target },  { 0x8E, transfer3Or5Target },  { 0x8F, transfer3Or5Target },  { 0x90, transfer2Mod },  { 0x91, transfer2Mod },  { 0x92, transfer2Mod },  { 0x93, transfer2Mod },  { 0x94, transfer2Mod },  { 0x95, transfer2Mod },  { 0x96, transfer2Mod },  { 0x97, transfer2Mod },  { 0x98, transfer2Mod },  { 0x99, transfer2Mod },  { 0x9A, transfer2Mod },  { 0x9B, transfer2Mod },  { 0x9C, transfer2Mod },  { 0x9D, transfer2Mod },  { 0x9E, transfer2Mod },  { 0x9F, transfer2Mod },  { 0xA0, transfer2 },  { 0xA1, transfer2 },  { 0xA2, transfer2 },  { 0xA3, transfer2Mod },  { 0xA4, transfer2Mod1 },  { 0xA5, transfer2Mod },  { 0xA6, noTransfer },  { 0xA7, noTransfer },  { 0xA8, transfer2 },  { 0xA9, transfer2 },  { 0xAA, transfer2 },  { 0xAB, transfer2Mod },  { 0xAC, transfer2Mod1 },  { 0xAD, transfer2Mod },  { 0xAE, transfer2Mod },  { 0xAF, transfer2Mod },  { 0xB0, transfer2Mod },  { 0xB1, transfer2Mod },  { 0xB2, transfer2Mod },  { 0xB3, transfer2Mod },  { 0xB4, transfer2Mod },  { 0xB5, transfer2Mod },  { 0xB6, transfer2Mod },  { 0xB7, transfer2Mod },  { 0xB8, noTransfer },  { 0xB9, noTransfer },  { 0xBA, transfer2Mod1 },  { 0xBB, transfer2Mod },  { 0xBC, transfer2Mod },  { 0xBD, transfer2Mod },  { 0xBE, transfer2Mod },  { 0xBF, transfer2Mod },  { 0xC0, transfer2Mod },  { 0xC1, transfer2Mod },  { 0xC2, noTransfer },  { 0xC3, noTransfer },  { 0xC4, noTransfer },  { 0xC5, noTransfer },  { 0xC6, noTransfer },  { 0xC7, transfer2Mod },  { 0xC8, transfer2 },  { 0xC9, transfer2 },  { 0xCA, transfer2 },  { 0xCB, transfer2 },  { 0xCC, transfer2 },  { 0xCD, transfer2 },  { 0xCE, transfer2 },  { 0xCF, transfer2 },  { 0xD0, noTransfer },  { 0xD1, transfer2Mod },  { 0xD2, transfer2Mod },  { 0xD3, transfer2Mod },  { 0xD4, noTransfer },  { 0xD5, transfer2Mod },  { 0xD6, noTransfer },  { 0xD7, noTransfer },  { 0xD8, transfer2Mod },  { 0xD9, transfer2Mod },  { 0xDA, noTransfer },  { 0xDB, transfer2Mod },  { 0xDC, transfer2Mod },  { 0xDD, transfer2Mod },  { 0xDE, noTransfer },  { 0xDF, transfer2Mod },  { 0xE0, noTransfer },  { 0xE1, transfer2Mod },  { 0xE2, transfer2Mod },  { 0xE3, noTransfer },  { 0xE4, noTransfer },  { 0xE5, transfer2Mod },  { 0xE6, noTransfer },  { 0xE7, noTransfer },  { 0xE8, transfer2Mod },  { 0xE9, transfer2Mod },  { 0xEA, noTransfer },  { 0xEB, transfer2Mod },  { 0xEC, transfer2Mod },  { 0xED, transfer2Mod },  { 0xEE, noTransfer },  { 0xEF, transfer2Mod },  { 0xF0, noTransfer },  { 0xF1, transfer2Mod },  { 0xF2, transfer2Mod },  { 0xF3, transfer2Mod },  { 0xF4, noTransfer },  { 0xF5, transfer2Mod },  { 0xF6, noTransfer },  { 0xF7, noTransfer },  { 0xF8, transfer2Mod },  { 0xF9, transfer2Mod },  { 0xFA, transfer2Mod },  { 0xFB, noTransfer },  { 0xFC, transfer2Mod },  { 0xFD, transfer2Mod },  { 0xFE, transfer2Mod },  { 0xFF, noTransfer },  { 0x00, lastEntry } }; PBYTE transferInstruction( PBYTE destination, PBYTE source, PBYTE* jumpAddress, LONG* extra ) {  X86_16BIT_INSTRUCTION op16 = { 0 };  X86INSTRUCTION* opPtr = { 0 };  *jumpAddress = TARGETLESS_X86INSTRUCTION;  *extra = 0;  op16.operandIs16 = 0;  op16.addressIs16 = 0;  op16.jumpAddress = jumpAddress;  op16.extra = extra;  opPtr = &instructionMap[source[0]];  return opPtr->pXferFunction( &op16, opPtr, destination, source ); } PBYTE transferData( X86_16BIT_INSTRUCTION* op16Ptr, X86INSTRUCTION* opPtr, PBYTE destination, PBYTE source ) {  LONG bytes = 0;  LONG fixedBytes = (opPtr->flagMask & ADDRESS_FLAG)   ? (op16Ptr->addressIs16 ? opPtr->size16 : opPtr->size)   : (op16Ptr->operandIs16 ? opPtr->size16 : opPtr->size);  bytes = fixedBytes;  if( opPtr->modeOffset > 0 )  {   BYTE rmMode = source[opPtr->modeOffset];   BYTE flags = regMemMode[rmMode];   if( flags & SIB_FLAG )   {    if( ( source[opPtr->modeOffset + 1] & 0x07 ) == 0x05 )    {     if( ( rmMode & 0xc0 ) == 0x00 )      bytes += 4;     else if( ( rmMode & 0xc0 ) == 0x40 )      bytes += 1;     else if( ( rmMode & 0xc0 ) == 0x80 )      bytes += 4;    }   }   bytes += flags & NOTSIB_FLAG;  }  memcpy( destination, source, bytes );  if( opPtr->relOffset )  *op16Ptr->jumpAddress = adjustData( op16Ptr, destination, source, fixedBytes, opPtr->relOffset );  if( opPtr->flagMask & NOENLARGE_FLAG )   *op16Ptr->extra = -*op16Ptr->extra;  if( opPtr->flagMask & DYNAMIC_FLAG )   *op16Ptr->jumpAddress = DYNAMIC_X86INSTRUCTION;  return source + bytes; } PBYTE transferDataPrefix( X86_16BIT_INSTRUCTION* op16Ptr, X86INSTRUCTION* opPtr, PBYTE destination, PBYTE source ) {  transferData( op16Ptr, opPtr, destination, source );  opPtr = &instructionMap[source[1]];  return opPtr->pXferFunction(op16Ptr, opPtr, destination + 1, source + 1); } PBYTE adjustData( X86_16BIT_INSTRUCTION* op16Ptr, PBYTE destination, PBYTE source, LONG bytes, LONG targetOffset ) {  LONG oldOffset = 0;  LONG newOffset = 0;  PBYTE target;  LONG targetSize = bytes - targetOffset;  PVOID targetAddr = &destination[targetOffset];  switch( targetSize )  {   case 1:    oldOffset = (LONG)*((PCHAR)targetAddr);    *op16Ptr->extra = 3;    break;   case 2:    oldOffset = (LONG)*((PSHORT)targetAddr);    *op16Ptr->extra = 2;    break;   case 4:    oldOffset = (LONG)*((PLONG)targetAddr);    *op16Ptr->extra = 0;    break;  }  target = source + bytes + oldOffset;  newOffset = oldOffset - (destination - source);  switch( targetSize )  {    case 1:     *((PCHAR)targetAddr) = (CHAR)newOffset;     break;    case 2:     *((PSHORT)targetAddr) = (SHORT)newOffset;     break;    case 4:     *((PLONG)targetAddr) = (LONG)newOffset;     break;  }  ASSERT( destination + bytes + newOffset == target );  return target; } PBYTE noTransferOp( X86_16BIT_INSTRUCTION* op16Ptr, X86INSTRUCTION* opPtr, PBYTE destination, PBYTE source ) { return source + 1; UNREFERENCED_PARAMETER( destination ); UNREFERENCED_PARAMETER( opPtr ); UNREFERENCED_PARAMETER( op16Ptr ); } PBYTE transferOp0F( X86_16BIT_INSTRUCTION* op16Ptr, X86INSTRUCTION* opPtr, PBYTE destination, PBYTE source ) { transferData( op16Ptr, opPtr, destination, source ); opPtr = &extendedInstructionMap[source[1]]; return opPtr->pXferFunction( op16Ptr, opPtr, destination + 1, source + 1 ); } PBYTE transferOp66( X86_16BIT_INSTRUCTION* op16Ptr, X86INSTRUCTION* opPtr, PBYTE destination, PBYTE source ) { op16Ptr->operandIs16 = 1; return transferDataPrefix( op16Ptr, opPtr, destination, source ); } PBYTE transferOp67( X86_16BIT_INSTRUCTION* op16Ptr, X86INSTRUCTION* opPtr, PBYTE destination, PBYTE source ) { op16Ptr->addressIs16 = 1; return transferDataPrefix( op16Ptr, opPtr, destination, source ); } PBYTE transferOpF6( X86_16BIT_INSTRUCTION* op16Ptr, X86INSTRUCTION* opPtr, PBYTE destination, PBYTE source ) {  if( (source[1] & 0x38) == 0x00 )  {   X86INSTRUCTION ce = { 0xf6, transfer2Mod1 };   return ce.pXferFunction( op16Ptr, &ce, destination, source );  }  {   X86INSTRUCTION ce = { 0xf6, transfer2Mod };   return ce.pXferFunction( op16Ptr, &ce, destination, source );  } } PBYTE transferOpF7( X86_16BIT_INSTRUCTION* op16Ptr, X86INSTRUCTION* opPtr, PBYTE destination, PBYTE source ) {  if( (source[1] & 0x38) == 0x00 )  {   X86INSTRUCTION ce = { 0xf7, transfer2ModOperand };   return ce.pXferFunction( op16Ptr, &ce, destination, source );  }  {   X86INSTRUCTION ce = { 0xf7, transfer2Mod };   return ce.pXferFunction( op16Ptr, &ce, destination, source );  } } PBYTE transferOpFF( X86_16BIT_INSTRUCTION* op16Ptr, PX86INSTRUCTION opPtr, PBYTE destination, PBYTE source ) {  if( source[1] == 0x15 || source[1] == 0x25 )  {   PBYTE* jumpAddress = *(PBYTE**) &source[2];   *op16Ptr->jumpAddress = *jumpAddress;  }  else if( (source[1] & 0x38) == 0x10 || (source[1] & 0x38) == 0x18 ||    (source[1] & 0x38) == 0x20 || (source[1] & 0x38) == 0x28 )  {   *op16Ptr->jumpAddress = DYNAMIC_X86INSTRUCTION;  }  {   X86INSTRUCTION ce = { 0xff, transfer2Mod };   return ce.pXferFunction( op16Ptr, &ce, destination, source );  } } //called by isJump when getx86Instruction wasn't enough to determine type ULONG getNextInstruction( PCHAR codePtr, ULONG initial, PCHAR destinationBuffer, ULONG destinationBufferLength ) {  PBYTE source = NULL;  PBYTE destination = NULL;  ULONG bytesCopied = 0;  PBYTE target = NULL;  LONG  extra = 0;  memset( destinationBuffer, 0, destinationBufferLength );  source = (PBYTE)codePtr;  destination = (PBYTE)destinationBuffer;  for( bytesCopied = 0; bytesCopied < initial; )  {   source = transferInstruction( destination, source, &target, &extra );   if( !source )   {    memset( destinationBuffer, 0, destinationBufferLength );    bytesCopied = 0;    break;   }   bytesCopied = (DWORD)source - (DWORD)codePtr;   if( bytesCopied >= destinationBufferLength )   {    ASSERT( FALSE );    break;   }   destination = (PBYTE)destinationBuffer + bytesCopied;  }  return bytesCopied; } // called by trampoline to check for jump type instruction BOOL isJump( PCHAR instruction, ULONG instructionLength ) {  BYTE firstByte;  BYTE secondByte;  PCHAR thisInstruction;  ULONG thisInstructionLength;  ULONG nextInstructionLength;  char instructionBuffer[MAX_INSTRUCTION] = { 0 };  thisInstruction = instruction;  thisInstructionLength = instructionLength;  while( thisInstructionLength > 0 )  {   // check all jump op codes   firstByte = thisInstruction[0];   secondByte = thisInstruction[1];   if( IS_BETWEEN( firstByte, 0x70, 0x7f ) )    return TRUE;   else if( IS_BETWEEN( firstByte, 0xca, 0xcb ) )    return TRUE;   else if( IS_BETWEEN( firstByte, 0xe0, 0xe3 ) )    return TRUE;   else if( IS_BETWEEN( firstByte, 0xe8, 0xeb ) )    return TRUE;   else if( IS_EQUAL( firstByte, 0xcf ) )    return TRUE;   else if( IS_EQUAL( firstByte, 0xf3 ) )    return TRUE;   else if( IS_EQUAL( firstByte, 0xff ) )   {    if( secondByte == 0x15 || secondByte == 0x25 )     return TRUE;    if( (secondByte & 0x38) == 0x10 || (secondByte & 0x38) == 0x18 ||     (secondByte & 0x38) == 0x20 || (secondByte & 0x38) == 0x28 )     return TRUE;   }   else if( IS_EQUAL( firstByte, 0x0f ) )   {    if( IS_BETWEEN( secondByte, 0x80, 0x8f ) )     return TRUE;   }   memset( instructionBuffer, 0, sizeof(instructionBuffer) );   nextInstructionLength = getNextInstruction( thisInstruction, 1, instructionBuffer, MAX_INSTRUCTION );   if( nextInstructionLength <= 0 )    break;   thisInstructionLength -= nextInstructionLength;   thisInstruction += nextInstructionLength;  }  return FALSE; } #pragma optimize( "", on ) 

Parsing x86 instructions are shown in Figure 4-3.

image from book
Figure 4-3

In general, transferInstruction uses the first byte of the target function to determine the type and size of the x86 instruction at that location. The first byte is used as an index into the instructionMap, which maps the first byte into a full x86 instruction. Once the size of instruction is known and determined to be something other than a jump, the instruction can be transferred to the trampoline and overwritten with a jump that transfers control to the injected detour function, which in turn calls the original function as well as any function(s) you wish to inject before and/or after the original function.




Professional Rootkits
Professional Rootkits (Programmer to Programmer)
ISBN: 0470101547
EAN: 2147483647
Year: 2007
Pages: 229
Authors: Ric Vieler

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net