Skip to content

Instantly share code, notes, and snippets.

@alessandrocarminati
Last active June 24, 2024 08:35
Show Gist options
  • Save alessandrocarminati/3def436774839d3bce1ad99b9cbb7628 to your computer and use it in GitHub Desktop.
Save alessandrocarminati/3def436774839d3bce1ad99b9cbb7628 to your computer and use it in GitHub Desktop.
Hello world like example
.global _start
.section .text
_start:
mov x8, 0x40 //sys_write
mov x0, 1 //stdout
adrp x1, msg //msg base addr
add x1, x1, msg //msg offs
mov x2, msg_size //msg len
svc #0 //syscall
mov x8, 0x5d //sys_exit
mov x0, #0 //exit code
svc #0 //syscall
msg:
.asciz "hello\n"
msg_end:
msg_size = msg_end - msg
@alessandrocarminati
Copy link
Author

This can be used to built id:

echo -e "ENTRY(_start);\nSECTIONS\n{\n_start = 0x1000;\n. = 0x1000;\n.data : {\n*(.data)\n}\n}\n" >x.ld && as x.s -o x.o && ld -maarch64elf x.o -o x -T x.ld

Add the cross compiler prefix if needed

@alessandrocarminati
Copy link
Author

alessandrocarminati commented Jun 24, 2024

