Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fit with libc-2.33 fix #20 #21

Merged
merged 7 commits into from
Jul 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

*.pyc
42 changes: 28 additions & 14 deletions heap_viewer/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
# HeapViewer - by @danigargu
#

from typing import Dict
from .version import Version
import sys
import json
import idc
Expand All @@ -18,7 +20,7 @@
main_arena = None
malloc_par = None
global_max_fast = None
libc_version = None
libc_version: Version = None
libc_base = None
stop_during_tracing = None
start_tracing_at_startup = None
Expand All @@ -29,11 +31,31 @@

m = sys.modules[__name__]


def load():
config = None
m.ptr_size = get_arch_ptrsize()
m.libc_version = get_libc_version()
m.libc_base = get_libc_base()
libc_version = get_libc_version()

try:
with open(CONFIG_PATH, 'rb') as f:
config = json.loads(f.read())
except Exception as e:
# default config
config = {}
m.libc_offsets = config.get('libc_offsets')

if isinstance(m.libc_offsets, Dict):
libc_version = libc_version or m.libc_offsets.get("glibc_version")
if not libc_version:
DEFAULT_LIBC_VERSION = '2.33'
libc_version = DEFAULT_LIBC_VERSION # default libc version
print(
f'Warning:libc version fetch fail,you should configure in config-panel manually,default set to {DEFAULT_LIBC_VERSION}')
libc_version = Version(libc_version)
print(f'libc version set to:{libc_version}')
m.libc_version = libc_version

if m.ptr_size == 4:
m.get_ptr = idc.get_wide_dword
Expand All @@ -43,19 +65,12 @@ def load():
m.ptr_mask = (1 << 8*m.ptr_size)-1
m.program_module = get_program_module()

try:
with open(CONFIG_PATH, 'rb') as f:
config = json.loads(f.read())
except Exception as e:
# default config
config = {}

m.stop_during_tracing = config.get('stop_during_tracing', True)
m.start_tracing_at_startup = config.get('start_tracing_at_startup', False)
m.detect_double_frees_and_overlaps = config.get('detect_double_frees_and_overlaps', True)
m.detect_double_frees_and_overlaps = config.get(
'detect_double_frees_and_overlaps', True)
m.filter_library_calls = config.get('filter_library_calls', False)
m.hexdump_limit = config.get('hexdump_limit', 1024)
m.libc_offsets = config.get('libc_offsets')

main_arena = None
malloc_par = None
Expand All @@ -64,13 +79,12 @@ def load():
main_arena = m.libc_offsets.get("main_arena")
malloc_par = m.libc_offsets.get("mp_")
global_max_fast = m.libc_offsets.get("global_max_fast")

if main_arena is not None:
main_arena += m.libc_base

if malloc_par is not None:
malloc_par += m.libc_base

m.main_arena = main_arena
m.malloc_par = malloc_par

Expand All @@ -92,10 +106,10 @@ def save():
config_json = dump().encode("utf-8")
f.write(config_json)


"""
def update_file(data):
config = json.loads(data)
with open(CONFIG_PATH, 'wb') as f:
f.write(json.dumps(config, indent=4))
"""

2 changes: 1 addition & 1 deletion heap_viewer/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def log(msg):

# --------------------------------------------------------------------------
def get_struct(address, struct_type):
assert idaapi.is_loaded(address) == True, "Can't access memory at 0x%x" % address
assert idaapi.is_loaded(address) , f'memory at {hex(address)} is not loaded.\nthere maybe something wrong with your libc-version detect.'
sbytes = idaapi.get_bytes(address, sizeof(struct_type))
struct = struct_type.from_buffer_copy(sbytes)
struct._addr = address
Expand Down
10 changes: 6 additions & 4 deletions heap_viewer/ptmalloc.py
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,7 @@ def parse_heap(self, address=None):
if not heap_base:
return results

heap_size = idc.get_segm_end(heap_base) - heap_base
heap_end = idc.get_segm_end(heap_base)

