angr / vex

A patched version of VEX to work with PyVEX.
GNU General Public License v2.0
104 stars 44 forks source link

Feat/amd64 retf #53

Closed dannyp303 closed 1 year ago

dannyp303 commented 1 year ago

This is the simplest possible form of RETF for my current use case.

The difference between this implementation and the RET implementation is RETF additionally pops R_CS from the stack.

To complete the implementation RETF should check for protected_mode (currently unimplemented in AMD64) and if protected, check the privilege level of the code segment using the selector (Also unimplemented in AMD64). Additional values are popped from the stack if the PL is different from the current one, making this impl invalid for that scenario.

See this explination of the RETF procedure from The AMD64 user manual

Returns from a procedure previously entered by a CALL Far instruction. This form of the RET
instruction returns to a calling procedure in a different segment than the current code segment. It can
return to the same CPL or to a less privileged CPL.
RET Far pops a target CS and rIP from the stack. If the new code segment is less privileged than the
current code segment, the stack pointer is incremented by the number of bytes indicated by the
immediate operand, if present; then a new SS and rSP are also popped from the stack.
The final value of rSP is incremented by the number of bytes indicated by the immediate operand, if
present. This action skips over the parameters (previously passed to the subroutine) that are no longer
needed.
All stack pops are determined by the operand size. If necessary, the target rIP is zero-extended to 64
bits before assuming program control.
If the CPL changes, the data segment selectors are set to NULL for any of the data segments (DS, ES,
FS, GS) not accessible at the new CPL.
See RET (Near) for information on near returns—returns to procedures located inside the current code
segment. For details about control-flow instructions,

Protected mode and segment selectors are implemented in x86 already, they should be at least similar.

dannyp303 commented 1 year ago

Figured I would leave the IRSB for the current code


   t0:Ity_I64 t1:Ity_I64 t2:Ity_I64 t3:Ity_I16 t4:Ity_I16 t5:Ity_I64 t6:Ity_I64 t7:Ity_I64

   00 | ------ IMark(0x4134, 1, 0) ------
   01 | t0 = GET:I64(rsp)
   02 | t1 = LDle:I64(t0)
   03 | t5 = Add64(t0,0x0000000000000008)
   04 | t4 = LDle:I16(t5)
   05 | t2 = Add64(t0,0x000000000000000a)
   06 | PUT(rsp) = t2
   07 | PUT(cs_seg) = t4
   08 | t6 = Sub64(t0,0x0000000000000080)
   09 | ====== AbiHint(0xt6, 128, t1) ======
   NEXT: PUT(rip) = t1; Ijk_Ret
}
rhelmot commented 1 year ago

Looks great, thanks!