Skip to content

Commit

Permalink
version 2.9.7:
Browse files Browse the repository at this point in the history
  * drop python <3.8 support
  * improve structs package for bitfield support and computation of
    fields' offsets for chosen pointer size (32 or 64 bits)
  • Loading branch information
bdcht committed Feb 11, 2022
1 parent dac8e00 commit 3f062db
Show file tree
Hide file tree
Showing 15 changed files with 294 additions and 131 deletions.
2 changes: 0 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
language: python
python:
- '3.6'
- '3.7'
- '3.8'
branches:
only:
Expand Down
9 changes: 8 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Amoco
Description
===========

Amoco is a python (>=3.7) package dedicated to symbolic analysis of binaries.
Amoco is a python (>=3.8) package dedicated to symbolic analysis of binaries.

It features:

Expand Down Expand Up @@ -96,6 +96,12 @@ Please see `LICENSE`_.
Changelog
=========

- `v2.9.7`_

* drop python <3.8 support
* improve structs package for bitfield support and computation of
fields' offsets for chosen pointer size (32 or 64 bits)

- `v2.9.6`_

* merge Qt GUI ImageView
Expand Down Expand Up @@ -385,6 +391,7 @@ Changelog
.. _sqlalchemy: http://www.sqlalchemy.org
.. _QDarkStyleSheet: https://github.com/ColinDuquesnoy/QDarkStyleSheet
.. _LICENSE: https://github.com/bdcht/amoco/blob/release/LICENSE
.. _v2.9.7: https://github.com/bdcht/amoco/releases/tag/v2.9.7
.. _v2.9.6: https://github.com/bdcht/amoco/releases/tag/v2.9.6
.. _v2.9.5: https://github.com/bdcht/amoco/releases/tag/v2.9.5
.. _v2.9.4: https://github.com/bdcht/amoco/releases/tag/v2.9.4
Expand Down
21 changes: 9 additions & 12 deletions amoco/sa/ghidra.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
b = ghidra_bridge.GhidraBridge(namespace=__module__.__dict__)

def select_range(begin,end):
from ghidra.program.model.address import setCurrentSelection, AddressSet
setCurrentSelection = ghidra.program.model.address.setCurrentSelection
AddressSet = ghidra.program.model.address.AddressSet
setCurrentSelection(AddressSet(toAddr(begin),toAddr(end)))

def add_memory_block(name,start,size,val=None,access="rw"):
Expand All @@ -19,35 +20,32 @@ def add_memory_block(name,start,size,val=None,access="rw"):
return blk

def setPointer(address,size=4):
from ghidra.program.model.data import PointerDataType
PointerDataType = ghidra.program.model.data.PointerDataType
if isinstance(address,int):
address = toAddr(address)
ls = currentProgram.getListing()
ls.createData(address, PointerDataType.dataType, size)

def setFunctionName(address,name):
from ghidra.program.model.symbol.SourceType import USER_DEFINED
USER_DEFINED = ghidra.program.model.symbol.SourceType.USER_DEFINED
if isinstance(address,int):
address = toAddr(address)
f = getFunctionAt(address)
f.setName(name, USER_DEFINED)

def create_labels(labels):
from ghidra.program.model.symbol.SourceType import USER_DEFINED
USER_DEFINED = ghidra.program.model.symbol.SourceType.USER_DEFINED
sym = currentProgram.symbolTable
for a,r in labels.items():
if isinstance(a,int):
a = toAddr(a)
sym.createLabel(a, r, USER_DEFINED)

def get_decompiled(func_name):
from ghidra.app.decompiler import DecompileOptions
from ghidra.app.decompiler import DecompInterface
from ghidra.util.task import ConsoleTaskMonitor
func = getGlobalFunctions(func_name)[0]
options = DecompileOptions()
monitor = ConsoleTaskMonitor()
ifc = DecompInterface()
options = ghidra.app.decompiler.DecompileOptions()
monitor = ghidra.util.task.ConsoleTaskMonitor()
ifc = ghidra.app.decompiler.DecompInterface()
ifc.setOptions(options)
ifc.openProgram(func.getProgram())
res = ifc.decompileFunction(func, 1000, monitor)
Expand Down Expand Up @@ -79,11 +77,10 @@ def get_decompiled_symbols(func_name):
print(" nameLocked: {}".format(symbol.nameLocked))

def get_ast_nodes(func_name):
from ghidra.app.decompiler import ClangStatement
res = get_decompiled(func_name)
# get (decompiled) high-function object from res:
def walk(node,L):
if type(node) == ClangStatement:
if type(node) == ghidra.app.decompiler.ClangStatement:
L.append(node)
else:
for i in range(node.numChildren()):
Expand Down
14 changes: 7 additions & 7 deletions amoco/system/baremetal/imx6.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ def __init__(self, data="", offset=0):
if data:
self.unpack(data, offset)

