[section .tbss nobits alloc noexec write tls align=8] errno: resb 4 [size errno 4] [section .text] [global __errno_location:function] __errno_location: mov rax, [fs:0] add rax, errno wrt ..tpoff ret __errno_location_size EQU $-__errno_location [size __errno_location __errno_location_size] [global __syscall_error:function] __syscall_error: neg rax mov rcx, [fs:0] mov [rcx + errno wrt ..tpoff], eax neg rax ret __syscall_error_size EQU $-__syscall_error [size __syscall_error __syscall_error_size] %macro cendfunc 1 %1 %+ size EQU $-%1 [size %1 %1 %+ size] %endmacro %macro IF0 1+ %endmacro %macro IF1 1+ %1 %endmacro %macro SYSCALL 3 [global %1 %+ :function] %1: mov eax, %2 IF%3 mov r10, rcx syscall cmp rax, -4095 jbe .Lok call __syscall_error .Lok: ret cendfunc %1 %endmacro %macro SYSCALL_NOERR 3 [global %1 %+ :function] %1: mov eax, %2 IF%3 mov r10, rcx syscall ret cendfunc %1 %endmacro SYSCALL_NOERR mmap, 9, 1 SYSCALL_NOERR mremap, 25, 1 SYSCALL mprotect, 10, 0 SYSCALL_NOERR munmap, 11, 0 SYSCALL mlock, 149, 0 SYSCALL munlock, 150, 0 SYSCALL_NOERR gettimeofday, 96, 0 SYSCALL settimeofday, 164, 0 SYSCALL ntp_adjtime, 159, 0 SYSCALL nanosleep, 35, 0 ; FIXME: should return 20-ret, not ret. SYSCALL getpriority, 140, 0 SYSCALL setpriority, 141, 0 SYSCALL access, 21, 0 SYSCALL open, 2, 0 SYSCALL poll, 7, 0 SYSCALL read, 0, 0 SYSCALL readv, 19, 0 SYSCALL write, 1, 0 SYSCALL writev, 20, 0 SYSCALL lseek, 8, 0 SYSCALL fsync, 74, 0 SYSCALL fdatasync, 75, 0 SYSCALL close, 3, 0 SYSCALL dup2, 33, 0 SYSCALL link, 86, 0 SYSCALL unlink, 87, 0 SYSCALL rename, 82, 0 SYSCALL getpid, 39, 0 SYSCALL kill, 62, 0 SYSCALL fork, 57, 0 SYSCALL setsid, 112, 0 SYSCALL uname, 63, 0 SYSCALL _exit, 60, 0 SYSCALL futex, 202, 1 ;SYSCALL sigprocmask, 14, 1 SYSCALL klogctl, 103, 0 SYSCALL_NOERR __arch_prctl, 158, 0 SYSCALL lookup_dcookie, 212, 0 ; for oprofile SYSCALL getrusage, 98, 0 SYSCALL __lsysinfo, 99, 0 [global sigprocmask:function] sigprocmask: mov r10, 0x08 mov eax, 14 syscall cmp rax, -4096 jbe .Lok call __syscall_error .Lok: ret cendfunc sigprocmask [global ioctl] ioctl: push rbp mov rbp, rsp mov QWORD [rbp-32], rdx mov DWORD [rbp-72], 16 lea rax, [rbp+16] mov QWORD [rbp-64], rax lea rax, [rbp-48] mov QWORD [rbp-56], rax mov eax, 16 syscall pop rbp ret cendfunc ioctl [global __xmknod] __xmknod: mov rdi, rsi mov rsi, rdx mov rdx, rcx mov eax, 4 syscall cmp rax, -4096 jbe .Lok call __syscall_error .Lok: ret cendfunc __xmknod [global __xstat] __xstat: mov rdi, rsi mov rsi, rdx mov eax, 4 syscall cmp rax, -4096 jbe .Lok call __syscall_error .Lok: ret cendfunc __xstat [global __fxstat] __fxstat: mov rdi, rsi mov rsi, rdx mov eax, 5 syscall cmp rax, -4096 jbe .Lok call __syscall_error .Lok: ret cendfunc __fxstat [global __lxstat] __lxstat: mov rdi, rsi mov rsi, rdx mov eax, 6 syscall cmp rax, -4096 jbe .Lok call __syscall_error .Lok: ret cendfunc __lxstat ;[global strlen:function] ;strlen: ; xor rax, rax ; pxor mm1, mm1 ;.loop: ; movq mm0, [rdi+rax] ; pcmpeqb mm0, mm1 ; pmovmskb rcx, mm0 ; add rax, 8 ; test rcx, rcx ; jz .loop ; sub rax, 8 ; bsf ecx, ecx ; add rax, rcx ; emms ; ret ;cendfunc strlen [global strlen:function] strlen: xor rax, rax pxor mm1, mm1 .loop: movq mm0, [rdi+rax] pcmpeqb mm0, mm1 pmovmskb rcx, mm0 add rax, 8 test rcx, rcx jz .loop sub rax, 8 bsf ecx, ecx add rax, rcx emms ret cendfunc strlen [global wcslen:function] wcslen: xor rax, rax pxor mm1, mm1 .loop: movq mm0, [rdi+rax] pcmpeqw mm0, mm1 pmovmskb rcx, mm0 add rax, 8 test rcx, rcx jz .loop sub rax, 8 bsf ecx, ecx add rax, rcx shr rax, 1 emms ret cendfunc wcslen [global backtrace:function] backtrace: push rbp mov rbp, rsp lea r9, [rbp] jb .Lbacktraceexit0 mov rcx, rbp xor edx, edx .Lbacktraceloop: lea eax, [rdx+1] mov r8, [rcx+8] mov [rdi+8*rdx], r8 mov rcx, [rcx] cmp esi, eax jbe .Lbacktraceexit cmp rcx, r9 jb .Lbacktraceexit mov edx, eax cmp [rel __libc_stack_end], rcx ja .Lbacktraceloop .Lbacktraceexit: pop rbp ret .Lbacktraceexit0: xor eax, eax jmp .Lbacktraceexit cendfunc backtrace ; The default MXCSR state is 0x1f80, so we just store 0x9f80 ; and directly call ldmxcsr, saving us a call to stmxcsr. [global disable_denormals:function] disable_denormals: mov QWORD [rsp-8], 0x9f80 ldmxcsr [rsp-8] ret cendfunc disable_denormals [global __stack_chk_fail:function] __stack_chk_fail: push rbp mov rbp, rsp mov edx, 45 mov esi, __stack_chk_fail_msg1 mov edi, 1 mov eax, 1 syscall sub rsp, 16 mov QWORD [rbp-8], -2337 xor edi, edi lea rsi, [rbp-8] xor rdx, rdx mov r10, 0x08 mov eax, 14 syscall mov eax, 39 syscall mov esi, 6 mov edi, eax mov eax, 62 syscall ud2 add rsp, 16 pop rbp ret cendfunc __stack_chk_fail [global handle_intel_cacheinfo:function] handle_intel_cacheinfo: push rbp mov rbp, rsp xor esi, esi mov r8d, 4 push rbx jmp .Lintelstart .Lintelnextiter: shr eax, 5 and eax, 7 cmp eax, edi je .Lcalculatecachesize .Lintelstart: mov eax, r8d mov ecx, esi cpuid add esi, 1 test al, 31 jne .Lintelnextiter xor eax, eax jmp .Lintelret .Lcalculatecachesize: mov eax, ebx mov edx, ebx shr ebx, 12 and eax, 4095 shr edx, 22 and ebx, 1023 inc eax inc edx inc ebx imul eax, edx imul eax, ebx .Lintelret: pop rbx pop rbp ret cendfunc handle_intel_cacheinfo [extern main] [type main function] [global _start:function] _start: ; Clear the frame pointer. The ABI suggests this be done, to mark the outermost frame obviously. xor rbp, rbp rdtsc sal rdx, 0x20 add rax, rdx xor rax, 0xFF0A0D00 mov [rel __stack_chk_guard], rax xor rax, 0xDEADBEEF mov [rel __pointer_chk_guard], rax ; Jesus fucking christ. gcc now assumes that the pointer to the stack canary value will be in thread-local storage (WTF?!?) ; So yes, we need to set a minimal TCB header here. mmap() a page, ; and store the address of __stack_chk_guard 40 bytes into it, which is where gcc will try to pull it from. ; We now also fill in __pointer_chk_guard, which is 48 bytes into the same page. ; Then call prctl with the magic value of cmd=0x1002, which corresponds to ARCH_SET_FS, to set the value ; of the FS segment selector to the page we just allocated. And then we are done. Yay. ; (Whose idea was it to put stack canaries in TLS? Of all the things that *should* be thread-local, ; that is very much not one of them). xor r9, r9 mov r8, -1 mov r10d, 0x4022 mov edx, 3 mov rsi, 0x10000 xor rdi, rdi sub rsp, 8 mov eax, 9 syscall ; unsigned long *r = mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, 0x4022, -1, 0) mov rsi, rax mov r8, rax add r8, 0x1000 mov [rax ], r8 ; r[0] = (size_t)(r+0x1000); mov [rax+16], r8 ; r[2] = (size_t)(r+0x1000); mov rcx, [__stack_chk_guard] mov [rax+40], rcx ; r[5] = (size_t)__stack_chk_guard; mov rcx, [__pointer_chk_guard] mov [rax+48], rcx ; r[6] = (size_t)__pointer_chk_guard; mov edi, 0x1002 mov eax, 158 syscall ; arch_prctl(ARCH_SET_FS, r) mov QWORD [rsp], 4096 lea rsi, [rsp] xor edi, edi xor rdx, rdx mov r10, 0x08 mov eax, 14 syscall add rsp, 8 ; Disable denormals for SSE/SSE2 (i.e. enable FTZ/DAZ in the MXCSR) call disable_denormals pop rdi ; Pop the argument count. mov rsi, rsp ; argv starts just at the current stack top. lea r8, [rsi+8*rdi+8] ; rdi currently contains the __environ pointer mov [rel __environ], r8 ; Align the stack to a 16 byte boundary to follow the ABI. and rsp, ~15 ; Provide the highest stack address to the user code (for stacks which grow downwards). mov [rel __libc_stack_end], rsp ; start the fun call main movsxd rdi, eax mov eax, 60 syscall ret cendfunc _start SECTION .note.GNU-stack noexec progbits SECTION .data.rel.ro alloc noexec write align=4 ;[global __stack_chk_guard:object] __stack_chk_guard: dq 0 [size __stack_chk_guard 8] ;[global __pointer_chk_guard:object] __pointer_chk_guard: dq 0 [size __pointer_chk_guard 8] SECTION .bss [global __libc_stack_end:object] __libc_stack_end: resb 8 [size __libc_stack_end 8] [global __environ:object] [weak environ] [type environ object] environ: __environ: resb 8 [size environ 8] [size __environ 8] SECTION .data [global __data_start:object] [weak data_start] [type data_start object] data_start: __data_start: dq 0 [size data_start 8] [size __data_start 8] [section .rodata align=32] __stack_chk_fail_msg1: db 'stack smashing detected: program terminated.',0x10 [size __stack_chk_fail_msg1 46]