refactor: make asm cleanup/fixup work in memory

This commit is contained in:
Dobin
2024-04-28 19:43:08 +01:00
parent c82c99e0eb
commit 1b245e5506
4 changed files with 132 additions and 166 deletions
+3 -6
View File
@@ -8,10 +8,9 @@ from model.carrier import Carrier, DataReuseEntry, IatRequest
logger = logging.getLogger("AsmParser")
def parse_asm_file(carrier, filename):
def parse_asm_file(carrier: Carrier, asm_text: str) -> List[str]:
lines_out = []
with open(filename, 'r', encoding='utf-8') as asmfile:
lines = asmfile.readlines()
lines = asm_text.split("\n")
current_segment = None
current_datareuse_entry= None
@@ -143,9 +142,7 @@ def parse_asm_file(carrier, filename):
lines_out.append(line)
with open(filename, "w") as f:
for line in lines_out:
f.write(line + "\n")
return lines_out
def convert_asm_db_to_bytes(line: str) -> bytes:
+17 -44
View File
@@ -8,7 +8,7 @@ from helper import *
from config import config
from observer import observer
from model import *
from phases.masmshc import process_file, Params
from phases.masmshc import masm_shc, Params
from model.carrier import Carrier
from model.exehost import ExeHost
from phases.asmparser import parse_asm_file
@@ -35,37 +35,23 @@ def compile_dev(
])
if not os.path.isfile(asm_out):
raise Exception("Error: Compiling failed")
file_to_lf(asm_out)
observer.add_text_file("carrier_asm_orig", file_readall_text(asm_out))
# Assembly cleanup (masm_shc)
asm_clean_file = asm_out + ".clean"
asm_text: str = file_readall_text(asm_out)
observer.add_text_file("carrier_asm_orig", asm_text)
logger.info("---[ ASM masm_shc: {} ".format(asm_out))
params = Params(asm_out, asm_clean_file,
inline_strings=False, # not for DATA_REUSE
remove_crt=True,
append_rsp_stub=True) # required atm
process_file(params)
asm_text_lines: List[str] = parse_asm_file(Carrier(), asm_text)
asm_text = masm_shc(asm_text_lines)
observer.add_text_file("carrier_asm_cleanup", asm_text)
if not os.path.isfile(asm_clean_file):
raise Exception("Error: Cleaned up ASM file {} was not created".format(
asm_clean_file
))
# Move to destination we expect
shutil.move(asm_clean_file, asm_out)
if config.debug:
observer.add_text_file("carrier_asm_cleanup", file_readall_text(asm_out))
with open(asm_out, "w") as f:
f.write(asm_text)
def compile(
c_in: FilePath,
asm_out: FilePath,
payload_len: int,
carrier: Carrier,
source_style: FunctionInvokeStyle,
exe_host: ExeHost,
short_call_patching: bool = False,
):
logger.info("--[ Compile C to ASM: {} -> {} ".format(c_in, asm_out))
@@ -80,26 +66,13 @@ def compile(
])
if not os.path.isfile(asm_out):
raise Exception("Error: Compiling failed")
file_to_lf(asm_out)
observer.add_text_file("carrier_asm_orig", file_readall_text(asm_out))
asm_text = file_readall_text(asm_out)
observer.add_text_file("carrier_asm_orig", asm_text)
# Fixup assembly file
parse_asm_file(carrier, asm_out)
asm_text_lines = parse_asm_file(carrier, asm_text) # Fixup assembly file
asm_text = masm_shc(asm_text_lines) # Cleanup assembly file
observer.add_text_file("carrier_asm_final", asm_text)
# Cleanup assembly file
asm_clean_file = asm_out + ".clean"
logger.info("---[ ASM masm_shc: {} ".format(asm_out))
params = Params(asm_out, asm_clean_file,
inline_strings=False, # not for DATA_REUSE
remove_crt=True,
append_rsp_stub=True) # required atm
process_file(params)
if not os.path.isfile(asm_clean_file):
raise Exception("Error: Cleaned up ASM file {} was not created".format(
asm_clean_file
))
# Move to destination we expect
shutil.move(asm_clean_file, asm_out)
# Log result
observer.add_text_file("carrier_asm_cleanup", file_readall_text(asm_out))
# write back. Next step would be compiling this file
with open(asm_out, "w") as f:
f.write(asm_text)
+16 -19
View File
@@ -1,10 +1,13 @@
import re
import os
import logging
import io
from typing import List
logger = logging.getLogger("masmshc")
g_is32bit = False
# original source: https://github.com/hasherezade/masm_shc/blob/master/masm_shc/main.cpp
# Converted to python by chatgpt, with some manual fixups
class Params:
@@ -71,21 +74,23 @@ _TEXT ENDS
"""
ofile.write(stub)
def process_file(params):
global g_is32bit
try:
with open(params.infile, "r") as file, open(params.outfile, "w") as ofile:
def masm_shc(asm_text_lines: List[str]) -> str:
g_is32bit = False
consts_lines = {}
seg_name = ""
const_name = ""
code_start = False
line_count = 0
for line in file.readlines():
#for line_count, line in enumerate(file):
tokens = split_to_tokens(line)
params = Params("", "",
inline_strings=False, # not for DATA_REUSE
remove_crt=True,
append_rsp_stub=True) # required atm
ofile = io.StringIO()
#print("Tokens: {}".format(" ".join(tokens)))
line_count = 0
for line in asm_text_lines:
line = line + "\n" # lol
tokens = split_to_tokens(line)
if not tokens:
ofile.write(line)
@@ -177,15 +182,7 @@ def process_file(params):
ofile.write(line) # copy line
except FileNotFoundError as e:
print(f"[ERROR] {e}")
return False
if params.inline_strings:
print("[INFO] Strings have been inlined. It may require to change some short jumps (jmp SHORT) into jumps (jmp)")
return True
if __name__ == "__main__":
# Example usage
params = Params("test.asm", "testout.asm", True, True, True)
process_file(params)
return ofile.getvalue()
+4 -5
View File
@@ -109,6 +109,9 @@ def start(settings: Settings) -> int:
prepare_project("default", settings)
# Do the thing and catch the errors
if False:
start_real(settings)
else:
try:
start_real(settings)
except Exception as e:
@@ -146,11 +149,7 @@ def start_real(settings: Settings):
phases.compiler.compile(
c_in = settings.main_c_path,
asm_out = settings.main_asm_path,
payload_len = project.payload.len,
carrier = project.carrier,
source_style = project.settings.source_style,
exe_host = project.exe_host,
short_call_patching = project.settings.short_call_patching)
carrier = project.carrier)
# Assemble: Assemble .asm to .shc (ASM -> SHC)
if settings.generate_shc_from_asm: