Counter Strike : Global Offensive Source Code
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.

1281 lines
64 KiB

  1. //========= Copyright � 1996-2006, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Implementation for various PE helper functions
  4. //
  5. //=============================================================================//
  6. #ifdef _WIN32
  7. #include "disassembler.h"
  8. #include "windows.h"
  9. #pragma warning (disable: 4311) // warning C4311: 'type cast' : pointer truncation from 'bla *' to 'unsigned int'
  10. #pragma warning (disable: 4127) // warning C4127: conditional expression is constant
  11. #pragma warning (disable: 4244) // warning C4244: 'initializing' : conversion from 'unsigned int' to 'char', possible loss of data
  12. #pragma warning (disable: 4996) // warning C4996: 'function': This function or variable may be unsafe. Consider using function_s instead.
  13. #pragma warning (disable: 4100) // warning C4100: 'format' : unreferenced formal parameter
  14. typedef struct
  15. {
  16. unsigned char m_OpCodeB1; // first opcode byte
  17. unsigned char m_OpCodeB2; // second opcode byte
  18. unsigned char m_OpCodeB3; // third opcode byte
  19. unsigned char m_OpCodeB4; // fourth opcode byte
  20. unsigned char m_TotalLength; // total length of opcodes and data
  21. int m_cOpCodeBytesToMatch; // Normally 1, 2 if this is a 2 byte opcode, 3 if it's 3 bytes (ie, has x64 prefix or such)
  22. EOpCodeOffsetType m_EOffsetType; // if true, this opcode has IP relative data
  23. } KnownOpCode_t;
  24. // Set of opcodes that we know how to relocate safely from function preambles when
  25. // installing function detours.
  26. static const KnownOpCode_t s_rgKnownOpCodes[] =
  27. {
  28. #ifndef _WIN64
  29. { 0x08, 0xE9, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // or cl,ch
  30. { 0x0F, 0x57, 0xC0, 0x00, 3, 3, k_ENoRelativeOffsets }, // xorps xmm0,xmm0 (simd)
  31. { 0x31, 0xC0, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // xor eax,eax
  32. { 0x31, 0xD2, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // xor edx,edx
  33. { 0x31, 0xED, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // xor ebp,ebp
  34. { 0x31, 0xF6, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // xor esi,esi
  35. { 0x32, 0xC0, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // xor al,al
  36. { 0x33, 0xC0, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // xor eax,eax
  37. { 0x33, 0xF6, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // xor esi,esi
  38. { 0x3C, 0x00, 0x00, 0x00, 2, 1, k_ENoRelativeOffsets }, // cmp al,immediate byte
  39. { 0x39, 0x74, 0x00, 0x00, 4, 2, k_ENoRelativeOffsets }, // cmp dword ptr [rega+regb*coefficient+imm8],esi -- rega, regb, and coefficient depend on value of byte 3
  40. { 0x3D, 0x00, 0x00, 0x00, 5, 1, k_ENoRelativeOffsets }, // cmp eax,immediate dword
  41. { 0x3F, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // aas (ascii adjust al after subtraction)
  42. { 0x40, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // inc eax
  43. { 0x41, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // inc ecx
  44. { 0x42, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // inc edx
  45. { 0x43, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // inc ebx
  46. { 0x44, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // inc esp
  47. { 0x45, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // inc ebp
  48. { 0x46, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // inc esi
  49. { 0x47, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // inc edi
  50. { 0x48, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // dec eax
  51. { 0x49, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // dec ecx
  52. { 0x4A, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // dec edx
  53. { 0x4B, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // dec ebx
  54. { 0x4C, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // dec esp
  55. { 0x4D, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // dec ebp
  56. { 0x4E, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // dec esi
  57. { 0x4F, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // dec edi
  58. { 0x50, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // push eax
  59. { 0x51, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // push ecx
  60. { 0x52, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // push edx
  61. { 0x53, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // push ebx
  62. { 0x54, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // push esp
  63. { 0x55, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // push ebp
  64. { 0x56, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // push esi
  65. { 0x57, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // push edi
  66. { 0x58, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // pop eax
  67. { 0x59, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // pop ecx
  68. { 0x5A, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // pop edx
  69. { 0x5B, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // pop ebx
  70. { 0x5C, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // pop esp
  71. { 0x5D, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // pop ebp
  72. { 0x5E, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // pop esi
  73. { 0x5F, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // pop edi
  74. { 0x60, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // pushad
  75. { 0x61, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // popad
  76. { 0x64, 0xA1, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov eax,dword ptr fs:[imm32]
  77. { 0x68, 0x00, 0x00, 0x00, 5, 1, k_ENoRelativeOffsets }, // push immediate doubleword
  78. { 0x6A, 0x00, 0x00, 0x00, 2, 1, k_ENoRelativeOffsets }, // push immediate byte
  79. { 0x80, 0x3D, 0x00, 0x00, 7, 2, k_ENoRelativeOffsets }, // cmp byte ptr ds:[dword],imm8
  80. { 0x81, 0xEC, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // sub esp immediate dword
  81. { 0x81, 0xF9, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // cmp ecx, immediate dword
  82. { 0x83, 0x3D, 0x00, 0x00, 7, 2, k_ENoRelativeOffsets }, // cmp dword ptr to immediate byte
  83. { 0x83, 0x40, 0x00, 0x00, 4, 2, k_ENoRelativeOffsets }, // add dword ptr [eax+imm8],imm8
  84. { 0x83, 0x41, 0x00, 0x00, 4, 2, k_ENoRelativeOffsets }, // add dword ptr [ecx+imm8],imm8
  85. { 0x83, 0x6C, 0x00, 0x00, 5, 2, k_ENoRelativeOffsets }, // sub dword ptr [rega+regb*coefficient+imm8a],imm8b -- rega, regb, and coefficient depend on value of byte 3
  86. { 0x83, 0x7C, 0x00, 0x00, 5, 2, k_ENoRelativeOffsets }, // cmp dword ptr [rega+regb*coefficient+imm8a],imm8b -- rega, regb, and coefficient depend on value of byte 3
  87. { 0x83, 0x7D, 0x00, 0x00, 4, 2, k_ENoRelativeOffsets }, // cmp dword ptr [ebp+imm8],imm8
  88. { 0x83, 0xC0, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // add eax immediate byte
  89. { 0x83, 0xC1, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // add ecx immediate byte
  90. { 0x83, 0xC2, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // add edx immediate byte
  91. { 0x83, 0xC3, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // add ebx immediate byte
  92. { 0x83, 0xC4, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // add esp immediate byte
  93. { 0x83, 0xC5, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // add ebp immediate byte
  94. { 0x83, 0xC6, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // add esi immediate byte
  95. { 0x83, 0xC7, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // add edi immediate byte
  96. { 0x83, 0xE4, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // and esp,0FFFFFF00+immediate byte
  97. { 0x83, 0xE8, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // sub eax immediate byte
  98. { 0x83, 0xE9, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // sub ecx immediate byte
  99. { 0x83, 0xEA, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // sub edx immediate byte
  100. { 0x83, 0xEB, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // sub ebx immediate byte
  101. { 0x83, 0xEC, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // sub esp immediate byte
  102. { 0x83, 0xED, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // sub ebp immediate byte
  103. { 0x83, 0xEE, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // sub esi immediate byte
  104. { 0x83, 0xEF, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // sub edi immediate byte
  105. { 0x83, 0xFA, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // lock cmp edx,imm8
  106. { 0x85, 0xC7, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // test edi,eax
  107. { 0x85, 0xC8, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // test eax,ecx
  108. { 0x85, 0xC9, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // test ecx,ecx
  109. { 0x85, 0xCA, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // test edx,ecx
  110. { 0x87, 0x05, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // xchg eax, dword ptr
  111. { 0x89, 0xE5, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov ebp,esp
  112. { 0x89, 0x5C, 0x24, 0x00, 4, 3, k_ENoRelativeOffsets }, // mov dword ptr [esp+imm8],ebx
  113. { 0x8B, 0x00, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov eax,dword ptr [eax]
  114. { 0x8B, 0x01, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov eax,dword ptr [ecx]
  115. { 0x8B, 0x02, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov eax,dword ptr [edx]
  116. { 0x8B, 0x03, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov eax,dword ptr [ebx]
  117. { 0x8B, 0x06, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov eax,dword ptr [esi]
  118. { 0x8B, 0x07, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov eax,dword ptr [edi]
  119. { 0x8B, 0x08, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov ecx,dword ptr [eax]
  120. { 0x8B, 0x09, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov ecx,dword ptr [ecx]
  121. { 0x8B, 0x0B, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov ecx,dword ptr [ebx]
  122. { 0x8B, 0x0D, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov ecx,dword ptr [_gpsi]
  123. { 0x8B, 0x0E, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov ecx,dword ptr [esi]
  124. { 0x8B, 0x0F, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov ecx,dword ptr [edi]
  125. { 0x8B, 0x10, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov edx,dword ptr [eax]
  126. { 0x8B, 0x11, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov edx,dword ptr [ecx]
  127. { 0x8B, 0x12, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov edx,dword ptr [edx]
  128. { 0x8B, 0x13, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov edx,dword ptr [ebx]
  129. { 0x8B, 0x16, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov edx,dword ptr [esi]
  130. { 0x8B, 0x17, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov edx,dword ptr [edi]
  131. { 0x8B, 0x18, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov ebx,dword ptr [eax]
  132. { 0x8B, 0x19, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov ebx,dword ptr [ecx]
  133. { 0x8B, 0x1B, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov ebx,dword ptr [ebx]
  134. { 0x8B, 0x1E, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov ebx,dword ptr [edi]
  135. { 0x8B, 0x1F, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov ebx,dword ptr [esi]
  136. { 0x8B, 0x30, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov esi,dword ptr [eax]
  137. { 0x8B, 0x31, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov esi,dword ptr [ecx]
  138. { 0x8B, 0x32, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov esi,dword ptr [edx]
  139. { 0x8B, 0x33, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov esi,dword ptr [ebx]
  140. { 0x8B, 0x34, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov esi,dword ptr [edi+eax], 3rd byte determines ptr
  141. { 0x8B, 0x35, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov esi,dword ptr [_gpsi]
  142. { 0x8B, 0x36, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov esi,dword ptr [esi]
  143. { 0x8B, 0x37, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov esi,dword ptr [edi]
  144. { 0x8B, 0x38, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov edi,dword ptr [eax]
  145. { 0x8B, 0x39, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov edi,dword ptr [ecx]
  146. { 0x8B, 0x3B, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov edi,dword ptr [ebx]
  147. { 0x8B, 0x3E, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov edi,dword ptr [esi]
  148. { 0x8B, 0x3F, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov edi,dword ptr [edi]
  149. { 0x8B, 0x40, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov eax,dword ptr [eax+rawbyte]
  150. { 0x8B, 0x41, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov eax,dword ptr [ecx+rawbyte]
  151. { 0x8B, 0x42, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov eax,dword ptr [edx+rawbyte]
  152. { 0x8B, 0x43, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov eax,dword ptr [ebx+rawbyte]
  153. { 0x8B, 0x44, 0x00, 0x00, 4, 2, k_ENoRelativeOffsets }, // mov eax,dword ptr [esp+rawbyte]
  154. { 0x8B, 0x45, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov eax,dword ptr [ebp+rawbyte]
  155. { 0x8B, 0x46, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov eax,dword ptr [esi+rawbyte]
  156. { 0x8B, 0x47, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov eax,dword ptr [edi+rawbyte]
  157. { 0x8B, 0x48, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov ecx,dword ptr [eax+rawbyte]
  158. { 0x8B, 0x49, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov ecx,dword ptr [ecx+rawbyte]
  159. { 0x8B, 0x4A, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov ecx,dword ptr [edx+rawbyte]
  160. { 0x8B, 0x4B, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov ecx,dword ptr [ebx+rawbyte]
  161. { 0x8B, 0x4C, 0x00, 0x00, 4, 2, k_ENoRelativeOffsets }, // mov ecx,dword ptr [esp+rawbyte]
  162. { 0x8B, 0x4D, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov ecx,dword ptr [ebp+rawbyte]
  163. { 0x8B, 0x4E, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov ecx,dword ptr [esi+rawbyte]
  164. { 0x8B, 0x4F, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov ecx,dword ptr [edi+rawbyte]
  165. { 0x8B, 0x50, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov edx,dword ptr [eax+rawbyte]
  166. { 0x8B, 0x51, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov edx,dword ptr [ecx+rawbyte]
  167. { 0x8B, 0x52, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov edx,dword ptr [edx+rawbyte]
  168. { 0x8B, 0x53, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov edx,dword ptr [ebx+rawbyte]
  169. { 0x8B, 0x54, 0x00, 0x00, 4, 2, k_ENoRelativeOffsets }, // mov edx,dword ptr [esp+rawbyte]
  170. { 0x8B, 0x55, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov edx,dword ptr [ebp+rawbyte]
  171. { 0x8B, 0x56, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov edx,dword ptr [esi+rawbyte]
  172. { 0x8B, 0x57, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov edx,dword ptr [edi+rawbyte]
  173. { 0x8B, 0x58, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov ebx,dword ptr [eax+rawbyte]
  174. { 0x8B, 0x59, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov ebx,dword ptr [ecx+rawbyte]
  175. { 0x8B, 0x5A, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov ebx,dword ptr [edx+rawbyte]
  176. { 0x8B, 0x5B, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov ebx,dword ptr [ebx+rawbyte]
  177. { 0x8B, 0x5C, 0x00, 0x00, 4, 2, k_ENoRelativeOffsets }, // mov ebx,dword ptr [esp+rawbyte]
  178. { 0x8B, 0x5D, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov ebx,dword ptr [ebp+rawbyte]
  179. { 0x8B, 0x5E, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov ebx,dword ptr [esi+rawbyte]
  180. { 0x8B, 0x5F, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov ebx,dword ptr [edi+rawbyte]
  181. { 0x8B, 0x60, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov esp,dword ptr [eax+rawbyte]
  182. { 0x8B, 0x61, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov esp,dword ptr [ecx+rawbyte]
  183. { 0x8B, 0x62, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov esp,dword ptr [edx+rawbyte]
  184. { 0x8B, 0x63, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov esp,dword ptr [ebx+rawbyte]
  185. { 0x8B, 0x64, 0x00, 0x00, 4, 2, k_ENoRelativeOffsets }, // mov esp,dword ptr [esp+rawbyte]
  186. { 0x8B, 0x65, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov esp,dword ptr [ebp+rawbyte]
  187. { 0x8B, 0x66, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov esp,dword ptr [esi+rawbyte]
  188. { 0x8B, 0x67, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov esp,dword ptr [edi+rawbyte]
  189. { 0x8B, 0x68, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov ebp,dword ptr [eax+rawbyte]
  190. { 0x8B, 0x69, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov ebp,dword ptr [ecx+rawbyte]
  191. { 0x8B, 0x6A, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov ebp,dword ptr [edx+rawbyte]
  192. { 0x8B, 0x6B, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov ebp,dword ptr [ebx+rawbyte]
  193. { 0x8B, 0x6C, 0x00, 0x00, 4, 2, k_ENoRelativeOffsets }, // mov ebp,dword ptr [esp+rawbyte]
  194. { 0x8B, 0x6D, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov ebp,dword ptr [ebp+rawbyte]
  195. { 0x8B, 0x6E, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov ebp,dword ptr [esi+rawbyte]
  196. { 0x8B, 0x6F, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov ebp,dword ptr [edi+rawbyte]
  197. { 0x8B, 0x70, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov esi,dword ptr [eax+rawbyte]
  198. { 0x8B, 0x71, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov esi,dword ptr [ecx+rawbyte]
  199. { 0x8B, 0x72, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov esi,dword ptr [edx+rawbyte]
  200. { 0x8B, 0x73, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov esi,dword ptr [ebx+rawbyte]
  201. { 0x8B, 0x74, 0x00, 0x00, 4, 2, k_ENoRelativeOffsets }, // mov esi,dword ptr [esp+rawbyte]
  202. { 0x8B, 0x75, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov esi,dword ptr [ebp+rawbyte]
  203. { 0x8B, 0x76, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov esi,dword ptr [esi+rawbyte]
  204. { 0x8B, 0x77, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov esi,dword ptr [edi+rawbyte]
  205. { 0x8B, 0x78, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov edi,dword ptr [eax+rawbyte]
  206. { 0x8B, 0x79, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov edi,dword ptr [ecx+rawbyte]
  207. { 0x8B, 0x7A, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov edi,dword ptr [edx+rawbyte]
  208. { 0x8B, 0x7B, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov edi,dword ptr [ebx+rawbyte]
  209. { 0x8B, 0x7C, 0x00, 0x00, 4, 2, k_ENoRelativeOffsets }, // mov edi,dword ptr [esp+rawbyte]
  210. { 0x8B, 0x7D, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov edi,dword ptr [ebp+rawbyte]
  211. { 0x8B, 0x7E, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov edi,dword ptr [esi+rawbyte]
  212. { 0x8B, 0x7F, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov edi,dword ptr [edi+rawbyte]
  213. { 0x8B, 0x80, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov eax,dword ptr [eax+rawdword]
  214. { 0x8B, 0x81, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov eax,dword ptr [ecx+rawdword]
  215. { 0x8B, 0x82, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov eax,dword ptr [edx+rawdword]
  216. { 0x8B, 0x83, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov eax,dword ptr [ebx+rawdword]
  217. { 0x8B, 0x84, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov eax,dword ptr [esp+rawdword]
  218. { 0x8B, 0x85, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov eax,dword ptr [ebp+rawdword]
  219. { 0x8B, 0x86, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov eax,dword ptr [esi+rawdword]
  220. { 0x8B, 0x87, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov eax,dword ptr [edi+rawdword]
  221. { 0x8B, 0x88, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov ecx,dword ptr [eax+rawdword]
  222. { 0x8B, 0x89, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov ecx,dword ptr [ecx+rawdword]
  223. { 0x8B, 0x8A, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov ecx,dword ptr [edx+rawdword]
  224. { 0x8B, 0x8B, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov ecx,dword ptr [ebx+rawdword]
  225. { 0x8B, 0x8C, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov ecx,dword ptr [esp+rawdword]
  226. { 0x8B, 0x8D, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov ecx,dword ptr [ebp+rawdword]
  227. { 0x8B, 0x8E, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov ecx,dword ptr [esi+rawdword]
  228. { 0x8B, 0x8F, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov ecx,dword ptr [edi+rawdword]
  229. { 0x8B, 0x90, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov edx,dword ptr [eax+rawdword]
  230. { 0x8B, 0x91, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov edx,dword ptr [ecx+rawdword]
  231. { 0x8B, 0x92, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov edx,dword ptr [edx+rawdword]
  232. { 0x8B, 0x93, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov edx,dword ptr [ebx+rawdword]
  233. { 0x8B, 0x94, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov edx,dword ptr [esp+rawdword]
  234. { 0x8B, 0x95, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov edx,dword ptr [ebp+rawdword]
  235. { 0x8B, 0x96, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov edx,dword ptr [esi+rawdword]
  236. { 0x8B, 0x97, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov edx,dword ptr [edi+rawdword]
  237. { 0x8B, 0x98, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov ebx,dword ptr [eax+rawdword]
  238. { 0x8B, 0x99, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov ebx,dword ptr [ecx+rawdword]
  239. { 0x8B, 0x9A, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov ebx,dword ptr [edx+rawdword]
  240. { 0x8B, 0x9B, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov ebx,dword ptr [ebx+rawdword]
  241. { 0x8B, 0x9C, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov ebx,dword ptr [esp+rawdword]
  242. { 0x8B, 0x9D, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov ebx,dword ptr [ebp+rawdword]
  243. { 0x8B, 0x9E, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov ebx,dword ptr [esi+rawdword]
  244. { 0x8B, 0x9F, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov ebx,dword ptr [edi+rawdword]
  245. { 0x8B, 0xB0, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov esi,dword ptr [eax+rawdword]
  246. { 0x8B, 0xB1, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov esi,dword ptr [ecx+rawdword]
  247. { 0x8B, 0xB2, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov esi,dword ptr [edx+rawdword]
  248. { 0x8B, 0xB3, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov esi,dword ptr [ebx+rawdword]
  249. { 0x8B, 0xB4, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov esi,dword ptr [esp+rawdword]
  250. { 0x8B, 0xB5, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov esi,dword ptr [ebp+rawdword]
  251. { 0x8B, 0xB6, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov esi,dword ptr [esi+rawdword]
  252. { 0x8B, 0xB7, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov esi,dword ptr [edi+rawdword]
  253. { 0x8B, 0xB8, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov edi,dword ptr [eax+rawdword]
  254. { 0x8B, 0xB9, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov edi,dword ptr [ecx+rawdword]
  255. { 0x8B, 0xBA, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov edi,dword ptr [edx+rawdword]
  256. { 0x8B, 0xBB, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov edi,dword ptr [ebx+rawdword]
  257. { 0x8B, 0xBC, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov edi,dword ptr [ebx+rawdword]
  258. { 0x8B, 0xBD, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov edi,dword ptr [ebp+rawdword]
  259. { 0x8B, 0xBE, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov edi,dword ptr [esi+rawdword]
  260. { 0x8B, 0xBF, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov edi,dword ptr [edi+rawdword]
  261. { 0x8B, 0xC0, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov eax,eax
  262. { 0x8B, 0xC1, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov eax,ecx
  263. { 0x8B, 0xC2, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov eax,edx
  264. { 0x8B, 0xC3, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov eax,ebx
  265. { 0x8B, 0xC4, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov eax,esp
  266. { 0x8B, 0xC5, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov eax,ebp
  267. { 0x8B, 0xC6, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov eax,esi
  268. { 0x8B, 0xC7, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov eax,edi
  269. { 0x8B, 0xC8, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov ecx,eax
  270. { 0x8B, 0xC9, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov ecx,ecx
  271. { 0x8B, 0xCA, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov ecx,edx
  272. { 0x8B, 0xCB, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov ecx,ebx
  273. { 0x8B, 0xCC, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov ecx,esp
  274. { 0x8B, 0xCD, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov ecx,ebp
  275. { 0x8B, 0xCE, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov ecx,esi
  276. { 0x8B, 0xCF, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov ecx,edi
  277. { 0x8B, 0xD0, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov edx,eax
  278. { 0x8B, 0xD1, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov edx,ecx
  279. { 0x8B, 0xD2, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov edx,edx
  280. { 0x8B, 0xD3, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov edx,ebx
  281. { 0x8B, 0xD4, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov edx,esp
  282. { 0x8B, 0xD5, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov edx,ebp
  283. { 0x8B, 0xD6, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov edx,esi
  284. { 0x8B, 0xD7, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov edx,edi
  285. { 0x8B, 0xD8, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov ebx,eax
  286. { 0x8B, 0xD9, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov ebx,ecx
  287. { 0x8B, 0xDA, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov ebx,edx
  288. { 0x8B, 0xDB, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov ebx,ebx
  289. { 0x8B, 0xDC, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov ebx,ebx
  290. { 0x8B, 0xDD, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov ebx,ebp
  291. { 0x8B, 0xDE, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov ebx,esi
  292. { 0x8B, 0xDF, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov ebx,edi
  293. { 0x8B, 0xE0, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov esp,eax
  294. { 0x8B, 0xE1, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov esp,ecx
  295. { 0x8B, 0xE2, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov esp,edx
  296. { 0x8B, 0xE3, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov esp,ebx
  297. { 0x8B, 0xE4, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov esp,ebx
  298. { 0x8B, 0xE5, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov esp,ebp
  299. { 0x8B, 0xE6, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov esp,esi
  300. { 0x8B, 0xE7, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov esp,edi
  301. { 0x8B, 0xE8, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov ebp,eax
  302. { 0x8B, 0xE9, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov ebp,eax
  303. { 0x8B, 0xEA, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov ebp,edx
  304. { 0x8B, 0xEB, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov ebp,ebx
  305. { 0x8B, 0xEC, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov ebp,esp
  306. { 0x8B, 0xED, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov ebp,ebp
  307. { 0x8B, 0xEE, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov ebp,esi
  308. { 0x8B, 0xEF, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov ebp,edi
  309. { 0x8B, 0xD3, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov edx,ebx
  310. { 0x8B, 0xD5, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov edx,ebp
  311. { 0x8B, 0xD6, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov edx,esi
  312. { 0x8B, 0xD7, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov edx,edi
  313. { 0x8B, 0xF0, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov esi,eax
  314. { 0x8B, 0xF1, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov esi,ecx
  315. { 0x8B, 0xF2, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov esi,edx
  316. { 0x8B, 0xF3, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov esi,ebx
  317. { 0x8B, 0xF4, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov esi,esp
  318. { 0x8B, 0xF5, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov esi,ebp
  319. { 0x8B, 0xF6, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov esi,esi
  320. { 0x8B, 0xF7, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov esi,edi
  321. { 0x8B, 0xF8, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov edi,eax
  322. { 0x8B, 0xF9, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov edi,ecx
  323. { 0x8B, 0xFA, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov edi,edx
  324. { 0x8B, 0xFB, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov edi,ebx
  325. { 0x8B, 0xFC, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov edi,esp
  326. { 0x8B, 0xFD, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov edi,ebp
  327. { 0x8B, 0xFE, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov edi,esi
  328. { 0x8B, 0xFF, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov edi,edi
  329. { 0x8D, 0x44, 0x24, 0x00, 4, 3, k_ENoRelativeOffsets }, // lea eax,[esp+imm8]
  330. { 0x8D, 0x45, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // lea eax,[ebp+imm8]
  331. { 0x8D, 0x4C, 0x24, 0x00, 4, 3, k_ENoRelativeOffsets }, // lea ecx,[esp+imm8]
  332. { 0x8D, 0x64, 0x24, 0x00, 4, 3, k_ENoRelativeOffsets }, // lea esp,[esp+imm8]
  333. { 0x8D, 0xA4, 0x24, 0x00, 7, 3, k_ENoRelativeOffsets }, // lea esp,[esp+imm32]
  334. { 0x8D, 0xAC, 0x24, 0x00, 7, 3, k_ENoRelativeOffsets }, // lea ebp,[esp+imm32]
  335. { 0x90, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // nop
  336. { 0x97, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // xchg eax,edi
  337. { 0x9C, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // pushfd
  338. { 0x9D, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // popfd
  339. { 0xA0, 0x00, 0x00, 0x00, 5, 1, k_ENoRelativeOffsets }, // mov al,byte ptr ds:[imm32]
  340. { 0xB9, 0x00, 0x00, 0x00, 5, 1, k_ENoRelativeOffsets }, // mov immediate doubleword into ecx
  341. { 0xBA, 0x00, 0x00, 0x00, 5, 1, k_ENoRelativeOffsets }, // mov immediate doubleword into edx
  342. { 0xBB, 0x00, 0x00, 0x00, 5, 1, k_ENoRelativeOffsets }, // mov immediate doubleword into ebx
  343. { 0xBC, 0x00, 0x00, 0x00, 5, 1, k_ENoRelativeOffsets }, // mov immediate doubleword into esp
  344. { 0xBD, 0x00, 0x00, 0x00, 5, 1, k_ENoRelativeOffsets }, // mov immediate doubleword into ebp
  345. { 0xBE, 0x00, 0x00, 0x00, 5, 1, k_ENoRelativeOffsets }, // mov immediate doubleword into esi
  346. { 0xB8, 0x00, 0x00, 0x00, 5, 1, k_ENoRelativeOffsets }, // mov immediate doubleword into eax
  347. { 0xBF, 0x00, 0x00, 0x00, 5, 1, k_ENoRelativeOffsets }, // mov immediate doubleword into edi
  348. { 0xA1, 0x00, 0x00, 0x00, 5, 1, k_ENoRelativeOffsets }, // mov eax, dword ptr
  349. { 0xA2, 0x00, 0x00, 0x00, 5, 1, k_ENoRelativeOffsets }, // mov byte ptr, al
  350. { 0xA3, 0x00, 0x00, 0x00, 5, 1, k_ENoRelativeOffsets }, // mov dword ptr, eax
  351. { 0xC3, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // ret
  352. { 0xC7, 0x05, 0x00, 0x00, 10, 1, k_ENoRelativeOffsets }, // mov dword ptr ds:[dword],dword
  353. { 0xC9, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // leave
  354. { 0xCC, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // int3
  355. { 0xD0, 0x00, 0x00, 0x00, 2, 1, k_ENoRelativeOffsets }, // shr, sar, or rcr (shift right style operations on registers)
  356. // 0xF0 is the lock prefix
  357. { 0xF0, 0x0F, 0xBA, 0x2D, 9, 4, k_ENoRelativeOffsets }, // lock bts dword ptr ds:[dword], imm byte
  358. { 0xFA, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // cli
  359. { 0xF8, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // clc
  360. { 0xFC, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // cld
  361. { 0xFF, 0x15, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // call dword ptr ds:[imm32]
  362. { 0xFF, 0x48, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // dec dword ptr [eax+imm8]
  363. { 0xFF, 0x61, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // jmp dword ptr [ecx+imm8]
  364. { 0xFF, 0x74, 0x00, 0x00, 4, 2, k_ENoRelativeOffsets }, // push dword ptr
  365. { 0xFF, 0x75, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // push dword ptr type 2
  366. { 0xFF, 0x25, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // jmp dword ptr -- this is often at the start of win32 api functions that are just stubs to call some __imp__func call
  367. { 0xE8, 0x00, 0x00, 0x00, 5, 1, k_EDWORDOffsetAtByteTwo }, // call DWORD rel
  368. { 0xE9, 0x00, 0x00, 0x00, 5, 1, k_EDWORDOffsetAtByteTwo }, // jmp DWORD rel
  369. { 0xEB, 0x00, 0x00, 0x00, 2, 1, k_EBYTEOffsetAtByteTwo }, // jmp byte rel
  370. #else
  371. //
  372. // 64 bit specific opcodes
  373. //
  374. { 0x0F, 0x1F, 0x00, 0x00, 3, 3, k_ENoRelativeOffsets }, // nop dword ptr[rax] (canonical 3-byte NOP)
  375. { 0x0F, 0x1F, 0x40, 0x00, 4, 3, k_ENoRelativeOffsets }, // nop dword ptr[rax+imm8] (canonical 4-byte NOP)
  376. { 0x0F, 0x1F, 0x44, 0x00, 5, 3, k_ENoRelativeOffsets }, // nop dword ptr[rax+rax+imm8] (canonical 5-byte NOP)
  377. { 0x0F, 0x1F, 0x80, 0x00, 7, 3, k_ENoRelativeOffsets }, // nop dword ptr[rax+0x0] (canonical 7-byte NOP)
  378. { 0x0F, 0xB6, 0x53, 0x00, 4, 3, k_ENoRelativeOffsets }, // movzx edx,byte ptr[rbx+byte]
  379. { 0x33, 0xD2, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // xor edx,edx
  380. // 0x40 indicates 64bit operands
  381. { 0x40, 0x50, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // push rax
  382. { 0x40, 0x51, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // push rcx
  383. { 0x40, 0x52, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // push rdx
  384. { 0x40, 0x53, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // push rbx
  385. { 0x40, 0x54, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // push rsp
  386. { 0x40, 0x55, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // push rbp
  387. { 0x40, 0x56, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // push rsi
  388. { 0x41, 0x50, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // push r8
  389. { 0x41, 0x51, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // push r9
  390. { 0x41, 0x52, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // push r10
  391. { 0x41, 0x53, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // push r11
  392. { 0x41, 0x54, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // push r12
  393. { 0x41, 0x55, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // push r13
  394. { 0x41, 0x56, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // push r14
  395. { 0x41, 0x57, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // push r15
  396. { 0x41, 0x58, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // pop r8
  397. { 0x41, 0x59, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // pop r9
  398. { 0x41, 0x5A, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // pop r10
  399. { 0x41, 0x5B, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // pop r11
  400. { 0x41, 0x5C, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // pop r12
  401. { 0x41, 0x5D, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // pop r13
  402. { 0x41, 0x5E, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // pop r14
  403. { 0x41, 0x5F, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // pop r15
  404. { 0x41, 0x8B, 0xC0, 0x00, 3, 3, k_ENoRelativeOffsets }, // mov eax,r8d
  405. { 0x41, 0x8B, 0xD8, 0x00, 3, 3, k_ENoRelativeOffsets }, // mov ebx,r8d
  406. { 0x41, 0xB0, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov r8b, imm8
  407. { 0x41, 0xB1, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov r9b, imm8
  408. { 0x41, 0xB8, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov r8d, imm32
  409. { 0x41, 0xB9, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // mov r9d, imm32
  410. // 44 is a prefix that indicates the mod r/m field is extended
  411. { 0x44, 0x89, 0x44, 0x00, 5, 3, k_ENoRelativeOffsets }, // mov dword ptr [rsp+...], reg
  412. { 0x44, 0x8D, 0x42, 0x00, 4, 3, k_ENoRelativeOffsets }, // lea r8d[rdx+...]
  413. { 0x45, 0x33, 0xC0, 0x00, 3, 3, k_ENoRelativeOffsets }, // xor r8d,r8d
  414. { 0x45, 0x33, 0xC9, 0x00, 3, 3, k_ENoRelativeOffsets }, // xor r9d,r9d
  415. // 48 is a prefix that indicates the operation takes 64 bit operands
  416. { 0x48, 0x81, 0xEC, 0x00, 7, 3, k_ENoRelativeOffsets }, // sub rsp, imm32
  417. { 0x48, 0x63, 0xC9, 0x00, 3, 3, k_ENoRelativeOffsets }, // movsxd rcx,ecx
  418. { 0x48, 0x63, 0xD2, 0x00, 3, 3, k_ENoRelativeOffsets }, // movsxd rdx,edx
  419. { 0x48, 0x83, 0x64, 0x00, 6, 3, k_ENoRelativeOffsets }, // and qword ptr [rsp+...], immediate
  420. { 0x48, 0x83, 0xEC, 0x00, 4, 3, k_ENoRelativeOffsets }, // sub rsp, immediate
  421. { 0x48, 0x83, 0xE9, 0x00, 4, 3, k_ENoRelativeOffsets }, // sub rcx, immediate byte
  422. { 0x48, 0x83, 0xC1, 0x00, 4, 3, k_ENoRelativeOffsets }, // add rcx, immediate byte
  423. { 0x48, 0x85, 0xC0, 0x00, 3, 3, k_ENoRelativeOffsets }, // test rax,rax
  424. { 0x48, 0x85, 0xC9, 0x00, 3, 3, k_ENoRelativeOffsets }, // test rcx,rcx
  425. { 0x48, 0x85, 0xD2, 0x00, 3, 3, k_ENoRelativeOffsets }, // text rdx,rdx
  426. { 0x48, 0x89, 0x4C, 0x00, 5, 3, k_ENoRelativeOffsets }, // mov qword ptr[...+...+imm byte],rcx
  427. { 0x48, 0x89, 0x54, 0x00, 5, 3, k_ENoRelativeOffsets }, // mov qword ptr[rsp+...],rdx
  428. { 0x48, 0x89, 0x58, 0x00, 4, 3, k_ENoRelativeOffsets }, // mov qword ptr[rax+...],rbx
  429. { 0x48, 0x89, 0x5C, 0x00, 5, 3, k_ENoRelativeOffsets }, // mov qword ptr[rsp+...], reg
  430. { 0x48, 0x89, 0x68, 0x00, 4, 3, k_ENoRelativeOffsets }, // mov qword ptr[rax+...],rbp
  431. { 0x48, 0x89, 0x6C, 0x00, 5, 3, k_ENoRelativeOffsets }, // mov qword ptr[rsp+...],rbp
  432. { 0x48, 0x89, 0x70, 0x00, 4, 3, k_ENoRelativeOffsets }, // mov qword ptr[rax+...],rsi
  433. { 0x48, 0x89, 0x74, 0x00, 5, 3, k_ENoRelativeOffsets }, // mov qword ptr[rsp+...],rsi
  434. { 0x48, 0x8B, 0x01, 0x00, 3, 3, k_ENoRelativeOffsets }, // mov rax,qword ptr [rcx]
  435. { 0x48, 0x8B, 0x04, 0x24, 4, 4, k_ENoRelativeOffsets }, // mov rax,qword ptr [rsp]
  436. { 0x48, 0x8B, 0x44, 0x00, 5, 3, k_ENoRelativeOffsets }, // mov rax,qword ptr[...+...+imm byte]
  437. { 0x48, 0x8B, 0x49, 0x00, 4, 3, k_ENoRelativeOffsets }, // mov rcx,qword ptr[rcx+im8]
  438. { 0x48, 0x8B, 0x84, 0x00, 8, 3, k_ENoRelativeOffsets }, // mov rax,qword ptr[rsp+dword]
  439. { 0x48, 0x8B, 0xC1, 0x00, 3, 3, k_ENoRelativeOffsets }, // mov rax,rcx
  440. { 0x48, 0x8B, 0xC3, 0x00, 3, 3, k_ENoRelativeOffsets }, // mov ebx,r8d
  441. { 0x48, 0x8B, 0xC4, 0x00, 3, 3, k_ENoRelativeOffsets }, // mov rax,rsp
  442. { 0x48, 0x8B, 0xD9, 0x00, 3, 3, k_ENoRelativeOffsets }, // mov rbx,rbx
  443. { 0x48, 0x8B, 0xEC, 0x00, 3, 3, k_ENoRelativeOffsets }, // mov rbp,rsp
  444. { 0x48, 0x8B, 0xFA, 0x00, 3, 3, k_ENoRelativeOffsets }, // mov rdi,rdx
  445. { 0x48, 0xB8, 0x00, 0x00, 10, 2, k_ENoRelativeOffsets }, // mov rax,imm64
  446. { 0x48, 0xB9, 0x00, 0x00, 10, 2, k_ENoRelativeOffsets }, // mov rcx,imm64
  447. { 0x48, 0xC7, 0x44, 0x00, 9, 3, k_ENoRelativeOffsets }, // mov qword ptr[rsp+...], dword immediate
  448. { 0x48, 0xC7, 0xC0, 0x00, 7, 3, k_ENoRelativeOffsets }, // mov rax,dword ptr
  449. { 0x48, 0x8D, 0x05, 0x00, 7, 3, k_EDWORDOffsetAtByteFour }, // lea rax, [imm dword offset]
  450. { 0x48, 0x8D, 0x0D, 0x00, 7, 3, k_EDWORDOffsetAtByteFour }, // lea rcx, [imm dword offset]
  451. { 0x48, 0x8D, 0x15, 0x00, 7, 3, k_EDWORDOffsetAtByteFour }, // lea rdx, [imm dword offset]
  452. { 0x48, 0x8D, 0x1D, 0x00, 7, 3, k_EDWORDOffsetAtByteFour }, // lea rbx, [imm dword offset]
  453. { 0x48, 0x8D, 0x44, 0x24, 5, 4, k_ENoRelativeOffsets }, // lea rax, [rsp+imm byte]
  454. { 0x48, 0x8D, 0x4C, 0x24, 5, 4, k_ENoRelativeOffsets }, // lea rcx, [rsp+imm byte]
  455. { 0x48, 0x8D, 0x54, 0x24, 5, 4, k_ENoRelativeOffsets }, // lea rdx, [rsp+imm byte]
  456. { 0x48, 0x8D, 0x5C, 0x24, 5, 4, k_ENoRelativeOffsets }, // lea rbx, [rsp+imm byte]
  457. { 0x48, 0xFF, 0x25, 0x00, 7, 3, k_EDWORDOffsetAtByteFour }, // jmp QWORD PTR [rip+dword] -- RIP-relative indirect jump
  458. { 0x49, 0x89, 0x5B, 0x00, 4, 3, k_ENoRelativeOffsets }, // qword ptr[r11 + byte], rbx
  459. { 0x49, 0x89, 0x73, 0x00, 4, 3, k_ENoRelativeOffsets }, // qword ptr[r11 + byte], rsi
  460. { 0x49, 0x8B, 0xC1, 0x00, 3, 3, k_ENoRelativeOffsets }, // qword rax, r9
  461. { 0x4C, 0x3B, 0xCF, 0x00, 3, 3, k_ENoRelativeOffsets }, // cmp r9,rdi
  462. { 0x4C, 0x89, 0x40, 0x00, 4, 3, k_ENoRelativeOffsets }, // mov qword ptr [rax+immediate byte],r8
  463. { 0x4C, 0x89, 0x48, 0x00, 4, 3, k_ENoRelativeOffsets }, // mov qword ptr [rax+immediate byte],r9
  464. { 0x4C, 0x89, 0x44, 0x00, 5, 3, k_ENoRelativeOffsets }, // mov qword ptr [rsp+imm byte],r8
  465. { 0x4C, 0x89, 0x4C, 0x00, 5, 3, k_ENoRelativeOffsets }, // mov qword ptr [...+...+imm byte],r9
  466. { 0x4C, 0x8B, 0xC2, 0x00, 3, 3, k_ENoRelativeOffsets }, // mov r8,rdx
  467. { 0x4C, 0x8B, 0xD1, 0x00, 3, 3, k_ENoRelativeOffsets }, // mov r10,rcx
  468. { 0x4C, 0x8B, 0xDC, 0x00, 3, 3, k_ENoRelativeOffsets }, // mov r11,rsp
  469. { 0x4C, 0x8D, 0x44, 0x00, 5, 3, k_ENoRelativeOffsets }, // lea reg,[rsp+...]
  470. { 0x4D, 0x85, 0xC0, 0x00, 3, 3, k_ENoRelativeOffsets }, // test r8,r8
  471. { 0x4D, 0x85, 0xC9, 0x00, 3, 3, k_ENoRelativeOffsets }, // test r9,r9
  472. { 0x50, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // push rax
  473. { 0x51, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // push rcx
  474. { 0x52, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // push rdx
  475. { 0x53, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // push rbx
  476. { 0x54, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // push rsp
  477. { 0x55, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // push rbp
  478. { 0x56, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // push rsi
  479. { 0x57, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // push rdi
  480. // 0x64 and 0x65 are prefixes for FS or GS relative memory addressing
  481. { 0x64, 0x48, 0x89, 0x04, 5, 4, k_ENoRelativeOffsets }, // mov qword ptr fs:[register-based offset], rax
  482. { 0x65, 0x48, 0x8b, 0x00, 9, 3, k_ENoRelativeOffsets }, // mov reg,qword ptr gs:[dword]
  483. { 0x66, 0x90, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // xchg ax,ax - canonical 2-byte NOP
  484. { 0x66, 0x0F, 0x1F, 0x44, 6, 4, k_ENoRelativeOffsets }, // nop word ptr[rax+...] - canonical 6-byte NOP
  485. { 0x81, 0x3A, 0x00, 0x00, 6, 2, k_ENoRelativeOffsets }, // cmp prt[rdx], 4 bytes
  486. { 0x89, 0x70, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov dword ptr[rax+...],esi
  487. { 0x89, 0x4C, 0x00, 0x00, 4, 2, k_ENoRelativeOffsets }, // mov dword ptr[rsp+...],ecx
  488. { 0x8B, 0x40, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov eax,dword ptr [rax+rawbyte]
  489. { 0x8B, 0x41, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov eax,dword ptr [rcx+rawbyte]
  490. { 0x8B, 0x42, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov eax,dword ptr [rdx+rawbyte]
  491. { 0x8B, 0x43, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov eax,dword ptr [rbx+rawbyte]
  492. { 0x8B, 0x44, 0x00, 0x00, 4, 2, k_ENoRelativeOffsets }, // mov eax,dword ptr [rsp+rawbyte]
  493. { 0x8B, 0x45, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov eax,dword ptr [rbp+rawbyte]
  494. { 0x8B, 0x46, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov eax,dword ptr [rsi+rawbyte]
  495. { 0x8B, 0x47, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // mov eax,dword ptr [rdi+rawbyte]
  496. { 0x8B, 0xC0, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov eax,eax
  497. { 0x8B, 0xC1, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov eax,ecx
  498. { 0x8B, 0xC2, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov eax,edx
  499. { 0x8B, 0xC3, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov eax,ebx
  500. { 0x8B, 0xC5, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov eax,ebp
  501. { 0x8B, 0xC6, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov eax,esi
  502. { 0x8B, 0xC7, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov eax,edi
  503. { 0x8B, 0xD3, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov edx,ebx
  504. { 0x8B, 0xD5, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov edx,ebp
  505. // bugbug jmccaskey - the below is correct, but will break detours of LoadLibraryExW on x64.
  506. // need to work out exactly what is wrong there, right now we work fine failing to detour it, and
  507. // there seems to be some set of interlinking stubs we may double detour between LoadLibarExA/W
  508. // somehow.
  509. //{ 0x8B, 0xD6, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov edx,esi
  510. { 0x8B, 0xD7, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // mov edx,edi
  511. { 0xB8, 0x00, 0x00, 0x00, 5, 1, k_ENoRelativeOffsets }, // mov eax, immediate dword
  512. { 0xB9, 0x00, 0x00, 0x00, 5, 1, k_ENoRelativeOffsets }, // mov ecx, immediate dword
  513. { 0xBA, 0x00, 0x00, 0x00, 5, 1, k_ENoRelativeOffsets }, // mov edx, immediate dword
  514. { 0xE8, 0x00, 0x00, 0x00, 5, 1, k_EDWORDOffsetAtByteTwo }, // call DWORD rel
  515. { 0xE9, 0x00, 0x00, 0x00, 5, 1, k_EDWORDOffsetAtByteTwo }, // jmp DWORD rel
  516. { 0xEB, 0x00, 0x00, 0x00, 2, 1, k_EBYTEOffsetAtByteTwo }, // jmp BYTE rel
  517. { 0x90, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // nop
  518. { 0xCC, 0x00, 0x00, 0x00, 1, 1, k_ENoRelativeOffsets }, // int 3
  519. // F0 is the lock prefix
  520. { 0xF0, 0x83, 0x41, 0x00, 5, 3, k_ENoRelativeOffsets }, // lock add dword ptr[rcx+...], immediate
  521. { 0xF0, 0x83, 0x05, 0x00, 8, 3, k_EDWORDOffsetAtByteFour }, // lock add dword ptr[rel], immediate byte
  522. { 0xF6, 0xC1, 0x00, 0x00, 3, 2, k_ENoRelativeOffsets }, // test c1,byte
  523. { 0xFF, 0x25, 0x00, 0x00, 6, 2, k_EDWORDOffsetAtByteThree }, // jmp dword offset
  524. { 0xFF, 0xE0, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // jmp rax
  525. { 0xFF, 0xF0, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // push rax
  526. { 0xFF, 0xF1, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // push rcx
  527. { 0xFF, 0xF2, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // push rdx
  528. { 0xFF, 0xF3, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // push rbx
  529. { 0xFF, 0xF4, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // push rsp
  530. { 0xFF, 0xF5, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // push rbp
  531. { 0xFF, 0xF6, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // push rsi
  532. { 0xFF, 0xF7, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // push rdi
  533. { 0xFF, 0xF8, 0x00, 0x00, 2, 2, k_ENoRelativeOffsets }, // push rsp
  534. #endif
  535. };
  536. //-----------------------------------------------------------------------------
  537. // Purpose: tries to parse the opcode and returns length in bytes if known
  538. //-----------------------------------------------------------------------------
  539. bool ParseOpcode( unsigned char *pOpcode, int &nLength, EOpCodeOffsetType &eOffsetType )
  540. {
  541. for ( int i=0; i < sizeof(s_rgKnownOpCodes)/sizeof(s_rgKnownOpCodes[0]); i++ )
  542. {
  543. const KnownOpCode_t &opcode = s_rgKnownOpCodes[i];
  544. if ( pOpcode[0] == opcode.m_OpCodeB1 )
  545. {
  546. if ( opcode.m_cOpCodeBytesToMatch < 2 || pOpcode[1] == opcode.m_OpCodeB2 )
  547. {
  548. if ( opcode.m_cOpCodeBytesToMatch < 3 || pOpcode[2] == opcode.m_OpCodeB3 )
  549. {
  550. if ( opcode.m_cOpCodeBytesToMatch < 4 || pOpcode[3] == opcode.m_OpCodeB4 )
  551. {
  552. nLength = opcode.m_TotalLength;
  553. eOffsetType = opcode.m_EOffsetType;
  554. return true;
  555. }
  556. }
  557. }
  558. }
  559. }
  560. return false;
  561. }
  562. // New disassembler code
  563. typedef unsigned char uint8;
  564. // data from http://www.intel.com/design/processor/manuals/253667.pdf appendix A pages A-10 and up
  565. // Table Key
  566. // 0-9 number of bytes of data following opcode
  567. // specials:
  568. #define opcMODRMBYTE 0x10
  569. #define M0 0x10 // ModRM byte that cannot have extra displacement
  570. #define Mb 0x10 // ModRM byte that may have extra byte displcement
  571. #define Mw 0x30 // ModRM byte that may have extra dword displacement
  572. #define M1 0x11 // ModRM byte ( with possible displacement ) PLUS 1 byte immediate
  573. #define M4 0x34 // ModRM byte ( with possible displacement ) PLUS 2 byte immediate
  574. #define MF 0x70 // ModRM byte that defines opcode
  575. #define UU 0x80 // I dont understand this instruction - disassembly will fail
  576. #define opcRELATIVEJUMP 0x100
  577. #define opcUNCONDITIONALJUMP 0x400
  578. #define R1 0x301 // conditional relative jump/call - 1 byte offset
  579. #define R4 0x304 // conditional relative jump/call - 4 byte offset
  580. #define C1 0x201 // absolute jump/call - 1 byte offset ?
  581. #define C4 0x204 // absolute jump/call - 4 byte offset ?
  582. #define uC6 0x206 // absolute jump/call - 6 byte offset
  583. #define CM 0x230 // jump with modrm byte ( probably jmp [eax] or jmp [eax+stuff]
  584. #define uR1 0x701 // unconditional relative jump - 1 byte offset
  585. #define uR4 0x704 // unconditional relative jump - 4 byte offset
  586. #define uJ1 0x701 // unconditional jump - 1 byte offset
  587. #define uJ4 0x704 // unconditional jump - 4 byte offset
  588. #define opcRETURN 0x800
  589. #define E0 0x800 // return ( a jump we cant follow )
  590. #define E2 0x802 // return ( a jump we cant follow )
  591. #define XC 0x1000 // coprocessor instruction - floating point - disassembly will fail
  592. #define XX 0x2000 // start of 2 byte opcode
  593. #define IS 0x4000
  594. #define opcOPERANDSIZEOVERRIDE 0x4000
  595. #define AS 0x8000
  596. #define MP 0x3000 // meaningless prefix
  597. #define MQ 0x5000 // meaningless prefix
  598. // 1 byte opcode map
  599. int rgOpData[256]=
  600. {
  601. // 0 1 2 3 4 5 6 7 8 9 A B C D E F
  602. /*0*/ Mb, Mw, Mb, Mw, 1, 4, 0, 0, Mb, Mw, Mb, Mw, 1, 4, 0, XX,
  603. /*1*/ Mb, Mw, Mb, Mw, 1, 4, 0, 0, Mb, Mw, Mb, Mw, 1, 4, 0, 0,
  604. /*2*/ Mb, Mw, Mb, Mw, 1, 4, 0, 0, Mb, Mw, Mb, Mw, 1, 4, 0, 0,
  605. /*3*/ Mb, Mw, Mb, Mw, 1, 4, 0, 0, Mb, Mw, Mb, Mw, 1, 4, 0, 0,
  606. /*4*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  607. /*5*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  608. /*6*/ 0, 0, UU, M0, 0, 0, IS, UU, 4, M4, 1, M1, 0, 0, 0, 0,
  609. /*7*/ R1, R1, R1, R1, R1, R1, R1, R1, R1, R1, R1, R1, R1, R1, R1, R1, // relative jumps
  610. /*8*/ M1, M4, M1, M1, Mb, Mw, Mb, Mw, Mb, Mw, Mb, Mw, Mw, Mw, Mw, Mw,
  611. /*9*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, C4, 0, 0, 0, 0, 0,
  612. /*a*/ 4, 4, 4, 4, 0, 0, 0, 0, 1, 4, 0, 0, 0, 0, 0, 0,
  613. /*b*/ 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, 4, 4, 4, 4, 4,
  614. /*c*/ M1, M1, E2, E0, UU, UU, M1, M4, 5, 0, 2, 0, 0, 1, 0, 0,
  615. /*d*/ 1, 1, 1, 1, 1, 1, 1, 1, XC, XC, XC, XC, XC, XC, XC, XC,
  616. /*e*/ R1, R1, R1, R1, 1, 1, 1, 1, R4,uR4,uC6,uR1, 0, 0, 0, 0,
  617. /*f*/ MP, 0, MP, MP, 0, 0, MF, MF, 0, 0, 0, 0, 0, 0, UU, CM
  618. };
  619. // e8 = call
  620. // e9 = jump
  621. // f2/f3 prefixes only a small subset of instructions - otherwise its part of a 3 byte opcode
  622. // A6 A7 AA AB AD AE
  623. // 2 byte opcode map
  624. int rgOpData2[256]=
  625. {
  626. // 0 1 2 3 4 5 6 7 8 9 A B C D E F
  627. /*0*/ UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU,
  628. /*1*/ UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU,
  629. /*2*/ UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU,
  630. /*3*/ 0, 0, 0, 0, 0, 0, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU,
  631. /*4*/ Mw, Mw, Mw, Mw, Mw, Mw, Mw, Mw, Mw, Mw, Mw, Mw, Mw, Mw, Mw, Mw,
  632. /*5*/ UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU,
  633. /*6*/ UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU,
  634. /*7*/ UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU,
  635. /*8*/ R4, R4, R4, R4, R4, R4, R4, R4, R4, R4, R4, R4, R4, R4, R4, R4, // far relative jumps
  636. /*9*/ M0, M0, M0, M0, M0, M0, M0, M0, M0, M0, M0, M0, M0, M0, M0, M0,
  637. /*a*/ 0, 0, 0, Mw, M1, Mw, UU, UU, 0, 0, 0, Mw, M1, Mw, UU, Mw,
  638. /*b*/ Mb, Mw, UU, Mw, UU, UU, Mb, Mw, UU, UU, UU, Mw, Mw, Mw, Mb, Mw,
  639. /*c*/ Mb, Mw, UU, UU, UU, UU, UU, UU, 0, 0, 0, 0, 0, 0, 0, 0,
  640. /*d*/ UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU,
  641. /*e*/ UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU,
  642. /*f*/ UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU, UU
  643. };
  644. #ifdef VACTOOL
  645. #define OPCODE_NAMES
  646. #endif
  647. #ifdef OPCODE_NAMES
  648. char *rgOpcodeNames[256]=
  649. {
  650. "add", "add", "add", "add", "add", "add", "push", "pop", "or", "or", "or", "or", "or", "or", "push", "",
  651. "adc", "adc", "adc", "adc", "adc", "adc", "push", "pop", "sbb", "sbb", "sbb", "sbb", "sbb", "sbb", "push", "pop",
  652. "and", "and", "and", "and", "and", "and", "sege", "daa", "sub", "sub", "sub", "sub", "sub", "sub", "segc", "das",
  653. "xor", "xor", "xor", "xor", "xor", "xor", "segs", "aaa", "cmp", "cmp", "cmp", "cmp", "cmp", "cmp", "segd", "aas",
  654. "inc", "inc", "inc", "inc", "inc", "inc", "inc", "inc", "dec", "dec", "dec", "dec", "dec", "dec", "dec", "dec",
  655. "push", "push", "push", "push", "push", "push", "push", "push", "pop", "pop", "pop", "pop", "pop", "pop", "pop", "pop",
  656. "pusha", "popa", "bound", "arpl", "segf", "segg", "pre", "pre", "push", "imul", "push", "imul", "ins", "ins", "outs", "outs",
  657. "jo", "jno", "jb", "jnb", "je", "jne", "jbe", "ja", "js", "jns", "jp", "jnp", "jl", "jge", "jle", "jg",
  658. "", "", "", "", "test", "test", "xchg", "xchg", "mov", "mov", "mov", "mov", "mov", "lea", "mov", "pgp",
  659. "nop", "xchg", "xchg", "xchg", "xchg", "xchg", "xchg", "xchg", "cbw", "cwd", "call", "wait", "pushf","popf", "sahf", "lahf",
  660. "mov", "mov", "mov", "mov", "movs", "movs", "cmps", "cmps", "test", "test", "stos", "stos", "lods", "lods", "scas", "scas",
  661. "mov", "mov", "mov", "mov", "mov", "mov", "mov", "mov", "mov", "mov", "mov", "mov", "mov", "mov", "mov", "mov",
  662. "shlr", "shlr", "retn", "retn", "les", "lds", "mov", "mov", "enter","leave", "retf", "retf", "int3", "int", "into", "iret",
  663. "shlr", "shlr", "shlr", "shlr", "aam", "aad", "", "xlat", "", "", "", "", "", "", "", "",
  664. "loop", "loop", "loop", "jcxz", "in", "in", "out", "out", "call", "jmp", "jmp", "jmp", "in", "in", "out", "out",
  665. "lock", "", "repne", "repe", "hlt", "cmc", "unry", "unry", "clc", "stc", "cli", "sti", "cld", "std", "dinc", "dinc",
  666. };
  667. #endif
  668. uint8 rgOpcodeValid[256]=
  669. {
  670. //0 "add", "add", "add", "add", "add", "add", "push", "pop", "or", "or", "or", "or", "or", "or", "push", "",
  671. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  672. //1 "adc", "adc", "adc", "adc", "adc", "adc", "push", "pop", "sbb", "sbb", "sbb", "sbb", "sbb", "sbb", "push", "pop",
  673. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  674. //2 "and", "and", "and", "and", "and", "and", "sege", "daa", "sub", "sub", "sub", "sub", "sub", "sub", "segc", "das",
  675. 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0,
  676. //3 "xor", "xor", "xor", "xor", "xor", "xor", "segs", "aaa", "cmp", "cmp", "cmp", "cmp", "cmp", "cmp", "segd", "aas",
  677. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  678. //4 "inc", "inc", "inc", "inc", "inc", "inc", "inc", "inc", "dec", "dec", "dec", "dec", "dec", "dec", "dec", "dec",
  679. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  680. //5 "push", "push", "push", "push", "push", "push", "push", "push", "pop", "pop", "pop", "pop", "pop", "pop", "pop", "pop",
  681. 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1,
  682. //6 "pusha", "popa", "bound", "arpl", "segf", "segg", "pre", "pre", "push", "imul", "push", "imul", "ins", "ins", "outs", "outs",
  683. 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 0, 0, 0, 0,
  684. //7 "jo", "jno", "jb", "jnb", "je", "jne", "jbe", "ja", "js", "jns", "jp", "jnp", "jl", "jge", "jle", "jg",
  685. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  686. //8 "", "", "", "", "test", "test", "xchg", "xchg", "mov", "mov", "mov", "mov", "mov", "lea", "mov", "pgp",
  687. 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1,
  688. //9 "nop", "xchg", "xchg", "xchg", "xchg", "xchg", "xchg", "xchg", "cbw", "cwd", "call", "wait", "pushf","popf", "sahf", "lahf",
  689. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  690. //A "mov", "mov", "mov", "mov", "movs", "movs", "cmps", "cmps", "test", "test", "stos", "stos", "lods", "lods", "scas", "scas",
  691. 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  692. //B "mov", "mov", "mov", "mov", "mov", "mov", "mov", "mov", "mov", "mov", "mov", "mov", "mov", "mov", "mov", "mov",
  693. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  694. //C "shlr", "shlr", "retn", "retn", "les", "lds", "mov", "mov", "enter","leave","retf", "retf", "int3", "int", "into", "iret",
  695. 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
  696. //D "shlr", "shlr", "shlr", "shlr", "aam", "aad", "", "xlat", "", "", "", "", "", "", "", "",
  697. 1, 1, 1, 1, 1, 1, 1, 0, 1, 2, 1, 1, 1, 1, 1, 1,
  698. // "loop", "loop", "loop", "jcxz", "in", "in", "out", "out", "call", "jmp", "jmp", "jmp", "in", "in", "out", "out",
  699. 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0,
  700. // "lock", "", "repne", "repe", "hlt", "cmc", "unry", "unry", "clc", "stc", "cli", "sti", "cld", "std", "dinc", "dinc",
  701. 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
  702. };
  703. //-----------------------------------------------------------------------------
  704. // Purpose: parse a modrm byte, determine size of data
  705. // http://www.intel.com/design/processor/manuals/253666.pdf sections 2.1.3 to 2.1.5
  706. //-----------------------------------------------------------------------------
  707. bool BParseModRMByte( uint8 bOpcode, int w, uint8 *pubCode, OPCODE_t *pOpcode )
  708. {
  709. // 2nd byte is a modrm byte
  710. int mod = (pubCode[0] >> 6) & 0x03;
  711. int other = (pubCode[0] >> 3 ) & 0x07;
  712. int rm = (pubCode[0]) & 0x07;
  713. if ( w == MF )
  714. {
  715. // the "other" bits define the opcode - we need a full table here
  716. // currently bOpcode == F6/F7 and other == 0 is the only thing we care about
  717. // because its the only thing we extra immediate data
  718. // http://www.intel.com/design/processor/manuals/253667.pdf table A-6
  719. // opcode extensions by group number
  720. if ( bOpcode == 0xF6 && other == 0 )
  721. {
  722. pOpcode->cubOpcode += 1;
  723. }
  724. else if ( bOpcode == 0xF7 && other == 0 )
  725. {
  726. pOpcode->cubOpcode += 4;
  727. }
  728. }
  729. if ( mod == 0x03 )
  730. {
  731. return true;
  732. }
  733. if ( rm == 0x04 )
  734. {
  735. // There is a SIB byte following
  736. pOpcode->cubOpcode += 1;
  737. int sib = pubCode[1];
  738. // if the bottom 3 bits of the SIB = 5
  739. // then there is an additional displacement
  740. // which depends on the mod for its size
  741. if ( ( sib & 0x07 ) == 0x05 )
  742. {
  743. if ( mod == 0x01 )
  744. {
  745. pOpcode->cubOpcode += 1;
  746. pOpcode->cubImmed += 1;
  747. }
  748. else if ( mod == 0x10 || mod == 0x00 )
  749. {
  750. pOpcode->cubOpcode += 4;
  751. pOpcode->cubImmed += 4;
  752. }
  753. // bail out ?
  754. return true;
  755. }
  756. }
  757. if ( mod == 0x02 )
  758. {
  759. pOpcode->cubOpcode += 4;
  760. pOpcode->cubImmed = 4;
  761. }
  762. else if ( mod == 0x01 )
  763. {
  764. pOpcode->cubOpcode += 1;
  765. }
  766. else if ( mod == 0 && rm == 0x05 )
  767. {
  768. pOpcode->cubOpcode += 4;
  769. pOpcode->cubImmed = 4;
  770. }
  771. return true;
  772. }
  773. //-----------------------------------------------------------------------------
  774. // Purpose: parse an instruction
  775. // cub = total size of instruction and data and displacements
  776. // bRelative = relative jump?
  777. // uJumpDestination = jump offset if jump
  778. // cubLeft = fail if try to disassemble more bytes than are left
  779. //-----------------------------------------------------------------------------
  780. bool BParseCode( int w, uint8 *pubCode, OPCODE_t *pOpcode, int cubLeft )
  781. {
  782. // how much immediate data is there?
  783. pOpcode->cubImmed = w & 0x0f;
  784. if ( w == opcOPERANDSIZEOVERRIDE )
  785. {
  786. pOpcode->cubOpcode++;
  787. if ( pOpcode->cubOpcode > cubLeft )
  788. return false;
  789. pubCode++;
  790. pOpcode->bOpcode = pubCode[0];
  791. w = rgOpData[ pubCode[0] ];
  792. pOpcode->cubImmed = ( w & 0x0f );
  793. // override dword to word
  794. // leave byte alone
  795. if ( pOpcode->cubImmed == 4 )
  796. pOpcode->cubImmed = 2;
  797. }
  798. if ( w == MQ )
  799. {
  800. pOpcode->cubOpcode++;
  801. if ( pOpcode->cubOpcode > cubLeft )
  802. return false;
  803. // we only understand rep/ne
  804. switch ( pubCode[1] )
  805. {
  806. case 0xA6:
  807. case 0xA7:
  808. case 0xAA:
  809. case 0xAB:
  810. case 0xAD:
  811. case 0xAE:
  812. case 0xAF:
  813. return true;
  814. }
  815. return false;
  816. }
  817. if ( w == MP )
  818. {
  819. // skip meaningless prefix
  820. pOpcode->cubOpcode++;
  821. if ( pOpcode->cubOpcode > cubLeft )
  822. return false;
  823. pubCode++;
  824. pOpcode->bOpcode = pubCode[0];
  825. w = rgOpData[ pubCode[0] ];
  826. pOpcode->cubImmed = ( w & 0x0f );
  827. }
  828. pOpcode->cubOpcode += pOpcode->cubImmed;
  829. if ( pOpcode->cubOpcode > cubLeft )
  830. return false;
  831. pOpcode->bRelative = ( w & opcRELATIVEJUMP ) ? true : false;
  832. pOpcode->bCantContinue = false;
  833. if ( w & opcRETURN || w & opcUNCONDITIONALJUMP )
  834. pOpcode->bCantContinue = true;
  835. pOpcode->bURJ = w == uR1;
  836. pOpcode->uJump = 0;
  837. pOpcode->bJumpOrCall = ( w & 0x200 ) ? true : false;
  838. if ( w < 0x10 )
  839. {
  840. return true;
  841. }
  842. else if ( w & opcMODRMBYTE )
  843. {
  844. // modrm byte
  845. pOpcode->cubOpcode ++;
  846. if ( pOpcode->cubOpcode > cubLeft )
  847. return false;
  848. pOpcode->bModRM = true;
  849. if (! BParseModRMByte( pubCode[0], w, &pubCode[1], pOpcode ) )
  850. return false;
  851. if ( pOpcode->cubOpcode > cubLeft )
  852. return false;
  853. }
  854. if ( w == XX )
  855. {
  856. pOpcode->cubOpcode ++;
  857. if ( pOpcode->cubOpcode > cubLeft )
  858. return false;
  859. w = rgOpData2[ pubCode[1] ];
  860. return BParseCode( w, &pubCode[1], pOpcode, cubLeft );
  861. }
  862. else if ( w == XC )
  863. {
  864. // coprocessor instruction
  865. pOpcode->cubOpcode ++;
  866. if ( pOpcode->cubOpcode > cubLeft )
  867. return false;
  868. uint8 b = pubCode[1];
  869. if ( b <= 0xBF )
  870. {
  871. // if < BF then its a regular modrm byte ( I think )
  872. // size overrides?
  873. pOpcode->bModRM = true;
  874. if (! BParseModRMByte( pubCode[0], w, &pubCode[1], pOpcode ) )
  875. return false;
  876. if ( pOpcode->cubOpcode > cubLeft )
  877. return false;
  878. }
  879. }
  880. else if ( w == UU || w == XC )
  881. {
  882. return false;
  883. }
  884. if ( pOpcode->cubImmed )
  885. {
  886. int iubImmed = pOpcode->cubOpcode - pOpcode->cubImmed;
  887. pOpcode->uImmed = 0;
  888. if ( pOpcode->cubImmed == 4 )
  889. pOpcode->uImmed = *(DWORD *)(&pubCode[iubImmed]);
  890. else if ( pOpcode->cubImmed == 2 )
  891. pOpcode->uImmed = *(WORD *)(&pubCode[iubImmed]);
  892. else if ( pOpcode->cubImmed == 1 )
  893. pOpcode->uImmed = pubCode[iubImmed];
  894. // if its a jump or call and there is no modrm byte
  895. // we know where its going
  896. // if there is a modrm/sib then it could be
  897. // jmp dword ptr [edx*4+1006982ch] or something
  898. // and we cant eval that
  899. if ( pOpcode->bJumpOrCall && !pOpcode->bModRM )
  900. pOpcode->uJump = pOpcode->uImmed;
  901. }
  902. return true;
  903. }
  904. //-----------------------------------------------------------------------------
  905. // Purpose: disassemble one instruction
  906. // returns false if not understood or we run out of bytes in cubLeft
  907. // pubCode - code to disasm
  908. // pOpcode - return info here
  909. // cubLeft - max bytes to look at
  910. //-----------------------------------------------------------------------------
  911. bool ParseCode( uint8 *pubCode, OPCODE_t *pOpcode, int cubLeft )
  912. {
  913. int w = rgOpData[ pubCode[0] ];
  914. pOpcode->bOpcode = pubCode[0];
  915. pOpcode->bRelative = false;
  916. pOpcode->bCantContinue = false;
  917. pOpcode->bModRM = false;
  918. pOpcode->bJumpOrCall = false;
  919. pOpcode->bURJ = false;
  920. pOpcode->cubImmed = 1;
  921. pOpcode->cubOpcode = 1;
  922. pOpcode->uJump = 0;
  923. pOpcode->uImmed = 0;
  924. return BParseCode( w, pubCode, pOpcode, cubLeft );
  925. }
  926. uint32 ComputeJumpAddress( OPCODE_t *pOpcode, uint32 uVACurrent )
  927. {
  928. if ( pOpcode->bRelative && pOpcode->uJump )
  929. {
  930. switch ( pOpcode->cubImmed )
  931. {
  932. case 1:
  933. {
  934. char bOffset = pOpcode->uJump;
  935. uVACurrent += bOffset;
  936. }
  937. break;
  938. case 2:
  939. {
  940. short wOffset = pOpcode->uJump;
  941. uVACurrent += wOffset;
  942. }
  943. break;
  944. case 4:
  945. {
  946. int nOffset = pOpcode->uJump;
  947. uVACurrent += nOffset;
  948. }
  949. break;
  950. }
  951. pOpcode->uJump = uVACurrent + pOpcode->cubOpcode;
  952. }
  953. return pOpcode->uJump;
  954. }
  955. #ifdef OPCODE_NAMES
  956. bool OpcodeText( OPCODE_t *pOpcode, char *rgchText )
  957. {
  958. strncpy( rgchText, rgOpcodeNames[pOpcode->bOpcode], 32 );
  959. return true;
  960. }
  961. #endif
  962. bool LikelyValid( OPCODE_t *pOpcode )
  963. {
  964. return rgOpcodeValid[pOpcode->bOpcode] >= 1;
  965. }
  966. bool LikelyNewValid( OPCODE_t *pOpcode )
  967. {
  968. return rgOpcodeValid[pOpcode->bOpcode] == 2;
  969. }
  970. //-----------------------------------------------------------------------------
  971. // Purpose: disassemble - return how many bytes we understood
  972. //-----------------------------------------------------------------------------
  973. int Disassemble( unsigned char *pubStart, int cub )
  974. {
  975. unsigned char *pub = pubStart;
  976. int cubLeft = cub;
  977. int cubUnderstood = 0;
  978. OPCODE_t opcode;
  979. while ( cubLeft > 0 && ParseCode( pub, &opcode, cubLeft ) )
  980. {
  981. pub += opcode.cubOpcode;
  982. cubLeft -= opcode.cubOpcode;
  983. cubUnderstood += opcode.cubOpcode;
  984. }
  985. return cubUnderstood;
  986. }
  987. //-----------------------------------------------------------------------------
  988. // Purpose: disassemble - return how many bytes we understood
  989. //-----------------------------------------------------------------------------
  990. int DisassembleSingleFunction( unsigned char *pubStart, int cub )
  991. {
  992. unsigned char *pub = pubStart;
  993. int cubLeft = cub;
  994. int cubUnderstood = 0;
  995. OPCODE_t opcode;
  996. while ( cubLeft > 0 && ParseCode( pub, &opcode, cubLeft ) )
  997. {
  998. pub += opcode.cubOpcode;
  999. cubLeft -= opcode.cubOpcode;
  1000. cubUnderstood += opcode.cubOpcode;
  1001. if ( opcode.bCantContinue )
  1002. return cubUnderstood;
  1003. }
  1004. return cubUnderstood;
  1005. }
  1006. //-----------------------------------------------------------------------------
  1007. // Purpose: disassemble cubMin bytes
  1008. //-----------------------------------------------------------------------------
  1009. int CubDisasm( uint8 *pub, int cubLeft, int cubMin )
  1010. {
  1011. int cubUnderstood = Disassemble( pub, cubLeft );
  1012. if ( cubUnderstood < cubMin )
  1013. return 0;
  1014. return cubUnderstood;
  1015. }
  1016. #ifdef VACTOOL
  1017. //#define DASMTEST
  1018. #endif
  1019. #ifdef DASMTEST
  1020. #include <stdio.h>
  1021. #include "vstdlib/strtools.h"
  1022. char *PchNextItem( char *pchStart, char *pchCopy )
  1023. {
  1024. *pchCopy = 0;
  1025. while ( *pchStart == ' ' || *pchStart == '\t' )
  1026. {
  1027. pchStart++;
  1028. }
  1029. if ( *pchStart == 0 || *pchStart == '\n' )
  1030. return NULL;
  1031. while ( !( *pchStart == ' ' || *pchStart == '\t' || *pchStart == 0 || *pchStart == '\n' ) )
  1032. {
  1033. *pchCopy++ = *pchStart++;
  1034. }
  1035. *pchCopy = 0;
  1036. return pchStart;
  1037. }
  1038. int ReadDisasmTextFile( const char *pszFileName )
  1039. {
  1040. FILE *pFile = fopen( pszFileName, "rt" );
  1041. if ( !pFile )
  1042. {
  1043. printf( "Failed to open file %s", pszFileName );
  1044. return 0;
  1045. }
  1046. char rgchLine[ 1024 ];
  1047. char rgchLine2[ 1024 ];
  1048. char rgchLine3[ 1024 ];
  1049. bool bNewInsLast = false;
  1050. unsigned char rgubCode[32];
  1051. int cubCode = 0;
  1052. int nLine = 0;
  1053. while ( fgets( rgchLine, sizeof(rgchLine), pFile ) )
  1054. {
  1055. nLine++;
  1056. // read data, format: ID, type, class, name, hash
  1057. // eg "1912","1","3","OGZ.dll","4ea1f025d3e5744f656e1822d72ea445"
  1058. char *pchPos = rgchLine;
  1059. char *pchColon = strstr( pchPos, ":" );
  1060. bool bNewIns = pchColon != NULL;
  1061. if ( bNewIns )
  1062. {
  1063. // this line has a colon - its a new opcode
  1064. // so disasm the last opcode
  1065. int cubUnderstood = CubDisasm( rgubCode, cubCode, cubCode );
  1066. if ( cubUnderstood != cubCode )
  1067. {
  1068. if ( bNewInsLast )
  1069. printf("Failed to disassemble %s \n", rgchLine2 );
  1070. else
  1071. printf("Failed to disassemble %s %s\n", rgchLine3, rgchLine2 );
  1072. //__asm int 3;
  1073. }
  1074. cubCode = 0;
  1075. pchPos = pchColon + 1;
  1076. }
  1077. char rgchCopy[16];
  1078. rgchCopy[0] = '0';
  1079. rgchCopy[1] = 'x';
  1080. int ich = 0;
  1081. while ( ich < 31 && pchPos )
  1082. {
  1083. pchPos = PchNextItem( pchPos, rgchCopy+2 );
  1084. if ( !pchPos && pchColon )
  1085. {
  1086. cubCode = 0;
  1087. break;
  1088. }
  1089. if ( !pchPos || rgchCopy[2] == 0 )
  1090. break;
  1091. ich = pchPos - rgchLine;
  1092. if ( ich > 31 )
  1093. break;
  1094. rgubCode[cubCode] = V_atoi( rgchCopy );
  1095. // ignore runs of CC - the file format doesnt make sense
  1096. if ( cubCode == 0 && rgubCode[cubCode] == 0xCC )
  1097. break;
  1098. cubCode++;
  1099. }
  1100. bNewInsLast = bNewIns;
  1101. memcpy( rgchLine3, rgchLine2, sizeof( rgchLine ) );
  1102. memcpy( rgchLine2, rgchLine, sizeof( rgchLine ) );
  1103. }
  1104. fclose( pFile );
  1105. return 1;
  1106. }
  1107. void TestDisassemble()
  1108. {
  1109. //ReadDisasmTextFile( "\\schemacompiler.txt" );
  1110. ReadDisasmTextFile( "\\serverdisasm.txt" );
  1111. unsigned char *pubStartCode;
  1112. int cubCode = 0;
  1113. __asm mov eax, overcode
  1114. __asm sub eax, startcode
  1115. __asm mov cubCode, eax
  1116. __asm mov eax, startcode
  1117. __asm mov pubStartCode,eax
  1118. __asm jmp overcode
  1119. startcode:
  1120. __asm jmp dword ptr [edx*4+1006982Ch]
  1121. __asm jmp eax
  1122. __asm _emit 0x55
  1123. __asm _emit 0x8b
  1124. __asm _emit 0xec
  1125. __asm _emit 0x90
  1126. __asm _emit 0x5d
  1127. __asm _emit 0xe9
  1128. __asm _emit 0x16
  1129. __asm _emit 0x4d
  1130. __asm _emit 0xdd
  1131. __asm _emit 0xb9
  1132. __asm _emit 0x90
  1133. __asm _emit 0x90
  1134. __asm _emit 0x90
  1135. __asm _emit 0x90
  1136. __asm _emit 0x90
  1137. overcode:
  1138. Disassemble( pubStartCode, cubCode );
  1139. }
  1140. #endif
  1141. #endif // _WIN32