-
-
Save moratorium08/2fa8dbd4150c8db547a1f3a31d5499ac 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
from keystone import * | |
import struct | |
import sys | |
arch = KS_ARCH_X86 | |
mode = KS_MODE_64 | |
ks = Ks(arch, mode) | |
memory_top = 0x900000 | |
memory_size = 100000 | |
entry_point = 0x500078 | |
def asm(code): | |
c, _ = ks.asm(code) | |
return ''.join([chr(x) for x in c]) | |
def p8(x): | |
return struct.pack("<B", x) | |
def p16(x): | |
return struct.pack("<H", x) | |
def p32(x): | |
return struct.pack("<L", x) | |
def p64(x): | |
return struct.pack("<Q", x) | |
def gen_header(code): | |
elfh = '' | |
elfh += '\x7fELF' # magic | |
elfh += p8(2) # Class: 2 is 64bit | |
elfh += p8(1) # Endinan: little endian | |
elfh += p8(1) # ELF Version: EV Current | |
elfh += p8(0) # EI_OSABI: It is often set to 0 regardless of the target platform.(Wikipedia) | |
elfh += p8(0) # ABI version: (not used) | |
elfh += p8(0) * 7 # Padding: currently unused | |
elfh += p16(2) # e_type: 2 is exectable file | |
elfh += p16(0x3e) # e_machine: 0x3e is x86-64 | |
elfh += p32(1) # e_version: original version(maybe whatever) | |
elfh += p64(entry_point) # e_entry: entry point | |
elfh += p64(0x40) # e_phoff: program header table offset -> 64bit is 0x40 | |
elfh += p64(0) # e_shoff: section header table offset -> notable | |
elfh += p32(0) # e_flags: maybe whatever | |
elfh += p16(0x40) # e_ehsize: ELF Header Size | |
elfh += p16(0x38) # e_phentsize | |
elfh += p16(1) # e_phnum: the number of program header entries | |
elfh += p16(0) # e_shentsize: no section headers | |
elfh += p16(0) # e_shnum: no section headers | |
elfh += p16(0) # e_shstrndx: no section headers | |
# Program Header | |
prmh = '' | |
prmh += p32(1) # p_type: type of segment | |
prmh += p32(5) # p_flags: memory segment permission. 0b101 -> Exec + Read | |
prmh += p64(0x40 + 0x38) # p_offset: offset of the segment | |
prmh += p64(entry_point) # p_vaddr: virtual address to be mapped in memory | |
prmh += p64(entry_point) # p_paddr: physical address to be mapped in memory (maybe not used in my machine) | |
prmh += p64(len(code)) # p_filesz: file size of this segment | |
prmh += p64(len(code)) # p_memsz: file size of this segment | |
prmh += p64(0x1000) # p_align: alignment | |
return elfh + prmh | |
def inc_ptr(): | |
code = asm('inc rbx') | |
return code | |
def dec_ptr(): | |
code = asm('dec rbx') | |
return code | |
def inc_val(): | |
code = asm('mov al, [rbx]') | |
code += asm('inc al') | |
code += asm('mov [rbx], al') | |
return code | |
def dec_val(): | |
code = asm('mov al, [rbx]') | |
code += asm('dec al') | |
code += asm('mov [rbx], al') | |
return code | |
def put_char(): | |
code = asm('mov rax, 1') | |
code += asm('mov rdi, 1') | |
code += asm('mov rsi, rbx') | |
code += asm('mov rdx, 1') | |
code += asm('syscall') | |
return code | |
def get_char(): | |
code = asm('mov rax, 0') | |
code += asm('mov rdi, 0') | |
code += asm('mov rsi, rbx') | |
code += asm('mov rdx, 1') | |
code += asm('syscall') | |
return code | |
def push_fun(addr): | |
code = asm('mov al, [rbx]') | |
code += asm('cmp al, 0') | |
code += asm('je %d' % addr) | |
return code | |
def pop_fun(addr): | |
code = asm('mov al, [rbx]') | |
code += asm('cmp al, 0') | |
code += asm('jne %d' % (addr - len(code))) | |
return code | |
def epilogue(): | |
code = '' | |
code += asm('mov rax, 60') | |
code += asm('mov rdi, 0') | |
code += asm('syscall') | |
return code | |
def prologue(): | |
code = '' | |
# create the area of 'memory' | |
code += asm('mov rax, 9') # mmap | |
code += asm('mov rdi, %d' % memory_top) | |
code += asm('mov rsi, %d' % memory_size) # size | |
code += asm('mov rdx, 7') | |
code += asm('mov r10, 34') | |
code += asm('mov r8, 0xffffffffff') | |
code += asm('mov r9, 0') | |
code += asm('syscall') | |
# use rbx as current memory addr | |
code += asm('mov rbx, %d' % memory_top) | |
return code | |
class InvalidSyntax(Exception): | |
pass | |
def inner(base, root=False): | |
code = '' | |
while True: | |
c = sys.stdin.read(1) | |
if not c: | |
break | |
if c == '>': | |
code += inc_ptr() | |
elif c == '<': | |
code += dec_ptr() | |
elif c == '+': | |
code += inc_val() | |
elif c == '-': | |
code += dec_val() | |
elif c == '.': | |
code += put_char() | |
elif c == ',': | |
code += get_char() | |
elif c == '[': | |
code += inner(base + len(code)) | |
elif c == ']': | |
if len(code) > 129: | |
tmp = push_fun(130) | |
else: | |
tmp = push_fun(129) | |
code += pop_fun(-len(code)) | |
return push_fun(len(code)) + code | |
if root: | |
return code | |
raise InvalidSyntax | |
def main(): | |
base = entry_point | |
code = prologue() | |
code += inner(base + len(code), root=True) | |
code += epilogue() | |
h = gen_header(code) | |
artifact = h + code | |
return artifact | |
open('bf', 'w').write(main()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment