Last active
June 4, 2019 06:35
-
-
Save Haraguroicha/522a89839de4c54a1618638f574f413e to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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