.global _start
.section .text
_start:
        sub sp, sp, 0x10
        ldr w1, [sp, #0x04]
        ldr w0, [sp, #0x08]
        add w0, w1, w0
        str w0, [sp, #0x0c]
loop:
        b loop
        mov x8, 0x5d
        mov x0, #0
        svc #0

Gab's c on native

prefix="" && echo -e "int main(){\nint a,b,c;\na = b + c;\nwhile (1);\nreturn a;\n}\n"| ${prefix}gcc -x c -o m -

asm ver

fn="mm" && prefix="" && echo -e ".global _start\n.section .text\n_start:\nsub sp, sp, 0x10\nldr w1, [sp, #0x04]\nldr w0, [sp, #0x08]\nadd w0, w1, w0\nstr w0, [sp, #0x0c]\nloop:\nb loop\nmov x8, 0x5d\nmov x0, #0\nsvc #0\n" >${fn}.s && echo -e "ENTRY(_start);\nSECTIONS\n{\n_start = 0x10000;\n. = 0x10000;\n.data : {\n*(.data)\n}\n}\n" >${fn}.ld && ${prefix}as ${fn}.s -o ${fn}.o && ${prefix}ld -maarch64elf ${fn}.o -o ${fn} -T ${fn}.ld

on Cross

prefix="aarch64-linux-gnu-" && echo -e "int main(){\nint a,b,c;\na = b + c;\nwhile (1);\nreturn a;\n}\n"| ${prefix}gcc -x c -o m -

asm ver

fn="mm" && prefix="aarch64-linux-gnu-" && echo -e ".global _start\n.section .text\n_start:\nsub sp, sp, 0x10\nldr w1, [sp, #0x04]\nldr w0, [sp, #0x08]\nadd w0, w1, w0\nstr w0, [sp, #0x0c]\nloop:\nb loop\nmov x8, 0x5d\nmov x0, #0\nsvc #0\n" >${fn}.s && echo -e "ENTRY(_start);\nSECTIONS\n{\n_start = 0x10000;\n. = 0x10000;\n.data : {\n*(.data)\n}\n}\n" >${fn}.ld && ${prefix}as ${fn}.s -o ${fn}.o && ${prefix}ld -maarch64elf ${fn}.o -o ${fn} -T ${fn}.ld

@alessandrocarminati
Copy link
Author

alessandrocarminati commented Jun 24, 2024

Test results on native:

$ # no flags produces a dynamic linked file: here's syscall caused by ld.so and the glib crt0.o
$ prefix="" && echo -e "int main(){\nint a,b,c;\na = b + c;\nwhile (1);\nreturn a;\n}\n"| ${prefix}gcc -x c -o m -
$ strace ./m
execve("./m", ["./m"], 0x7fecef0c70 /* 56 vars */) = 0
brk(NULL)                               = 0x55a2d5d000
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fa80c9000
faccessat(AT_FDCWD, "/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
newfstatat(3, "", {st_mode=S_IFREG|0644, st_size=34711, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 34711, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7fa80c0000
close(3)                                = 0
openat(AT_FDCWD, "/lib/aarch64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0\267\0\1\0\0\0\340u\2\0\0\0\0\0"..., 832) = 832
newfstatat(3, "", {st_mode=S_IFREG|0755, st_size=1641496, ...}, AT_EMPTY_PATH) = 0
mmap(NULL, 1810024, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fa7eda000
mmap(0x7fa7ee0000, 1744488, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0) = 0x7fa7ee0000
munmap(0x7fa7eda000, 24576)             = 0
munmap(0x7fa808a000, 40552)             = 0
mprotect(0x7fa8069000, 61440, PROT_NONE) = 0
mmap(0x7fa8078000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x188000) = 0x7fa8078000
mmap(0x7fa807e000, 48744, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fa807e000
close(3)                                = 0
set_tid_address(0x7fa80c9f30)           = 3279
set_robust_list(0x7fa80c9f40, 24)       = 0
rseq(0x7fa80ca600, 0x20, 0, 0xd428bc00) = 0
mprotect(0x7fa8078000, 16384, PROT_READ) = 0
mprotect(0x5583a20000, 4096, PROT_READ) = 0
mprotect(0x7fa80ce000, 8192, PROT_READ) = 0
prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
munmap(0x7fa80c0000, 34711)             = 0
^C--- SIGINT {si_signo=SIGINT, si_code=SI_KERNEL} ---
strace: Process 3279 detached

$ prefix="" && echo -e "int main(){\nint a,b,c;\na = b + c;\nwhile (1);\nreturn a;\n}\n"| ${prefix}gcc --static -x c -o m -
$ strace ./m
execve("./m", ["./m"], 0x7ff2047370 /* 56 vars */) = 0
brk(NULL)                               = 0x27a9a000
brk(0x27a9ab78)                         = 0x27a9ab78
set_tid_address(0x27a9a0d0)             = 3409
set_robust_list(0x27a9a0e0, 24)         = 0
rseq(0x27a9a7a0, 0x20, 0, 0xd428bc00)   = 0
uname({sysname="Linux", nodename="orangepi5plus", ...}) = 0
prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
readlinkat(AT_FDCWD, "/proc/self/exe", "/tmp/m", 4096) = 6
getrandom("\x79\x6f\x82\x3d\x2c\x94\x7f\xb2", 8, GRND_NONBLOCK) = 8
brk(0x27abbb78)                         = 0x27abbb78
brk(0x27abc000)                         = 0x27abc000
mprotect(0x48d000, 16384, PROT_READ)    = 0
^C--- SIGINT {si_signo=SIGINT, si_code=SI_KERNEL} ---
strace: Process 3409 detached
$ # repeat the same but producing static executable, only syscall coming from crt0.o
$ prefix="" && echo -e "int main(){\nint a,b,c;\na = b + c;\nwhile (1);\nreturn a;\n}\n"| ${prefix}gcc --static -x c -o m -
$ strace ./m
execve("./m", ["./m"], 0x7ff2047370 /* 56 vars */) = 0
brk(NULL)                               = 0x27a9a000
brk(0x27a9ab78)                         = 0x27a9ab78
set_tid_address(0x27a9a0d0)             = 3409
set_robust_list(0x27a9a0e0, 24)         = 0
rseq(0x27a9a7a0, 0x20, 0, 0xd428bc00)   = 0
uname({sysname="Linux", nodename="orangepi5plus", ...}) = 0
prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
readlinkat(AT_FDCWD, "/proc/self/exe", "/tmp/m", 4096) = 6
getrandom("\x79\x6f\x82\x3d\x2c\x94\x7f\xb2", 8, GRND_NONBLOCK) = 8
brk(0x27abbb78)                         = 0x27abbb78
brk(0x27abc000)                         = 0x27abc000
mprotect(0x48d000, 16384, PROT_READ)    = 0
^C--- SIGINT {si_signo=SIGINT, si_code=SI_KERNEL} ---
strace: Process 3409 detached

$ # build an equivalent asm file that produces static executable, without crt0.o
$ fn="mm" && prefix="" && echo -e ".global _start\n.section .text\n_start:\nsub sp, sp, 0x10\nldr w1, [sp, #0x04]\nldr w0, [sp, #0x08]\nadd w0, w1, w0\nstr w0, [sp, #0x0c]\nloop:\nb loop\nmov x8, 0x5d\nmov x0, #0\nsvc #0\n" >${fn}.s && echo -e "ENTRY(_start);\nSECTIONS\n{\n_start = 0x10000;\n. = 0x10000;\n.data : {\n*(.data)\n}\n}\n" >${fn}.ld && ${prefix}as ${fn}.s -o ${fn}.o && ${prefix}ld -maarch64elf ${fn}.o -o ${fn} -T ${fn}.ld
$ strace ./mm
execve("./mm", ["./mm"], 0x7fd8bd86d0 /* 56 vars */) = 0
^C--- SIGINT {si_signo=SIGINT, si_code=SI_KERNEL} ---
strace: Process 3525 detached
$ # same result unsing only c
$ prefix="" && echo -e "int _start(){int a,b,c;\na = b + c;\nwhile (1);\nreturn a;\n}\n"| ${prefix}gcc --static -nostartfiles -x c -o m -
$ strace ./m
execve("./m", ["./m"], 0x7fdd683ef0 /* 56 vars */) = 0
^C--- SIGINT {si_signo=SIGINT, si_code=SI_KERNEL} ---
strace: Process 4700 detached
$

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment