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

Added support for syscalls in dumpargs() #174

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
134 changes: 129 additions & 5 deletions peda.py
Original file line number Diff line number Diff line change
Expand Up @@ -997,6 +997,82 @@ def _get_function_args_64(self, code, argc=None):

return args

def _get_syscall_args_64(self, code, argc=None):
"""
Guess the number of arguments passed to a syscall - x86_64
"""

# just retrieve max 6 args
arg_order = ["rdi", "rsi", "rdx", "r10", "r8", "r9"]
p = re.compile(":\s*([^ ]*)\s*(.*),")
matches = p.findall(code)
regs = [r for (_, r) in matches]
p = re.compile(("di|si|dx|r10|r8|r9"))
m = p.findall(" ".join(regs))
m = list(set(m)) # uniqify
argc = 0
if "si" in m and "di" not in m: # dirty fix
argc += 1
argc += m.count("di")
if argc > 0:
argc += m.count("si")
if argc > 1:
argc += m.count("dx")
if argc > 2:
argc += m.count("r10")
if argc > 3:
argc += m.count("r8")
if argc > 4:
argc += m.count("r9")

if argc == 0:
return []

args = []
regs = self.getregs()
for i in range(argc):
args += [regs[arg_order[i]]]

return args

def _get_syscall_args_32(self, code, argc=None):
"""
Guess the number of arguments passed to a syscall - x86_32
"""

# just retrieve max 6 args
arg_order = ["ebx", "ecx", "edx", "esi", "edi", "ebp"]
p = re.compile(":\s*([^ ]*)\s*(.*),")
matches = p.findall(code)
regs = [r for (_, r) in matches]
p = re.compile(("bx|cx|dx|si|di|bp"))
m = p.findall(" ".join(regs))
m = list(set(m)) # uniqify
argc = 0
if "cx" in m and "bx" not in m: # dirty fix
argc += 1
argc += m.count("bx")
if argc > 0:
argc += m.count("cx")
if argc > 1:
argc += m.count("dx")
if argc > 2:
argc += m.count("si")
if argc > 3:
argc += m.count("di")
if argc > 4:
argc += m.count("bp")

if argc == 0:
return []

args = []
regs = self.getregs()
for i in range(argc):
args += [regs[arg_order[i]]]

return args

def get_function_args(self, argc=None):
"""
Get the guessed arguments passed to a function when stopped at a call instruction
Expand Down Expand Up @@ -1033,6 +1109,43 @@ def get_function_args(self, argc=None):

return args


def get_syscall_args(self, argc=None):
"""
Get the guessed arguments passed to a syscall when stopped at a syscall instruction

Args:
- argc: force to get specific number of arguments (Int)

Returns:
- list of arguments (List)
"""

args = []
regs = self.getregs()
if regs is None:
return []

(arch, bits) = self.getarch()
pc = self.getreg("pc")
prev_insts = self.prev_inst(pc, 12)

code = ""
if not prev_insts:
return []

for (addr, inst) in prev_insts[::-1]:
if "call" in inst.strip().split()[0]:
break
code = "0x%x:%s\n" % (addr, inst) + code

if "i386" in arch:
args = self._get_syscall_args_32(code, argc)
if "64" in arch:
args = self._get_syscall_args_64(code, argc)

return args

@memoized
def backtrace_depth(self, sp=None):
"""
Expand Down Expand Up @@ -3839,9 +3952,9 @@ def unptrace(self, *arg):
return

# get_function_args()
def dumpargs(self, *arg):
def dumpargs(self, syscall=False, *arg):
"""
Display arguments passed to a function when stopped at a call instruction
Display arguments passed to a function/syscall when stopped at a call instruction
Usage:
MYNAME [count]
count: force to display "count args" instead of guessing
Expand All @@ -3851,7 +3964,11 @@ def dumpargs(self, *arg):
if not self._is_running():
return

args = peda.get_function_args(count)
if syscall:
args = peda.get_syscall_args(count)
else:
args = peda.get_function_args(count)

if args:
msg("Guessed arguments:")
for (i, a) in enumerate(args):
Expand Down Expand Up @@ -4280,9 +4397,16 @@ def context_code(self, *arg):
msg(text)
if inst: # valid $PC
text = ""
opcode = inst.split(":\t")[-1].split()[0]
inst_semantics = inst.split(":\t")[-1].split()
opcode = inst_semantics[0]
# stopped at system call
if ("syscall" in opcode) or ("int" in opcode and inst_semantics[1] == "0x80"):
# by the way, int 0x80 ***should assume*** 32-bit architecture
text += peda.disassemble_around(pc, count)
msg(format_disasm_code(text, pc))
self.dumpargs(syscall=True)
# stopped at function call
if "call" in opcode:
elif "call" in opcode:
text += peda.disassemble_around(pc, count)
msg(format_disasm_code(text, pc))
self.dumpargs()
Expand Down