fix #1188: incorrect 32-bit syscall display on x64 (#1407)

* fix #1188: incorrect 32-bit syscall display on x64

* fix lint

* Update pwndbg/arguments.py
pull/1409/head
Disconnect3d 3 years ago committed by GitHub
parent d382fca97a
commit c5d880020e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -53,15 +53,26 @@ def get_syscall_name(instruction):
return None
syscall_register = pwndbg.lib.abi.ABI.syscall().syscall_register
syscall_arch = pwndbg.gdblib.arch.current
# If we are on x86/x64, return no syscall name for other instructions than syscall and int 0x80
# On x86/x64 `syscall` and `int <value>` instructions are in CS_GRP_INT
# but only `syscall` and `int 0x80` actually execute syscalls on Linux.
# So here, we return no syscall name for other instructions and we also
# handle a case when 32-bit syscalls are executed on x64
if syscall_register in ("eax", "rax"):
mnemonic = instruction.mnemonic
if not (mnemonic == "syscall" or (mnemonic == "int" and instruction.op_str == "0x80")):
is_32bit = mnemonic == "int" and instruction.op_str == "0x80"
if not (mnemonic == "syscall" or is_32bit):
return None
# On x64 the int 0x80 instruction executes 32-bit syscalls from i386
# On x86, the syscall_arch is already i386, so its all fine
if is_32bit:
syscall_arch = "i386"
syscall_number = getattr(pwndbg.gdblib.regs, syscall_register)
return pwndbg.constants.syscall(syscall_number) or "<unk_%d>" % syscall_number
return pwndbg.constants.syscall(syscall_number, syscall_arch) or "<unk_%d>" % syscall_number
def get(instruction):

@ -10,20 +10,20 @@ from . import thumb
arches = {"arm": arm, "armcm": arm, "i386": i386, "mips": mips, "x86-64": amd64, "aarch64": aarch64}
def syscall(value):
def syscall(number, arch):
"""
Given a value for a syscall number (e.g. execve == 11), return
the *name* of the syscall.
Given a syscall number and architecture, returns the name of the syscall.
E.g. execve == 59 on x86-64
"""
arch = arches.get(pwndbg.gdblib.arch.current, None)
arch = arches.get(arch, None)
if not arch:
if arch is None:
return None
prefix = "__NR_"
for k, v in arch.__dict__.items():
if v != value:
if v != number:
continue
if not k.startswith(prefix):

@ -0,0 +1,14 @@
global _start
; This binary is there to test syscall arguments display on x64
; along with 32-bit syscalls executed on x64
; Motivated by https://github.com/pwndbg/pwndbg/issues/1188
_start:
mov rax, 0
mov rdi, 0x1337
mov rsi, 0xdeadbeef
mov rcx, 0x10
syscall
mov eax, 10
int 0x80

@ -8,6 +8,7 @@ import tests
USE_FDS_BINARY = tests.binaries.get("use-fds.out")
TABSTOP_BINARY = tests.binaries.get("tabstop.out")
SYSCALLS_BINARY = tests.binaries.get("syscalls-x64.out")
def test_context_disasm_show_fd_filepath(start_binary):
@ -139,3 +140,48 @@ def test_source_code_tabstop(start_binary):
assert """ 8 return 0;\n""" in src
assert """ 9 }\n""" in src
assert """10 \n""" in src
def test_context_disasm_syscalls_args_display(start_binary):
start_binary(SYSCALLS_BINARY)
gdb.execute("nextsyscall")
dis = gdb.execute("context disasm", to_string=True)
assert dis == (
"LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA\n"
"──────────────────────[ DISASM / x86-64 / set emulate on ]──────────────────────\n"
" 0x400080 <_start> mov eax, 0\n"
" 0x400085 <_start+5> mov edi, 0x1337\n"
" 0x40008a <_start+10> mov esi, 0xdeadbeef\n"
" 0x40008f <_start+15> mov ecx, 0x10\n"
" ► 0x400094 <_start+20> syscall <SYS_read>\n"
" fd: 0x1337\n"
" buf: 0xdeadbeef\n"
" nbytes: 0x0\n"
" 0x400096 <_start+22> mov eax, 0xa\n"
" 0x40009b <_start+27> int 0x80\n"
" 0x40009d add byte ptr [rax], al\n"
" 0x40009f add byte ptr [rax], al\n"
" 0x4000a1 add byte ptr [rax], al\n"
" 0x4000a3 add byte ptr [rax], al\n"
"────────────────────────────────────────────────────────────────────────────────\n"
)
gdb.execute("nextsyscall")
dis = gdb.execute("context disasm", to_string=True)
assert dis == (
"LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA\n"
"──────────────────────[ DISASM / x86-64 / set emulate on ]──────────────────────\n"
" 0x400085 <_start+5> mov edi, 0x1337\n"
" 0x40008a <_start+10> mov esi, 0xdeadbeef\n"
" 0x40008f <_start+15> mov ecx, 0x10\n"
" 0x400094 <_start+20> syscall \n"
" 0x400096 <_start+22> mov eax, 0xa\n"
" ► 0x40009b <_start+27> int 0x80 <SYS_unlink>\n"
" name: 0x1337\n"
" 0x40009d add byte ptr [rax], al\n"
" 0x40009f add byte ptr [rax], al\n"
" 0x4000a1 add byte ptr [rax], al\n"
" 0x4000a3 add byte ptr [rax], al\n"
" 0x4000a5 add byte ptr [rax], al\n"
"────────────────────────────────────────────────────────────────────────────────\n"
)

Loading…
Cancel
Save