Skip to main content
`Ctrl`+`K`

# Code Examples

This section contains some examples of how to use libdebug. They are either snippets taken from our write-ups of CTF challenges, or ad-hoc examples. Please find the binary executables in the test/binaries folder.

## CyberChallenge.IT 2024 - Workshop

This script was used to show the various features of libdebug during the Workshop at the CyberChallenge.IT 2024 Finals. An explanation of the script, along with a brief introduction to libdebug, is available in the official stream of the event, starting from 2:17:00.

    from libdebug import debugger
    from string import ascii_letters, digits

    # Enable the escape_antidebug option to bypass the ptrace call
    d = debugger("main", escape_antidebug=True)

    def callback(_, __):
        # This will automatically issue a continue when the breakpoint is hit
        pass

    def on_enter_nanosleep(t, _):
        # This sets every argument to NULL to make the syscall fail
        t.syscall_arg0 = 0
        t.syscall_arg1 = 0
        t.syscall_arg2 = 0
        t.syscall_arg3 = 0

    alphabet = ascii_letters + digits + "_{}"

    flag = b""
    best_hit_count = 0

    while True:
        for c in alphabet:
            r = d.run()

            # Any time we call run() we have to reset the breakpoint and syscall handler
            bp = d.breakpoint(0x13e1, hardware=True, callback=callback, file="binary")
            d.handle_syscall("clock_nanosleep", on_enter=on_enter_nanosleep)

            d.cont()

            r.sendline(flag + c.encode())

            # This makes the debugger wait for the process to terminate
            d.wait()

            response = r.recvline()

            # `run()` will automatically kill any still-running process, but it's good practice to do it manually
            d.kill()

            if b"Yeah" in response:
                # The flag is correct
                flag += c.encode()
                print(flag)
                break

            if bp.hit_count > best_hit_count:
                # We have found a new flag character
                best_hit_count = bp.hit_count
                flag += c.encode()
                print(flag)
                break

        if c == "}":
            break

    print(flag)

## DEFCON Quals 2023 - nlinks

This is a script that solves the challenge nlinks from DEFCON Quals 2023. Please find the binary executables in the test/CTF folder.

    def get_passsphrase_from_class_1_binaries(previous_flag):
        flag = b""

        d = debugger("CTF/1")
        r = d.run()

        bp = d.breakpoint(0x7EF1, hardware=True, file="binary")

        d.cont()

        r.recvuntil(b"Passphrase:\n")

        # We send a fake flag after the valid password
        r.send(previous_flag + b"a" * 8)

        for _ in range(8):
            # Here we reached the breakpoint
            if not bp.hit_on(d):
                print("Here we should have hit the breakpoint")

            offset = ord("a") ^ d.regs.rbp
            d.regs.rbp = d.regs.r13

            # We calculate the correct character value and append it to the flag
            flag += (offset ^ d.regs.r13).to_bytes(1, "little")

            d.cont()

        r.recvline()

        d.kill()

        # Here the value of flag is b"\x00\x006\x00\x00\x00(\x00"
        return flag

    def get_passsphrase_from_class_2_binaries(previous_flag):
        bitmap = {}
        lastpos = 0
        flag = b""

        d = debugger("CTF/2")
        r = d.run()

        bp1 = d.breakpoint(0xD8C1, hardware=True, file="binary")
        bp2 = d.breakpoint(0x1858, hardware=True, file="binary")
        bp3 = d.breakpoint(0xDBA1, hardware=True, file="binary")

        d.cont()

        r.recvuntil(b"Passphrase:\n")
        r.send(previous_flag + b"a" * 8)

        while True:
            if d.regs.rip == bp1.address:
                # Prepare for the next element in the bitmap
                lastpos = d.regs.rbp
                d.regs.rbp = d.regs.r13 + 1
            elif d.regs.rip == bp2.address:
                # Update the bitmap
                bitmap[d.regs.r12 & 0xFF] = lastpos & 0xFF
            elif d.regs.rip == bp3.address:
                # Use the bitmap to calculate the expected character
                d.regs.rbp = d.regs.r13
                wanted = d.regs.rbp
                needed = 0
                for i in range(8):
                    if wanted & (2**i):
                        needed |= bitmap[2**i]
                flag += chr(needed).encode()

                if bp3.hit_count == 8:
                    # We have found all the characters
                    d.cont()
                    break

            d.cont()

        d.kill()

        # Here the value of flag is b"\x00\x00\x00\x01\x00\x00a\x00"
        return flag

    def get_passsphrase_from_class_3_binaries():
        flag = b""

        d = debugger("CTF/0")
        r = d.run()

        bp = d.breakpoint(0x91A1, hardware=True, file="binary")

        d.cont()

        r.send(b"a" * 8)

        for _ in range(8):

            # Here we reached the breakpoint
            if not bp.hit_on(d):
                print("Here we should have hit the breakpoint")

            offset = ord("a") - d.regs.rbp
            d.regs.rbp = d.regs.r13

            # We calculate the correct character value and append it to the flag
            flag += chr((d.regs.r13 + offset) % 256).encode("latin-1")

            d.cont()

        r.recvline()

        d.kill()

        # Here the value of flag is b"BM8\xd3\x02\x00\x00\x00"
        return flag

    def run_nlinks():
        flag0 = get_passsphrase_from_class_3_binaries()
        flag1 = get_passsphrase_from_class_1_binaries(flag0)
        flag2 = get_passsphrase_from_class_2_binaries(flag1)

        print(flag0, flag1, flag2)