Yes, of course! But if that's all you want, just copy the few lines of code. In fact, I blogged the creation of the tool and all of the code snippets I used:
import itertools
import binascii
import keystone
import capstone
def remove_whitespace(s: str) -> str:
return "".join(s.split())
def wraptext(s: str, size: int) -> list[str]:
# Thanks to https://stackoverflow.com/questions/9475241/split-string-every-nth-character
return [s[i:i + size] for i in range(0, len(s), size)]
def getbytes(hexstring: str) -> list[str]:
"""
Splits a hex string into a list of bytes. Convenient function because it accounts for both
whitespace-separated and un-separated hex strings.
"""
hexstring = remove_whitespace(hexstring)
assert len(hexstring) % 2 == 0, "Invalid hex string (odd length)"
return wraptext(hexstring, 2)
def make_ks(architecture: str) -> keystone.Ks:
if architecture == "32bit":
return keystone.Ks(keystone.KS_ARCH_ARM, keystone.KS_MODE_ARM)
elif architecture == "64bit":
return keystone.Ks(keystone.KS_ARCH_ARM64, keystone.KS_MODE_LITTLE_ENDIAN)
else:
raise ValueError(f"Unrecognized architecture: {architecture}. Only '32bit' and '64bit' are valid strings")
def make_cs(architecture: str) -> capstone.Cs:
if architecture == "32bit":
return capstone.Cs(capstone.CS_ARCH_ARM, capstone.CS_MODE_ARM)
elif architecture == "64bit":
return capstone.Cs(capstone.CS_ARCH_ARM64, capstone.CS_MODE_LITTLE_ENDIAN)
else:
raise ValueError(f"Unrecognized architecture: {architecture}. Only '32bit' and '64bit' are valid strings")
def armtohex(instruction: str, architecture: str) -> str:
ks = make_ks(architecture)
convertedhexlist = []
convertedinstruction = ks.asm(instruction, as_bytes=True)[0]
return binascii.hexlify(convertedinstruction).decode().upper()
def hextoarm(hexinstruction: str, architecture: str) -> list[str]:
cs = make_cs(architecture)
return next(cs.disasm_lite(bytearray.fromhex(hexinstruction), 0x0))[2:]
def generateaobfromarm(armcode: str, architecture: str) -> str:
# Convert string of code to list of instructions
instructions = list(itertools.chain(*[split1.split(";") for split1 in armcode.split("\n")]))
unknownhex = "??" * 4
hexlist = []
for instruction in instructions:
if instruction == "" or instruction.isspace():
continue
if "0x" in instruction or "#" in instruction:
hexlist.append(unknownhex)
else:
hexlist.append(armtohex(instruction, architecture))
# Hexlist is a list of 4 byte sequences, and we want our separator in between every byte, so we do this little
# maneuver.
aob = "".join(hexlist) # Unformatted
return " ".join(getbytes(aob))