Skip to content

Commit

Permalink
short: introduce shorter template for C/C++
Browse files Browse the repository at this point in the history
Enables 156KB/0ms with the shorter generation paradigm.
  • Loading branch information
byeongkeunahn committed Dec 1, 2023
1 parent 1d40959 commit fdea9c5
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 3 deletions.
6 changes: 5 additions & 1 deletion scripts/static-pie-gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@
code_raw_b91 = base91.encode(code_raw, use_rle=True).decode('ascii')
code_raw_b91_len = len(code_raw_b91)
code_raw_b91 = '"' + code_raw_b91 + '"'
if lang_name == "C":
# Escape '\' and '?'
code_raw_b91 = code_raw_b91.replace('\\', '\\\\')
code_raw_b91 = code_raw_b91.replace('?', '\\?')

# binary
with open(compressed_binary_path, "rb") as f:
Expand Down Expand Up @@ -124,7 +128,7 @@

# template
template_candidates = [template_path]
if lang_name == "Rust" and "x86_64" in target_name and "short" in template_path and len(code_raw) <= 4096 - 256:
if lang_name in ["C", "Rust"] and "x86_64" in target_name and "short" in template_path and len(code_raw) <= 4096 - 256:
template_candidates.append(template_path.replace("short", "shorter"))

out = None
Expand Down
12 changes: 10 additions & 2 deletions scripts/static-pie-prestub-amd64-print.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@
SPECIFIER = ".quad"
CHUNK_SIZE = 8
ENTRIES_PER_LINE = 4
if "--c" in sys.argv:
PREFIX = "0x"
SUFFIX = ""
SPECIFIER = ""
ENTRIES_PER_LINE = 100
else:
PREFIX = ""
SUFFIX = "h"

# pad to align at `CHUNK_SIZE`-byte boundary
while len(prestub) % CHUNK_SIZE != 0:
Expand All @@ -48,8 +56,8 @@ def to_hex_short(y):
nonzero_idx = len(out)
while nonzero_idx > 1 and out[nonzero_idx-1] == '0':
nonzero_idx -= 1
out2 = out[:nonzero_idx] + "h<<" + str((len(out) - nonzero_idx) * 4)
out = out + "h"
out2 = PREFIX + out[:nonzero_idx] + SUFFIX + "<<" + str((len(out) - nonzero_idx) * 4)
out = PREFIX + out + SUFFIX
if len(out2) < len(out):
out = out2
if ord(out[0]) >= ord('a'):
Expand Down
98 changes: 98 additions & 0 deletions scripts/static-pie-prestub-amd64-shorter-c.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
; -*- tab-width: 4 -*-
;
; The prestub for amd64-rust target
; (prestub: the code that runs before the stub and sets the stage)
;
; build: nasm -f bin -O9 static-pie-prestub-amd64-shorter-c.asm -o static-pie-prestub-amd64-shorter-c.bin
; note: after building with the above command, run static-pie-prestub-amd64-print.py static-pie-prestub-amd64-shorter-c.bin --c
; to obtain the form that can be embedded in Rust as inline assembly.

BITS 64
ORG 0
section .text

; Reserve space on stack
and rsp, 0xffffffffffffff80 ; ensures at least 128 bytes

; mprotect: make stack executable
mov eax, 10 ; mprotect
mov esi, 0x1000 ; len
push rdi ; Save binary_raw_base91
lea rdi, [rsp + 8] ; addr
push 7 ; protect (RWX)
pop rdx
and rdi, 0xfffffffffffff000 ; align to page boundary (4K)
syscall

; Relocate to stack
lea rsi, [rel _start]
lea rdi, [rsp + 8]
push rdi ; _start of relocated stub
mov ecx, _end - _start
rep movsb

; Jump to stack
pop rax ; _start of relocated stub
call rax

_start:

; Free the .text section
pop rdi ; Get RIP saved on stack by call instruction
and rdi, 0xfffffffffffff000
mov esi, 0x1000
mov eax, 11
syscall

; svc_alloc_rwx for Linux
_svc_alloc_rwx:
push 9
pop rax ; syscall id of x64 mmap
cdq ; rdx=0
xor r9d, r9d ; offset
xor edi, edi ; rdi=0
mov esi, eax ; size (anything in [1, 4096])
mov dl, 7 ; protect (safe since we have ensured rdx=0)
push 0x22
pop r10 ; flags
push -1
pop r8 ; fd
syscall
pop rsi ; restore rsi

; Current state: rax = new buffer
xchg rax, rdi ; rdi = new buffer

; Base91 decoder
_decode:
mov al, 0x1f ; syscall preserves all registers except rcx, r11, rax; hence at this point rax=(previous rdi)=0
_decode_loop:
shl eax, 13
_decode_loop_2:
lodsb
xor ecx, ecx ; ecx = 0
sub al, 0x23
jbe _decode_zeros
dec al
xchg eax, ecx
lodsb
sub al, 0x24
imul eax, eax, 91
add eax, ecx
_decode_output:
stosb
shr eax, 8
test ah, 16
jnz _decode_output
jmp _decode_loop
_decode_zeros:
xchg byte [rdi-1], cl ; ecx = cl = ((number of zeros) - 1), byte [rdi-1] = 0
rep stosb ; we have made sure the last byte is zero (in the packager)
jz _decode_loop_2

; Jump to entrypoint
_jump_to_entrypoint:
sub rdi, qword [rdi-8]
call rdi

_end:
Binary file added scripts/static-pie-prestub-amd64-shorter-c.bin
Binary file not shown.
10 changes: 10 additions & 0 deletions scripts/static-pie-template-amd64-shorter.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Generated with https://github.com/kiwiyou/basm-rs
// Learn rust (https://doc.rust-lang.org/book/) and get high performance out of the box!
// SOLUTION BEGIN
$$$$solution_src$$$$
// SOLUTION END
__attribute__((section(".text#")))unsigned long long s[]={0xab880e48348,0x485700001000be00,0x485a076a08247c8d,0x50ffffff000e781,0x4800000010358d48,0x5db95708247c8d,0x5fd0ff58a4f30000,0xbefffff000e78148,0xbb800001000,0x459958096a050f00,0x7b2c689ff31c931,0x5841ff6a5a41226a,0xc11fb097485e050f,0x76232cc931ac0de0,0x6b242cac91c8fe16,0x8e8c1aac8015bc0,0x86e0ebf77510c4f6,0x2b48dc74aaf3ff4f,0xd7fff87f};char t[]=$$$$binary_raw_base91$$$$;int main(){return 0;}
#if defined(__cplusplus)
extern "C"
#endif
int __libc_start_main(){return((int(*)(void*))s)(t);}

0 comments on commit fdea9c5

Please sign in to comment.