File: debug.py

package info (click to toggle)
pwntools 4.15.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 18,508 kB
  • sloc: python: 59,870; ansic: 48,351; asm: 45,047; sh: 396; makefile: 256
file content (105 lines) | stat: -rw-r--r-- 3,019 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
from __future__ import absolute_import
from __future__ import division

import argparse
import sys

from pwn import *
from pwnlib.commandline import common

parser = common.parser_commands.add_parser(
    'debug',
    help = 'Debug a binary in GDB',
    description = 'Debug a binary in GDB'
)
parser.add_argument(
    '-x', metavar='GDBSCRIPT',
    type=argparse.FileType('r'),
    help='Execute GDB commands from this file.'
)
parser.add_argument(
    '--pid',
    type=int,
    help="PID to attach to"
)
parser.add_argument(
    '-c', '--context',
    metavar = 'context',
    action = 'append',
    type   = common.context_arg,
    choices = common.choices,
    help = 'The os/architecture/endianness/bits the shellcode will run in (default: linux/i386), choose from: %s' % common.choices,
)
parser.add_argument(
    '--exec',

    # NOTE: Type cannot be "file" because we may be referring to a remote
    #       file, or a file on an Android device.
    type=str,

    dest='executable',
    help='File to debug'
)
parser.add_argument(
    '--process', metavar='PROCESS_NAME',
    help='Name of the process to attach to (e.g. "bash")'
)
parser.add_argument(
    '--sysroot', metavar='SYSROOT',
    type=str,
    default='',
    help="GDB sysroot path"
)

def main(args):
    gdbscript = ''
    if args.x:
        gdbscript = args.x.read()

    if context.os == 'android':
        context.device = adb.wait_for_device()

    if args.executable:
        if os.path.exists(args.executable):
            context.binary = ELF(args.executable)
            target = context.binary.path

        # This path does nothing, but avoids the "print_usage()"
        # path below.
        elif context.os == 'android':
            target = args.executable
    elif args.pid:
        target = int(args.pid)
    elif args.process:
        if context.os == 'android':
            target = adb.pidof(args.process)
        else:
            target = pidof(args.process)

        # pidof() returns a list
        if not target:
            log.error("Could not find a PID for %r", args.process)

        target = target[0]

        # pidof will sometimes return all PIDs, including init
        if target == 1:
            log.error("Got PID 1 from pidof.  Check the process name, or use --pid 1 to debug init")
    else:
        parser.print_usage()
        return 1

    if args.pid or args.process:
        pid = gdb.attach(target, gdbscript=gdbscript, sysroot=args.sysroot)

        # Since we spawned the gdbserver process, and process registers an
        # atexit handler to close itself, gdbserver will be terminated when
        # we exit.  This will manifest as a "remote connected ended" or
        # similar error message.  Hold it open for the user.
        log.info("GDB connection forwarding will terminate when you press enter")
        pause()
    else:
        gdb.debug(target, gdbscript=gdbscript, sysroot=args.sysroot).interactive()

if __name__ == '__main__':
    pwnlib.commandline.common.main(__file__, main)