def handle_hyx(self, event): """Handles incoming updates/ command requests from hyx etc :return True if hyx shouldnt be """ hyxtalker = self.hyxTalker if event & POLLHUP: # sock closed remaining_data = hyxtalker.hyxsock.recv(1000) if remaining_data: print(remaining_data) self.delete_hyx() return if event != POLLIN: raise NotImplementedError("unknown event: %s" % event) check = hyxtalker.hyxsock.recv(1) if check == CMD_REQUEST: cmd = hyxtalker.recvCommand() print("%s (hyx)" % cmd) if cmd.strip().startswith("fork"): # if this would not be done, hyx would interpret the new heap (sent when forking) as the result from the command hyxtalker.sendCommandResponse("forking") result = self.execute(cmd) print(result) else: result = self.execute(cmd) print(result) hyxtalker.sendCommandResponse(result) elif check == UPD_FROMBLOB or check == UPD_FROMBLOBNEXT: hyxtalker.getUpdate(isNextByte=(check == UPD_FROMBLOBNEXT)) else: warning(check, event) raise NotImplementedError
def readBytes(self, address, size): if not self.read_mem_file: filename = '/proc/%u/mem' % self.pid try: self.read_mem_file = open(filename, 'rb', 0) except IOError as err: message = "Unable to open %s: fallback to ptrace implementation" % filename if err.errno != EACCES: warning(message) else: info(message) self.readBytes = self._readBytes return self.readBytes(address, size) try: mem = self.read_mem_file mem.seek(address) data = mem.read(size) except (IOError, ValueError) as err: raise ProcessError( self, "readBytes(%s, %s) error: %s" % (formatAddress(address), size, err)) if len(data) == 0 and size: # Issue #10: If the process was not created by the debugger # (ex: fork), the kernel may deny reading private mappings of # /proc/pid/mem to the debugger, depending on the kernel # version and kernel config (ex: SELinux enabled or not). # # Fallback to PTRACE_PEEKTEXT. It is slower but a debugger # tracing the process is always allowed to use it. self.readBytes = self._readBytes return self.readBytes(address, size) return data
def analyseurl(urls): """ 功能:分析urls,返回列表格式的字典 字典格式:{'name':names,'urls':url} 这里将符合要求的页面信息插入数据库,还包括日志信息 还包括 key的判断???? """ returns = [] print urls html = urllib2.urlopen(urls, timeout=50) try: conn = sqlite3.connect(options.dbfile) cor = conn.cursor() cor.execute( 'create table if not exists keyofhtml( id integer primary key,urls text,key text,htmls text)' ) data = html.read() rr = re.compile(r"""content\=["|']text\/html\;charset\=(\w*?)["|']""") m = rr.search(data) if m: code = m.group(1) if code: data = data.decode(code) rekey = re.compile(keyinsys) good = rekey.search(data) if good: data = data.replace("'", '"') #纠结的单引号怎么处理? sqls = "insert into keyofhtml(urls,key,htmls) values('%s','%s','%s')" cor.execute(sqls % (urls, keyinsys, data)) conn.commit() conn.close() logging2.debug('reading ' + urls) logging2.info('what should i write here') logging2.warning('a warning here') logging2.error('a error test here') logging2.critical('what is a critical??') #print 'reading' except: print 'error' logging2.error('error ong reading ' + urls) soup = BeautifulSoup.BeautifulSoup(data) temp = soup.findAll('a', href=re.compile(r'http.*')) #为什么不直接用re匹配a标签 logging2.debug('analysing ' + urls) #print 'analysing' for tt in temp: hrefs = tt['href'] #have? if hrefs.startswith('http'): if tt.string: #span????? returns.append({'name': tt.string, 'urls': hrefs}) else: returns.append({'name': 'NoName', 'urls': hrefs}) else: continue return returns
def analyseurl(urls): """ 功能:分析urls,返回列表格式的字典 字典格式:{'name':names,'urls':url} 这里将符合要求的页面信息插入数据库,还包括日志信息 还包括 key的判断???? """ returns=[] print urls html = urllib2.urlopen(urls,timeout=50) try: conn = sqlite3.connect(options.dbfile) cor = conn.cursor() cor.execute('create table if not exists keyofhtml( id integer primary key,urls text,key text,htmls text)') data = html.read() rr = re.compile(r"""content\=["|']text\/html\;charset\=(\w*?)["|']""") m = rr.search(data) if m: code = m.group(1) if code: data = data.decode(code) rekey = re.compile(keyinsys) good = rekey.search(data) if good: data = data.replace("'",'"')#纠结的单引号怎么处理? sqls = "insert into keyofhtml(urls,key,htmls) values('%s','%s','%s')" cor.execute(sqls%(urls,keyinsys,data)) conn.commit() conn.close() logging2.debug('reading '+urls) logging2.info('what should i write here') logging2.warning('a warning here') logging2.error('a error test here') logging2.critical('what is a critical??') #print 'reading' except: print 'error' logging2.error('error ong reading '+urls) soup = BeautifulSoup.BeautifulSoup(data) temp = soup.findAll('a',href=re.compile(r'http.*'))#为什么不直接用re匹配a标签 logging2.debug('analysing '+urls) #print 'analysing' for tt in temp: hrefs = tt['href']#have? if hrefs.startswith('http'): if tt.string:#span????? returns.append({'name':tt.string,'urls':hrefs}) else: returns.append({'name':'NoName','urls':hrefs}) else: continue return returns
def cont(self, signum=0, singlestep=False): """continue execution of the process stops at: - a traced syscall (?trace) - an inserted function - specified breakpoints""" proc = self.ptraceProcess event = self._getNextEvent(signum, singlestep) if isinstance(event, str): # happens if an interesting syscall is hit return event if isinstance(event, ProcessSignal): if event.signum == SIGTRAP: # normal trap, maybe breakpoint? ip = proc.getInstrPointer() if self.inserted_function_data and self.inserted_function_data[ 1] == ip: return self._afterCallFunction() elif ip - 1 in proc.breakpoints.keys( ) and not singlestep: # did we hit a breakpoint? debug("cont calls reinsertBreakpoint") self.reinstertBreakpoint() return "hit breakpoint at %#x" % (ip - 1) elif singlestep: return self.where() else: print(self.where(), event) raise NotImplementedError else: if event.signum in SIGNALS_IGNORE.values(): event.signum = 0 else: warning("got %s, sending it back and continuing" % event) # warning(self.where()) return self.cont(event.signum, singlestep) else: debug("encountered %s" % event) if isinstance(event, ProcessEvent): raise event raise NotImplementedError
def terminate(self, wait_exit=True): if not self.running or not self.was_attached: return True warning("Terminate %s" % self) done = False try: if self.is_stopped: self.cont(SIGKILL) else: self.kill(SIGKILL) except PtraceError as event: if event.errno == ESRCH: done = True else: raise event if not done: if not wait_exit: return False self.waitExit() self._notRunning() return True
def _wait_event_pid(self, wanted_pid, blocking=True): """ Wait for a process event from the specified process identifier. If blocking=False, return None if there is no new event, otherwise return an object based on ProcessEvent. """ process = None while not process: try: pid, status = self._waitpid(wanted_pid, blocking) except OSError as err: if err.errno == ECHILD: process = self.dict[wanted_pid] return process.processTerminated() else: raise err if not blocking and not pid: return None try: process = self.dict[pid] except KeyError: warning("waitpid() warning: Unknown PID %r" % pid) return process.processStatus(status)
def inputLoop(self): print("type ? for help") while True: skip_hyx_update = False poll_result = self.inputPoll.poll() assert len(poll_result) > 0 if len(poll_result) == 1: name, fd, event = poll_result[0] if name == "hyx": skip_hyx_update = self.handle_hyx(event) elif name == "userinput": self.handle_stdin() elif "-out" in name: self.handle_procout(name, fd, event) elif "-err" in name: self.handle_stderr(event) else: # this happens when two sockets are written to at the "same" time for name, fd, event in poll_result: if "-out" in name: self.handle_procout(name, fd, event) break elif "-err" in name: self.handle_stderr(name) break info(poll_result) if self.hyxTalker: try: self.hyxTalker.updateHyx() except ValueError as e: warning("encountered %s when updating hyx" % e) self._switch_hyxtalker()
if good: #print 'good' data = data.replace("'",'"')#纠结的单引号怎么处理? sqls = "insert into keyofhtml(urls,key,htmls) values('%s','%s','%s')" try: cor.execute(sqls%(urls,keyinsys,data)) except UnicodeDecodeError,e: #print e cor.execute(sqls%(urls,keyinsys,'decode error')) logging2.error('reading '+urls+' decode error') conn.commit() #print 'donessss' conn.close() logging2.debug('reading '+urls) logging2.info('what should i write here') logging2.warning('a warning here') logging2.error('a error test here') logging2.critical('what is a critical??') #print 'reading' #except: #print 'error' #logging2.error('error ong reading '+urls) return returns def main(): i = 0 th = threading2.ThreadPool(workQueue,resultQueue,options.number) td = threading2.MyThread2(workQueue,resultQueue,i,10)#屏幕打印进程
if good: #print 'good' data = data.replace("'", '"') #纠结的单引号怎么处理? sqls = "insert into keyofhtml(urls,key,htmls) values('%s','%s','%s')" try: cor.execute(sqls % (urls, keyinsys, data)) except UnicodeDecodeError, e: #print e cor.execute(sqls % (urls, keyinsys, 'decode error')) logging2.error('reading ' + urls + ' decode error') conn.commit() #print 'donessss' conn.close() logging2.debug('reading ' + urls) logging2.info('what should i write here') logging2.warning('a warning here') logging2.error('a error test here') logging2.critical('what is a critical??') return returns def main(): """ 执行入口,层次判断,任务转移. >>> main() 时间 深度 当前完成 待完成 """ i = 0 th = threading2.ThreadPool(workQueue, resultQueue, options.number)
def get_own_segment(self, address=None): """injects an MMAP syscall so we get our own page for code""" if self.own_segment: return self.own_segment start = self.programinfo.getElfStart() address = address if address else start - 0x2000 debug("getownsegment adress = %x" % address) proc = self.ptraceProcess if proc.syscall_state.next_event == "exit": print("about to call syscall, returning") return # save state ip = proc.getInstrPointer() old_regs = proc.getregs() old_code = proc.readBytes(ip, len(inject_syscall_instr)) # prepare mmap syscall MAP_FIXED_NOREPLACE = 1048576 prot = PROT_EXEC mapflags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED_NOREPLACE length = 0x1000 fill_regs = ["rax", "rdi", "rsi", "rdx", "r10", "r8", "r9"] # calling convention for syscalls args = [9, address, length, prot, mapflags, -1, 0] # syscallcode, ..., filedescriptor, offset assert len(args) == len(fill_regs) for reg, arg in zip(fill_regs, args): proc.setreg(reg, arg) proc.writeBytes(ip, inject_syscall_instr) # step over the syscall proc.syscall() proc.waitSyscall() proc.syscall() proc.waitSyscall() result = proc.getreg("rax") debug("result= %x" % result) if result > 2**63 - 1: result -= 2**64 import errno if errno.EEXIST == -result: warning("mapping exists") return self.get_own_segment(address * 2) # restore state proc.writeBytes(ip, old_code) proc.setregs(old_regs) func_addr = address + 0x100 inject_code = """ call rax int3 int3 int3""" inject_code = pwn.asm(inject_code, arch="amd64") proc.writeBytes(func_addr, inject_code) nop_addr = address + 0x200 #proc.writeBytes(nop_addr, pwn.asm("nop\nint3")) # TODO jmp 0 proc.writeBytes(nop_addr, b"\xeb\xfe") # jumps to itself fork_addr = address + 0x300 proc.writeBytes(fork_addr, inject_syscall_instr) self.own_segment = InsertedGadgets(address, func_addr, nop_addr, fork_addr) return self.own_segment
def forkProcess(self): """ forks the process. If the process just syscalled (and is trapped in the syscall entry), the forked child starts just before that syscall. The processManager will switch to the newly created child automatically. Usage: fork gonna_crash_this (name is optional)""" """How does it work? If the process is about to enter a syscall: Modify $rax to contain the "fork" syscall code. Else: Insert a syscall instruction at the current $rip Step over the syscall, start tracing the new child. Restore the states of both processes. (Child does not reenter syscall) """ process = self.ptraceProcess ip = process.getInstrPointer() # save state regs = process.getregs() at_syscall_entry = process.syscall_state.next_event == "exit" # if process is about to syscall, dont inject if at_syscall_entry: # user wants to fork just before a syscall assert process.getreg( "rax" ) == 0xffFFffFFffFFffda # rax == -ENOSYS means we are most likely about to enter a syscall process.setreg("orig_rax", 57) else: #original = process.readBytes(ip, len(inject_syscall_instr)) #process.writeBytes(ip, inject_syscall_instr) process.setreg("rax", 57) # fork code process.setInstrPointer(self.get_own_segment().forkcode) process.singleStep() # continue till fork happended event = process.waitEvent() from ptrace.debugger.process_event import NewProcessEvent if not isinstance(event, NewProcessEvent): rax = process.getreg("rax") if rax > 2**64: converted_rax = -rax - 2**64 warning(errno.errorcode[converted_rax]) else: warning("unexpected %s in forkprocess" % event) assert isinstance(event, NewProcessEvent), str(event) process.syscall() # exit fork syscall process.waitSyscall() # restore state in parent and child process child = process.debugger.list[-1] assert child.getreg("rax") == 0 # successful fork process.setregs(regs) child.setregs(regs) if at_syscall_entry: # we just returned from our "inserted" fork syscall # now we need to restore the original state, meaning our # parent has to enter a syscall again. After that, restore registers ip = process.getInstrPointer() process.setInstrPointer(ip - 2) process.syscall() process.waitSyscall() process.setregs(regs) # child will enter syscall when user continues orig_rax = process.getreg("orig_rax") child.setreg("rax", orig_rax) child.setInstrPointer(ip - 2) else: pass #process.writeBytes(ip, original) #child.writeBytes(ip, original) child = ProcessWrapper(parent=self, ptraceprocess=child) self.children.append(child) return child
def parseInteger(text, procWrap=None): global ptraceProc_g ptraceProc_g = procWrap.ptraceProcess if procWrap else None # Remove spaces and convert to lower case text = text.strip() if " " in text: raise ValueError("Space are forbidden: %r" % text) text = text.lower() orig_text = text # replace symbols by their value def readSymbols(symbol): text = symbol.group(0) if procWrap is None: return text else: try: return str(procWrap.programinfo.getAddrOf(text)) except ValueError as e: debug(e) return text # Replace hexadecimal numbers by decimal numbers def readHexadecimal(regs): text = regs.group(0) if text.startswith("0x"): text = text[2:] elif not re.search("[a-f]", text): return text value = int(text, 16) return str(value) # (first_char)(rest)* if your symbol contains other characters, include them here symbol_regex = r"(?<!0x)[a-zA-Z_][a-zA-Z0-9_.]*" symbol_regex_with_library = symbol_regex + r"(:" + symbol_regex + ")?" text = re.sub(r"(?:0x)[0-9a-f]+", readHexadecimal, text) text = re.sub(symbol_regex_with_library, readSymbols, text) # Replace registers by their value text = REGISTER_REGEX.sub(readRegister, text) # Reject invalid characters if not re.match(r"^[()<>+*/&0-9-]+$", text): raise ValueError("Invalid expression: %r" % orig_text) # Use integer division (a//b) instead of float division (a/b) text = text.replace("/", "//") # Finally, evaluate the expression is_pointer = text.startswith("*") if is_pointer: text = text[1:] try: value = eval(text) value = truncateWord(value) except SyntaxError: raise ValueError("Invalid expression: %r" % orig_text) if is_pointer: assert isinstance(ptraceProc_g, PtraceProcess) # value = ptraceProc_g.readWord(value) try: value = ptraceProc_g.readBytes(value, 8) value = bytes2word(value) except PtraceError as e: warning(str(e)) value = 0 return value