I've made a small script to compile Go code with Python.
The result is not something I'm happy with, because:
- It seems overly complicated
- I'm worried the nested if-else with f string are unreadable
- Am I using the
subprocessmodule the correct way?
Any review is welcome.
#!/usr/bin/env python3
import argparse
import subprocess
import os
ARCHS = {
"32": "386",
"64": "amd64"
}
BUILDTYPES = ["exe", "dll"]
def parse_arguments():
parser = argparse.ArgumentParser(usage='%(prog)s [options] <buildtype> <architecture>',
description='Go builder',
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog='''
Python program to build go payloads
Examples:
./builder exe 32 --stripped
./builder dll 64 --upx --stripped
./builder dll 32
''')
parser.add_argument("buildtype", help="The type to build the paylopad with", type=str)
parser.add_argument("architecture", help="The architecture to build the paylopad with", type=str, default="32")
parser.add_argument("--stripped", "-s", help="Strip the payload of symbols", action="store_true", default=False)
parser.add_argument("--upx", "-u", help="Pack the payload with upx", action="store_true", default=False)
arguments = parser.parse_args()
if not arguments.buildtype.lower() in BUILDTYPES:
parser.error(f"{arguments.buildtype} is not a valid buildtype can only be {', '.join(BUILDTYPES)}")
if not arguments.architecture.lower() in ARCHS:
parser.error(f"{arguments.architecture} is not a valid architecture can only be {', '.join(ARCHS.keys())}")
arguments.architecture = ARCHS[arguments.architecture]
return arguments
def build_go(**kwargs):
enviroment = {
**os.environ,
"GOOS": "windows",
"GOARCH": f"{kwargs['architecture']}"
}
if kwargs['buildtype'].lower() == "dll":
enviroment["CGO_ENABLED"] = "1"
enviroment["CC"] = f"{'i686' if kwargs['architecture'] == '386' else 'x86_64'}-w64-mingw32-gcc"
build_type = f"go build -buildmode=c-shared" if kwargs["buildtype"].lower() == "dll" else "go build -tags exe"
stripped = "-s -w" if kwargs['stripped'] else ""
builder = f'''{build_type} -o GOLoader.{kwargs['buildtype']} -ldflags "-H=windowsgui {stripped}"'''
subprocess.check_output(builder, shell=True, env=enviroment)
if kwargs["stripped"]:
stripped = f"strip GOLoader.{kwargs['buildtype']}"
subprocess.check_output(stripped, shell=True)
if kwargs["upx"]:
upx = f"upx -f GOLoader.{kwargs['buildtype']} -9 --ultra-brute -o GOLoader.upx.{kwargs['buildtype']}"
subprocess.check_output(upx, shell=True)
if __name__ == '__main__':
args = parse_arguments()
build_go(**vars(args))