def unpack(self, data, offset=0):
def unpack(self, data, offset=0, psize=0):
StructFormatter.unpack(self, data, offset)
offset += 12
self.modulus = data[offset : offset + self.nlen]
Expand All @@ -205,7 +205,7 @@ def __init__(self, data="", offset=0):
if data:
self.unpack(data, offset)

def unpack(self, data, offset=0):
def unpack(self, data, offset=0, psize=0):
StructFormatter.unpack(self, data, offset)
assert self.header.tag == HAB_TAG_CRT
crtend = offset + self.header.length
Expand Down Expand Up @@ -241,7 +241,7 @@ def __init__(self, data="", offset=0):
if data:
self.unpack(data, offset)

def unpack(self, data, offset=0):
def unpack(self, data, offset=0, psize=0):
StructFormatter.unpack(self, data, offset)
assert self.header.tag == HAB_TAG_CSF
csfend = offset + self.header.length
Expand Down Expand Up @@ -298,7 +298,7 @@ def __init__(self, data="", offset=0):
if data:
self.unpack(data, offset)

def unpack(self, data, offset=0):
def unpack(self, data, offset=0, psize=0):
StructFormatter.unpack(self, data, offset)
assert self.cmd == HAB_CMD_CHK_DAT
self.flags = self.par >> 3
Expand Down Expand Up @@ -355,7 +355,7 @@ def __init__(self, data="", offset=0):
if data:
self.unpack(data, offset)

def unpack(self, data, offset=0):
def unpack(self, data, offset=0, psize=0):
StructFormatter.unpack(self, data, offset)
assert self.cmd == HAB_CMD_UNLK
if self.len > self.size():
Expand Down Expand Up @@ -400,7 +400,7 @@ def __init__(self, data="", offset=0):
if data:
self.unpack(data, offset)

def unpack(self, data, offset=0):
def unpack(self, data, offset=0, psize=0):
StructFormatter.unpack(self, data, offset)
assert self.cmd == HAB_CMD_INS_KEY
if self.len > self.size():
Expand Down Expand Up @@ -458,7 +458,7 @@ def blks_format(k, x, cls=None):
s.append((Token.Literal, ")"))
return highlight(s)

def unpack(self, data, offset=0):
def unpack(self, data, offset=0, psize=0):
StructFormatter.unpack(self, data, offset)
assert self.cmd == HAB_CMD_AUT_DAT
if self.len > self.size():
Expand Down
2 changes: 1 addition & 1 deletion amoco/system/baremetal/psx.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def __init__(self, data=None,offset=0):
if data:
self.unpack(data,offset)

def unpack(self, data, offset=0):
def unpack(self, data, offset=0, psize=0):
super().unpack(data, offset)
if self.magic != b"PS-X EXE":
raise TypeError("Wrong magic number, not a PS-X EXE file ?")
Expand Down
4 changes: 2 additions & 2 deletions amoco/system/elf.py
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,7 @@ def __init__(self, data=None):
if data:
self.unpack(data)

def unpack(self, data, offset=0):
def unpack(self, data, offset=0, psize=0):
StructFormatter.unpack(self, data, offset)
if self.ELFMAG0 != 0x7F or self.ELFMAG != b"ELF":
raise ElfError("Wrong magic number, not an ELF file ?")
Expand Down Expand Up @@ -543,7 +543,7 @@ def __init__(self, data=None):
if data:
self.unpack(data)

def unpack(self, data, offset=0):
def unpack(self, data, offset=0, psize=0):
f0 = self.fields[0]
self._v.e_ident = f0.unpack(data, offset)
offset += f0.size()
Expand Down
6 changes: 3 additions & 3 deletions amoco/system/fs/ufs.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ def __init__(self, data="", offset=0):
if data:
self.unpack(data, offset)

def unpack(self, data, offset=0):
def unpack(self, data, offset=0, psize=0):
sz = 0
for f in self.fields[:2]:
setattr(self, f.name, f.unpack(data, offset + sz, self.order))
Expand Down Expand Up @@ -385,7 +385,7 @@ def __init__(self, data="", offset=0):
if data:
self.unpack(data, offset)

def unpack(self, data, offset=0):
def unpack(self, data, offset=0, psize=0):
sz = 0
for f in self.fields[:3]:
setattr(self, f.name, f.unpack(data, offset + sz, self.order))
Expand Down Expand Up @@ -429,7 +429,7 @@ def __init__(self, data="", offset=0):
if data:
self.unpack(data, offset)

def unpack(self, data, offset=0):
def unpack(self, data, offset=0, psize=0):
sz = 0
for f in self.fields[:-1]:
setattr(self, f.name, f.unpack(data, offset + sz, self.order))
Expand Down
2 changes: 1 addition & 1 deletion amoco/system/pe.py
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@ def __init__(self, data=None, offset=0):
if data:
self.unpack(data, offset)

