Задача: Утилиты
Исходник: Дизассемблер длин инструкций (x86), язык: C++ [code #579, hits: 7421]
автор: - [добавлен: 25.01.2009]
  1. #define C_66 0x00000001 // 66-prefix
  2. #define C_67 0x00000002 // 67-prefix
  3. #define C_LOCK 0x00000004 // lock
  4. #define C_REP 0x00000008 // repz/repnz
  5. #define C_SEG 0x00000010 // seg-prefix
  6. #define C_OPCODE2 0x00000020 // 2nd opcode present (1st == 0F)
  7. #define C_MODRM 0x00000040 // modrm present
  8. #define C_SIB 0x00000080 // sib present
  9.  
  10. #define C_ANYPREFIX (C_66 | C_67 | C_LOCK | C_REP | C_SEG)
  11.  
  12. bool
  13. GetInstructionSize (
  14.  
  15. PBYTE pOpCode,
  16. PDWORD pdwInstructionSize)
  17.  
  18. {
  19. PBYTE opcode = pOpCode;
  20. DWORD i = 0;
  21.  
  22. BYTE disasm_seg = 0; // CS DS ES SS FS GS
  23. BYTE disasm_rep = 0; // REPZ/REPNZ
  24. BYTE disasm_opcode = 0; // opcode
  25. BYTE disasm_opcode2 = 0; // used when opcode == 0F
  26. BYTE disasm_modrm = 0; // modxxxrm
  27. BYTE disasm_sib = 0; // scale-index-base
  28. BYTE disasm_mem [8] = {0}; // mem addr value
  29. BYTE disasm_data [8] = {0}; // data value
  30.  
  31. DWORD disasm_len = 0; // 0 if error
  32. DWORD disasm_flag = 0; // C_xxx
  33. DWORD disasm_memsize = 0; // value = disasm_mem
  34. DWORD disasm_datasize = 0; // value = disasm_data
  35. DWORD disasm_defdata = 4; // == C_66 ? 2 : 4
  36. DWORD disasm_defmem = 4; // == C_67 ? 2 : 4
  37.  
  38. BYTE mod = 0;
  39. BYTE rm = 0;
  40.  
  41. if (! pOpCode) return false;
  42. if (! pdwInstructionSize) return false;
  43.  
  44. RETRY:
  45.  
  46. disasm_opcode = *opcode ++;
  47.  
  48. switch (disasm_opcode)
  49. {
  50. case 0x00: case 0x01: case 0x02: case 0x03:
  51. case 0x08: case 0x09: case 0x0A: case 0x0B:
  52. case 0x10: case 0x11: case 0x12: case 0x13:
  53. case 0x18: case 0x19: case 0x1A: case 0x1B:
  54. case 0x20: case 0x21: case 0x22: case 0x23:
  55. case 0x28: case 0x29: case 0x2A: case 0x2B:
  56. case 0x30: case 0x31: case 0x32: case 0x33:
  57. case 0x38: case 0x39: case 0x3A: case 0x3B:
  58. case 0x62: case 0x63:
  59. case 0x84: case 0x85: case 0x86: case 0x87:
  60. case 0x88: case 0x89: case 0x8A: case 0x8B:
  61. case 0x8C: case 0x8D: case 0x8E: case 0x8F:
  62. case 0xC4: case 0xC5:
  63. case 0xD0: case 0xD1: case 0xD2: case 0xD3:
  64. case 0xD8: case 0xD9: case 0xDA: case 0xDB:
  65. case 0xDC: case 0xDD: case 0xDE: case 0xDF:
  66. case 0xFE: case 0xFF:
  67.  
  68. disasm_flag |= C_MODRM;
  69. break;
  70.  
  71. case 0xCD:
  72.  
  73. disasm_datasize += (*opcode == 0x20 ? 1 + 4 : 1);
  74. break;
  75.  
  76. case 0xF6:
  77. case 0xF7:
  78.  
  79. disasm_flag |= C_MODRM;
  80. if (*opcode & 0x38) break;
  81.  
  82. // continue if <test ..., xx>
  83.  
  84. case 0x04: case 0x05: case 0x0C: case 0x0D:
  85. case 0x14: case 0x15: case 0x1C: case 0x1D:
  86. case 0x24: case 0x25: case 0x2C: case 0x2D:
  87. case 0x34: case 0x35: case 0x3C: case 0x3D:
  88.  
  89. if (disasm_opcode & 1)
  90. {
  91. disasm_datasize += disasm_defdata;
  92. }
  93. else
  94. {
  95. disasm_datasize ++;
  96. }
  97.  
  98. break;
  99.  
  100. case 0x6A:
  101. case 0xA8:
  102. case 0xB0: case 0xB1: case 0xB2: case 0xB3:
  103. case 0xB4: case 0xB5: case 0xB6: case 0xB7:
  104. case 0xD4: case 0xD5:
  105. case 0xE4: case 0xE5: case 0xE6: case 0xE7:
  106. case 0x70: case 0x71: case 0x72: case 0x73:
  107. case 0x74: case 0x75: case 0x76: case 0x77:
  108. case 0x78: case 0x79: case 0x7A: case 0x7B:
  109. case 0x7C: case 0x7D: case 0x7E: case 0x7F:
  110. case 0xEB:
  111. case 0xE0: case 0xE1: case 0xE2: case 0xE3:
  112.  
  113. disasm_datasize ++;
  114. break;
  115.  
  116. case 0x26: case 0x2E: case 0x36: case 0x3E:
  117. case 0x64: case 0x65:
  118.  
  119. if (disasm_flag & C_SEG) return false;
  120.  
  121. disasm_flag |= C_SEG;
  122. disasm_seg = disasm_opcode;
  123.  
  124. goto RETRY;
  125.  
  126. case 0xF0:
  127.  
  128. if (disasm_flag & C_LOCK) return false;
  129.  
  130. disasm_flag |= C_LOCK;
  131.  
  132. goto RETRY;
  133.  
  134. case 0xF2: case 0xF3:
  135.  
  136. if (disasm_flag & C_REP) return false;
  137.  
  138. disasm_flag |= C_REP;
  139. disasm_rep = disasm_opcode;
  140.  
  141. goto RETRY;
  142.  
  143. case 0x66:
  144. if (disasm_flag & C_66) return false;
  145.  
  146. disasm_flag |= C_66;
  147. disasm_defdata = 2;
  148.  
  149. goto RETRY;
  150.  
  151. case 0x67:
  152.  
  153. if (disasm_flag & C_67) return false;
  154.  
  155. disasm_flag |= C_67;
  156. disasm_defmem = 2;
  157.  
  158. goto RETRY;
  159.  
  160. case 0x6B:
  161. case 0x80:
  162. case 0x82:
  163. case 0x83:
  164. case 0xC0:
  165. case 0xC1:
  166. case 0xC6:
  167.  
  168. disasm_datasize ++;
  169. disasm_flag |= C_MODRM;
  170.  
  171. break;
  172.  
  173. case 0x69:
  174. case 0x81:
  175. case 0xC7:
  176.  
  177. disasm_datasize += disasm_defdata;
  178. disasm_flag |= C_MODRM;
  179.  
  180. break;
  181.  
  182. case 0x9A:
  183. case 0xEA:
  184.  
  185. disasm_datasize += (2 + disasm_defdata);
  186. break;
  187.  
  188. case 0xA0:
  189. case 0xA1:
  190. case 0xA2:
  191. case 0xA3:
  192.  
  193. disasm_memsize += disasm_defmem;
  194. break;
  195.  
  196. case 0x68:
  197. case 0xA9:
  198. case 0xB8: case 0xB9: case 0xBA: case 0xBB:
  199. case 0xBC: case 0xBD: case 0xBE: case 0xBF:
  200. case 0xE8:
  201. case 0xE9:
  202.  
  203. disasm_datasize += disasm_defdata;
  204. break;
  205.  
  206. case 0xC2:
  207. case 0xCA:
  208.  
  209. disasm_datasize += 2;
  210. break;
  211.  
  212. case 0xC8:
  213.  
  214. disasm_datasize += 3;
  215. break;
  216.  
  217. case 0xF1:
  218.  
  219. return false;
  220.  
  221. case 0x0F:
  222.  
  223. disasm_flag |= C_OPCODE2;
  224. disasm_opcode2 = *opcode ++;
  225.  
  226. switch (disasm_opcode2)
  227. {
  228. case 0x00: case 0x01: case 0x02: case 0x03:
  229. case 0x90: case 0x91: case 0x92: case 0x93:
  230. case 0x94: case 0x95: case 0x96: case 0x97:
  231. case 0x98: case 0x99: case 0x9A: case 0x9B:
  232. case 0x9C: case 0x9D: case 0x9E: case 0x9F:
  233. case 0xA3:
  234. case 0xA5:
  235. case 0xAB:
  236. case 0xAD:
  237. case 0xAF:
  238. case 0xB0: case 0xB1: case 0xB2: case 0xB3:
  239. case 0xB4: case 0xB5: case 0xB6: case 0xB7:
  240. case 0xBB:
  241. case 0xBC: case 0xBD: case 0xBE: case 0xBF:
  242. case 0xC0:
  243. case 0xC1:
  244.  
  245. disasm_flag |= C_MODRM;
  246. break;
  247.  
  248. case 0x06:
  249. case 0x08: case 0x09: case 0x0A: case 0x0B:
  250. case 0xA0: case 0xA1: case 0xA2: case 0xA8:
  251. case 0xA9:
  252. case 0xAA:
  253. case 0xC8: case 0xC9: case 0xCA: case 0xCB:
  254. case 0xCC: case 0xCD: case 0xCE: case 0xCF:
  255.  
  256. break;
  257.  
  258. case 0x80: case 0x81: case 0x82: case 0x83:
  259. case 0x84: case 0x85: case 0x86: case 0x87:
  260. case 0x88: case 0x89: case 0x8A: case 0x8B:
  261. case 0x8C: case 0x8D: case 0x8E: case 0x8F:
  262.  
  263. disasm_datasize += disasm_defdata;
  264. break;
  265.  
  266. case 0xA4:
  267. case 0xAC:
  268. case 0xBA:
  269.  
  270. disasm_datasize ++;
  271. disasm_flag |= C_MODRM;
  272.  
  273. break;
  274.  
  275. default:
  276.  
  277. return false;
  278.  
  279. }
  280.  
  281. break;
  282.  
  283. }
  284.  
  285. if (disasm_flag & C_MODRM)
  286. {
  287. disasm_modrm = *opcode ++;
  288.  
  289. mod = disasm_modrm & 0xC0;
  290. rm = disasm_modrm & 0x07;
  291.  
  292. if (mod != 0xC0)
  293. {
  294. if (mod == 0x40) disasm_memsize ++;
  295. if (mod == 0x80) disasm_memsize += disasm_defmem;
  296.  
  297. if (disasm_defmem == 2) // modrm16
  298. {
  299. if ((mod == 0x00) && (rm == 0x06))
  300. {
  301. disasm_memsize += 2;
  302. }
  303. }
  304. else // modrm32
  305. {
  306. if (rm == 0x04)
  307. {
  308. disasm_flag |= C_SIB;
  309. disasm_sib = *opcode ++;
  310. rm = disasm_sib & 0x07;
  311. }
  312.  
  313. if ((rm == 0x05) && (mod == 0x00))
  314. {
  315. disasm_memsize += 4;
  316. }
  317. }
  318. }
  319. }
  320.  
  321. for (i = 0; i < disasm_memsize; i ++)
  322. {
  323. disasm_mem [i] = *opcode ++;
  324. }
  325.  
  326. for (i = 0; i < disasm_datasize; i ++)
  327. {
  328. disasm_data [i] = *opcode ++;
  329. }
  330.  
  331. disasm_len = (DWORD) (opcode - pOpCode);
  332. *pdwInstructionSize = disasm_len;
  333.  
  334. return true;
  335. }
  336.  
  337. // found at http://www.rsdn.ru/forum/message/3120789.1.aspx

+добавить реализацию