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

rop: Improve density #2048

Merged
merged 1 commit into from
Apr 19, 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
7 changes: 7 additions & 0 deletions pwnlib/rop/call.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,13 @@ def __repr__(self):
fmt % self.target,
self.args)

def is_flat(self):
if isinstance(self, six.integer_types + (Unresolved,)):
return True
if not isinstance(self, Call):
return False
return bool(self.args or self.stack_arguments_before)

@property
def register_arguments(self):
return dict(zip(self.abi.register_arguments, self.args))
Expand Down
21 changes: 12 additions & 9 deletions pwnlib/rop/rop.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,10 @@
0x001c: 0x6 arg2
0x0020: b'iaaa' <pad>
0x0024: 0xdecafbad write(7, 8, 9)
0x0028: 0x10000000 <adjust @0x3c> add esp, 0x10; ret
0x0028: 0xfeedface exit()
0x002c: 0x7 arg0
0x0030: 0x8 arg1
0x0034: 0x9 arg2
0x0038: b'oaaa' <pad>
0x003c: 0xfeedface exit()

You can also append complex arguments onto stack when the stack pointer is known.

Expand Down Expand Up @@ -188,18 +186,16 @@
>>> rop.exit()
>>> print(rop.dump())
0x0000: 0x10000012 write(STDOUT_FILENO, 0x10000026, 8)
0x0004: 0x1000000e <adjust @0x18> add esp, 0x10; ret
0x0004: 0x1000002f exit()
0x0008: 0x1 STDOUT_FILENO
0x000c: 0x10000026 flag
0x0010: 0x8 arg2
0x0014: b'faaa' <pad>
0x0018: 0x1000002f exit()

The raw data from the ROP stack is available via `str`.
The raw data from the ROP stack is available via `r.chain()` (or `bytes(r)`).

>>> raw_rop = rop.chain()
>>> print(enhex(raw_rop))
120000100e000010010000002600001008000000666161612f000010
120000102f000010010000002600001008000000

Let's try it out!

Expand Down Expand Up @@ -927,7 +923,7 @@ def build(self, base = None, description = None):
# If there were arguments on the stack, we need to stick something
# in the slot where the return address goes.
if len(stackArguments) > 0:
if remaining:
if remaining and (remaining > 1 or Call.is_flat(chain[-1])):
fix_size = (1 + len(stackArguments))
fix_bytes = fix_size * context.bytes
adjust = self.search(move = fix_bytes)
Expand All @@ -944,6 +940,13 @@ def build(self, base = None, description = None):
stackArguments.append(Padding())

# We could not find a proper "adjust" gadget, but also didn't need one.
elif remaining:
_, nxslot = next(iterable)
stack.describe(self.describe(nxslot))
if isinstance(nxslot, Call):
stack.append(nxslot.target)
else:
stack.append(nxslot)
else:
stack.append(Padding("<return address>"))

Expand Down