mirror of
https://github.com/vivisect/vivisect
synced 2026-06-08 18:04:23 +00:00
Elf/Intel/Codeblocks fixes (#411)
* missing instr * more tweaks while I track down some of these graph build messages * another sprawling commit. Lots of cleanup. decoding fix for intel, qgraphtree fix atlas pointed out that I had initially mised, more better thunk detection, slightly more accurate emucode, and working on but not finished elf relocation additions * back that out for now * more tweaks as I try and get elf tests passing again * tons of test data mostly and a reloc fix * test update * Make it slick thanks to willi Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com> * clean up a bunch of exception related stuff and doc the new function thunker * Update vivisect/parsers/elf.py adding in a comment for @rakuy0 so i can approve this. Co-authored-by: Willi Ballenthin <willi.ballenthin@gmail.com> Co-authored-by: atlas0fd00m <atlas@r4780y.com>
This commit is contained in:
+7
-4
@@ -14,9 +14,9 @@ allows you a bunch of readelf-like functionality.
|
||||
and spit them back out in working order (not complete, you
|
||||
may notice some of the initial code).
|
||||
|
||||
Send bug reports to Invisigoth or Metr0.
|
||||
|
||||
Send bug reports to rakuyo or at1as in the issue tracker
|
||||
"""
|
||||
|
||||
# Copyright (C) 2007 Invisigoth - See LICENSE file for details
|
||||
import io
|
||||
import logging
|
||||
@@ -196,13 +196,16 @@ class ElfSection:
|
||||
return self.name
|
||||
|
||||
def __repr__(self):
|
||||
return 'Elf Sec: [%20s] @0x%.8x (%8d) ent/size: %8d/%8d align: %8d' % (
|
||||
flags = [name for idx, name in sh_flags.items() if idx & self.sh_flags]
|
||||
|
||||
return 'Elf Sec: [%20s] @0x%.8x (%8d) [ent/size: %8d/%8d] [align: %8d] [%s]' % (
|
||||
self.name,
|
||||
self.sh_addr,
|
||||
self.sh_offset,
|
||||
self.sh_entsize,
|
||||
self.sh_size,
|
||||
self.sh_addralign)
|
||||
self.sh_addralign,
|
||||
'Flags: ' + ', '.join(flags))
|
||||
|
||||
class Elf32Section(ElfSection, vs_elf.Elf32Section):
|
||||
def __init__(self, bigend=False):
|
||||
|
||||
@@ -486,7 +486,7 @@ class Amd64Disasm(e_i386.i386Disasm):
|
||||
memsz = OP_EXTRA_MEMSIZES[(operflags & OP_MEMMASK) >> 4]
|
||||
if memsz is not None:
|
||||
oper.tsize = memsz
|
||||
elif prefixes & PREFIX_ADDR_SIZE:
|
||||
if prefixes & PREFIX_ADDR_SIZE:
|
||||
if getattr(oper, 'reg', None) is not None:
|
||||
oper.reg |= RMETA_LOW32
|
||||
elif getattr(oper, 'index', None) is not None:
|
||||
|
||||
@@ -778,8 +778,8 @@ tbl32_660F[0xfe] = (0, INS_ADD, ADDRMETH_V | OPTYPE_x | OP_W, ADDRMETH_VEXSKIP
|
||||
|
||||
|
||||
tbl32_F20F = [(0, 0, ARG_NONE, ARG_NONE, ARG_NONE, ARG_NONE, 0, 0, 0, 0, 0) for x in range(256)]
|
||||
tbl32_F20F[0x10] = (0, INS_MOV, ADDRMETH_V | OPTYPE_sd | OP_W, ADDRMETH_VEXSKIP | ADDRMETH_VEXH | OPTYPE_x | OP_R, ADDRMETH_W | OPTYPE_sd | OP_R, ARG_NONE, cpu_PENTIUM2, "movsd", 0, 0, 0)
|
||||
tbl32_F20F[0x11] = (0, INS_MOV, ADDRMETH_W | OPTYPE_sd | OP_W, ADDRMETH_VEXSKIP | ADDRMETH_VEXH | OPTYPE_x | OP_R, ADDRMETH_V | OPTYPE_sd | OP_R, ARG_NONE, cpu_PENTIUM2, "movsd", 0, 0, 0)
|
||||
tbl32_F20F[0x10] = (0, INS_MOV, ADDRMETH_V | OPTYPE_sd | OP_W, ADDRMETH_VEXSKIP | ADDRMETH_VEXH | OPTYPE_x | OP_R, ADDRMETH_W | OPTYPE_sd | OP_MEM_Q | OP_R, ARG_NONE, cpu_PENTIUM2, "movsd", 0, 0, 0)
|
||||
tbl32_F20F[0x11] = (0, INS_MOV, ADDRMETH_W | OPTYPE_sd | OP_MEM_Q | OP_W, ADDRMETH_VEXSKIP | ADDRMETH_VEXH | OPTYPE_x | OP_R, ADDRMETH_V | OPTYPE_sd | OP_R, ARG_NONE, cpu_PENTIUM2, "movsd", 0, 0, 0)
|
||||
tbl32_F20F[0x12] = (0, INS_MOV, ADDRMETH_V | OPTYPE_x | OP_W, ADDRMETH_W | OPTYPE_x | OP_R, ARG_NONE, ARG_NONE, cpu_PENTIUM2, "movddup", 0, 0, 0)
|
||||
tbl32_F20F[0x2a] = (0, INS_OTHER, ADDRMETH_V | OPTYPE_sd | OP_R, ADDRMETH_VEXSKIP | ADDRMETH_H | OPTYPE_sd | OP_R, ADDRMETH_E | OPTYPE_y | OP_R, ARG_NONE, cpu_PENTIUM2, "cvtsi2sd", 0, 0, 0)
|
||||
tbl32_F20F[0x2c] = (0, INS_OTHER, ADDRMETH_G | OPTYPE_y | OP_R, ADDRMETH_W | OPTYPE_q | OP_R, ARG_NONE, ARG_NONE, cpu_PENTIUM2, "cvttsd2si", 0, 0, 0)
|
||||
@@ -922,7 +922,7 @@ tbl32_0F01_rest = [
|
||||
( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
( 0, INS_SYSTEM, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM2, "rdpkru", 0, 0, 0),
|
||||
( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
|
||||
( 0, INS_SYSTEM, ARG_NONE, ARG_NONE, ARG_NONE, cpu_OSPKE, "wrpkru", 0, 0, 0),
|
||||
( 0, INS_SYSTEM, ADDRMETH_E | OPTYPE_w | OP_W, ARG_NONE, ARG_NONE, cpu_80386, "lmsw", 0, 0, 0),
|
||||
( 0, INS_SYSTEM, ADDRMETH_E | OPTYPE_w | OP_W, ARG_NONE, ARG_NONE, cpu_80386, "lmsw", 0, 0, 0),
|
||||
( 0, INS_SYSTEM, ADDRMETH_E | OPTYPE_w | OP_W, ARG_NONE, ARG_NONE, cpu_80386, "lmsw", 0, 0, 0),
|
||||
|
||||
+16
-14
@@ -869,7 +869,7 @@ class IntelEmulator(i386RegisterContext, envi.Emulator):
|
||||
dsize = op.opers[0].tsize
|
||||
val = self.getOperValue(op, 0)
|
||||
if val == 0:
|
||||
raise envi.DivideByZero(self)
|
||||
raise e_exc.DivideByZero(self)
|
||||
|
||||
if dsize == 1:
|
||||
ax = self.getRegister(REG_AX)
|
||||
@@ -910,19 +910,20 @@ class IntelEmulator(i386RegisterContext, envi.Emulator):
|
||||
rem = tot % val
|
||||
|
||||
if tot > (2**64)-1:
|
||||
raise Exception('division exception')
|
||||
mesg = '0x%.8x: division exception on %s' % (op.va, str(op))
|
||||
raise e_exc.DivideError(self, msg=mesg)
|
||||
|
||||
self.setRegisterByName("rax", quot)
|
||||
self.setRegisterByName("rdx", rem)
|
||||
|
||||
else:
|
||||
raise envi.UnsupportedInstruction(self, op)
|
||||
raise e_exc.UnsupportedInstruction(self, op)
|
||||
|
||||
def i_enter(self, op):
|
||||
locsize = self.getOperValue(op, 0)
|
||||
depth = self.getOperValue(op, 1)
|
||||
if depth != 0:
|
||||
raise envi.UnsupportedInstruction(self, op)
|
||||
raise e_exc.UnsupportedInstruction(self, op)
|
||||
|
||||
esp = self.getRegister(REG_ESP)
|
||||
ebp = self.getRegister(REG_EBP)
|
||||
@@ -957,7 +958,7 @@ class IntelEmulator(i386RegisterContext, envi.Emulator):
|
||||
d = self.getOperValue(op, 0)
|
||||
d = e_bits.signed(d, 1)
|
||||
if d == 0:
|
||||
raise envi.DivideByZero(self)
|
||||
raise e_exc.DivideByZero(self)
|
||||
q = ax // d
|
||||
r = ax % d
|
||||
res = ((r & 0xff) << 8) | (q & 0xff)
|
||||
@@ -969,7 +970,7 @@ class IntelEmulator(i386RegisterContext, envi.Emulator):
|
||||
d = self.getOperValue(op, 0)
|
||||
d = e_bits.signed(d, 2)
|
||||
if d == 0:
|
||||
raise envi.DivideByZero(self)
|
||||
raise e_exc.DivideByZero(self)
|
||||
q = val // d
|
||||
r = val % d
|
||||
|
||||
@@ -982,7 +983,7 @@ class IntelEmulator(i386RegisterContext, envi.Emulator):
|
||||
d = self.getOperValue(op, 0)
|
||||
d = e_bits.signed(d, 4)
|
||||
if d == 0:
|
||||
raise envi.DivideByZero(self)
|
||||
raise e_exc.DivideByZero(self)
|
||||
q = val // d
|
||||
r = val % d
|
||||
|
||||
@@ -1052,13 +1053,13 @@ class IntelEmulator(i386RegisterContext, envi.Emulator):
|
||||
self.setOperValue(op, 0, res)
|
||||
|
||||
else:
|
||||
raise envi.UnsupportedInstruction(self, op)
|
||||
raise e_exc.UnsupportedInstruction(self, op)
|
||||
|
||||
self.setFlag(EFLAGS_PF, e_bits.is_parity_byte(res))
|
||||
self.setFlag(EFLAGS_SF, 0) # technically undefined in the manual, but zero'd on core-i7
|
||||
|
||||
def i_in(self, op):
|
||||
raise envi.UnsupportedInstruction(self, op)
|
||||
raise e_exc.UnsupportedInstruction(self, op)
|
||||
|
||||
def i_inc(self, op):
|
||||
size = op.opers[0].tsize
|
||||
@@ -1078,18 +1079,18 @@ class IntelEmulator(i386RegisterContext, envi.Emulator):
|
||||
self.setFlag(EFLAGS_PF, e_bits.is_parity_byte(sval))
|
||||
|
||||
def i_ud0(self, op):
|
||||
raise envi.BadOpcode(op)
|
||||
raise e_exc.BadOpcode(op)
|
||||
i_ud1 = i_ud0
|
||||
i_ud2 = i_ud0
|
||||
|
||||
def i_int(self, op):
|
||||
raise envi.BreakpointHit(self)
|
||||
raise e_exc.BreakpointHit(self)
|
||||
|
||||
def i_int1(self, op):
|
||||
raise envi.BreakpointHit(self)
|
||||
raise e_exc.BreakpointHit(self)
|
||||
|
||||
def i_int3(self, op):
|
||||
raise envi.BreakpointHit(self)
|
||||
raise e_exc.BreakpointHit(self)
|
||||
|
||||
def i_lea(self, op):
|
||||
base = self.getOperAddr(op, 1)
|
||||
@@ -1291,7 +1292,8 @@ class IntelEmulator(i386RegisterContext, envi.Emulator):
|
||||
self._emu_setGpReg(GPR_A, a, tsize)
|
||||
self._emu_setGpReg(GPR_D, d, tsize)
|
||||
else:
|
||||
raise Exception("i_mul called with invalid size of %d" % tsize)
|
||||
mesg = "i_mul called with invalid size of %d" % tsize
|
||||
raise e_exc.MultipleError(self, msg=mesg)
|
||||
|
||||
# If the high order stuff was used, set CF/OF
|
||||
if res >> (tsize * 8):
|
||||
|
||||
@@ -683,8 +683,8 @@ tbl32_660F[0xfe] = (0, INS_ADD, ADDRMETH_V | OPTYPE_dq | OP_W, ADDRMETH_W | OPTY
|
||||
(optable, optype, operand 0, operand 1, operand 2, CPU required, "opcodename", op0Register, op1Register, op2Register)
|
||||
"""
|
||||
tbl32_F20F = [(0, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, 0, 0, 0, 0) for x in range(256)]
|
||||
tbl32_F20F[0x10] = (0, INS_MOV, ADDRMETH_V | OPTYPE_sd | OP_W, ADDRMETH_W | OPTYPE_sd | OP_R, ARG_NONE, cpu_PENTIUM2, "movsd", 0, 0, 0)
|
||||
tbl32_F20F[0x11] = (0, INS_MOV, ADDRMETH_W | OPTYPE_sd | OP_W, ADDRMETH_V | OPTYPE_sd | OP_R, ARG_NONE, cpu_PENTIUM2, "movsd", 0, 0, 0)
|
||||
tbl32_F20F[0x10] = (0, INS_MOV, ADDRMETH_V | OPTYPE_sd | OP_W, ADDRMETH_W | OPTYPE_sd | OP_MEM_Q | OP_R, ARG_NONE, cpu_PENTIUM2, "movsd", 0, 0, 0)
|
||||
tbl32_F20F[0x11] = (0, INS_MOV, ADDRMETH_W | OPTYPE_sd | OP_MEM_Q | OP_W, ADDRMETH_V | OPTYPE_sd | OP_R, ARG_NONE, cpu_PENTIUM2, "movsd", 0, 0, 0)
|
||||
tbl32_F20F[0x12] = (0, INS_MOV, ADDRMETH_V | OPTYPE_sd | OP_W, ADDRMETH_W | OPTYPE_sd | OP_R, ARG_NONE, cpu_PENTIUM2, "movddup", 0, 0, 0)
|
||||
|
||||
tbl32_F20F[0x2a] = (0, INS_OTHER, ADDRMETH_V | OPTYPE_sd | OP_W, ADDRMETH_E | OPTYPE_ds | OP_R, ARG_NONE, cpu_PENTIUM2, "cvtsi2sd", 0, 0, 0)
|
||||
@@ -824,9 +824,9 @@ tbl32_0F01_rest = [
|
||||
(0, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, 0, 0, 0, 0),
|
||||
(0, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, 0, 0, 0, 0),
|
||||
(0, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, 0, 0, 0, 0),
|
||||
( 0, INS_SYSTEM, ADDRMETH_E | OPTYPE_w | OP_W, ARG_NONE, ARG_NONE, cpu_80386, "smsw", 0, 0, 0),
|
||||
(0, INS_SYSTEM, ADDRMETH_E | OPTYPE_w | OP_W, ARG_NONE, ARG_NONE, cpu_80386, "smsw", 0, 0, 0),
|
||||
(0, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, 0, 0, 0, 0),
|
||||
( 0, INS_SYSTEM, ADDRMETH_E | OPTYPE_w | OP_W, ARG_NONE, ARG_NONE, cpu_80386, "lmsw", 0, 0, 0),
|
||||
(0, INS_SYSTEM, ADDRMETH_E | OPTYPE_w | OP_W, ARG_NONE, ARG_NONE, cpu_80386, "lmsw", 0, 0, 0),
|
||||
(0, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, 0, 0, 0, 0),
|
||||
(0, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, 0, 0, 0, 0),
|
||||
(0, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, 0, 0, 0, 0),
|
||||
@@ -835,8 +835,8 @@ tbl32_0F01_rest = [
|
||||
(0, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, 0, 0, 0, 0),
|
||||
(0, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, 0, 0, 0, 0),
|
||||
(0, INS_SYSTEM, OP_REG | OP_W, ARG_NONE, ARG_NONE, cpu_PENTIUM2, "rdpkru", e_i386_regs.REG_EAX, 0, 0),
|
||||
(0, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, 0, 0, 0, 0),
|
||||
(0, INS_OTHER, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM2, "swapgs", 0, 0, 0),
|
||||
(0, INS_SYSTEM, ARG_NONE, ARG_NONE, ARG_NONE, cpu_OSPKE, "wrpkru", 0, 0, 0),
|
||||
(0, INS_OTHER, ARG_NONE, ARG_NONE, ARG_NONE, cpu_PENTIUM2, "swapgs", 0, 0, 0),
|
||||
(0, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, 0, 0, 0, 0),
|
||||
(0, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, 0, 0, 0, 0),
|
||||
(0, 0, ARG_NONE, ARG_NONE, ARG_NONE, 0, 0, 0, 0, 0),
|
||||
|
||||
@@ -255,6 +255,7 @@ cpu_AMD64 = 0x0000a000
|
||||
cpu_AESNI = 0x0000b000
|
||||
cpu_AVX = 0x0000c000
|
||||
cpu_BMI = 0x0000d000
|
||||
cpu_OSPKE = 0x0000e000
|
||||
|
||||
#eventually, change this for your own codes
|
||||
#ADDEXP_SCALE_OFFSET= 0
|
||||
|
||||
+4
-4
@@ -168,9 +168,9 @@ def getFormat(size, big_endian=False, signed=False):
|
||||
'''
|
||||
Returns the proper struct format for numbers up to 8 bytes in length
|
||||
Endianness and Signedness aware.
|
||||
|
||||
|
||||
Only useful for *full individual* numbers... ie. 1, 2, 4, 8. Numbers
|
||||
of 24-bits (3), 40-bit (5), 48-bits (6) or 56-bits (7) are not accounted
|
||||
of 24-bits (3), 40-bit (5), 48-bits (6) or 56-bits (7) are not accounted
|
||||
for here and will return None.
|
||||
'''
|
||||
return master_fmts[signed][big_endian][size]
|
||||
@@ -179,9 +179,9 @@ def getFloatFormat(size, big_endian=False):
|
||||
'''
|
||||
Returns the proper struct format for numbers up to 8 bytes in length
|
||||
Endianness and Signedness aware.
|
||||
|
||||
|
||||
Only useful for *full individual* numbers... ie. 1, 2, 4, 8. Numbers
|
||||
of 24-bits (3), 40-bit (5), 48-bits (6) or 56-bits (7) are not accounted
|
||||
of 24-bits (3), 40-bit (5), 48-bits (6) or 56-bits (7) are not accounted
|
||||
for here and will return None.
|
||||
'''
|
||||
return fmt_floats[big_endian][size]
|
||||
|
||||
+12
-1
@@ -130,9 +130,16 @@ class DivideByZero(EmuException):
|
||||
pass
|
||||
|
||||
|
||||
class MultiplyError(EmuException):
|
||||
"""
|
||||
Raised by an Emulator when multiply falls outside of the specified range
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class DivideError(EmuException):
|
||||
"""
|
||||
Raised by an Emulator whena a divide falls out
|
||||
Raised by an Emulator when a a divide falls out
|
||||
of the specified range.
|
||||
"""
|
||||
pass
|
||||
@@ -197,3 +204,7 @@ class InvalidOperand(Exception):
|
||||
def __repr__(self):
|
||||
return "%s at %s" % (self.__class__.__name__, str(self.valu))
|
||||
|
||||
class GeneralProtection(EnviException):
|
||||
def __init__(self, op):
|
||||
EnviException.__init__(self, 'General Protection exception (0x%.8x: %s)' % (op.va, str(op)))
|
||||
self.op = op
|
||||
|
||||
@@ -195,9 +195,9 @@ amd64MultiByteOpcodes = [
|
||||
('MOVDQU', 'F30F6FCA', 'movdqu xmm1,xmm2', 'movdqu xmm1,xmm2'),
|
||||
('MOVDQU (MEM)', 'F30F6F4810', 'movdqu xmm1,oword [rax + 16]', 'movdqu xmm1,oword [rax + 16]'),
|
||||
('MOVDQU (REP)', 'F3F30F6FCA', 'movdqu xmm1,xmm2', 'movdqu xmm1,xmm2'),
|
||||
('MOVSD', 'f20f100d28330608', 'movsd xmm1,oword [rip + 134624040]', 'movsd xmm1,oword [rip + 134624040]'),
|
||||
('MOVSD 2', 'f20f1145f0', 'movsd oword [rbp - 16],xmm0', 'movsd oword [rbp - 16],xmm0'),
|
||||
('MOVSD 3', 'f20f100d70790908', 'movsd xmm1,oword [rip + 134838640]', 'movsd xmm1,oword [rip + 134838640]'),
|
||||
('MOVSD', 'f20f100d28330608', 'movsd xmm1,qword [rip + 134624040]', 'movsd xmm1,qword [rip + 134624040]'),
|
||||
('MOVSD 2', 'f20f1145f0', 'movsd qword [rbp - 16],xmm0', 'movsd qword [rbp - 16],xmm0'),
|
||||
('MOVSD 3', 'f20f100d70790908', 'movsd xmm1,qword [rip + 134838640]', 'movsd xmm1,qword [rip + 134838640]'),
|
||||
('MOVSS', 'f30f1045f8', 'movss xmm0,dword [rbp - 8]', 'movss xmm0,dword [rbp - 8]'),
|
||||
('MOVSS 2', 'f30f1055d0', 'movss xmm2,dword [rbp - 48]', 'movss xmm2,dword [rbp - 48]'),
|
||||
('MOVSS 3', 'F30F110D41414100', 'movss dword [rip + 4276545],xmm1', 'movss dword [rip + 4276545],xmm1'),
|
||||
@@ -577,10 +577,11 @@ amd64VexOpcodes = [
|
||||
('VMOVSS', 'C5E210CE', 'vmovss xmm1,xmm3,xmm6', 'vmovss xmm1,xmm3,xmm6'),
|
||||
('VMOVSS 2', 'C5FA1008', 'vmovss xmm1,dword [rax]', 'vmovss xmm1,dword [rax]'),
|
||||
('VMOVSS 3', 'C5FA10CB', 'vmovss xmm1,xmm0,xmm3', 'vmovss xmm1,xmm0,xmm3'),
|
||||
('VMOVSD', 'C5FB1008', 'vmovsd xmm1,oword [rax]', 'vmovsd xmm1,oword [rax]'),
|
||||
('VMOVSD', 'C5FB1008', 'vmovsd xmm1,qword [rax]', 'vmovsd xmm1,qword [rax]'),
|
||||
('VMOVSD 2', 'C5EB10CB', 'vmovsd xmm1,xmm2,xmm3', 'vmovsd xmm1,xmm2,xmm3'),
|
||||
('VMOVSD 3', 'C5EB11CB', 'vmovsd xmm3,xmm2,xmm1', 'vmovsd xmm3,xmm2,xmm1'),
|
||||
('VMOVSD 4', 'C5FB111C2541414141', 'vmovsd oword [0x41414141],xmm3', 'vmovsd oword [0x41414141],xmm3'),
|
||||
('VMOVSD 4', 'C5FB111C2541414141', 'vmovsd qword [0x41414141],xmm3', 'vmovsd qword [0x41414141],xmm3'),
|
||||
('VMOVSD 5', '67C5FB1118', 'vmovsd qword [eax],xmm3', 'vmovsd qword [eax],xmm3'),
|
||||
|
||||
('HADDPS 1', 'C5CB7CCB', 'vhaddps xmm1,xmm6,xmm3', 'vhaddps xmm1,xmm6,xmm3'),
|
||||
('HADDPS 2', 'C5E77CD6', 'vhaddps ymm2,ymm3,ymm6', 'vhaddps ymm2,ymm3,ymm6'),
|
||||
@@ -594,7 +595,6 @@ amd64VexOpcodes = [
|
||||
('INSERTPS 5', 'C4E369211C25414141414C', 'vinsertps xmm3,xmm2,dword [0x41414141],76', 'vinsertps xmm3,xmm2,dword [0x41414141],76'),
|
||||
('INSERTPS 6', 'C4E3692198454141414C', 'vinsertps xmm3,xmm2,dword [rax + 1094795589],76', 'vinsertps xmm3,xmm2,dword [rax + 1094795589],76'),
|
||||
|
||||
('VMOVSD 3', '67C5FB1118', 'vmovsd oword [eax],xmm3', 'vmovsd oword [eax],xmm3'),
|
||||
('VPSLLDQ', 'C5F173D208', 'vpsrlq xmm1,xmm2,8', 'vpsrlq xmm1,xmm2,8'),
|
||||
('VPSRLD', 'C5E172D41B', 'vpsrld xmm3,xmm4,27', 'vpsrld xmm3,xmm4,27'),
|
||||
('VPSRLD', 'c5e172d063', 'vpsrld xmm3,xmm0,99', 'vpsrld xmm3,xmm0,99'),
|
||||
|
||||
@@ -162,9 +162,9 @@ i386MultiByteOpcodes = [
|
||||
('MOVDQU', 'F30F6FCA', 0x40, 'movdqu xmm1,xmm2', 'movdqu xmm1,xmm2'),
|
||||
('MOVDQU (MEM)', 'F30F6F4810', 0x40, 'movdqu xmm1,oword [eax + 16]', 'movdqu xmm1,oword [eax + 16]'),
|
||||
('MOVDQU (REP)', 'F3F30F6FCA', 0x40, 'movdqu xmm1,xmm2', 'movdqu xmm1,xmm2'),
|
||||
('MOVSD', 'f20f100d28330608', 0x40, 'movsd xmm1,oword [0x08063328]', 'movsd xmm1,oword [0x08063328]'),
|
||||
('MOVSD 2', 'f20f1145f0', 0x40, 'movsd oword [ebp - 16],xmm0', 'movsd oword [ebp - 16],xmm0'),
|
||||
('MOVSD 3', 'f20f100d70790908', 0x40, 'movsd xmm1,oword [0x08097970]', 'movsd xmm1,oword [0x08097970]'),
|
||||
('MOVSD', 'f20f100d28330608', 0x40, 'movsd xmm1,qword [0x08063328]', 'movsd xmm1,qword [0x08063328]'),
|
||||
('MOVSD 2', 'f20f1145f0', 0x40, 'movsd qword [ebp - 16],xmm0', 'movsd qword [ebp - 16],xmm0'),
|
||||
('MOVSD 3', 'f20f100d70790908', 0x40, 'movsd xmm1,qword [0x08097970]', 'movsd xmm1,qword [0x08097970]'),
|
||||
('MOVSS', 'f30f1045f8', 0x40, 'movss xmm0,dword [ebp - 8]', 'movss xmm0,dword [ebp - 8]'),
|
||||
('MOVSS 2', 'f30f1055d0', 0x40, 'movss xmm2,dword [ebp - 48]', 'movss xmm2,dword [ebp - 48]'),
|
||||
('MOVSS 3', 'F30F110D41414100', 0x40, 'movss dword [0x00414141],xmm1', 'movss dword [0x00414141],xmm1'),
|
||||
|
||||
@@ -68,7 +68,7 @@ class NodeColumn(QGraphicsItem):
|
||||
return self.x()
|
||||
|
||||
def getYMid(self):
|
||||
return self.y() + (int(self.boundingRect().height()) / 2)
|
||||
return self.y() + (int(self.boundingRect().height()) >> 1)
|
||||
|
||||
def drawLinesTo(self, colnode):
|
||||
'''
|
||||
|
||||
@@ -1238,7 +1238,7 @@ class VivWorkspace(e_mem.MemoryObject, viv_base.VivWorkspaceCore):
|
||||
self.delXref(va)
|
||||
|
||||
def makeJumpTable(self, op, tova, rebase=False, psize=4):
|
||||
fname = self.getMemoryMap(tova)[3]
|
||||
fname = self.getFileByVa(tova)
|
||||
imgbase = self.getFileMeta(fname, 'imagebase')
|
||||
|
||||
ptrbase = tova
|
||||
|
||||
@@ -82,6 +82,7 @@ def addAnalysisModules(vw):
|
||||
vw.addFuncAnalysisModule("vivisect.analysis.generic.noret")
|
||||
vw.addAnalysisModule("vivisect.analysis.generic.funcentries")
|
||||
vw.addAnalysisModule('vivisect.analysis.ms.msvcfunc')
|
||||
vw.addAnalysisModule("vivisect.analysis.generic.thunks")
|
||||
|
||||
vw.addAnalysisModule('vivisect.analysis.generic.strconst')
|
||||
|
||||
@@ -137,6 +138,7 @@ def addAnalysisModules(vw):
|
||||
vw.addFuncAnalysisModule("vivisect.analysis.elf.elfplt")
|
||||
# late-analysis ELF PLT tidying up, allowing unused PLT entries to be made into functions
|
||||
vw.addAnalysisModule("vivisect.analysis.elf.elfplt_late")
|
||||
vw.addAnalysisModule("vivisect.analysis.generic.thunks")
|
||||
vw.addAnalysisModule("vivisect.analysis.generic.pointers")
|
||||
|
||||
elif fmt == 'macho': # MACH-O ###################################################
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
'''
|
||||
Late-PLT analysis.
|
||||
|
||||
During codeflow analysis, we detect PLT entries organically (and consequently
|
||||
During codeflow analysis, we detect PLT entries organically (and consequently
|
||||
*accurately*), but often not all of them. This analysis module applies a few
|
||||
different algorithms to identify the ones which were not discovered during
|
||||
different algorithms to identify the ones which were not discovered during
|
||||
autoanalysis.
|
||||
|
||||
Formerly, we attempted to do this analysis before all other code analysis
|
||||
but due to so many varieties of PLT creation by different compilers on
|
||||
but due to so many varieties of PLT creation by different compilers on
|
||||
numerous hardware platforms and OSes, that method lead to many errors in PLT-
|
||||
identification, often hampering vital parts of vulnerability-research tools.
|
||||
We finally pulled the plug on preemptive analysis, in favor of letting auto-
|
||||
@@ -42,12 +42,12 @@ def analyzePLT(vw, pltva, pltsz):
|
||||
We make use of two different algorithms for each.
|
||||
The first algorithm measures the distance from the start of known good PLT
|
||||
functions and the GOT-referencing branch. The only weakness is that this
|
||||
method requires that the xref to the GOT is already identified (without
|
||||
throwing and emulator in there).
|
||||
method requires that the xref to the GOT is already identified (without
|
||||
throwing and emulator in there).
|
||||
|
||||
The second algorithm measures the distance between known good PLT entries
|
||||
and then attempts to identify divisors (up to 16 splits) which would make
|
||||
more than one PLT function fit between them. These attempted splits are
|
||||
more than one PLT function fit between them. These attempted splits are
|
||||
validated using heuristics of the potential functions which would be created
|
||||
by the division. PLT entries in the same PLT section are incredibly similar
|
||||
(not including the LazyLoader sometimes found at the beginning of a PLT)
|
||||
|
||||
@@ -76,10 +76,10 @@ def analyzeFunction(vw, funcva):
|
||||
break
|
||||
|
||||
try:
|
||||
op = vw.parseOpcode(va) # parseOpcode() pulls arch from the location db, if exists
|
||||
op = vw.parseOpcode(va)
|
||||
mnem[op.mnem] += 1
|
||||
except Exception:
|
||||
logger.warning('Codeblock bad opcode at 0x%x, ignoring error %s', va, e)
|
||||
except Exception as e:
|
||||
logger.warning('Codeblock bad opcode at 0x%x, breaking on error %s', va, e)
|
||||
break
|
||||
size += lsize
|
||||
opcount += 1
|
||||
@@ -145,7 +145,7 @@ def analyzeFunction(vw, funcva):
|
||||
vw.addCodeBlock(bva, bsize, funcva)
|
||||
bcnt += 1
|
||||
except Exception as e:
|
||||
logger.warning('Codeblock analysis hit exception: %s', e)
|
||||
logger.warning('Codeblock analysis for 0x%.8x hit exception: %s', funcva, e)
|
||||
break
|
||||
|
||||
vw.setFunctionMeta(funcva, 'Size', size)
|
||||
|
||||
@@ -98,6 +98,7 @@ class watcher(viv_imp_monitor.EmulationMonitor):
|
||||
self.hasret = True
|
||||
emu.stopEmu()
|
||||
|
||||
|
||||
def analyze(vw):
|
||||
|
||||
flist = vw.getFunctions()
|
||||
@@ -105,13 +106,11 @@ def analyze(vw):
|
||||
tried = set()
|
||||
while True:
|
||||
docode = []
|
||||
bcode = []
|
||||
bcode = []
|
||||
|
||||
vatodo = []
|
||||
vatodo = [ va for va, name in vw.getNames() if vw.getLocation(va) is None ]
|
||||
vatodo.extend( [tova for fromva, tova, reftype, rflags in vw.getXrefs(rtype=REF_PTR) if vw.getLocation(tova) is None] )
|
||||
|
||||
for va in set(vatodo):
|
||||
vatodo = set([va for va, name in vw.getNames() if vw.getLocation(va) is None and va not in tried])
|
||||
vatodo = vatodo.union([tova for _, tova, _, _ in vw.getXrefs(rtype=REF_PTR) if vw.getLocation(tova) is None and tova not in tried])
|
||||
for va in vatodo:
|
||||
loc = vw.getLocation(va)
|
||||
if loc is not None:
|
||||
if loc[L_LTYPE] == LOC_STRING:
|
||||
@@ -125,34 +124,47 @@ def analyze(vw):
|
||||
if vw.isDeadData(va):
|
||||
continue
|
||||
|
||||
# Make sure it's executable
|
||||
if not vw.isExecutable(va):
|
||||
continue
|
||||
|
||||
# Skip it if we've tried it already.
|
||||
if va in tried:
|
||||
continue
|
||||
|
||||
tried.add(va)
|
||||
emu = vw.getEmulator()
|
||||
wat = watcher(vw, va)
|
||||
emu.setEmulationMonitor(wat)
|
||||
|
||||
try:
|
||||
emu.runFunction(va, maxhit=1)
|
||||
except Exception:
|
||||
continue
|
||||
if wat.looksgood():
|
||||
docode.append(va)
|
||||
# flag to tell us to be greedy w/ finding code
|
||||
# XXX - visi is going to hate this..
|
||||
elif wat.iscode() and vw.greedycode:
|
||||
bcode.append(va)
|
||||
else:
|
||||
# if it's not exectuable, check to see if it's at least readable, in which case
|
||||
# we can check for other location types
|
||||
# otherwise, try emulating it to see if it feels like code
|
||||
if not vw.isExecutable(va):
|
||||
if not vw.isReadable(va):
|
||||
continue
|
||||
if vw.isProbablyUnicode(va):
|
||||
vw.makeUnicode(va)
|
||||
elif vw.isProbablyString(va):
|
||||
vw.makeString(va)
|
||||
else:
|
||||
emu = vw.getEmulator()
|
||||
wat = watcher(vw, va)
|
||||
emu.setEmulationMonitor(wat)
|
||||
|
||||
try:
|
||||
emu.runFunction(va, maxhit=1)
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
if wat.looksgood():
|
||||
docode.append(va)
|
||||
# flag to tell us to be greedy w/ finding code
|
||||
# XXX - visi is going to hate this..
|
||||
elif wat.iscode() and vw.greedycode:
|
||||
bcode.append(va)
|
||||
else:
|
||||
if vw.isProbablyUnicode(va):
|
||||
vw.makeUnicode(va)
|
||||
elif vw.isProbablyString(va):
|
||||
vw.makeString(va)
|
||||
else:
|
||||
# if we get all the way down here, and it has a name, it's gotta be *something*
|
||||
if vw.getName(va):
|
||||
vw.makePointer(va)
|
||||
|
||||
if len(docode) == 0:
|
||||
break
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
"""
|
||||
A simple analysis module to detect import thunks.
|
||||
"""
|
||||
|
||||
import envi
|
||||
import vivisect.const as v_const
|
||||
|
||||
|
||||
def analyzeFunction(vw, funcva):
|
||||
'''
|
||||
Quick n' dirty to find import thunks.
|
||||
'''
|
||||
for fromva, tova, rtype, rflags in vw.getXrefsFrom(funcva, v_const.REF_CODE):
|
||||
|
||||
# You goin NOWHERE!
|
||||
@@ -13,10 +13,71 @@ def analyzeFunction(vw, funcva):
|
||||
if loc is None:
|
||||
continue
|
||||
|
||||
# FIXME this could check for thunks to other known function pointers...
|
||||
|
||||
va, size, ltype, linfo = loc
|
||||
if ltype != v_const.LOC_IMPORT:
|
||||
continue
|
||||
|
||||
vw.makeFunctionThunk(funcva, linfo)
|
||||
|
||||
|
||||
def analyze(vw):
|
||||
'''
|
||||
Find function thunks that point to other function that aren't imports
|
||||
|
||||
General idea is that most function thunks (and not functions that just jump
|
||||
to a new function and never return) are usually one codeblock big. They do some
|
||||
setup, then jump/call/branch to a new place (and not just fall through).
|
||||
|
||||
So we run through all the functions we know about, filter down to only the ones
|
||||
of a single codeblock. If the last instruction in it isn't a call or a branch, skip
|
||||
it.
|
||||
|
||||
If we can then resolve where that branch/call is going to, set the new thing as a
|
||||
function thunk to it's target, and set the current function as a thunk.
|
||||
|
||||
There is a slight catch in that there are certain functions we don't want to call
|
||||
makeFunctionThunk on (since that overrides the old name), since we may have already
|
||||
received a real name for it, so in that case, just set the metadata for it being
|
||||
a thunk and move on.
|
||||
'''
|
||||
for fva in vw.getFunctions():
|
||||
# Skip things that are already thunks
|
||||
if vw.isFunctionThunk(fva):
|
||||
continue
|
||||
|
||||
blocks = vw.getFunctionBlocks(fva)
|
||||
if len(blocks) != 1:
|
||||
continue
|
||||
|
||||
block = vw.getCodeBlock(fva)
|
||||
va = block[0] + block[1] - 1
|
||||
|
||||
loc = vw.getLocation(va)
|
||||
if not loc:
|
||||
continue
|
||||
|
||||
op = vw.parseOpcode(loc[0])
|
||||
if not op.iflags & envi.IF_BRANCH and not op.iflags & envi.IF_CALL:
|
||||
continue
|
||||
|
||||
branches = op.getBranches()
|
||||
if len(branches) != 1:
|
||||
continue
|
||||
|
||||
bva, bflags = branches[0]
|
||||
if not vw.isFunction(bva):
|
||||
continue
|
||||
|
||||
if bflags & envi.BR_FALL:
|
||||
continue
|
||||
|
||||
va, size, ltype, linfo = vw.getLocation(fva)
|
||||
tname = vw.getName(bva)
|
||||
oldname = vw.getName(fva)
|
||||
|
||||
# mark it as a function thunk, but if it has an actual name (like xcharalloc in
|
||||
# chgrp), don't override the actual, given name
|
||||
if oldname == 'sub_0%x' % va:
|
||||
vw.makeFunctionThunk(fva, tname)
|
||||
else:
|
||||
vw.setFunctionMeta(fva, 'Thunk', tname)
|
||||
|
||||
+4
-11
@@ -231,16 +231,9 @@ class VivWorkspaceCore(viv_impapi.ImportApi):
|
||||
self.segments.append(einfo)
|
||||
|
||||
def _handleADDRELOC(self, einfo):
|
||||
if len(einfo) == 2: # FIXME: legacy: remove after 02/13/2020
|
||||
rva, rtype = einfo
|
||||
mmva, mmsz, mmperm, fname = self.getMemoryMap(rva) # FIXME: getFileByVa does not obey file defs
|
||||
imgbase = self.getFileMeta(fname, 'imagebase')
|
||||
data = None
|
||||
einfo = fname, rva-imgbase, rtype, data
|
||||
else:
|
||||
fname, ptroff, rtype, data = einfo
|
||||
imgbase = self.getFileMeta(fname, 'imagebase')
|
||||
rva = imgbase + ptroff
|
||||
fname, ptroff, rtype, data = einfo
|
||||
imgbase = self.getFileMeta(fname, 'imagebase')
|
||||
rva = imgbase + ptroff
|
||||
|
||||
self.reloc_by_va[rva] = rtype
|
||||
self.relocations.append(einfo)
|
||||
@@ -252,7 +245,7 @@ class VivWorkspaceCore(viv_impapi.ImportApi):
|
||||
# 'data' arg must be 'offset' number
|
||||
ptr = imgbase + data
|
||||
if ptr != (ptr & e_bits.u_maxes[self.psize]):
|
||||
logger.warning('RTYPE_BASEOFF calculated a bad pointer: 0x%x (imgbase: 0x%x)', ptr, imgbase)
|
||||
logger.warning('Relocations calculated a bad pointer: 0x%x (imgbase: 0x%x) (relocation: %d)', ptr, imgbase, rtype)
|
||||
|
||||
# writes are costly, especially on larger binaries
|
||||
if ptr != self.readMemoryPtr(rva):
|
||||
|
||||
+84
-29
@@ -1,14 +1,18 @@
|
||||
import struct
|
||||
import logging
|
||||
import traceback
|
||||
import collections
|
||||
|
||||
import Elf
|
||||
|
||||
import envi.bits as e_bits
|
||||
|
||||
import vivisect
|
||||
import vivisect.parsers as v_parsers
|
||||
import envi.bits as e_bits
|
||||
|
||||
from vivisect.const import *
|
||||
|
||||
from io import StringIO
|
||||
from io import BytesIO
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -26,7 +30,7 @@ def parseFile(vw, filename, baseaddr=None):
|
||||
return loadElfIntoWorkspace(vw, elf, filename=filename, baseaddr=baseaddr)
|
||||
|
||||
def parseBytes(vw, bytes, baseaddr=None):
|
||||
fd = StringIO(bytes)
|
||||
fd = BytesIO(bytes)
|
||||
elf = Elf.Elf(fd)
|
||||
return loadElfIntoWorkspace(vw, elf, baseaddr=baseaddr)
|
||||
|
||||
@@ -114,18 +118,18 @@ def makeFunctionTable(elf, vw, tbladdr, size, tblname, funcs, ptrs, baseaddr=0,
|
||||
|
||||
|
||||
arch_names = {
|
||||
Elf.EM_ARM:'arm',
|
||||
Elf.EM_386:'i386',
|
||||
Elf.EM_X86_64:'amd64',
|
||||
Elf.EM_MSP430:'msp430',
|
||||
Elf.EM_ARM: 'arm',
|
||||
Elf.EM_386: 'i386',
|
||||
Elf.EM_X86_64: 'amd64',
|
||||
Elf.EM_MSP430: 'msp430',
|
||||
}
|
||||
|
||||
archcalls = {
|
||||
'i386':'cdecl',
|
||||
'amd64':'sysvamd64call',
|
||||
'arm':'armcall',
|
||||
'thumb':'armcall',
|
||||
'thumb16':'armcall',
|
||||
'i386': 'cdecl',
|
||||
'amd64': 'sysvamd64call',
|
||||
'arm': 'armcall',
|
||||
'thumb': 'armcall',
|
||||
'thumb16': 'armcall',
|
||||
}
|
||||
|
||||
def loadElfIntoWorkspace(vw, elf, filename=None, baseaddr=None):
|
||||
@@ -196,7 +200,6 @@ def loadElfIntoWorkspace(vw, elf, filename=None, baseaddr=None):
|
||||
vw.setFileMeta(fname, 'runpath', hasRUNPATH(elf))
|
||||
vw.setFileMeta(fname, 'stripped', isStripped(elf))
|
||||
|
||||
strtabs = {}
|
||||
secnames = []
|
||||
for sec in elf.getSections():
|
||||
secnames.append(sec.getName())
|
||||
@@ -243,6 +246,7 @@ def loadElfIntoWorkspace(vw, elf, filename=None, baseaddr=None):
|
||||
if sec.sh_offset and sec.sh_size:
|
||||
sec.sh_addr = baseaddr + sec.sh_offset
|
||||
|
||||
|
||||
# First add all section definitions so we have them
|
||||
for sec in secs:
|
||||
sname = sec.getName()
|
||||
@@ -404,7 +408,7 @@ def loadElfIntoWorkspace(vw, elf, filename=None, baseaddr=None):
|
||||
# applyRelocs is specifically prior to "process Dynamic Symbols" because Dynamics-only symbols
|
||||
# (ie. not using Section Headers) may not get all the symbols. Some ELF's simply list too
|
||||
# small a space using SYMTAB and SYMTABSZ
|
||||
applyRelocs(elf, vw, addbase, baseaddr)
|
||||
postfix = applyRelocs(elf, vw, addbase, baseaddr)
|
||||
|
||||
# process Dynamic Symbols - this must happen *after* relocations, which can expand the size of this
|
||||
for s in elf.getDynSyms():
|
||||
@@ -434,8 +438,8 @@ def loadElfIntoWorkspace(vw, elf, filename=None, baseaddr=None):
|
||||
try:
|
||||
vw.addExport(sva, EXP_DATA, dmglname, fname, makeuniq=True)
|
||||
vw.setComment(sva, s.name)
|
||||
except Exception as e:
|
||||
vw.vprint('WARNING: %s' % e)
|
||||
except Exception:
|
||||
vw.vprint('STT_OBJECT Warning: %s' % traceback.format_exc())
|
||||
|
||||
elif stype == Elf.STT_HIOS:
|
||||
# So aparently Elf64 binaries on amd64 use HIOS and then
|
||||
@@ -448,8 +452,8 @@ def loadElfIntoWorkspace(vw, elf, filename=None, baseaddr=None):
|
||||
new_functions.append(("DynSym: STT_HIOS", sva))
|
||||
vw.addExport(sva, EXP_FUNCTION, dmglname, fname, makeuniq=True)
|
||||
vw.setComment(sva, s.name)
|
||||
except Exception as e:
|
||||
vw.vprint('WARNING: %s' % e)
|
||||
except Exception:
|
||||
vw.vprint('STT_HIOS Warning:\n%s' % traceback.format_exc())
|
||||
|
||||
elif stype == Elf.STT_MDPROC: # there's only one that isn't HI or LO...
|
||||
sva = s.st_other
|
||||
@@ -459,12 +463,19 @@ def loadElfIntoWorkspace(vw, elf, filename=None, baseaddr=None):
|
||||
try:
|
||||
vw.addExport(sva, EXP_DATA, dmglname, fname, makeuniq=True)
|
||||
vw.setComment(sva, s.name)
|
||||
except Exception as e:
|
||||
vw.vprint('WARNING: %s' % e)
|
||||
except Exception:
|
||||
vw.vprint('STT_MDPROC Warning:\n%s' % traceback.format_exc())
|
||||
|
||||
else:
|
||||
logger.debug("DYNSYM:\t%r\t%r\t%r\t%r", s, s.getInfoType(), 'other', hex(s.st_other))
|
||||
|
||||
if dmglname in postfix:
|
||||
for rlva, addend in postfix[dmglname]:
|
||||
if addbase:
|
||||
vw.addRelocation(rlva, RTYPE_BASEPTR, sva + addend - baseaddr)
|
||||
else:
|
||||
vw.addRelocation(rlva, RTYPE_BASEPTR, sva + addend)
|
||||
|
||||
vw.addVaSet("FileSymbols", (("Name", VASET_STRING), ("va", VASET_ADDRESS)))
|
||||
vw.addVaSet("WeakSymbols", (("Name", VASET_STRING), ("va", VASET_ADDRESS)))
|
||||
|
||||
@@ -475,16 +486,17 @@ def loadElfIntoWorkspace(vw, elf, filename=None, baseaddr=None):
|
||||
for s in elf.getSymbols():
|
||||
sva = s.st_value
|
||||
dmglname = demangle(s.name)
|
||||
|
||||
logger.debug('symbol val: 0x%x\ttype: %r\tbind: %r\t name: %r', sva,
|
||||
Elf.st_info_type.get(s.st_info, s.st_info),
|
||||
Elf.st_info_bind.get(s.st_other, s.st_other),
|
||||
s.name)
|
||||
|
||||
if s.st_info == Elf.STT_FILE:
|
||||
if s.getInfoType() == Elf.STT_FILE:
|
||||
vw.setVaSetRow('FileSymbols', (dmglname, sva))
|
||||
continue
|
||||
|
||||
if s.st_info == Elf.STT_NOTYPE:
|
||||
elif s.getInfoType() == Elf.STT_NOTYPE:
|
||||
# mapping symbol
|
||||
if arch in ('arm', 'thumb', 'thumb16'):
|
||||
symname = s.getName()
|
||||
@@ -504,6 +516,34 @@ def loadElfIntoWorkspace(vw, elf, filename=None, baseaddr=None):
|
||||
# Data Items (eg. literal pool)
|
||||
logger.info('mapping (NOTYPE) data symbol: 0x%x: %r', sva, dmglname)
|
||||
data_ptrs.append(sva)
|
||||
elif s.getInfoType() == Elf.STT_OBJECT:
|
||||
symname = s.getName()
|
||||
if addbase:
|
||||
sva += baseaddr
|
||||
if symname:
|
||||
vw.makeName(sva, symname, filelocal=True, makeuniq=True)
|
||||
valu = vw.readMemoryPtr(sva)
|
||||
if not vw.isValidPointer(valu) and s.st_size == vw.psize:
|
||||
vw.makePointer(sva, follow=False)
|
||||
else:
|
||||
'''
|
||||
Most of this is replicated in makePointer with follow=True. We specifically don't use that, since that kicks off a bunch of other analysis that isn't safe to run yet (it blows up in fun ways), but we still want these locations made first, so that other analysis modules know to not monkey with these and so I can set sizes and what not.
|
||||
while ugly, this does cover a couple nice use cases like pointer tables/arrays of pointers being present.
|
||||
'''
|
||||
if not valu:
|
||||
new_pointers.append((sva, valu, symname))
|
||||
elif vw.isProbablyUnicode(sva):
|
||||
vw.makeUnicode(sva, size=s.st_size)
|
||||
elif vw.isProbablyString(sva):
|
||||
vw.makeString(sva, size=s.st_size)
|
||||
elif s.st_size % vw.getPointerSize() == 0 and s.st_size >= vw.getPointerSize():
|
||||
# so it could be something silly like an array
|
||||
for addr in range(sva, sva+s.st_size, vw.psize):
|
||||
valu = vw.readMemoryPtr(addr)
|
||||
if vw.isValidPointer(valu):
|
||||
new_pointers.append((addr, valu, symname))
|
||||
else:
|
||||
vw.makeNumber(sva, size=s.st_size)
|
||||
|
||||
# if the symbol has a value of 0, it is likely a relocation point which gets updated
|
||||
sname = demangle(s.name)
|
||||
@@ -523,7 +563,7 @@ def loadElfIntoWorkspace(vw, elf, filename=None, baseaddr=None):
|
||||
sva += baseaddr
|
||||
if vw.isValidPointer(sva) and len(dmglname):
|
||||
try:
|
||||
if s.st_other == Elf.STB_WEAK:
|
||||
if s.getInfoBind() == Elf.STB_WEAK:
|
||||
logger.info('WEAK symbol: 0x%x: %r', sva, sname)
|
||||
vw.setVaSetRow('WeakSymbols', (sname, sva))
|
||||
dmglname = '__weak_' + dmglname
|
||||
@@ -571,6 +611,7 @@ def applyRelocs(elf, vw, addbase=False, baseaddr=0):
|
||||
'''
|
||||
process relocations / strings (relocs use Dynamic Symbols)
|
||||
'''
|
||||
postfix = collections.defaultdict(list)
|
||||
arch = arch_names.get(elf.e_machine)
|
||||
relocs = elf.getRelocs()
|
||||
logger.debug("reloc len: %d", len(relocs))
|
||||
@@ -587,10 +628,11 @@ def applyRelocs(elf, vw, addbase=False, baseaddr=0):
|
||||
logger.debug('relocs: 0x%x: %s (%s)', rlva, dmglname, name)
|
||||
if arch in ('i386', 'amd64'):
|
||||
if name:
|
||||
#if dmglname ==
|
||||
if rtype == Elf.R_X86_64_IRELATIVE:
|
||||
# before making import, let's fix up the pointer as a BASEPTR Relocation
|
||||
ptr = r.r_addend
|
||||
vw.addRelocation(rlva, vivisect.RTYPE_BASEPTR, ptr)
|
||||
vw.addRelocation(rlva, RTYPE_BASEPTR, ptr)
|
||||
logger.info('Reloc: R_X86_64_IRELATIVE 0x%x', rlva)
|
||||
|
||||
if rtype in (Elf.R_386_JMP_SLOT, Elf.R_X86_64_GLOB_DAT, Elf.R_X86_64_IRELATIVE):
|
||||
@@ -598,8 +640,15 @@ def applyRelocs(elf, vw, addbase=False, baseaddr=0):
|
||||
vw.makeImport(rlva, "*", dmglname)
|
||||
vw.setComment(rlva, name)
|
||||
|
||||
elif rtype in (Elf.R_386_32, Elf.R_386_COPY, Elf.R_X86_64_TPOFF64):
|
||||
pass
|
||||
elif rtype == Elf.R_386_COPY: # Also covers X86_64_COPY
|
||||
# the linker is responsible for filling these in so we probably won't have these
|
||||
vw.addRelocation(rlva, RTYPE_BASERELOC, 0)
|
||||
|
||||
elif rtype == Elf.R_386_32: # Also covers X86_64_64
|
||||
# a direct punch in plus an addend
|
||||
# but things like libstc++ use this type for vtables in the rel.dyn
|
||||
# section without actually specifying an addend
|
||||
postfix[dmglname].append((rlva, getattr(r, 'r_addend', 0)))
|
||||
|
||||
else:
|
||||
logger.warning('unknown reloc type: %d %s (at %s)', rtype, name, hex(rlva))
|
||||
@@ -609,13 +658,13 @@ def applyRelocs(elf, vw, addbase=False, baseaddr=0):
|
||||
if rtype == Elf.R_386_RELATIVE: # R_X86_64_RELATIVE is the same number
|
||||
ptr = vw.readMemoryPtr(rlva)
|
||||
logger.info('R_386_RELATIVE: adding Relocation 0x%x -> 0x%x (name: %s) ', rlva, ptr, dmglname)
|
||||
vw.addRelocation(rlva, vivisect.RTYPE_BASEPTR, ptr)
|
||||
vw.addRelocation(rlva, RTYPE_BASEPTR, ptr)
|
||||
|
||||
elif rtype == Elf.R_X86_64_IRELATIVE:
|
||||
# first make it a relocation that is based on the imagebase
|
||||
ptr = r.r_addend
|
||||
logger.info('R_X86_64_IRELATIVE: adding Relocation 0x%x -> 0x%x (name: %r %r) ', rlva, ptr, name, dmglname)
|
||||
vw.addRelocation(rlva, vivisect.RTYPE_BASEPTR, ptr)
|
||||
vw.addRelocation(rlva, RTYPE_BASEPTR, ptr)
|
||||
|
||||
# next get the target and find a name, since the reloc itself doesn't have one
|
||||
tgt = vw.readMemoryPtr(rlva)
|
||||
@@ -626,9 +675,13 @@ def applyRelocs(elf, vw, addbase=False, baseaddr=0):
|
||||
logger.info('Reloc: making Import 0x%x (name: %s.%s) ', rlva, fn, symname)
|
||||
vw.makeImport(rlva, fn, symname)
|
||||
|
||||
elif rtype == Elf.R_X86_64_TPOFF64:
|
||||
pass
|
||||
elif rtype == Elf.R_386_TLS_DTPMOD32:
|
||||
pass
|
||||
else:
|
||||
logger.warning('unknown reloc type: %d %s (at %s)', rtype, name, hex(rlva))
|
||||
logger.info(r.tree())
|
||||
logger.warning(r.tree())
|
||||
|
||||
|
||||
if arch in ('arm', 'thumb', 'thumb16'):
|
||||
@@ -765,6 +818,8 @@ def applyRelocs(elf, vw, addbase=False, baseaddr=0):
|
||||
except vivisect.InvalidLocation as e:
|
||||
logger.warning("NOTE\t%r", e)
|
||||
|
||||
return postfix
|
||||
|
||||
def isPLT(vw, va):
|
||||
'''
|
||||
Do a decent check to see if this va is in a PLT section
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import base64
|
||||
import logging
|
||||
from io import BytesIO
|
||||
|
||||
@@ -389,17 +388,17 @@ def loadPeIntoWorkspace(vw, pe, filename=None, baseaddr=None):
|
||||
vw.addNoReturnApi("kernel32.ExitProcess")
|
||||
vw.addNoReturnApi("kernel32.ExitThread")
|
||||
vw.addNoReturnApi("kernel32.FatalExit")
|
||||
vw.addNoReturnApiRegex("^msvcr.*\._CxxThrowException$")
|
||||
vw.addNoReturnApiRegex("^msvcr.*\.abort$")
|
||||
vw.addNoReturnApiRegex("^msvcr.*\.exit$")
|
||||
vw.addNoReturnApiRegex("^msvcr.*\._exit$")
|
||||
vw.addNoReturnApiRegex("^msvcr.*\.quick_exit$")
|
||||
vw.addNoReturnApiRegex(r"^msvcr.*\._CxxThrowException$")
|
||||
vw.addNoReturnApiRegex(r"^msvcr.*\.abort$")
|
||||
vw.addNoReturnApiRegex(r"^msvcr.*\.exit$")
|
||||
vw.addNoReturnApiRegex(r"^msvcr.*\._exit$")
|
||||
vw.addNoReturnApiRegex(r"^msvcr.*\.quick_exit$")
|
||||
vw.addNoReturnApiRegex(r"^api_ms_win_crt_runtime_.*\._invalid_parameter_noinfo_noreturn$")
|
||||
vw.addNoReturnApiRegex(r"^api_ms_win_crt_runtime_.*\.exit$")
|
||||
vw.addNoReturnApiRegex(r"^api_ms_win_crt_runtime_.*\._exit$")
|
||||
# https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/invalid-parameter-functions?view=vs-2019
|
||||
# TODO: Again, there's a couple in there that have conditional termination that we should check for
|
||||
#vw.addNoReturnApiRegex("vcruntime140.__std_terminate")
|
||||
vw.addNoReturnApiRegex("^api_ms_win_crt_runtime_.*\._invalid_parameter_noinfo_noreturn$")
|
||||
vw.addNoReturnApiRegex("^api_ms_win_crt_runtime_.*\.exit$")
|
||||
vw.addNoReturnApiRegex("^api_ms_win_crt_runtime_.*\._exit$")
|
||||
# TODO: we should add abort and terminate on the conditions that there are no signal handlers
|
||||
# registered
|
||||
# https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/cexit-c-exit?view=vs-2019
|
||||
|
||||
@@ -137,6 +137,12 @@ chown_data = {
|
||||
('chown', 0x210010, 2, 0xc0d4),
|
||||
('chown', 0x210060, 2, 0x210070),
|
||||
('chown', 0x210078, 2, 0x210100),
|
||||
('chown', 0x210080, 0, 0),
|
||||
('chown', 0x210088, 0, 0),
|
||||
('chown', 0x210090, 0, 0),
|
||||
('chown', 0x2100a0, 0, 0),
|
||||
('chown', 0x2100a8, 0, 0),
|
||||
('chown', 0x2100c0, 0, 0),
|
||||
],
|
||||
|
||||
'names': [
|
||||
|
||||
@@ -2374,6 +2374,7 @@ libc_data = {
|
||||
|
||||
'relocs': [
|
||||
('libc_2_27', 0x3e7620, 2, 0x3ec560),
|
||||
('libc_2_27', 0x3e7628, 2, 0x3efbc0),
|
||||
('libc_2_27', 0x3e7630, 2, 0x21470),
|
||||
('libc_2_27', 0x3e7638, 2, 0x199e10),
|
||||
('libc_2_27', 0x3e7640, 2, 0x19a0b0),
|
||||
@@ -3642,12 +3643,18 @@ libc_data = {
|
||||
('libc_2_27', 0x3ec630, 2, 0x1b596e),
|
||||
('libc_2_27', 0x3ec638, 2, 0x1b596e),
|
||||
('libc_2_27', 0x3ec640, 2, 0x1b596e),
|
||||
('libc_2_27', 0x3ec660, 2, 0x3ec680),
|
||||
('libc_2_27', 0x3ec6e8, 2, 0x3ec760),
|
||||
('libc_2_27', 0x3ec708, 2, 0x3ed8b0),
|
||||
('libc_2_27', 0x3ec720, 2, 0x3eb780),
|
||||
('libc_2_27', 0x3ec758, 2, 0x3e82a0),
|
||||
('libc_2_27', 0x3ec7c8, 2, 0x3eba00),
|
||||
('libc_2_27', 0x3ec7e8, 2, 0x3ed8c0),
|
||||
('libc_2_27', 0x3ec800, 2, 0x3eb8c0),
|
||||
('libc_2_27', 0x3ec838, 2, 0x3e82a0),
|
||||
('libc_2_27', 0x3ec840, 2, 0x3ec680),
|
||||
('libc_2_27', 0x3ec848, 2, 0x3ec760),
|
||||
('libc_2_27', 0x3ec850, 2, 0x3eba00),
|
||||
('libc_2_27', 0x3ec858, 2, 0x21eb0),
|
||||
],
|
||||
|
||||
@@ -5541,6 +5548,7 @@ libc_data = {
|
||||
(0x21bcb00, 'libc_2_27.sys_nerr_2'),
|
||||
(0x21bcb04, 'libc_2_27.sys_nerr_0'),
|
||||
(0x21bcb10, 'libc_2_27.h_nerr'),
|
||||
(0x23e7628, 'libc_2_27.ptr__res_023e7628'),
|
||||
(0x23e7630, 'libc_2_27.ptr_init_function_0_023e7630'),
|
||||
(0x23e76a8, 'libc_2_27.ptr_hdestroy_023e76a8'),
|
||||
(0x23e7770, 'libc_2_27.ptr__IO_default_finish_023e7770'),
|
||||
@@ -5847,8 +5855,10 @@ libc_data = {
|
||||
(0x23ec508, 'libc_2_27.__progname_full'),
|
||||
(0x23ec660, 'libc_2_27._IO_list_all'),
|
||||
(0x23ec680, 'libc_2_27._IO_2_1_stderr_'),
|
||||
(0x23ec6e8, 'libc_2_27.ptr__IO_2_1_stdout__023ec6e8'),
|
||||
(0x23ec758, 'libc_2_27.ptr__IO_file_jumps_023ec758'),
|
||||
(0x23ec760, 'libc_2_27._IO_2_1_stdout_'),
|
||||
(0x23ec7c8, 'libc_2_27.ptr__IO_2_1_stdin__023ec7c8'),
|
||||
(0x23ec838, 'libc_2_27.ptr__IO_file_jumps_023ec838'),
|
||||
(0x23ec840, 'libc_2_27.stderr'),
|
||||
(0x23ec848, 'libc_2_27.stdout'),
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -34,10 +34,9 @@ def do_analyze(vw):
|
||||
logging.warning("ERROR in analysis module: (%r): %r", mod, e, exc_info=1)
|
||||
|
||||
comparators = {
|
||||
'names': lambda x,y: x[0] == y[0],
|
||||
'relocs': lambda x,y: x == y,
|
||||
'imports': lambda x,y: x[:3] == y[:3],
|
||||
'exports': lambda x,y: x[:1] == y[:1] and x[3] == y[3],
|
||||
'names': lambda x, y: x[0] == y[0],
|
||||
'imports': lambda x, y: x[:3] == y[:3],
|
||||
'exports': lambda x, y: x[:1] == y[:1] and x[3] == y[3],
|
||||
}
|
||||
|
||||
class ELFTests(unittest.TestCase):
|
||||
@@ -179,7 +178,7 @@ class ELFTests(unittest.TestCase):
|
||||
break
|
||||
if not equiv or not cmpr(obs, equiv):
|
||||
newfail += 1
|
||||
logger.warning("%s: o: %-80s\tn: %s" % (testname, obs, equiv))
|
||||
logger.warning("%s: o: %-80s\tn: %s" % (testname, equiv, obs))
|
||||
|
||||
return oldfail, newfail
|
||||
|
||||
|
||||
+353
-11
@@ -147,14 +147,253 @@ class VivisectTest(unittest.TestCase):
|
||||
(134544390, 'DivideByZero at 0x804fc06'),
|
||||
(134545954, 'DivideByZero at 0x8050222'),
|
||||
(134546126, 'DivideByZero at 0x80502ce')],
|
||||
'WeakSymbols': [('__x86.get_pc_thunk.bx', 134519744), ('__udivdi3', 134583136),
|
||||
('lstat64', 134583968), ('__TMC_END__', 134615780),
|
||||
('fstat64', 134583920), ('__umoddi3', 134583424),
|
||||
('fstatat64', 134584016), ('atexit', 134583824),
|
||||
('__dso_handle', 134615476), ('__divdi3', 134582800),
|
||||
('_dl_relocate_static_pie', 134519728), ('stat64', 134583872)],
|
||||
'WeakSymbols': [('data_start', 0x80611b0),
|
||||
('program_invocation_name', 0x8061300),
|
||||
('program_invocation_short_name', 0x80612f0),
|
||||
('__gmon_start__', 0x8060ffc)],
|
||||
'PointersFromFile': [(134614800, 134519888, 'vdir', 'fini_function_0'),
|
||||
(134614796, 134519936, 'vdir', 'init_function_0')],
|
||||
(134614796, 134519936, 'vdir', 'init_function_0'),
|
||||
(0x805a00c, 0x805d77c, 'vdir', 'long_options'),
|
||||
(0x805a01c, 0x805e7c9, 'vdir', 'long_options'),
|
||||
(0x805a02c, 0x805da20, 'vdir', 'long_options'),
|
||||
(0x805a03c, 0x805d6fa, 'vdir', 'long_options'),
|
||||
(0x805a04c, 0x805d700, 'vdir', 'long_options'),
|
||||
(0x805a05c, 0x805d70a, 'vdir', 'long_options'),
|
||||
(0x805a06c, 0x805d722, 'vdir', 'long_options'),
|
||||
(0x805a07c, 0x805d731, 'vdir', 'long_options'),
|
||||
(0x805a08c, 0x805d737, 'vdir', 'long_options'),
|
||||
(0x805a09c, 0x805d741, 'vdir', 'long_options'),
|
||||
(0x805a0ac, 0x805d751, 'vdir', 'long_options'),
|
||||
(0x805a0bc, 0x805d75a, 'vdir', 'long_options'),
|
||||
(0x805a0cc, 0x805d76d, 'vdir', 'long_options'),
|
||||
(0x805a0dc, 0x805d54a, 'vdir', 'long_options'),
|
||||
(0x805a0ec, 0x805d534, 'vdir', 'long_options'),
|
||||
(0x805a0fc, 0x805d775, 'vdir', 'long_options'),
|
||||
(0x805a10c, 0x805d780, 'vdir', 'long_options'),
|
||||
(0x805a11c, 0x805d78f, 'vdir', 'long_options'),
|
||||
(0x805a12c, 0x805d798, 'vdir', 'long_options'),
|
||||
(0x805a13c, 0x805d7a2, 'vdir', 'long_options'),
|
||||
(0x805a14c, 0x805d7a5, 'vdir', 'long_options'),
|
||||
(0x805a15c, 0x805d7be, 'vdir', 'long_options'),
|
||||
(0x805a16c, 0x805d7e6, 'vdir', 'long_options'),
|
||||
(0x805a17c, 0x805d7eb, 'vdir', 'long_options'),
|
||||
(0x805a18c, 0x805d585, 'vdir', 'long_options'),
|
||||
(0x805a19c, 0x805d7f2, 'vdir', 'long_options'),
|
||||
(0x805a1ac, 0x805d7fe, 'vdir', 'long_options'),
|
||||
(0x805a1bc, 0x805d806, 'vdir', 'long_options'),
|
||||
(0x805a1cc, 0x805d597, 'vdir', 'long_options'),
|
||||
(0x805a1dc, 0x805d811, 'vdir', 'long_options'),
|
||||
(0x805a1ec, 0x805d55f, 'vdir', 'long_options'),
|
||||
(0x805a1fc, 0x805d81b, 'vdir', 'long_options'),
|
||||
(0x805a20c, 0x805d551, 'vdir', 'long_options'),
|
||||
(0x805a21c, 0x805d82e, 'vdir', 'long_options'),
|
||||
(0x805a22c, 0x805d558, 'vdir', 'long_options'),
|
||||
(0x805a23c, 0x805d836, 'vdir', 'long_options'),
|
||||
(0x805a24c, 0x805d571, 'vdir', 'long_options'),
|
||||
(0x805a25c, 0x805d579, 'vdir', 'long_options'),
|
||||
(0x805a26c, 0x805d841, 'vdir', 'long_options'),
|
||||
(0x805a27c, 0x805d84c, 'vdir', 'long_options'),
|
||||
(0x805a28c, 0x805d854, 'vdir', 'long_options'),
|
||||
(0x805a29c, 0x805d85b, 'vdir', 'long_options'),
|
||||
(0x805a2ac, 0x805dae1, 'vdir', 'long_options'),
|
||||
(0x805a2e0, 0x805d860, 'vdir', 'sort_args'),
|
||||
(0x805a2e4, 0x805d558, 'vdir', 'sort_args'),
|
||||
(0x805a2e8, 0x805d54a, 'vdir', 'sort_args'),
|
||||
(0x805a2ec, 0x805d865, 'vdir', 'sort_args'),
|
||||
(0x805a2f0, 0x805dae1, 'vdir', 'sort_args'),
|
||||
(0x805a30c, 0x805d86f, 'vdir', 'time_args'),
|
||||
(0x805a310, 0x805d875, 'vdir', 'time_args'),
|
||||
(0x805a314, 0x805d87c, 'vdir', 'time_args'),
|
||||
(0x805a318, 0x805d880, 'vdir', 'time_args'),
|
||||
(0x805a31c, 0x805d886, 'vdir', 'time_args'),
|
||||
(0x805a324, 0x0, 'vdir', 'format_types'),
|
||||
(0x805a340, 0x805d88d, 'vdir', 'format_args'),
|
||||
(0x805a344, 0x805d895, 'vdir', 'format_args'),
|
||||
(0x805a348, 0x805d89a, 'vdir', 'format_args'),
|
||||
(0x805a34c, 0x805d8a1, 'vdir', 'format_args'),
|
||||
(0x805a350, 0x805d8ac, 'vdir', 'format_args'),
|
||||
(0x805a354, 0x805d8b3, 'vdir', 'format_args'),
|
||||
(0x805a358, 0x805d8bc, 'vdir', 'format_args'),
|
||||
(0x805a384, 0x805e7dd, 'vdir', 'when_args'),
|
||||
(0x805a388, 0x805d8ca, 'vdir', 'when_args'),
|
||||
(0x805a38c, 0x805d8ce, 'vdir', 'when_args'),
|
||||
(0x805a390, 0x805d8d4, 'vdir', 'when_args'),
|
||||
(0x805a394, 0x805d8da, 'vdir', 'when_args'),
|
||||
(0x805a398, 0x805d860, 'vdir', 'when_args'),
|
||||
(0x805a39c, 0x805d8dd, 'vdir', 'when_args'),
|
||||
(0x805a3a0, 0x805d8e5, 'vdir', 'when_args'),
|
||||
(0x805a3a4, 0x805d8e2, 'vdir', 'when_args'),
|
||||
(0x805a3ac, 0x0, 'vdir', 'indicator_style_types'),
|
||||
(0x805a3bc, 0x805d860, 'vdir', 'indicator_style_args'),
|
||||
(0x805a3c0, 0x805d8e9, 'vdir', 'indicator_style_args'),
|
||||
(0x805a3c4, 0x805d798, 'vdir', 'indicator_style_args'),
|
||||
(0x805a3c8, 0x805d78f, 'vdir', 'indicator_style_args'),
|
||||
(0x805a3d8, 0x805d566, 'vdir', 'time_style_args'),
|
||||
(0x805a3dc, 0x805d905, 'vdir', 'time_style_args'),
|
||||
(0x805a3e0, 0x805d90a, 'vdir', 'time_style_args'),
|
||||
(0x805a3e4, 0x805b6f2, 'vdir', 'time_style_args'),
|
||||
(0x805a3ec, 0x0, 'vdir', 'time_style_types'),
|
||||
(0x805a3fc, 0x805d987, 'vdir', 'indicator_name'),
|
||||
(0x805a400, 0x805d98a, 'vdir', 'indicator_name'),
|
||||
(0x805a404, 0x805d98d, 'vdir', 'indicator_name'),
|
||||
(0x805a408, 0x805d76a, 'vdir', 'indicator_name'),
|
||||
(0x805a40c, 0x805d8da, 'vdir', 'indicator_name'),
|
||||
(0x805a410, 0x805d990, 'vdir', 'indicator_name'),
|
||||
(0x805a414, 0x805d993, 'vdir', 'indicator_name'),
|
||||
(0x805a418, 0x805d996, 'vdir', 'indicator_name'),
|
||||
(0x805a41c, 0x805d999, 'vdir', 'indicator_name'),
|
||||
(0x805a420, 0x805d90b, 'vdir', 'indicator_name'),
|
||||
(0x805a424, 0x805d99c, 'vdir', 'indicator_name'),
|
||||
(0x805a428, 0x805d99f, 'vdir', 'indicator_name'),
|
||||
(0x805a42c, 0x805d9a2, 'vdir', 'indicator_name'),
|
||||
(0x805a430, 0x805d858, 'vdir', 'indicator_name'),
|
||||
(0x805a434, 0x805d9a5, 'vdir', 'indicator_name'),
|
||||
(0x805a438, 0x805d9a8, 'vdir', 'indicator_name'),
|
||||
(0x805a43c, 0x805d9ab, 'vdir', 'indicator_name'),
|
||||
(0x805a440, 0x805d9ae, 'vdir', 'indicator_name'),
|
||||
(0x805a444, 0x805d71f, 'vdir', 'indicator_name'),
|
||||
(0x805a448, 0x805d9b1, 'vdir', 'indicator_name'),
|
||||
(0x805a44c, 0x805d9b4, 'vdir', 'indicator_name'),
|
||||
(0x805a450, 0x805d9b7, 'vdir', 'indicator_name'),
|
||||
(0x805a454, 0x805d9ba, 'vdir', 'indicator_name'),
|
||||
(0x805a458, 0x805d9bd, 'vdir', 'indicator_name'),
|
||||
(0x805b524, 0x804e130, 'vdir', 'sort_functions'),
|
||||
(0x805b528, 0x804e150, 'vdir', 'sort_functions'),
|
||||
(0x805b52c, 0x804e1b0, 'vdir', 'sort_functions'),
|
||||
(0x805b530, 0x804e1d0, 'vdir', 'sort_functions'),
|
||||
(0x805b534, 0x804e230, 'vdir', 'sort_functions'),
|
||||
(0x805b538, 0x804e250, 'vdir', 'sort_functions'),
|
||||
(0x805b53c, 0x804e2b0, 'vdir', 'sort_functions'),
|
||||
(0x805b540, 0x804e2d0, 'vdir', 'sort_functions'),
|
||||
(0x805b544, 0x804e330, 'vdir', 'sort_functions'),
|
||||
(0x805b548, 0x804e350, 'vdir', 'sort_functions'),
|
||||
(0x805b54c, 0x804e3b0, 'vdir', 'sort_functions'),
|
||||
(0x805b550, 0x804e3d0, 'vdir', 'sort_functions'),
|
||||
(0x805b554, 0x804e430, 'vdir', 'sort_functions'),
|
||||
(0x805b558, 0x804e450, 'vdir', 'sort_functions'),
|
||||
(0x805b55c, 0x804e4b0, 'vdir', 'sort_functions'),
|
||||
(0x805b560, 0x804e4d0, 'vdir', 'sort_functions'),
|
||||
(0x805b564, 0x804e530, 'vdir', 'sort_functions'),
|
||||
(0x805b568, 0x804e550, 'vdir', 'sort_functions'),
|
||||
(0x805b56c, 0x804e5b0, 'vdir', 'sort_functions'),
|
||||
(0x805b570, 0x804e5d0, 'vdir', 'sort_functions'),
|
||||
(0x805b574, 0x804e630, 'vdir', 'sort_functions'),
|
||||
(0x805b578, 0x804e650, 'vdir', 'sort_functions'),
|
||||
(0x805b57c, 0x804e6b0, 'vdir', 'sort_functions'),
|
||||
(0x805b580, 0x804e6d0, 'vdir', 'sort_functions'),
|
||||
(0x805b584, 0x804e730, 'vdir', 'sort_functions'),
|
||||
(0x805b588, 0x804e740, 'vdir', 'sort_functions'),
|
||||
(0x805b58c, 0x804e790, 'vdir', 'sort_functions'),
|
||||
(0x805b590, 0x804e7a0, 'vdir', 'sort_functions'),
|
||||
(0x805b5a4, 0x804e7f0, 'vdir', 'sort_functions'),
|
||||
(0x805b5a8, 0x804e810, 'vdir', 'sort_functions'),
|
||||
(0x805b5ac, 0x804e870, 'vdir', 'sort_functions'),
|
||||
(0x805b5b0, 0x804e890, 'vdir', 'sort_functions'),
|
||||
(0x805b5b4, 0x804e8f0, 'vdir', 'sort_functions'),
|
||||
(0x805b5b8, 0x804e910, 'vdir', 'sort_functions'),
|
||||
(0x805b5bc, 0x804e970, 'vdir', 'sort_functions'),
|
||||
(0x805b5c0, 0x804e990, 'vdir', 'sort_functions'),
|
||||
(0x805b5c4, 0x804e9f0, 'vdir', 'sort_functions'),
|
||||
(0x805b5c8, 0x804ea10, 'vdir', 'sort_functions'),
|
||||
(0x805b5cc, 0x804ea70, 'vdir', 'sort_functions'),
|
||||
(0x805b5d0, 0x804ea90, 'vdir', 'sort_functions'),
|
||||
(0x805b5d4, 0x804eaf0, 'vdir', 'sort_functions'),
|
||||
(0x805b5d8, 0x804eb10, 'vdir', 'sort_functions'),
|
||||
(0x805b5dc, 0x804eb70, 'vdir', 'sort_functions'),
|
||||
(0x805b5e0, 0x804eb90, 'vdir', 'sort_functions'),
|
||||
(0x805b5e4, 0x804ebf0, 'vdir', 'sort_functions'),
|
||||
(0x805b5e8, 0x804ec10, 'vdir', 'sort_functions'),
|
||||
(0x805b5ec, 0x804ec70, 'vdir', 'sort_functions'),
|
||||
(0x805b5f0, 0x804ec90, 'vdir', 'sort_functions'),
|
||||
(0x805b5f4, 0x804ecf0, 'vdir', 'sort_functions'),
|
||||
(0x805b5f8, 0x804ed10, 'vdir', 'sort_functions'),
|
||||
(0x805b5fc, 0x804ed70, 'vdir', 'sort_functions'),
|
||||
(0x805b600, 0x804ed90, 'vdir', 'sort_functions'),
|
||||
(0x805e014, 0x0, 'vdir', 'default_tuning'),
|
||||
(0x805e050, 0x805d722, 'vdir', 'block_size_args'),
|
||||
(0x805e054, 0x805d7a2, 'vdir', 'block_size_args'),
|
||||
(0x805e75c, 0x805d7fe, 'vdir', 'quoting_style_args'),
|
||||
(0x805e760, 0x805e7b0, 'vdir', 'quoting_style_args'),
|
||||
(0x805e764, 0x805e7b6, 'vdir', 'quoting_style_args'),
|
||||
(0x805e768, 0x805e7c3, 'vdir', 'quoting_style_args'),
|
||||
(0x805e76c, 0x805e7d0, 'vdir', 'quoting_style_args'),
|
||||
(0x805e770, 0x805edb8, 'vdir', 'quoting_style_args'),
|
||||
(0x805e774, 0x805e7e4, 'vdir', 'quoting_style_args'),
|
||||
(0x805e778, 0x805e7c9, 'vdir', 'quoting_style_args'),
|
||||
(0x805e77c, 0x805b6f2, 'vdir', 'quoting_style_args'),
|
||||
(0x805e780, 0x805e7ec, 'vdir', 'quoting_style_args'),
|
||||
(0x805e788, 0x0, 'vdir', 'quoting_style_vals'),
|
||||
(0x805f3a0, 0x0, 'vdir', '__FRAME_END__'),
|
||||
(0x80611b4, 0x0, 'vdir', '__dso_handle'),
|
||||
(0x80611bc, 0x805b722, 'vdir', 'color_indicator'),
|
||||
(0x80611c4, 0x805dca1, 'vdir', 'color_indicator'),
|
||||
(0x80611d4, 0x805b789, 'vdir', 'color_indicator'),
|
||||
(0x80611ec, 0x805d420, 'vdir', 'color_indicator'),
|
||||
(0x80611f4, 0x805d426, 'vdir', 'color_indicator'),
|
||||
(0x80611fc, 0x805d435, 'vdir', 'color_indicator'),
|
||||
(0x8061204, 0x805d42c, 'vdir', 'color_indicator'),
|
||||
(0x806120c, 0x805d432, 'vdir', 'color_indicator'),
|
||||
(0x8061214, 0x805d432, 'vdir', 'color_indicator'),
|
||||
(0x806122c, 0x805d438, 'vdir', 'color_indicator'),
|
||||
(0x8061234, 0x805d42c, 'vdir', 'color_indicator'),
|
||||
(0x806123c, 0x805d43e, 'vdir', 'color_indicator'),
|
||||
(0x8061244, 0x805d444, 'vdir', 'color_indicator'),
|
||||
(0x806124c, 0x805d44a, 'vdir', 'color_indicator'),
|
||||
(0x8061254, 0x805d450, 'vdir', 'color_indicator'),
|
||||
(0x806125c, 0x805d456, 'vdir', 'color_indicator'),
|
||||
(0x8061264, 0x805d45c, 'vdir', 'color_indicator'),
|
||||
(0x8061274, 0x805d462, 'vdir', 'color_indicator'),
|
||||
(0x8061280, 0x805d8ef, 'vdir', 'long_time_format'),
|
||||
(0x8061284, 0x805d8f9, 'vdir', 'long_time_format'),
|
||||
(0x8061294, 0x805dd7b, 'vdir', 'Version'),
|
||||
(0x8061298, 0x8050730, 'vdir', 'argmatch_die'),
|
||||
(0x80612a0, 0x80612a8, 'vdir', 'slotvec'),
|
||||
(0x80612ac, 0x806231c, 'vdir', 'slotvec0'),
|
||||
(0x80612e0, 0x8058980, 'vdir', 'obstack_alloc_failed_handler'),
|
||||
(0x80612e4, 0x0, 'vdir', '__TMC_END__'),
|
||||
(0x806131c, 0x0, 'vdir', 'completed.7282'),
|
||||
(0x8061324, 0x0, 'vdir', 'print_dir_name'),
|
||||
(0x806132c, 0x0, 'vdir', 'current_time'),
|
||||
(0x8061334, 0x0, 'vdir', 'print_with_color'),
|
||||
(0x8061335, 0x0, 'vdir', 'directories_first'),
|
||||
(0x8061336, 0x0, 'vdir', 'check_symlink_mode'),
|
||||
(0x8061337, 0x0, 'vdir', 'color_symlink_as_referent'),
|
||||
(0x8061340, 0x0, 'vdir', 'immediate_dirs'),
|
||||
(0x8061348, 0x0, 'vdir', 'recursive'),
|
||||
(0x8061350, 0x0, 'vdir', 'dev_ino_obstack'),
|
||||
(0x8061384, 0x0, 'vdir', 'print_scontext'),
|
||||
(0x8061385, 0x0, 'vdir', 'print_block_size'),
|
||||
(0x8061386, 0x0, 'vdir', 'format_needs_stat'),
|
||||
(0x8061387, 0x0, 'vdir', 'format_needs_type'),
|
||||
(0x8061388, 0x0, 'vdir', 'dired'),
|
||||
(0x806138c, 0x0, 'vdir', 'dired_obstack'),
|
||||
(0x80613b8, 0x0, 'vdir', 'subdired_obstack'),
|
||||
(0x80613e4, 0x0, 'vdir', 'print_hyperlink'),
|
||||
(0x80613fc, 0x0, 'vdir', 'used_color'),
|
||||
(0x806140c, 0x0, 'vdir', 'RFC3986'),
|
||||
(0x806150c, 0x0, 'vdir', 'caught_signals'),
|
||||
(0x806158c, 0x0, 'vdir', 'qmark_funny_chars'),
|
||||
(0x8061594, 0x0, 'vdir', 'sort_reverse'),
|
||||
(0x8061595, 0x0, 'vdir', 'numeric_ids'),
|
||||
(0x8061596, 0x0, 'vdir', 'print_inode'),
|
||||
(0x80615ac, 0x0, 'vdir', 'print_owner'),
|
||||
(0x80615b8, 0x0, 'vdir', 'output_block_size'),
|
||||
(0x80615c0, 0x0, 'vdir', 'print_group'),
|
||||
(0x80615c1, 0x0, 'vdir', 'print_author'),
|
||||
(0x80615c8, 0x0, 'vdir', 'align_variable_outer_quotes'),
|
||||
(0x80615d0, 0x0, 'vdir', 'abformat'),
|
||||
(0x80621d0, 0x0, 'vdir', 'use_abformat'),
|
||||
(0x80621dc, 0x0, 'vdir', 'print_dir.first'),
|
||||
(0x80621dd, 0x0, 'vdir', 'cwd_some_quoted'),
|
||||
(0x80621e4, 0x0, 'vdir', 'any_has_acl'),
|
||||
(0x8062210, 0x0, 'vdir', 'has_capability_cache.unsupported_device'),
|
||||
(0x8062218, 0x0, 'vdir', 'getfilecon_cache.unsupported_device'),
|
||||
(0x8062220, 0x0, 'vdir', 'file_has_acl_cache.unsupported_device'),
|
||||
(0x806222c, 0x0, 'vdir', 'failed_strcoll'),
|
||||
(0x80622d4, 0x0, 'vdir', 'ignore_EPIPE'),
|
||||
(0x80622ec, 0x0, 'vdir', 'default_quoting_options'),
|
||||
(0x806231c, 0x0, 'vdir', 'slot0'),
|
||||
],
|
||||
'EmucodeFunctions': [(134582272,), (134583808,), (134552688,), (134556176,), (134548256,), (134575648,),
|
||||
(134549936,), (134556208,), (134548240,), (134582048,), (134577216,), (134572896,),
|
||||
(134582304,), (134576528,), (134573136,), (134556288,), (134548224,), (134572128,),
|
||||
@@ -225,7 +464,7 @@ class VivisectTest(unittest.TestCase):
|
||||
|
||||
# tuples are Name, Number of Locations, Size in bytes, Percentage of space
|
||||
ans = {0: ('Undefined', 0, 53337, 14),
|
||||
1: ('Num/Int', 712, 3695, 0),
|
||||
1: ('Num/Int', 713, 3695, 0),
|
||||
2: ('String', 265, 6485, 1),
|
||||
3: ('Unicode', 174, 5596, 1),
|
||||
4: ('Pointer', 361, 2888, 0),
|
||||
@@ -443,6 +682,88 @@ class VivisectTest(unittest.TestCase):
|
||||
]
|
||||
self.assertEqual(casevas, cases)
|
||||
|
||||
def test_chgrp_sections(self):
|
||||
'''
|
||||
Test that section information lines up with what we expect
|
||||
'''
|
||||
vw = self.chgrp_vw
|
||||
segments = set([
|
||||
(0x08048154, 0x000013, '.interp', 'chgrp'),
|
||||
(0x08048168, 0x000020, '.note.ABI-tag', 'chgrp'),
|
||||
(0x08048188, 0x00004c, '.gnu.hash', 'chgrp'),
|
||||
(0x080481d4, 0x0004e0, '.dynsym', 'chgrp'),
|
||||
(0x080486b4, 0x000343, '.dynstr', 'chgrp'),
|
||||
(0x080489f8, 0x00009c, '.gnu.version', 'chgrp'),
|
||||
(0x08048a94, 0x000080, '.gnu.version_r', 'chgrp'),
|
||||
(0x08048b14, 0x000038, '.rel.dyn', 'chgrp'),
|
||||
(0x08048b4c, 0x000218, '.rel.plt', 'chgrp'),
|
||||
(0x08048d64, 0x000023, '.init', 'chgrp'),
|
||||
(0x08048d90, 0x000440, '.plt', 'chgrp'),
|
||||
(0x080491d0, 0x000008, '.plt.got', 'chgrp'),
|
||||
(0x080491e0, 0x00745b, '.text', 'chgrp'),
|
||||
(0x0805063c, 0x000014, '.fini', 'chgrp'),
|
||||
(0x08050650, 0x001be6, '.rodata', 'chgrp'),
|
||||
(0x08052238, 0x00006c, '.eh_frame_hdr', 'chgrp'),
|
||||
(0x080522a4, 0x000284, '.eh_frame', 'chgrp'),
|
||||
(0x08053f0c, 0x000004, '.init_array', 'chgrp'),
|
||||
(0x08053f10, 0x000004, '.fini_array', 'chgrp'),
|
||||
(0x08053f14, 0x0000e8, '.dynamic', 'chgrp'),
|
||||
(0x08053ffc, 0x000004, '.got', 'chgrp'),
|
||||
(0x08054000, 0x000118, '.got.plt', 'chgrp'),
|
||||
(0x08054118, 0x000050, '.data', 'chgrp'),
|
||||
(0x08054170, 0x000184, '.bss', 'chgrp'),
|
||||
(0x08048000, 0x00a528, 'PHDR0', 'chgrp'),
|
||||
(0x08053f0c, 0x0003e8, 'PHDR1', 'chgrp')
|
||||
])
|
||||
self.assertEqual(segments, set(vw.getSegments()))
|
||||
|
||||
def test_chgrp_exports(self):
|
||||
'''
|
||||
Test that some fo the exports/names made by the elf parser
|
||||
aren't accidentally made into functions.
|
||||
'''
|
||||
vw = self.chgrp_vw
|
||||
exports = [
|
||||
# .rodata
|
||||
(0x08050650, 4, v_const.LOC_POINTER, 'chgrp._fp_hw'),
|
||||
(0x08050654, 4, v_const.LOC_POINTER, 'chgrp._IO_stdin_used'),
|
||||
|
||||
# long options is really an array of pointers, but that isn't obvi
|
||||
# (0x08050748, 4, v_const.LOC_POINTER, 'chgrp.long_options'),
|
||||
#(0x08050850, 0x27, v_const.LOC_STRING, None),
|
||||
|
||||
(0x8054170, 4, v_const.LOC_POINTER, 'chgrp.program_invocation_short_name@@GLIBC_2.0'),
|
||||
(0x8054178, 4, v_const.LOC_POINTER, 'chgrp.stderr@@GLIBC_2.0'),
|
||||
(0x8054180, 4, v_const.LOC_POINTER, 'chgrp.program_invocation_name@@GLIBC_2.0'),
|
||||
(0x8054190, 4, v_const.LOC_POINTER, 'chgrp.optind@@GLIBC_2.0'),
|
||||
(0x8054194, 4, v_const.LOC_POINTER, 'chgrp.stdout@@GLIBC_2.0'),
|
||||
(0x8054198, 4, v_const.LOC_POINTER, 'chgrp.optarg@@GLIBC_2.0'),
|
||||
(0x805419c, 1, v_const.LOC_NUMBER, 'chgrp.completed.7282'),
|
||||
|
||||
# .data pointers/numbers
|
||||
(0x805411c, 4, v_const.LOC_POINTER, 'chgrp.__dso_handle'),
|
||||
(0x8054120, 4, v_const.LOC_POINTER, 'chgrp.Version'),
|
||||
(0x8054124, 4, v_const.LOC_POINTER, 'chgrp.exit_failure'),
|
||||
(0x8054128, 4, v_const.LOC_POINTER, 'chgrp.slotvec'),
|
||||
(0x805412c, 4, v_const.LOC_POINTER, 'chgrp.nslots'),
|
||||
(0x8054130, 8, v_const.LOC_NUMBER, 'chgrp.slotvec0'), # this one kinda pulls double duty as both 4 and 8....
|
||||
# Another horrible little saved space of bytes for....well technically a struct, not that we
|
||||
# can easily detect that
|
||||
# (0x8054138, 4, v_const.LOC_POINTER, 'chgrp.quote_quoting_options'),
|
||||
]
|
||||
|
||||
for va, size, ltyp, name in exports:
|
||||
loc = vw.getLocation(va)
|
||||
try:
|
||||
self.assertIsNotNone(loc)
|
||||
self.assertEqual(loc[v_const.L_VA], va)
|
||||
self.assertEqual(loc[v_const.L_SIZE], size)
|
||||
self.assertEqual(loc[v_const.L_LTYPE], ltyp)
|
||||
self.assertEqual(vw.getName(loc[v_const.L_VA]), name)
|
||||
except:
|
||||
breakpoint()
|
||||
print('wat')
|
||||
|
||||
def test_libfunc_meta_equality(self):
|
||||
'''
|
||||
both vdir and chgrp have a bunch of library functions in common, and while the addresses
|
||||
@@ -549,13 +870,16 @@ class VivisectTest(unittest.TestCase):
|
||||
<va> should be actually be a VA in the middle of a string
|
||||
<strtbl> should be a table of *string* pointers, not code block pointers
|
||||
'''
|
||||
vw = self.vdir_vw
|
||||
badva = 0x0805b6f2
|
||||
loctup = self.vdir_vw.getLocation(badva, range=False)
|
||||
loctup = vw.getLocation(badva, range=False)
|
||||
self.assertEqual((134592163, 86, 2, [(134592242, 7)]), loctup)
|
||||
|
||||
# this should directly reflect what's in src/ls.c for color_indicator
|
||||
strtbl = 0x805e75c
|
||||
loctup = self.vdir_vw.getLocation(strtbl)
|
||||
self.assertEqual(loctup, (strtbl, 4, 4, None))
|
||||
loctup = vw.getLocation(strtbl)
|
||||
for idx, addr in enumerate(range(strtbl, strtbl + 40, 4)):
|
||||
self.assertEqual(vw.getLocation(addr), (addr, 4, 4, None))
|
||||
|
||||
def test_consecutive_jump_table_diff_func(self):
|
||||
jumptabl = [
|
||||
@@ -850,3 +1174,21 @@ class VivisectTest(unittest.TestCase):
|
||||
op = vw.parseOpcode(0x140010ef2)
|
||||
self.assertEqual(str(op), 'mov rax,qword [rsi + 56]')
|
||||
self.assertEqual(len(vw._op_cache), 1)
|
||||
|
||||
def test_function_thunks(self):
|
||||
vw = self.firefox_vw
|
||||
|
||||
thunks = set([fva for fva in vw.getFunctions() if vw.isFunctionThunk(fva)])
|
||||
impthunk = [0x140049920, 0x1400498a0, 0x140049ba0, 0x140049b10, 0x140049bb0, 0x140049c30, 0x140049b30,
|
||||
0x140049ab0, 0x1400498b0, 0x140049830, 0x140049930, 0x140049a30, 0x1400497b0, 0x140049730,
|
||||
0x140049bc0, 0x140049940, 0x1400498c0, 0x140049ac0, 0x140049c40, 0x140049a40, 0x1400497c0,
|
||||
0x140049840, 0x14001d2c0, 0x140049740, 0x140049ad0, 0x140049850, 0x14001d050, 0x140049bd0,
|
||||
0x140049950, 0x1400497d0, 0x1400498d0, 0x140049750, 0x140049c50, 0x140049b50, 0x140049ae0,
|
||||
0x140049be0, 0x1400498e0, 0x140049860, 0x14000dde0, 0x140049b60, 0x1400497e0, 0x140049760,
|
||||
0x140015c60, 0x140049af0, 0x1400499f0, 0x1400498f0, 0x1400496f0, 0x140049870, 0x1400497f0,
|
||||
0x140049770, 0x140049bf0, 0x140049b80, 0x140049780, 0x140049a00, 0x140049900, 0x140049700,
|
||||
0x140049800, 0x140049880, 0x140049c00, 0x140049b00, 0x140049a10, 0x140049790, 0x140049810,
|
||||
0x140049a90, 0x140049710, 0x14001ef10, 0x140049890, 0x140049910, 0x140049b90, 0x140049c10,
|
||||
0x140049b40, 0x140049aa0, 0x1400497a0, 0x140049720, 0x140049820, 0x140049a20]
|
||||
|
||||
self.assertEqual(thunks, set(impthunk))
|
||||
|
||||
Reference in New Issue
Block a user