-
Notifications
You must be signed in to change notification settings - Fork 33
Expand file tree
/
Copy pathhaystack-reverse
More file actions
141 lines (110 loc) · 4.71 KB
/
haystack-reverse
File metadata and controls
141 lines (110 loc) · 4.71 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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#!/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__ = '''
Reverse heap analysis.
'''
import argparse
import logging
import os
import sys
import haystack
from haystack import argparse_utils
from haystack.config import Config
from haystack.reverse import signature, reversers
log = logging.getLogger('haystack-reverse')
def reverseInstances(opt):
context = reversers.reverseInstances(opt.dumpname)
return
def writeReversedTypes(opt):
'''reverse types from a memorydump, and write structure definition to file '''
context, sizeCache = signature.makeSizeCaches(opt.dumpname)
context = signature.makeReversedTypes(context, sizeCache)
outfile = file(Config.getCacheFilename(Config.REVERSED_TYPES_FILENAME, context.dumpname),'w')
for revStructType in context.listReversedTypes():
outfile.write(revStructType.toString())
outfile.close()
log.info('[+] Wrote to %s'%(outfile.name))
return
def showStructures(opt):
''' show sorted structure instances groups to stdout '''
context, sizeCache = signature.makeSizeCaches(opt.dumpname)
for chains in signature.buildStructureGroup(context, sizeCache, opt.size ):
signature.printStructureGroups(context, chains, opt.originAddr )
return
def saveSignatures(opt):
''' translate a memdump into a signature based file '''
context, sig = signature.makeSignatures(opt.dumpname)
outfile = Config.getCacheFilename(Config.SIGNATURES_FILENAME, context.dumpname)
file(outfile,'w').write(sig)
log.info('[+] Signature written to %s'%(outfile))
return
def printParents(opt):
''' print the parental structures '''
log.info('[+] Load context')
context = reversers.getContext(opt.dumpname)
log.info('[+] find offsets of struct_addr:%x'%(opt.address))
i = 0
try:
for st in context.listStructuresForPointerValue(opt.address):
st.decodeFields()
print st.toString()
i+=1
except ValueError,e:
log.info('[+] Found no structures.')
return
log.info('[+] Found %d structures.'%( i ))
return
def argparser():
rootparser = argparse.ArgumentParser(prog='haystack-reverser',
description='Several tools to reverse engineer structures on the heap.')
subparsers = rootparser.add_subparsers(help='sub-command help')
instances = subparsers.add_parser('instances',
help='Reverse and list structures instances with virtual address and member types.')
instances.set_defaults(func=reverseInstances)
typemap = subparsers.add_parser('typemap',
help='Reverse and list of structure types.')
typemap.set_defaults(func=writeReversedTypes)
show = subparsers.add_parser('show', help='Show sorted structure instances groups by size and signature')
show.add_argument('--size', type=int, action='store', default=None,
help='Limit to a specific structure size')
show.add_argument('--originAddr', type=str, action='store', default=None,
help='Limit to structure similar to the structure pointed at originAddr')
show.set_defaults(func=showStructures)
parent = subparsers.add_parser('parent', help='print parental structures pointing to this address.')
parent.add_argument('address', type=argparse_utils.int16, action='store', default=None,
help='Hex address of the child structure.')
parent.set_defaults(func=printParents)
#oldies
makesig = subparsers.add_parser('makesig', help='make signatures for dumpname')
makesig.set_defaults(func=saveSignatures)
rootparser.add_argument('--debug', action='store_true', help='Debug mode on.')
rootparser.add_argument('dumpname', type=argparse_utils.readable, action='store', help='Source memory dump by haystack.')
return rootparser
def main(argv):
parser = argparser()
opts = parser.parse_args(argv)
level=logging.WARNING
if opts.debug :
level=logging.DEBUG
flog = os.path.sep.join([Config.cacheDir,'log'])
logging.basicConfig(level=level, filename=flog, filemode='w')
logging.getLogger('haystack-reverse').setLevel(logging.DEBUG)
logging.getLogger('signature').setLevel(logging.DEBUG)
logging.getLogger('reversers').setLevel(logging.DEBUG)
logging.getLogger().debug('[+] **** COMPLETE debug log to %s'%(flog))
else:
logging.getLogger('haystack-reverse').setLevel(logging.INFO)
logging.getLogger('signature').setLevel(logging.INFO)
logging.getLogger('reversers').setLevel(logging.INFO)
sh=logging.StreamHandler(stream=sys.stdout)
logging.getLogger('signature').addHandler( sh )
logging.getLogger('reversers').addHandler( sh )
logging.getLogger('haystack-reverse').addHandler( sh )
opts.func(opts)
if __name__ == "__main__":
sys.path.append(os.getcwd())
main(sys.argv[1:])