'''
For prevent incorrect parsing in glibc > 2.25 (i386)
Expand All @@ -521,10 +521,12 @@ def parse_heap(self, address=None):
chunk = self.get_chunk(chunk_addr)
real_size = chunk.norm_size

if real_size == 0 or real_size > heap_size:
status = 'Corrupt'
if real_size == 0:
status = 'attempt get 0 size chunk'
stop_parse = True
elif chunk_addr + real_size >= heap_end:
status = 'attempt get ptr overflowed chunk'
stop_parse = True

elif chunk_addr == arena.top:
status = 'arena->top'
stop_parse = True
Expand Down
33 changes: 33 additions & 0 deletions heap_viewer/version/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
class Version(float):
def __init__(self, ver: str = None):
self = ver if isinstance(ver, float) else float(ver)

def __lt__(self, __x: float) -> bool:
if isinstance(__x, str):
__x = float(__x)
return super().__lt__(__x)

def __gt__(self, __x: float) -> bool:
if isinstance(__x, str):
__x = float(__x)
return super().__gt__(__x)

def __eq__(self, __x: object) -> bool:
if isinstance(__x, str):
__x = float(__x)
return super().__eq__(__x)

def __ne__(self, __x: object) -> bool:
if isinstance(__x, str):
__x = float(__x)
return super().__ne__(__x)

def __ge__(self, __x: float) -> bool:
if isinstance(__x, str):
__x = float(__x)
return super().__ge__(__x)

def __le__(self, __x: float) -> bool:
if isinstance(__x, str):
__x = float(__x)
return super().__le__(__x)
21 changes: 13 additions & 8 deletions heap_viewer/widgets/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@
from heap_viewer import misc

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


class ConfigWidget(CustomWidget):
def __init__(self, parent=None):
super(ConfigWidget, self).__init__(parent)
self._create_gui()

def _create_gui(self):
def _create_gui(self):
self.t_config = QtWidgets.QTextEdit()
self.t_config.setFixedHeight(440)

Expand All @@ -29,16 +31,18 @@ def _create_gui(self):
self.btn_update_config.clicked.connect(self.update_config)
self.btn_dump_config.clicked.connect(self.dump_config)

hbox_update_config = QtWidgets.QHBoxLayout()
hbox_update_config.addWidget(QtWidgets.QLabel("Config file (config.json)"))
hbox_update_config = QtWidgets.QHBoxLayout()
hbox_update_config.addWidget(
QtWidgets.QLabel("Config file (config.json)"))
hbox_update_config.addWidget(self.btn_update_config)
hbox_update_config.addWidget(self.btn_dump_config)
hbox_update_config.addStretch(1)

groupbox_tracer = QtWidgets.QGroupBox("Tracer options")
self.opt1 = QtWidgets.QCheckBox("Start tracing at startup")
self.opt2 = QtWidgets.QCheckBox("Stop during tracing")
self.opt3 = QtWidgets.QCheckBox("Detect double frees and chunk overlaps")
self.opt3 = QtWidgets.QCheckBox(
"Detect double frees and chunk overlaps")
self.opt4 = QtWidgets.QCheckBox("Filter library calls")

vbox_tracer = QtWidgets.QVBoxLayout()
Expand All @@ -60,22 +64,23 @@ def _create_gui(self):

form_offsets = QtWidgets.QFormLayout()
form_offsets.setSpacing(5)
form_offsets.setLabelAlignment(Qt.AlignLeft|Qt.AlignVCenter)
form_offsets.setLabelAlignment(Qt.AlignLeft | Qt.AlignVCenter)

self.t_main_arena = QtWidgets.QLineEdit()
self.t_malloc_par = QtWidgets.QLineEdit()
self.t_global_max_fast = QtWidgets.QLineEdit()

self.t_glibc_version = QtWidgets.QLineEdit('2.33')
self.offset_widgets = {
'main_arena': self.t_main_arena,
'malloc_par': self.t_malloc_par,
'global_max_fast': self.t_global_max_fast
'global_max_fast': self.t_global_max_fast,
'glibc_version': self.t_glibc_version,
}

form_offsets.addRow("main_arena", self.t_main_arena)
form_offsets.addRow("mp_ (malloc_par)", self.t_malloc_par)
form_offsets.addRow("global_max_fast", self.t_global_max_fast)

form_offsets.addRow("glibc_version", self.t_glibc_version)

groupbox_offsets = QtWidgets.QGroupBox("glibc offsets (optional)")
groupbox_offsets.setLayout(form_offsets)
Expand Down