Skip to content

Instantly share code, notes, and snippets.

@Haraguroicha
Last active June 4, 2019 06:35
Show Gist options
  • Save Haraguroicha/522a89839de4c54a1618638f574f413e to your computer and use it in GitHub Desktop.
Save Haraguroicha/522a89839de4c54a1618638f574f413e to your computer and use it in GitHub Desktop.
var list64 = ['rax', 'rcx', 'rdx', 'rbx', 'rsp', 'rbp', 'rsi', 'rdi']
var list32 = ['eax', 'ecx', 'edx', 'ebx', 'esp', 'ebp', 'esi', 'edi']
var list16 = ['ax', 'cx', 'dx', 'bx', 'sp', 'bp', 'si', 'di']
var list8 = ['al', 'cl', 'dl', 'bl', 'spl', 'bpl', 'sil', 'dil']
// function for extend op code list from one to manys
function extend_op(o) {
var new_op_codes = []
// only extend when `extend_set` not null
if (o.extend_set != null) {
for (var i in o.extend_set) {
var op_code = o.extend_set[i]
// clone object, can replace by lodash
var op = Object.assign({}, o) // clone
op.op_list = Object.assign([], o.op_list) // array need clone again
op.op_list[op.extend_loc] -= 0 - i // prevent to use operator `+=` for misappend as string
op.log = op.log.replace(/%reg/, op_code) // replace log `%reg` to correct register
new_op_codes.push(op) // append extended op_list
}
} else {
new_op_codes = [ o ]
}
return new_op_codes
}
// convert bytes to chars
function btoc(b) {
return b.map(b=>String.fromCharCode(b)).join('')
}
// convert chars to bytes
function ctob(c) {
return Array.from(c).map(c=>c.charCodeAt(0))
}
// format char as hex format string
function hexString(c) {
return hex(c.charCodeAt(0))
}
// format byte as hex format string
function hex(b) {
return '0x' + (b < 0x10 ? '0' + b.toString(0x10) : b.toString(0x10))
}
var op_code = [
{op_list:[0x50], extend_set: list64, extend_loc: 0, log: 'push %reg', comment: 'push r64', handler: 'push_single_main64', data_bytes: 0},
{op_list:[0x58], extend_set: list64, extend_loc: 0, log: 'pop %reg', comment: 'pop r64', handler: 'pop_single_main64', data_bytes: 0},
{op_list:[0xb0], extend_set: list8, extend_loc: 0, log: 'mov %reg, %value', comment: 'mov r8, const8', handler: 'mov_single_main8', data_bytes: 1},
{op_list:[0x66,0xb8], extend_set: list16, extend_loc: 1, log: 'mov %reg, %value', comment: 'mov r16, const16', handler: 'mov_single_main16', data_bytes: 2},
{op_list:[0x66,0xc7,0xc0], extend_set: list16, extend_loc: 2, log: 'mov %reg, %value', comment: 'mov r16, const16', handler: 'mov_single_main16', data_bytes: 2},
{op_list:[0xb8], extend_set: list32, extend_loc: 0, log: 'mov %reg, %value', comment: 'mov r32, const32', handler: 'mov_single_main32', data_bytes: 4},
{op_list:[0xc7,0xc0], extend_set: list32, extend_loc: 1, log: 'mov %reg, %value', comment: 'mov r32, const32', handler: 'mov_single_main32', data_bytes: 4},
{op_list:[0x48,0xc7,0xc0], extend_set: list64, extend_loc: 2, log: 'mov %reg, %value', comment: 'mov r64, const32', handler: 'mov_single_main64', data_bytes: 4},
{op_list:[0x48,0xb8], extend_set: list64, extend_loc: 1, log: 'mov %reg, %value', comment: 'movabs r64, const64', handler: 'mov_single_main64', data_bytes: 8},
{op_list:[0x90], extend_set: null, extend_loc: null, log: 'nop', comment: 'nop', handler: 'nop', data_bytes: 0},
{op_list:[0x0f,0x05], extend_set: null, extend_loc: null, log: 'syscall', comment: 'syscall', handler: 'syscall', data_bytes: 0},
] // original op_code list
.map(extend_op) // extend the op_code list
.flat() // then flatten them
// parse code to binary op code
function parse_code(code) {
var bin = [] // op bin array
var bin_pos = -1 // for record last position
while (code.length > 0) { // until `code` buffer empty
if (bin.length == bin_pos) {
// after once run and length of bin and last pos was same, means there can't continue,
// to prevent infinity loop, we print error message and break the loop.
console.error("Can't continue, op_code all not match")
break
} else {
bin_pos = bin.length
}
for (var op of op_code) {
// convert to string to compare is easier then array compare, but also can use lodash of `_.isEqual()`
if (btoc(op.op_list) == code.substr(0, op.op_list.length)) {
code = code.slice(op.op_list.length) // slice out the op_code byte(s)
if (op.data_bytes > 0) { // only process when `data_bytes` greater then zero
if (code.length < op.data_bytes) { // check the left bytes is safe to process
console.warn("op_code %s need %d bytes, but left %d", op.handler, op.data_bytes, code.length)
}
op.data = [].concat(ctob(code.substr(0, op.data_bytes))) // slice the data to store
code = code.slice(op.data.length) // slice out the data from buffer
}
bin.push(op) // push matched op to bin array
}
}
}
console.log("Parsed code\n===\n%s\n===\nUnparsed bytes: (%d) [ %s ]", bin.map(b => b.log.replace(/%value/, (b.data || []).map(hex).join(', ')) + '\n\tcomment: ' + b.comment).join('\n'), code.length, Array.from(code).map(hexString).join(', '))
return bin
}
var code = "\x90\x55\x90\x59\x90\x0f\x05\xb0\x01\xbf\x02\x00\x00\x00\x0f\x05"
parse_code(code)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment