Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

short: introduce shorter template for C/C++ #29

Merged
merged 1 commit into from
Dec 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);}
Loading