Elian posted a nice answer that explains the theory
here is an implementation using capstone and python
import sys
import capstone
print ( "dissecting a stram of hex pairs to its components in x86")
if(len(sys.argv) < 2):
sys.exit("usage python %s quoted_hex_pairs like %s" % ( sys.argv[0] ,
"\"F0 0D 15 F0 0D BA D0 12 50 0D\""))
CODE = []
a = sys.argv[1].split(' ')
for i in range(0,len(a),1):
CODE.append( chr(int(a[i],16)))
CODESTR = ''.join(CODE)
md = capstone.Cs(capstone.CS_ARCH_X86, capstone.CS_MODE_64)
md.detail = True
for i in md.disasm(CODESTR, 0x1000):
print "TLDR:"
for j in range( 0,len(i.opcode),1):
if(i.opcode[j] !=0):
print "%02x" % i.opcode[j],
print "\n"
print ( "FULL DETAILS" )
print ( "i.address", i.address ); print ( "i.mnemonic", i.mnemonic )
print ( "i.op_str" , i.op_str ); print ( "i.id" , i.id )
print ( "i.size" , i.size ); print ( "i.bytes" , i.bytes )
print ( "i.prefix" , i.prefix ); print ( "i.opcode" , i.opcode )
print ( "i.rex" , i.rex ); print ( "i.addr_size" , i.addr_size )
print ( "i.modrm" , i.modrm ); print ( "i.sib" , i.sib )
print ( "i.disp" , i.disp ); print ( "i.sib_index" , i.sib_index )
print ( "i.sib_scale" , i.sib_scale ); print ( "i.sib_base" , i.sib_base )
print ( "i.sse_cc" , i.sse_cc ); print ( "i.avx_cc" , i.avx_cc )
print ( "i.avx_sae" , i.avx_sae ); print ( "i.avx_rm" , i.avx_rm )
output
python capstest.py "44 0f 45 c8"
dissecting a stram of hex pairs to its components in x86
TLDR:
0f 45
FULL DETAILS
('i.address', 4096L)
('i.mnemonic', u'cmovne')
('i.op_str', u'r9d, eax')
('i.id', 83L)
('i.size', 4)
('i.bytes', bytearray(b'D\x0fE\xc8'))
('i.prefix', [0, 0, 0, 0])
('i.opcode', [15, 69, 0, 0])
('i.rex', 68)
('i.addr_size', 8)
('i.modrm', 200)
('i.sib', 0)
('i.disp', 0)
('i.sib_index', 0L)
('i.sib_scale', 0)
('i.sib_base', 0L)
('i.sse_cc', 0L)
('i.avx_cc', 0L)
('i.avx_sae', False)
('i.avx_rm', 0L)