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)
Beispiel #2
0
    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")
Beispiel #3
0
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))

#
Beispiel #4
0
    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')
Beispiel #5
0
                    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