Create main.py

This commit is contained in:
Sam Sneed 2024-07-27 15:16:22 -05:00 committed by GitHub
parent 23375cf005
commit 7947fde413
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

177
main.py Normal file
View file

@ -0,0 +1,177 @@
from capstone import *
from keystone import *
import argparse
# Disassemble x86_64 binary
def disassemble_x86_64(binary_path):
with open(binary_path, 'rb') as f:
code = f.read()
md = Cs(CS_ARCH_X86, CS_MODE_64)
instructions = list(md.disasm(code, 0x1000))
return instructions
# Translate x86_64 instructions to ARM64
def translate_instructions(x86_instructions):
translated_instructions = []
for ins in x86_instructions:
arm64_instruction = translate_x86_to_arm64(ins)
translated_instructions.extend(arm64_instruction)
return translated_instructions
# Assemble ARM64 instructions into binary
def assemble_arm64(instructions, output_path):
ks = Ks(KS_ARCH_ARM64, KS_MODE_ARM)
encoding, count = ks.asm('\n'.join(instructions))
with open(output_path, 'wb') as f:
f.write(bytearray(encoding))
# Extended translation logic for x86_64 to ARM64
def translate_x86_to_arm64(x86_ins):
reg_mapping = {
'rax': 'x0', 'rbx': 'x1', 'rcx': 'x2', 'rdx': 'x3',
'rsi': 'x4', 'rdi': 'x5', 'rbp': 'x6', 'rsp': 'x7',
'r8': 'x8', 'r9': 'x9', 'r10': 'x10', 'r11': 'x11',
'r12': 'x12', 'r13': 'x13', 'r14': 'x14', 'r15': 'x15',
'r16': 'x16', 'r17': 'x17', 'r18': 'x18', 'r19': 'x19',
'r20': 'x20', 'r21': 'x21', 'r22': 'x22', 'r23': 'x23',
'r24': 'x24', 'r25': 'x25', 'r26': 'x26', 'r27': 'x27',
'r28': 'x28', 'r29': 'x29', 'r30': 'x30'
}
arm64_instructions = []
def generate_arm64_instruction(opcode, operands):
return f"{opcode} {' ,'.join(operands)}"
def handle_immediate(operand):
if operand.startswith('0x'):
return f'#{operand}'
return operand
def parse_operands(op_str):
return [op.strip() for op in op_str.split(',')]
if x86_ins.mnemonic == 'mov':
operands = parse_operands(x86_ins.op_str)
if operands[0] in reg_mapping and operands[1] in reg_mapping:
arm64_instructions.append(generate_arm64_instruction('mov', [reg_mapping[operands[0]], reg_mapping[operands[1]]]))
elif operands[1].startswith('0x'):
arm64_instructions.append(generate_arm64_instruction('mov', [reg_mapping[operands[0]], handle_immediate(operands[1])]))
elif x86_ins.mnemonic == 'add':
operands = parse_operands(x86_ins.op_str)
if len(operands) == 2 and operands[0] in reg_mapping and operands[1] in reg_mapping:
arm64_instructions.append(generate_arm64_instruction('add', [reg_mapping[operands[0]], reg_mapping[operands[0]], reg_mapping[operands[1]]]))
elif len(operands) == 3 and operands[0] in reg_mapping and operands[1] in reg_mapping and operands[2] in reg_mapping:
arm64_instructions.append(generate_arm64_instruction('add', [reg_mapping[operands[0]], reg_mapping[operands[1]], reg_mapping[operands[2]]]))
elif x86_ins.mnemonic == 'sub':
operands = parse_operands(x86_ins.op_str)
if len(operands) == 2 and operands[0] in reg_mapping and operands[1] in reg_mapping:
arm64_instructions.append(generate_arm64_instruction('sub', [reg_mapping[operands[0]], reg_mapping[reg_mapping[operands[1]]], handle_immediate('0')]))
elif len(operands) == 3 and operands[0] in reg_mapping and operands[1] in reg_mapping and operands[2] in reg_mapping:
arm64_instructions.append(generate_arm64_instruction('sub', [reg_mapping[operands[0]], reg_mapping[operands[1]], reg_mapping[operands[2]]]))
elif x86_ins.mnemonic == 'mul':
operands = parse_operands(x86_ins.op_str)
if len(operands) == 2 and operands[0] in reg_mapping and operands[1] in reg_mapping:
arm64_instructions.append(generate_arm64_instruction('mul', [reg_mapping[operands[0]], reg_mapping[operands[1]]]))
elif x86_ins.mnemonic == 'div':
operands = parse_operands(x86_ins.op_str)
if len(operands) == 2 and operands[0] in reg_mapping and operands[1] in reg_mapping:
arm64_instructions.append(generate_arm64_instruction('udiv', [reg_mapping[operands[0]], reg_mapping[operands[1]]]))
elif x86_ins.mnemonic == 'nop':
arm64_instructions.append('nop')
elif x86_ins.mnemonic == 'cmp':
operands = parse_operands(x86_ins.op_str)
if len(operands) == 2 and operands[0] in reg_mapping and operands[1] in reg_mapping:
arm64_instructions.append(generate_arm64_instruction('cmp', [reg_mapping[operands[0]], reg_mapping[operands[1]]]))
elif x86_ins.mnemonic == 'jmp':
arm64_instructions.append(f'b {x86_ins.op_str}')
elif x86_ins.mnemonic == 'call':
arm64_instructions.append(f'bl {x86_ins.op_str}')
elif x86_ins.mnemonic == 'ret':
arm64_instructions.append('ret')
elif x86_ins.mnemonic == 'push':
operands = parse_operands(x86_ins.op_str)
if operands[0] in reg_mapping:
arm64_instructions.append(f'stmd sp!, {{{reg_mapping[operands[0]]}}}')
elif x86_ins.mnemonic == 'pop':
operands = parse_operands(x86_ins.op_str)
if operands[0] in reg_mapping:
arm64_instructions.append(f'ldmd sp!, {{{reg_mapping[operands[0]]}}}')
elif x86_ins.mnemonic == 'and':
operands = parse_operands(x86_ins.op_str)
if len(operands) == 3 and operands[0] in reg_mapping and operands[1] in reg_mapping:
arm64_instructions.append(generate_arm64_instruction('and', [reg_mapping[operands[0]], reg_mapping[operands[1]], handle_immediate(operands[2])]))
elif x86_ins.mnemonic == 'or':
operands = parse_operands(x86_ins.op_str)
if len(operands) == 3 and operands[0] in reg_mapping and operands[1] in reg_mapping:
arm64_instructions.append(generate_arm64_instruction('orr', [reg_mapping[operands[0]], reg_mapping[operands[1]], handle_immediate(operands[2])]))
elif x86_ins.mnemonic == 'xor':
operands = parse_operands(x86_ins.op_str)
if len(operands) == 3 and operands[0] in reg_mapping and operands[1] in reg_mapping:
arm64_instructions.append(generate_arm64_instruction('eor', [reg_mapping[operands[0]], reg_mapping[operands[1]], handle_immediate(operands[2])]))
elif x86_ins.mnemonic == 'shl':
operands = parse_operands(x86_ins.op_str)
if len(operands) == 2 and operands[0] in reg_mapping and operands[1] in reg_mapping:
arm64_instructions.append(generate_arm64_instruction('lsl', [reg_mapping[operands[0]], reg_mapping[operands[1]], handle_immediate('1')]))
elif x86_ins.mnemonic == 'shr':
operands = parse_operands(x86_ins.op_str)
if len(operands) == 2 and operands[0] in reg_mapping and operands[1] in reg_mapping:
arm64_instructions.append(generate_arm64_instruction('lsr', [reg_mapping[operands[0]], reg_mapping[operands[1]], handle_immediate('1')]))
elif x86_ins.mnemonic == 'sar':
operands = parse_operands(x86_ins.op_str)
if len(operands) == 2 and operands[0] in reg_mapping and operands[1] in reg_mapping:
arm64_instructions.append(generate_arm64_instruction('asr', [reg_mapping[operands[0]], reg_mapping[operands[1]], handle_immediate('1')]))
elif x86_ins.mnemonic == 'test':
operands = parse_operands(x86_ins.op_str)
if len(operands) == 2 and operands[0] in reg_mapping and operands[1] in reg_mapping:
arm64_instructions.append(generate_arm64_instruction('tst', [reg_mapping[operands[0]], reg_mapping[operands[1]]]))
elif x86_ins.mnemonic == 'setcc':
# Assuming setcc instruction sets flags based on the condition, might be translated to conditional branches
arm64_instructions.append(f'ccmp {x86_ins.op_str}')
elif x86_ins.mnemonic == 'cmovcc':
# Conditional move based on flags, may need conditional branch handling
arm64_instructions.append(f'csel {x86_ins.op_str}')
return arm64_instructions
def main():
parser = argparse.ArgumentParser(description='Translate x86_64 binary to ARM64 binary')
parser.add_argument('-i', '--input', required=True, help='Path to the input x86_64 binary file')
parser.add_argument('-o', '--output', required=True, help='Path to the output ARM64 binary file')
args = parser.parse_args()
x86_binary_path = args.input
arm64_binary_path = args.output
# Disassemble x86_64 binary
x86_instructions = disassemble_x86_64(x86_binary_path)
# Translate x86_64 instructions to ARM64
arm64_instructions = translate_instructions(x86_instructions)
# Assemble ARM64 instructions into new binary
assemble_arm64(arm64_instructions, arm64_binary_path)
print("Translation complete. ARM64 binary created at", arm64_binary_path)
if __name__ == "__main__":
main()