File: disasm.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 (113 lines) | stat: -rw-r--r-- 3,018 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
106
107
108
109
110
111
112
113
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import argparse
import re
import string
import sys

import pwnlib.args
pwnlib.args.free_form = False

from pwn import *
from pwnlib.commandline import common

parser = common.parser_commands.add_parser(
    'disasm',
    help = 'Disassemble bytes into text format',
    description = 'Disassemble bytes into text format'
)

parser.add_argument(
    'hex',
    metavar = 'hex',
    nargs = '*',
    help = 'Hex-string to disassemble. If none are supplied, then it uses stdin in non-hex mode.'
)

parser.add_argument(
    '-c', '--context',
    metavar = 'arch_or_os',
    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(
    "-a","--address",
    metavar='address',
    help="Base address",
    type=str,
    default='0'
)


parser.add_argument(
    '--color',
    help="Color output",
    action='store_true',
    default=sys.stdout.isatty()
)

parser.add_argument(
    '--no-color',
    help="Disable color output",
    action='store_false',
    dest='color'
)


def main(args):
    if len(args.hex) > 0:
        dat = ''.join(args.hex).encode('utf-8', 'surrogateescape')
        dat = dat.translate(None, string.whitespace.encode('ascii'))
        if not set(string.hexdigits.encode('ascii')) >= set(dat):
            print("This is not a hex string")
            exit(-1)
        dat = unhex(dat)
    else:
        dat = getattr(sys.stdin, 'buffer', sys.stdin).read()


    if args.color:
        from pygments import highlight
        from pygments.formatters import TerminalFormatter
        from pwnlib.lexer import PwntoolsLexer

        dis = disasm(dat, vma=safeeval.const(args.address))

        # Note: those patterns are copied from disasm function
        pattern = '^( *[0-9a-f]+: *)((?:[0-9a-f]+ )+ *)(.*)'
        lines = []
        for line in dis.splitlines():
            match = re.search(pattern, line)
            if not match:
                # Append as one element tuple
                lines.append((line,))
                continue

            groups = match.groups()
            o, b, i = groups

            lines.append((o, b, i))


        highlight_bytes = lambda t: ''.join(map(lambda x: x.replace('00', text.red('00')).replace('0a', text.red('0a')), group(2, t)))
        for line in lines:
            if len(line) == 3:
                o, b, i = line
                b = ' '.join(highlight_bytes(bb) for bb in b.split(' '))
                i = highlight(i.strip(), PwntoolsLexer(), TerminalFormatter()).strip()
                i = i.replace(',',', ')
                print(o,b,i)
            else:
                print(line[0])
        return

    print(disasm(dat, vma=safeeval.const(args.address)))

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