def unpack(self, data, offset=0):
def unpack(self, data, offset=0, psize=0):
magic = data[offset : offset + 2]
if magic == b"\x0b\x01":
logger.verbose("PE32 Magic found")
Expand Down
11 changes: 7 additions & 4 deletions amoco/system/structs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,13 +164,13 @@ class that inherits StructCore, in which case the previous class is used
"H": 2,
"i": 4,
"I": 4,
"l": 4,
"L": 4,
"l": 0,
"L": 0,
"f": 4,
"q": 8,
"Q": 8,
"d": 8,
"P": 8,
"P": 0,
}
integer = pp.Regex(r"[0-9][0-9]*")
integer.setParseAction(lambda r: int(r[0]))
Expand Down Expand Up @@ -229,6 +229,9 @@ def __init__(self, fmt, **kargs):
f_align = self.alignments[f_type]
else:
f_cls = Field
if isinstance(f_count, list):
f_cls = BitFieldEx
f_name = f_name.split('/')
f_type = kargs.get(f_type, f_type)
f_align = 0
self.fields.append(
Expand Down Expand Up @@ -273,7 +276,7 @@ def TypeDefine(newname, typebase, typecount=0, align_value=0):
if typecount:
t.fields[0].count = typecount
if align_value:
t.fields[0].align_value = align_value
t.fields[0]._align_value = align_value
return t

# ------------------------------------------------------------------------------
Expand Down
53 changes: 37 additions & 16 deletions amoco/system/structs/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,20 +81,21 @@ def format(cls):
return cls.fields[cls.union].format()

@classmethod
def size(cls):
def size(cls, psize=0):
"""
This is a class method that basically computes the sum of
the sizes of fields (or the largest field if a union) while
taking into account the possible alignements constraints.
It uses the *class* fields instances so that the resulting
value is infinite if any of these field is a VarField.
"""
A = cls.align_value()
psize = {32:4, 64:8}.get(psize,psize)
A = cls.align_value(psize)
sz = 0
for f in cls.fields:
if cls.union is False and not cls.packed:
sz = f.align(sz)
fsz = f.size()
sz = f.align(sz, psize)
fsz = f.size(psize)
if cls.union is False:
sz += fsz
elif fsz > sz:
Expand Down Expand Up @@ -146,15 +147,15 @@ def __eq__(self, other):
return False

@classmethod
def align_value(cls):
return max([f.align_value for f in cls.fields])
def align_value(cls,psize=0):
return max([f.align_value(psize) for f in cls.fields])

def unpack(self, data, offset=0):
def unpack(self, data, offset=0, psize=0):
for f in self.fields:
if self.union is False and not self.packed:
offset = f.align(offset)
offset = f.align(offset, psize)
try:
value = f.unpack(data, offset)
value = f.unpack(data, offset, psize)
except Exception:
name = self.__class__.__name__
logger.error("error unpacking %s %s"%(name,str(f)))
Expand All @@ -172,10 +173,10 @@ def unpack(self, data, offset=0):
# is a dict with subnames/subvalues:
self._v.__dict__.update(value)
if self.union is False:
offset += f.size()
offset += f.size(psize)
return self

def pack(self, data=None):
def pack(self, data=None, psize=0):
if data is None:
data = []
for f in self.fields:
Expand All @@ -190,29 +191,49 @@ def pack(self, data=None):
parts = []
offset = 0
for f, v in zip(self.fields, data):
p = f.pack(v)
p = f.pack(v,psize)
if not self.packed:
pad = f.align(offset) - offset
pad = f.align(offset,psize) - offset
p = b"\0" * pad + p
parts.append(p)
if self.union is False:
res = b"".join(parts)
if not self.packed:
res = res.ljust(self.size(), b"\0")
res = res.ljust(self.size(psize), b"\0")
return res
else:
return parts[self.union]

def offset_of(self, name):
def offset_of(self, name, psize=0):
if self.union is not False:
return 0
o = 0
for f in self.fields:
o = f.align(o,psize)
if f.name == name:
return o
o = f.align(o) + f.size()
o += f.size(psize)
raise AttributeError(name)

def offsets(self,psize=0):
if self.union is not False:
return [(0,f.size(psize)) for f in self.fields]
o = 0
offsets = []
for f in self.fields:
o = f.align(o,psize)
if hasattr(f,'subsizes'):
oo = 0
for x in f.subsizes:
xo = float("%d.%d"%(o,oo))
so = float(".%d"%x)
oo += x
offsets.append((xo,so))
else:
offsets.append((o,f.size(psize)))
o += f.size(psize)
return offsets

# ------------------------------------------------------------------------------


Expand Down
Loading

0 comments on commit 3f062db

Please sign in to comment.