Skip to content

Commit 202f8c8

Browse files
committed
fix print code for sigreturn frame.
1 parent f360b26 commit 202f8c8

File tree

3 files changed

+21
-29
lines changed

3 files changed

+21
-29
lines changed

angrop/rop_chain.py

Lines changed: 11 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -406,47 +406,29 @@ def dstr(self):
406406
prefix_len = bs*2+2
407407
prefix = " "*prefix_len
408408

409-
# build a lookup map for sigreturn frame values
410-
# key: index in _values, value: (frame_object, register_name)
411-
sigreturn_map = {}
409+
sigreturn_map = {} # start_offset -> frame and end offset
412410
for frame, start_offset in self._sigreturn_frames:
413-
# iterate through frame registers to build the map
411+
# iterate through frame registers to build a map
414412
frame_words = frame.to_words()
415-
for i, word_value in enumerate(frame_words):
416-
value_idx = start_offset + i
417-
if value_idx < len(self._values):
418-
# find which register this word belongs to
419-
offset_in_bytes = i * frame.word_size
420-
for reg_offset, reg_name in frame._registers.items():
421-
if reg_offset == offset_in_bytes:
422-
sigreturn_map[value_idx] = (frame, reg_name, word_value)
423-
break
424-
425-
for idx, v in enumerate(self._values):
413+
sigreturn_map[start_offset] = (frame, start_offset + len(frame_words))
414+
idx = 0
415+
while idx < len(self._values):
416+
v = self._values[idx]
426417
if v.symbolic:
427418
res += prefix + f" {v.ast}\n"
419+
idx += 1
428420
continue
429421
for g in self._gadgets:
430422
if g.addr == v.concreted:
431423
fmt = f"%#0{prefix_len}x"
432424
res += fmt % g.addr + f": {g.dstr()}\n"
433425
break
434426
else:
435-
# check if this value belongs to a sigreturn frame
436427
if idx in sigreturn_map:
437-
frame, reg_name, _ = sigreturn_map[idx]
438-
concrete_val = v.concreted
439-
# only show if value is non-zero or it's a critical register
440-
# critical registers: rip/rsp/pc/sp
441-
is_critical = reg_name in (
442-
self._p.arch.register_names[self._p.arch.ip_offset],
443-
self._p.arch.register_names[self._p.arch.sp_offset],
444-
)
445-
is_nonzero = concrete_val != 0
446-
if is_critical or is_nonzero:
447-
res += prefix + f"[sigreturn frame] {reg_name}: {concrete_val:#x}\n"
448-
else:
449-
res += prefix + f" {v.concreted:#x}\n"
428+
sigframe, idx = sigreturn_map[idx]
429+
res += sigframe.dstr(prefix=prefix)
430+
continue
431+
idx += 1
450432
return res
451433

452434
def pp(self):

angrop/sigreturn.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,3 +132,12 @@ def offset_of(self, reg):
132132
@property
133133
def word_size(self):
134134
return self._word_size
135+
136+
def dstr(self, prefix: str = "") -> str:
137+
lines = [f"{prefix} <SigreturnFrame for {self.arch_name}>"]
138+
for offset in sorted(self._registers.keys()):
139+
reg = self._registers[offset]
140+
val = self._values[reg]
141+
if val != 0:
142+
lines.append(prefix + f" {reg:15} : 0x{val:0{self._word_size*2}x}")
143+
return "\n".join(lines)

tests/test_ropchain.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ def test_sigreturn_chain_i386():
7171
assert state.solver.eval(mem) == val
7272

7373
def test_sigreturn_chain_amd64():
74+
# TODO: simulate the sigreturn syscall and verify the register again?
7475
cache_path = os.path.join(CACHE_DIR, "amd64_glibc_2.19")
7576
proj = angr.Project(os.path.join(BIN_DIR, "tests", "x86_64", "libc.so.6"), auto_load_libs=False)
7677
rop = proj.analyses.ROP()

0 commit comments

Comments
 (0)