Skip to content

Commit

Permalink
Initial support for debugging with official branch of Kenshoto's VTrace.
Browse files Browse the repository at this point in the history
Good support for ELF file format (both 32 and 64 bits).
Code analysis engine enhanced. Now it handles data refereces to locations defined as code (i.e., functions referenced at the entry point in GCC compiled programs).
Other minor fixes
  • Loading branch information
joxean committed Nov 27, 2011
1 parent 55e79fc commit 0294733
Show file tree
Hide file tree
Showing 51 changed files with 69,888 additions and 827 deletions.
1,253 changes: 469 additions & 784 deletions Elf/__init__.py

Large diffs are not rendered by default.

95 changes: 88 additions & 7 deletions Elf/elf_lookup.py
Original file line number Diff line number Diff line change
Expand Up @@ -326,13 +326,62 @@
R_386_TLS_DTPMOD32:"ID of module containing symbol",
R_386_TLS_DTPOFF32:"Offset in TLS block",
R_386_TLS_TPOFF32:"Negated offset in static TLS block",
#R_386_NUM:"",
}

## Define e_flags to 386
r_types = r_types_386
R_X86_64_NONE = 0
R_X86_64_64 = 1
R_X86_64_PC32 = 2
R_X86_64_GOT32 = 3
R_X86_64_PLT32 = 4
R_X86_64_COPY = 5
R_X86_64_GLOB_DAT = 6
R_X86_64_JUMP_SLOT = 7
R_X86_64_RELATIVE = 8
R_X86_64_GOTPCREL = 9
R_X86_64_32 = 10
R_X86_64_32S = 11
R_X86_64_16 = 12
R_X86_64_PC16 = 13
R_X86_64_8 = 14
R_X86_64_PC8 = 15
R_X86_64_DTPMOD64 = 16
R_X86_64_DTPOFF64 = 17
R_X86_64_TPOFF64 = 18
R_X86_64_TLSGD = 19
R_X86_64_TLSLD = 20
R_X86_64_DTPOFF32 = 21
R_X86_64_GOTTPOFF = 22
R_X86_64_TPOFF32 = 23
R_X86_64_NUM = 24

r_types_amd64 = {
R_X86_64_NONE :'No reloc',
R_X86_64_64 :'Direct 64 bit ',
R_X86_64_PC32 :'PC relative 32 bit signed',
R_X86_64_GOT32 :'32 bit GOT entry',
R_X86_64_PLT32 :'32 bit PLT address',
R_X86_64_COPY :'Copy symbol at runtime',
R_X86_64_GLOB_DAT :'Create GOT entry',
R_X86_64_JUMP_SLOT :'Create PLT entry',
R_X86_64_RELATIVE :'Adjust by program base',
R_X86_64_GOTPCREL :'32 bit signed PC relative offset to GOT',
R_X86_64_32 :'Direct 32 bit zero extended',
R_X86_64_32S :'Direct 32 bit sign extended',
R_X86_64_16 :'Direct 16 bit zero extended',
R_X86_64_PC16 :'16 bit sign extended pc relative',
R_X86_64_8 :'Direct 8 bit sign extended ',
R_X86_64_PC8 :'8 bit sign extended pc relative',
R_X86_64_DTPMOD64 :'ID of module containing symbol',
R_X86_64_DTPOFF64 :'Offset in modules TLS block',
R_X86_64_TPOFF64 :'Offset in initial TLS block',
R_X86_64_TLSGD :'32 bit signed PC relative offset to two GOT entries for GD symbol',
R_X86_64_TLSLD :'32 bit signed PC relative offset to two GOT entries for LD symbol',
R_X86_64_DTPOFF32 :'Offset in TLS block',
R_X86_64_GOTTPOFF :'32 bit signed PC relative offset to GOT entry for IE symbol',
R_X86_64_TPOFF32 :'Offset in initial TLS block',
}

