vxKernel/vxgos/boards/fxcg50/generate.py

140 lines
4.2 KiB
Python

"""
generate - post-build script used to generate bootlaoder blob with ASLR
"""
import os
import sys
import subprocess
__all__ = [
'generate_aslr_blob',
'generate_image'
]
#---
# Internals
#---
def _patch_got_section(symfile, section):
""" fetch all address of the GOT table
"""
for sec in section:
if sec[0] != '.got':
continue
got_base_addr = int(sec[2], base=16)
for i in range(0, int(sec[4], base=16), 4):
print(f" > reloc GOT entry {got_base_addr+i:08x}...")
symfile.write((got_base_addr + i).to_bytes(4, 'big'))
break
#---
# Public
#---
def generate_aslr_blob(binpath, symtab, sectab):
""" generate bootloader final blob with ASLR
The objectif of this script is to generate the final bootloader blob with
ASLR. To performs this, we will performs 3 steps:
* generate the raw binary file of the bootloader (objcpy)
* generate the raw ALSR symbols table
* generate the complet blootloader image
@args
> binpath (str) - binary file
> symtab (list) - list of all reloc information (readelf -r binpath)
> sectab (list) - list of all sections information (readelf -S binpath)
@return
> Nothings
"""
print('- generate raw binary...')
if os.path.exists(f"{binpath}.raw"):
os.remove(f"{binpath}.raw")
cmd = f"sh-elf-vhex-objcopy -O binary -R .bss {binpath} {binpath}.raw"
subprocess.run(
cmd.split(),
capture_output=False,
check=False
)
print('- generate raw symtab...')
if os.path.exists(f"{binpath}.symtab"):
os.remove(f"{binpath}.symtab")
need_patch_got = False
with open(f"{binpath}.symtab", 'xb') as symfile:
for i, sym in enumerate(symtab):
# direct 32bits address
if sym[2] == 'R_SH_DIR32':
print(f" > reloc 'R_SH_DIR32' sym at {sym[0]}")
symfile.write(int(sym[0], base=16).to_bytes(4, 'big'))
continue
# GOT related jump
if sym[2] == 'R_SH_GOT32':
need_patch_got = True
continue
# Other
if sym[2] not in [
'R_SH_PLT32',
'R_SH_GOT32',
'R_SH_GOTPC',
'R_SH_GOTOFF'
]:
print(f" > [{i}] reloc {sym[2]} not supported")
sys.exit(84)
if need_patch_got:
_patch_got_section(symfile, sectab)
symfile.write(int('00000000', base=16).to_bytes(4, 'big'))
print('- generate the full bootloader...')
if os.path.exists(f"{binpath}.bzImage"):
os.remove(f"{binpath}.bzImage")
with open(f"{binpath}.bzImage", 'xb') as bzimgfile:
with open(f"{binpath}.raw", 'rb') as rawbinfile:
bzimgfile.write(rawbinfile.read())
with open(f"{binpath}.symtab", 'rb') as symtabfile:
bzimgfile.write(symtabfile.read())
return f"{binpath}.bzImage"
def generate_image(prefix_build, bootloader_path, _):
""" generate complet image (g3a) file
TODO
"""
image = bytearray(0)
with open(bootloader_path, 'rb') as bootloaderfile:
image += bootloaderfile.read()
# (todo) os/kernel
image_size = len(image)
# patch first two instruction of the image (see <vxgos/bootloader>)
image[0] = 0b00000000 # (MSB) nop
image[1] = 0b00001001 # (LSB) nop
image[2] = 0b11010000 # (MSB) mov.l @(1*, PC), r0
image[3] = 0b00000001 # (LSB) mov.l @(1*, PC), r0
image[8] = (image_size & 0xff000000) >> 24
image[9] = (image_size & 0x00ff0000) >> 16
image[10] = (image_size & 0x0000ff00) >> 8
image[11] = (image_size & 0x000000ff) >> 0
bzimage = f"{prefix_build}/vxgos.bzImage"
if os.path.exists(bzimage):
os.remove(bzimage)
with open(bzimage, 'xb') as bzimage:
bzimage.write(image)
prefix = os.path.dirname(__file__)
subprocess.run(
[
'/usr/bin/env',
'python3',
f"{prefix}/g3a_generator.py",
f"{prefix_build}/vxgos.g3a",
f"{prefix_build}/vxgos.bzImage",
f"{prefix}/icon-sel.png",
f"{prefix}/icon-uns.png",
],
capture_output=False,
check=False
)