-
Notifications
You must be signed in to change notification settings - Fork 33
Expand file tree
/
Copy pathhaystack
More file actions
111 lines (88 loc) · 4.46 KB
/
haystack
File metadata and controls
111 lines (88 loc) · 4.46 KB
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
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright (C) 2011 Loic Jaquemet loic.jaquemet+python@gmail.com
#
__author__ = "Loic Jaquemet loic.jaquemet+python@gmail.com"
__doc__ = '''
Structure search and operation on live process.
'''
import argparse
import logging
import os
import sys
from haystack import argparse_utils
from haystack import abouchet, watch
log = logging.getLogger('haystack')
def argparser():
"""
Builds the argparse tree.
See the command line --help .
"""
rootparser = argparse.ArgumentParser(prog='haystack', description='Live memory tools on heap structures.')
rootparser.add_argument('--debug', dest='debug', action='store_const', const=True, help='setLevel to DEBUG')
rootparser.add_argument('--quiet', dest='quiet', action='store_const', const=True, help='setLevel to ERROR only')
rootparser.add_argument('--interactive', dest='interactive', action='store_const', const=True, help='drop to python command line after action')
rootparser.add_argument('--nommap', dest='mmap', action='store_const', const=False, default=True, help='disable mmap()-ing')
rootparser.add_argument('structName', type=str, help='Structure type name')
rootparser.add_argument('--baseOffset', type=str, help='base offset of the memory map in the dump file.')
target = rootparser.add_mutually_exclusive_group(required=True)
target.add_argument('--pid', type=int, help='Target PID')
target.add_argument('--memfile', type=argparse.FileType('r'), help='Use a file memory dump instead of a live process ID')
target.add_argument('--dumpname', type=argparse_utils.readable, help='Use a haystack memory dump instead of a live process ID')
output = rootparser.add_mutually_exclusive_group(required=True)
output.add_argument('--string', dest='human', action='store_const', const=True, help='Print results as human readable string')
output.add_argument('--json', dest='json', action='store_const', const=True, help='Print results as json readable string')
output.add_argument('--pickled', dest='pickled', action='store_const', const=True, help='Print results as pickled string')
subparsers = rootparser.add_subparsers(help='sub-command help')
search_parser = subparsers.add_parser('search', help='search help')
search_parser.add_argument('--fullscan', action='store_const', const=True, default=False, help='do a full memory scan, otherwise, restrict to the heap')
search_parser.add_argument('--maxnum', type=int, action='store', default=1, help='Limit to maxnum numbers of results')
search_parser.add_argument('--hint', type=argparse_utils.int16, action='store', default=0, help='hintOffset to start at in hex')
search_parser.set_defaults(func=abouchet._search_cmdline)
#
refresh_parser = subparsers.add_parser('refresh', help='refresh help')
refresh_parser.add_argument('addr', type=str, help='Structure memory address')
refresh_parser.set_defaults(func=abouchet.refresh)
#
watch_parser = subparsers.add_parser('watch', help='watch a structure in a live process')
watch_parser.add_argument('addr', type=argparse_utils.int16, help='Structure memory address')
watch_parser.add_argument('refresh_rate', type=int, action='store', default=0, help='Seconds between refresh')
watch_parser.add_argument('varname', type=str, action='store', default=None, help='structure member name (eg. pointername.valuename)')
watch_parser.set_defaults(func=watch.watch)
return rootparser
def main(argv):
parser = argparser()
opts = parser.parse_args(argv)
level = logging.INFO
if opts.debug:
level=logging.DEBUG
elif opts.quiet:
level=logging.ERROR
if opts.debug :
flog = os.path.normpath('log')
logging.basicConfig(level=level, filename=flog, filemode='w')
print ('[+] **** COMPLETE debug log to %s'%(flog))
else:
logging.basicConfig(level=level)
sh=logging.StreamHandler(sys.stdout) # 2.6, 2.7 compat
#logging.getLogger('abouchet').addHandler( sh )
logging.getLogger('haystack').addHandler( sh )
if opts.json:
log.warning('the JSON feature is experimental and probably wont work.')
try:
opts.func(opts)
except ImportError,e:
log.error('Structure type does not exists.')
log.error('sys.path is %s'%sys.path)
print e
if opts.pid:
log.debug("done for pid %d"%opts.pid)
elif opts.memfile:
log.debug("done for file %s"%opts.memfile.name)
elif opts.dumpname:
log.debug("done for file %s"%opts.dumpname)
return 0
if __name__ == "__main__":
sys.path.append(os.getcwd())
main(sys.argv[1:])