## Define e_flags to 386
SHT_NULL = 0
SHT_PROGBITS = 1
SHT_SYMTAB = 2
Expand Down Expand Up @@ -504,10 +553,42 @@
DT_PREINIT_ARRAY = 32
DT_PREINIT_ARRAYSZ = 33
DT_NUM = 34
DT_LOOS = 0x6000000d
DT_HIOS = 0x6ffff000
DT_LOPROC = 0x70000000
DT_HIPROC = 0x7fffffff
DT_GNU_PRELINKED = 0x6ffffdf5
DT_GNU_CONFLICTSZ = 0x6ffffdf6
DT_GNU_LIBLISTSZ = 0x6ffffdf7
DT_CHECKSUM = 0x6ffffdf8
DT_PLTPADSZ = 0x6ffffdf9
DT_MOVEENT = 0x6ffffdfa
DT_MOVESZ = 0x6ffffdfb
DT_FEATURE_1 = 0x6ffffdfc
DT_POSFLAG_1 = 0x6ffffdfd
DT_SYMINSZ = 0x6ffffdfe
DT_SYMINENT = 0x6ffffdff
DT_GNU_HASH = 0x6ffffef5
DT_TLSDESC_PLT = 0x6ffffef6
DT_TLSDESC_GOT = 0x6ffffef7
DT_GNU_CONFLICT = 0x6ffffef8
DT_GNU_LIBLIST = 0x6ffffef9
DT_CONFIG = 0x6ffffefa
DT_DEPAUDIT = 0x6ffffefb
DT_AUDIT = 0x6ffffefc
DT_PLTPAD = 0x6ffffefd
DT_MOVETAB = 0x6ffffefe
DT_SYMINFO = 0x6ffffeff
DT_VERSYM = 0x6ffffff0
DT_RELACOUNT = 0x6ffffff9
DT_RELCOUNT = 0x6ffffffa
DT_FLAGS_1 = 0x6ffffffb
DT_VERDEF = 0x6ffffffc
DT_VERDEFNUM = 0x6ffffffd
DT_VERNEED = 0x6ffffffe
DT_VERNEEDNUM = 0x6fffffff
DT_AUXILIARY = 0x7ffffffd
DT_FILTER = 0x7fffffff
DT_LOOS = 0x6000000d
DT_HIOS = 0x6ffff000
DT_LOPROC = 0x70000000
DT_HIPROC = 0x7fffffff
#DT_PROCNUM = DT_MIPS_NUM

