class GDB: def __init__(self): self.gdbmi = None self.timeout = 10 self.command = "" self.opLog = None def gdbStart(self, gdbPath): #open log file logFile = 'copy_to_flash_' + str( datetime.now().strftime("%Y-%m-%d_%H:%M:%S")) + '.log' self.opLog = open(logFile, 'w+') #open gdb self.gdbmi = GdbController(gdb_path=gdbPath, gdb_args=None, time_to_check_for_additional_output_sec=4.5, rr=False, verbose=False) #print('started gdb') def gdbSendCommand(self, command): self.command = command if self.gdbmi is None: return False #send command and get output. response = self.gdbmi.write(command, timeout_sec=self.timeout) if len(response) == 0: return False return response def gdbClose(self): #close gdb if self.gdbmi is None: return False self.gdbmi.send_signal_to_gdb("SIGINT") self.gdbmi.send_signal_to_gdb(2) self.gdbmi.interrupt_gdb() assert self.gdbmi.exit() is None assert self.gdbmi.gdb_process is None self.opLog.close() return True def getResponseTypeMsg(self, response): TypeMsg = "" typeMsgNum = str(response).count("payload") #get exact gdb console response. for line in range(typeMsgNum): if (str(response[line]['type'])) == "console": TypeMsg += (str(response[line]['payload'])) self.opLog.write("The output of " + self.command + " :\n" + TypeMsg + "\n") return TypeMsg def gdbSendSignal(self, sig): if self.gdbmi is None: return False self.gdbmi.send_signal_to_gdb(sig)
def test_controller(self): """Build a simple C program, then run it with GdbController and verify the output is parsed as expected""" # Initialize object that manages gdb subprocess gdbmi = GdbController() c_hello_world_binary = self._get_c_program("hello", "pygdbmiapp.a") if USING_WINDOWS: c_hello_world_binary = c_hello_world_binary.replace("\\", "/") # Load the binary and its symbols in the gdb subprocess responses = gdbmi.write("-file-exec-and-symbols %s" % c_hello_world_binary, timeout_sec=1) # Verify output was parsed into a list of responses assert len(responses) != 0 response = responses[0] assert set(response.keys()) == { "message", "type", "payload", "stream", "token" } assert response["message"] == "thread-group-added" assert response["type"] == "notify" assert response["payload"] == {"id": "i1"} assert response["stream"] == "stdout" assert response["token"] is None responses = gdbmi.write( ["-file-list-exec-source-files", "-break-insert main"]) assert len(responses) != 0 responses = gdbmi.write(["-exec-run", "-exec-continue"], timeout_sec=3) found_match = False print(responses) for r in responses: if (r.get( "payload", "" ) == " leading spaces should be preserved. So should trailing spaces. " ): found_match = True assert found_match is True # Test GdbTimeoutError exception got_timeout_exception = False try: gdbmi.get_gdb_response(timeout_sec=0) except GdbTimeoutError: got_timeout_exception = True assert got_timeout_exception is True # Close gdb subprocess if not USING_WINDOWS: # access denied on windows gdbmi.send_signal_to_gdb("SIGINT") gdbmi.send_signal_to_gdb(2) gdbmi.interrupt_gdb() responses = gdbmi.exit() assert responses is None assert gdbmi.gdb_process is None # Test NoGdbProcessError exception got_no_process_exception = False try: responses = gdbmi.write("-file-exec-and-symbols %s" % c_hello_world_binary) except NoGdbProcessError: got_no_process_exception = True assert got_no_process_exception is True # Respawn and test signal handling gdbmi.spawn_new_gdb_subprocess() responses = gdbmi.write("-file-exec-and-symbols %s" % c_hello_world_binary, timeout_sec=1) responses = gdbmi.write(["-break-insert main", "-exec-run"]) if not USING_WINDOWS: gdbmi.interrupt_gdb() gdbmi.send_signal_to_gdb(2) gdbmi.send_signal_to_gdb("sigTeRm") try: gdbmi.send_signal_to_gdb("sigterms") # exception must be raised assert False except ValueError: assert True responses = gdbmi.write("-exec-run") if not USING_WINDOWS: gdbmi.send_signal_to_gdb("sigstop")
gdbmi = GdbController() gdbmi.write('set cwd ./bin') gdbmi.write('-file-exec-file ./bin/amicomputable') gdbmi.write('set disassembly-flavor intel') gdbmi.write('set environment LD_PRELOAD %s/quick_sort.so' % DIRNAME) gdbmi.write('run') print("The PIE offset of the sorting function is: %s" % hex(SORTARR_PIE_OFF)) # # Search the sort array function # Cf. Writeup (SOON) # sleep(0.5) gdbmi.send_signal_to_gdb('SIGINT') gdbmi.interrupt_gdb() res = gdbmi.write('') curr_addy = [ x['payload']['frame']['addr'] for x in res if x['type'] == 'notify' ][0] curr_addy = int(curr_addy, 16) print("We just break on: %s" % hex(curr_addy)) sortarr_addy = (curr_addy & 0xFFFFFFFFFFFFF000) + SORTARR_PIE_OFF print("Sorting function is located at: %s" % hex(sortarr_addy)) #
def test_controller(self): """Build a simple C program, then run it with GdbController and verify the output is parsed as expected""" # Initialize object that manages gdb subprocess gdbmi = GdbController() c_hello_world_binary = self._get_c_program('hello', 'pygdbmiapp.a') if USING_WINDOWS: c_hello_world_binary = c_hello_world_binary.replace('\\', '/') # Load the binary and its symbols in the gdb subprocess responses = gdbmi.write('-file-exec-and-symbols %s' % c_hello_world_binary, timeout_sec=1) # Verify output was parsed into a list of responses assert(len(responses) != 0) response = responses[0] assert(set(response.keys()) == set(['message', 'type', 'payload', 'stream', 'token'])) assert(response['message'] == 'thread-group-added') assert(response['type'] == 'notify') assert(response['payload'] == {'id': 'i1'}) assert(response['stream'] == 'stdout') assert(response['token'] is None) responses = gdbmi.write(['-file-list-exec-source-files', '-break-insert main']) assert(len(responses) != 0) responses = gdbmi.write(['-exec-run', '-exec-continue'], timeout_sec=3) found_match = False for r in responses: if r.get('payload', '') == ' leading spaces should be preserved. So should trailing spaces. ': found_match = True assert(found_match is True) # Test GdbTimeoutError exception got_timeout_exception = False try: gdbmi.get_gdb_response(timeout_sec=0) except GdbTimeoutError: got_timeout_exception = True assert(got_timeout_exception is True) # Close gdb subprocess if not USING_WINDOWS: # access denied on windows gdbmi.send_signal_to_gdb('SIGINT') gdbmi.send_signal_to_gdb(2) gdbmi.interrupt_gdb() responses = gdbmi.exit() assert(responses is None) assert(gdbmi.gdb_process is None) # Test NoGdbProcessError exception got_no_process_exception = False try: responses = gdbmi.write('-file-exec-and-symbols %s' % c_hello_world_binary) except NoGdbProcessError: got_no_process_exception = True assert(got_no_process_exception is True) # Respawn and test signal handling gdbmi.spawn_new_gdb_subprocess() responses = gdbmi.write('-file-exec-and-symbols %s' % c_hello_world_binary, timeout_sec=1) responses = gdbmi.write(['-break-insert main', '-exec-run']) if not USING_WINDOWS: gdbmi.interrupt_gdb() gdbmi.send_signal_to_gdb(2) gdbmi.send_signal_to_gdb('sigTeRm') try: gdbmi.send_signal_to_gdb('sigterms') # exception must be raised assert(False) except ValueError: assert(True) responses = gdbmi.write('-exec-run') if not USING_WINDOWS: gdbmi.send_signal_to_gdb('sigstop')
print "[%d] NORMAL EXIT %s" % (num, fn) response = gdbmi.exit() continue else: print "err:%s" % fn pprint(response) response = gdbmi.exit() break else: print "err:%s" % fn pprint(response) response = gdbmi.exit() break response = gdbmi.write('bt') #pprint(response) response = gdbmi.send_signal_to_gdb( 'SIGKILL') # name of signal is okay # response = gdbmi.send_signal_to_gdb(2) # value of signal is okay too # response = gdbmi.interrupt_gdb() # sends SIGINT to gdb # response = gdbmi.write('continue') response = gdbmi.exit() print "Total files %d. Total analyzed:%d." % (num, cnt) print "Classes:" j = 0 for key, value in res.items(): j += 1 print "CLASS[%d]:" % j print key print value