Someone brought back this #qrcode sticker from #39c3.
-
-
1. The 20 bytes of text ("What could go wrong?") that directly follow the last "regular" instruction are XOR'ed with some magic numbers 4 bytes at a time, turning them into something completely different.
2. Two syscalls are executed in series, the type of the second syscall is hereby determined by subtracting a hardcoded value from the return value of the first syscall.
3. Execution seemingly progresses into the XOR-modified text buffer.
🧵 2/5
-
1. The 20 bytes of text ("What could go wrong?") that directly follow the last "regular" instruction are XOR'ed with some magic numbers 4 bytes at a time, turning them into something completely different.
2. Two syscalls are executed in series, the type of the second syscall is hereby determined by subtracting a hardcoded value from the return value of the first syscall.
3. Execution seemingly progresses into the XOR-modified text buffer.
🧵 2/5
However, upon closer inspection, what actually happens is:
1. The XORs turn the string "What could go wrong?" into "You are beautiful!\ny" (ignore the "y", it's not used).
2. The first syscall is a write(2) that writes the modified string to stdout (FD 1), and returns the number of bytes written (19). From that, 18 is subtracted to construct the next syscall, exit(2).
3. Here execution terminates, and never progresses into the text buffer.
🧵 3/5
-
However, upon closer inspection, what actually happens is:
1. The XORs turn the string "What could go wrong?" into "You are beautiful!\ny" (ignore the "y", it's not used).
2. The first syscall is a write(2) that writes the modified string to stdout (FD 1), and returns the number of bytes written (19). From that, 18 is subtracted to construct the next syscall, exit(2).
3. Here execution terminates, and never progresses into the text buffer.
🧵 3/5
So, all in all, what this code actually does is a barebones equivalent of (as C code):
puts("You are beautiful!\n");
exit(0);A fun little challenge to reverse engineer, even without notable x86 assembly experience.
🧵 4/5
-
So, all in all, what this code actually does is a barebones equivalent of (as C code):
puts("You are beautiful!\n");
exit(0);A fun little challenge to reverse engineer, even without notable x86 assembly experience.
🧵 4/5
However, I'd like to report a "bug" to whoever wrote this code: 😜
If stdout is not writable (e.g. by piping the output into /dev/full, which returns ENOSPC on write), the second syscall is not an exit(2), but another, nonexistent syscall, and execution actually progresses into the string, where it segfaults.
🧵 5/5
-
However, I'd like to report a "bug" to whoever wrote this code: 😜
If stdout is not writable (e.g. by piping the output into /dev/full, which returns ENOSPC on write), the second syscall is not an exit(2), but another, nonexistent syscall, and execution actually progresses into the string, where it segfaults.
🧵 5/5
Also a shoutout to Linux documentation: Once you learn that "INT 0x80" is the instruction to perform a syscall, most information regarding what syscalls are being made can be found in Linux manpages and C headers:
syscall(2) contains calling conventions for syscalls for a lot of CPU architectures, including i386, where we learn that EAX is used for the syscall number and the return value, and (in that order) EBX, ECX and EDX are used for the first 3 arguments of a syscall.
-
Also a shoutout to Linux documentation: Once you learn that "INT 0x80" is the instruction to perform a syscall, most information regarding what syscalls are being made can be found in Linux manpages and C headers:
syscall(2) contains calling conventions for syscalls for a lot of CPU architectures, including i386, where we learn that EAX is used for the syscall number and the return value, and (in that order) EBX, ECX and EDX are used for the first 3 arguments of a syscall.
/usr/include/asm/unistd_32.h contains the numeric syscall identifiers (i.e. 1 = exit, 4 = write), used in EAX.
The manpages of the syscalls exit(2) and write(2) document which arguments they take and in what order.
This is how I figured out that what these syscalls actually do is a write(1, "You are beautiful!\n", 19) and an exit(0).
-
undefined oblomov@sociale.network shared this topic