dt_types = {
Expand Down
20 changes: 20 additions & 0 deletions anal/x86analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,21 @@ def belongsTo(self, offset, func):
def resolveAddress(self, addr):
addr = str(addr)
if addr.find("[") > -1:
addr = addr.strip(" ")
addr = addr.strip("[").strip("]")
if addr.find("+") > -1 or addr.find("-") > -1:
return addr, False, True

name = self.pyew.resolveName(addr)
if name in self._imports:
return addr, True, False
elif addr.find(",") > -1:
part = addr.split(",")
if len(part) == 2:
try:
addr = int(part[1], 16)
except:
return None, False, True
else:
try:
addr = int(addr, 16)
Expand Down Expand Up @@ -270,6 +278,18 @@ def createFunction(self, addr):
# Break the basic block and clear 'lines', we don't want to
# continue analyzing the next assembler lines
break_bb = 2
elif mnem.startswith("MOV") or mnem.startswith("PUSH"):
if mnem == "PUSH":
val, isimport, isbreak = self.resolveAddress(l.operands)
else:
val, isimport, isbreak = self.resolveAddress(l.operands)

if val is not None:
addr = val
if self.pyew.executableMemory(addr):
offset = self.pyew.getOffsetFromVirtualAddress(addr)
f.addOutConnection(offset)
self.queue.append(offset)

i += 1
# Do we have to clear anything?
Expand Down
15 changes: 10 additions & 5 deletions gcluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,10 +253,11 @@ def clear(self):
self.data = []

def processFile(self, filename):
#print "[+] Analyzing file %s" % filename
pyew = CPyew(batch=False)
sys.stderr.write("[+] Analyzing file %s\n" % filename)
sys.stderr.flush()
pyew = CPyew(batch=True)
pyew.deepcodeanalysis = self.deep
pyew.analysis_timeout = 0
pyew.analysis_timeout = 15
pyew.loadFile(filename)

if pyew.format in ["PE", "ELF"]:
Expand Down Expand Up @@ -297,7 +298,11 @@ def compareExpert(self):

def processFiles(self):
for f in self.files:
self.processFile(f)
try:
self.processFile(f)
except:
sys.stderr.write("Error: %s\n" % str(sys.exc_info()[1]))
sys.stderr.flush()

def main(prog1, prog2):
cluster = CGraphCluster()
Expand Down Expand Up @@ -330,7 +335,7 @@ def compareDirectory(path):
for stat in pyew.program_stats:
data = data + ":".join(map(str, pyew.program_stats[stat].values())).replace(".", ",") + ":"
phash, dones = cprimes.generateHash(pyew)
print "%s:%s:%s:%s%d:%s" % (hash, pyew.f.name, str(phash.as_integer_ratio()[0]), data, len(pyew.functions), str(alist.adjacency_lists(pyew)))
print "%s:%s:%s:%s%d:%s" % (hash, pyew.f.name, str(phash.as_integer_ratio()[0]), data, len(pyew.functions), str(alist.createAdjacencyList(pyew)))

def usage():
print "Usage:", sys.argv[0], "<prog 1> <prog 2> | <directory>"
Expand Down
4 changes: 4 additions & 0 deletions plugins/UserDB.TXT
Original file line number Diff line number Diff line change
Expand Up @@ -26603,3 +26603,7 @@ ep_only=True
signature=B8 ?? ?? ?? 01 50 64 FF 35 00 00 00 00 64 89 25 00 00 00 00 33 C0 89 08 50 45 43 6F 6D 70 61 63 74 32 00
ep_only=True

[WinRAR SFX]
signature=E8 E3 FE FF FF 33 C0 50 50 50 50 E8 BE 2B 00 00
ep_only=True

6 changes: 3 additions & 3 deletions plugins/virustotal.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,14 @@ def printSummary(self):
if match:
print

def virusTotalSearch(pyew):
def virusTotalSearch(pyew, doprint=True):
""" Search the sample in Virus Total """
buf = pyew.getBuffer()
x = hashlib.md5(buf).hexdigest()

scanner = CVirusTotalScanner()
scanner.printResults = True
scanner.scan(pyew.filename, argmd5=x)
scanner.printResults = doprint
return scanner.scan(pyew.filename, argmd5=x)

functions={"vt":virusTotalSearch}

41 changes: 33 additions & 8 deletions pyew.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ def showHelp(pyew):
print "?/help Show this help"
print "x/dump/hexdump Show hexadecimal dump"
print "s/seek Seek to a new offset"
print "v/vseek Seek a to virtual address (PE and ELF only)"
print "b Return to previous offset"
print "g/G Goto BOF (g) or EOF (G)"
print "+/- Go forward/backward one block (specified by pyew.bsize)"
Expand All @@ -99,7 +100,10 @@ def showHelp(pyew):
print "wa data Write ASCII data to file"
print "file Load as new file the buffer from the current offset"
print "ret Return to the original file (use after 'file')"
print "interact Open an interactive Python console"
print "interact Open an interactive Python console"
if pyew.has_debug:
print pyew.debugHelp()

print
print "Cryptographic functions: md5, sha1, sha224, sha256, sha384, sha512"
print
Expand Down Expand Up @@ -280,7 +284,7 @@ def main(filename):
except:
cmd = raw_input(prompt)

if cmd in ["", "b"] and (last_cmd in ["b", "x", "c", "d", "dump", "hexdump", "dis", "pd", "p", "r", "buf"] or last_cmd.isdigit()):
if cmd in ["", "b"] and (last_cmd in ["b", "x", "c", "d", "dump", "hexdump", "dis", "pd", "p", "r", "buf", "stepi"] or last_cmd.isdigit()):
if cmd == "b":
tmp = pyew.previousoffset.pop()

Expand Down Expand Up @@ -308,6 +312,8 @@ def main(filename):
pyew.seek(pyew.offset)
if last_cmd.isdigit():
last_cmd = "c"
elif last_cmd in ["stepi"]:
cmd = "stepi"
else:
pyew.offset = pyew.offset+pyew.bsize
pyew.seek(pyew.offset)
Expand All @@ -328,7 +334,8 @@ def main(filename):
print
elif cmd.lower() in ["x", "dump", "hexdump"]:
print pyew.hexdump(pyew.buf, pyew.hexcolumns, baseoffset=pyew.offset)
elif cmd.split(" ")[0] in ["s", "seek"]:
elif cmd.split(" ")[0] in ["s", "seek", "v", "vseek"]:
virtual = cmd.split(" ")[0].startswith("v")
data = cmd.split(" ")
if len(data) > 1:
if data[1].lower() in ["ep", "entrypoint"]:
Expand All @@ -348,21 +355,27 @@ def main(filename):
break
else:
pyew.offset = int(data[1])

pyew.seek(pyew.offset)
if virtual:
pyew.vseek(pyew.offset)
else:
pyew.seek(pyew.offset)
elif cmd.lower().split(" ")[0] in ["c", "d", "dis", "pd"]:
data = cmd.lower().split(" ")
if len(data) > 1:
if pyew.virtual:
off = self.getVirtualAddressFromOffset(pyew.offset)
else:
off = pyew.offset
if not data[1].startswith("/"):
type = int(data[1])
dis = pyew.disassemble(pyew.buf, pyew.processor, pyew.type, pyew.lines, pyew.bsize, baseoffset=pyew.offset)
dis = pyew.disassemble(pyew.buf, pyew.processor, pyew.type, pyew.lines, pyew.bsize, baseoffset=off)
print dis
else:
cmd = data[1:]
if len(cmd) > 1:
ret = pyew.dosearch(pyew.f, cmd[0][1:2], cmd[1], cols=60, doprint=False, offset=pyew.offset)
ret = pyew.dosearch(pyew.f, cmd[0][1:2], cmd[1], cols=60, doprint=False, offset=off)
else:
ret = pyew.dosearch(pyew.f, cmd[0][1:2], "", cols=60, doprint=False, offset=pyew.offset)
ret = pyew.dosearch(pyew.f, cmd[0][1:2], "", cols=60, doprint=False, offset=off)

for x in ret:
dis = pyew.disassemble(x.values()[0], pyew.processor, pyew.type, pyew.lines, pyew.bsize, baseoffset=x.keys()[0])
Expand Down Expand Up @@ -496,7 +509,19 @@ def main(filename):
pyew.f.seek(pyew.offset)
pyew.f.write(data)
pyew.seek(pyew.offset)
elif cmd.split(" ")[0] == "f":
if not 'names' in dir(pyew):
print "No function found"
else:
print "Function\tNodes\tEdges\tComplexity"
for f in pyew.names:
if pyew.function_stats.has_key(f) and not pyew.names[f].startswith("j_"):
nodes, edges, cc = pyew.function_stats[f]
print pyew.names[f].ljust(10), "\t", nodes, "\t", edges, "\t", cc
else:
if pyew.has_debug and pyew.debugHandler(cmd):
continue

if cmd.find("=") > -1 or cmd.startswith("print") or cmd.startswith("import "):
exec(cmd)
else:
Expand Down
Loading

0 comments on commit 0294733

Please sign in to comment.