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:
James Gross
2021-08-19 16:33:01 -04:00
committed by GitHub
parent ad6fbba99a
commit efd49c4dc3
25 changed files with 5049 additions and 161 deletions
+7 -4
View File
@@ -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):
+1 -1
View File
@@ -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:
+3 -3
View File
@@ -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
View File
@@ -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):
+6 -6
View File
@@ -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),
+1
View File
@@ -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
View File
@@ -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
View File
@@ -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
+6 -6
View File
@@ -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'),
+3 -3
View File
@@ -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'),
+1 -1
View File
@@ -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):
'''
+1 -1
View File
@@ -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
+2
View File
@@ -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 ###################################################
+6 -6
View File
@@ -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)
+4 -4
View File
@@ -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)
+36 -24
View File
@@ -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
+67 -6
View File
@@ -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
View File
@@ -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
View File
@@ -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
+8 -9
View File
@@ -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
+6
View File
@@ -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
+4 -5
View File
@@ -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
View File
@@ -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))