rizin icon indicating copy to clipboard operation
rizin copied to clipboard

ROP gadget "stub" printing

Open notxvilka opened this issue 3 months ago • 3 comments

While writing ROP chain we often need to do menial work to track registers and such. To speed up the process without invoking complex solvers we could generate "stubs" that are helpful from the first sight and can be understood immediately.

For example, for the following gadget:

  0x00021ff8           0000a0e3  mov r0, 0
  0x00021ffc           3080bde8  pop {r4, r5, pc}
Gadget size: 8

the "stub" could look like:

# Overwrites r0
chain += b'\xf8\x1f\x02\x00' # <- gadget address 0x21ff8
chain += b'\x00\x00\x00\x00' # r4
chain += b'\x00\x00\x00\x00' # r5
chain += b'\x00\x00\x00\x00' # pc <- next gadget address

The needed information is at RzRopGadgetInfo (can be extended if necessary)

We also could think about automatic stack adjustment in such a stub if gadget changes the stack, e.g.:

chain += b'\x00' * 0x14

Another option, would be using struct.pack() to make addresses more readable, for example:

# Overwrites r0
chain += struct.pack("<I", 0x21ff8) # <- gadget address
chain += b'\x00\x00\x00\x00' # r4
chain += b'\x00\x00\x00\x00' # r5
chain += struct.pack("<I", 0) # pc <- next gadget address

where struct.pack(<fmt>) determined by the target architecture bitness automatically.

Depending on how the result would look like, it makes sense to also include the gadget disassembly in the comments, e.g.:

# Overwrites r0
chain += struct.pack("<I", 0x21ff8) # <- gadget address "mov r0, 0; pop {r4, r5, pc}"
chain += b'\x00\x00\x00\x00' # r4
chain += b'\x00\x00\x00\x00' # r5
chain += struct.pack("<I", 0) # pc <- next gadget address

We already have such helpers for the raw bytestream (see pc subcommands), would make sense to do the same for the ROP.

It might even be possible to generate such stubs/chains using various languages that are already supported by pc commands:

╭pc [<len>]  # Generate a C/C++ byte array.
│pca [<len>] # Generate a byte array in GAS assembly.
│pcA [<len>] # Generate a byte array in GAS assembly with instructions in comments.
│pcb [<len>] # Generate a bash script with the byte array.
│pcg [<len>] # Generate a Golang byte array.
│pcJ [<len>] # Generate a Java byte array.
│pcj [<len>] # Generate a JSON byte array.
│pck [<len>] # Generate a Kotlin byte array.
│pcn [<len>] # Generate a NodeJS buffer.
│pco [<len>] # Generate a Objective-C/C++ byte array.
│pcp [<len>] # Generate a Python byte array.
│pcr [<len>] # Generate a Rust byte array.
│pcs [<len>] # Generate a Swift byte array.

notxvilka avatar Sep 18 '25 14:09 notxvilka

I would like to work on this issue, please assign it to me.

Zaki-Mohd avatar Nov 15 '25 13:11 Zaki-Mohd

You can just work on it. Please see CONTRIBUTING.md for how to start.

Rot127 avatar Nov 15 '25 15:11 Rot127

Hello everyone, This is a high-value feature that will significantly speed up ROP chain development. I would like to take this on immediately. My Approach: Integration with Existing Tools: The most logical path is to integrate the new ROP stub generation logic with the existing multi-language payload output mechanism (the pc subcommands).[1] This will allow us to immediately support C, Python (struct.pack), and others. Data Source: I will use the information already available in RzRopGadgetInfo (and extend it if necessary) to accurately track register changes (mov r0, 0) and stack adjustments. Output Formatting: I will focus on generating highly readable output, ensuring comments include the gadget's disassembly and the necessary data fields for popped registers (r4, r5, etc.).

koushikcs562 avatar Nov 16 '25 17:11 koushikcs562