@ -1,6 +1,7 @@
from __future__ import annotations
import argparse
from typing import Tuple
import pwnlib . rop . srop
@ -11,7 +12,23 @@ import pwndbg.commands
import pwndbg . gdblib . arch
import pwndbg . gdblib . memory
import pwndbg . gdblib . regs
from pwndbg . lib . regs import amd64 as amd64_regset
from pwndbg . lib . regs import amd64 , arm , aarch64 , i386
# Grab frame values from pwntools. Offsets are defined as the offset to stack pointer when syscall instruction is called
# Offsets and names are from Linux kernel source. x86_64, for example, from CONFIG_X86_64 struct rt_sigframe (Linux Kernel /arch/x86/include/asm/sigframe.h)
SIGRETURN_FRAME_LAYOUTS : dict [ str , list [ Tuple [ int , str ] ] ] = {
" x86-64 " : [ ( - 8 , " &pretcode " ) ] + list ( pwnlib . rop . srop . registers [ " amd64 " ] . items ( ) ) ,
" i386 " : list ( pwnlib . rop . srop . registers [ " i386 " ] . items ( ) ) ,
" aarch64 " : list ( pwnlib . rop . srop . registers [ " aarch64 " ] . items ( ) ) ,
}
SIGRETURN_CORE_REGISTER : dict [ str , set [ str ] ] = {
" x86-64 " : { * amd64 . gpr , amd64 . frame , amd64 . stack , amd64 . pc } ,
" i386 " : { * i386 . gpr , i386 . frame , i386 . stack , i386 . pc } ,
" aarch64 " : { * aarch64 . gpr , " sp " , " pc " } ,
}
parser = argparse . ArgumentParser ( description = " Display the SigreturnFrame at the specific address " )
@ -40,56 +57,31 @@ parser.add_argument(
@pwndbg.commands.ArgparsedCommand ( parser )
@pwndbg.commands.OnlyWhenRunning
@pwndbg.commands.OnlyWithArch ( [ " x86-64 " ])
@pwndbg.commands.OnlyWithArch ( [ " x86-64 " , " i386 " , " aarch64 " ])
def sigreturn ( address : int = None , display_all = False , print_address = False ) :
address = pwndbg . gdblib . regs . sp if address is None else address
arch_name = pwndbg . gdblib . arch . name
if arch_name == " x86-64 " :
sigreturn_x86_64 ( address , display_all , print_address )
SIGRETURN_FRAME_SIZE_x86_64 = 256
# Grab frame values from pwntools. Offsets are defined as the offset to stack pointer when syscall instruction is called
# Offsets and names are from "CONFIG_X86_64 struct rt_sigframe, Linux Kernel /arch/x86/include/asm/sigframe.h
SIGRETURN_FRAME_LAYOUT_x86_64 = sorted (
[ ( - 8 , " &pretcode " ) ] + list ( pwnlib . rop . srop . SigreturnFrame ( arch = " amd64 " ) . registers . items ( ) )
)
# Core registers
SIGRETURN_REGISTERS_x86_64 = {
* amd64_regset . gpr ,
amd64_regset . frame ,
amd64_regset . stack ,
amd64_regset . pc ,
}
def print_value ( string : str , address : int , print_address ) :
addr = " "
if print_address :
addr = f " { M . get ( address ) } : "
print ( f " { addr } { string } " )
def sigreturn_x86_64 ( address : int , display_all : bool , print_address : bool ) :
ptr_size = pwndbg . gdblib . arch . ptrsize
frame_layout = SIGRETURN_FRAME_LAYOUTS [ pwndbg . gdblib . arch . name ]
core_registers = SIGRETURN_CORE_REGISTER [ pwndbg . gdblib . arch . name ]
# Offset to the stack pointer where the frame values really begins. Start reading memory there.
# Can be negative, 0, or positive
frame_start_offset = SIGRETURN_FRAME_LAYOUT_x86_64 [ 0 ] [ 0 ]
frame_start_offset = frame_layout [ 0 ] [ 0 ]
mem = pwndbg . gdblib . memory . read ( address + frame_start_offset , SIGRETURN_FRAME_SIZE_x86_64 )
read_size = frame_layout [ - 1 ] [ 0 ] - frame_start_offset + ptr_size
for stack_offset , reg in SIGRETURN_FRAME_LAYOUT_x86_64 :
mem = pwndbg . gdblib . memory . read ( address + frame_start_offset , read_size )
for stack_offset , reg in frame_layout :
# Subtract the offset of start of frame, to get the correct offset into "mem"
mem_offset = stack_offset - frame_start_offset
regname = C . register ( reg . ljust ( 4 ) . upper ( ) )
value = pwndbg . gdblib . arch . unpack ( mem [ mem_offset : mem_offset + ptr_size ] )
if reg in SIGRETURN_REGISTERS_x86_64 :
if reg in core_registers :
desc = pwndbg . chain . format ( value )
print_value ( f " { regname } { desc } " , address + stack_offset , print_address )
@ -102,3 +94,10 @@ def sigreturn_x86_64(address: int, display_all: bool, print_address: bool):
elif display_all :
print_value ( f " { reg } { M . get ( value ) } " , address + stack_offset , print_address )
def print_value ( string : str , address : int , print_address ) :
addr = " "
if print_address :
addr = f " { M . get ( address ) } : "
print ( f " { addr } { string } " )