Skip to content

Commit

Permalink
Shellcraft stackargs (#2219)
Browse files Browse the repository at this point in the history
From: Peace-Maker <[email protected]>

* Shellcraft: Fix spilling syscall args to the stack

There was a typo in the generated syscall template causing only the last
stack argument to be generated.

$ shellcraft -f asm mips.linux.sendto 3 0x123456 0x100 0 0xabcdefff 0x10
The 0xabcdefff argument was missing.

* Shellcraft: Generate 6 syscall arguments for unknown functions

There are syscalls with 6 arguments like mmap and sendto which couldn't
be called with all 6 arguments set.

$ shellcraft -f asm mips.linux.mmap2 0 0x1000
'PROT_READ | PROT_WRITE | PROT_EXEC' 'MAP_PRIVATE | MAP_ANONYMOUS' -1 0

* Shellcraft: Fix typo in error message

The `syscalls` variable is only present in the generate.py, not the
generated template.

* Regenerate syscall templates

* MIPS shellcraft: Push last two syscall arguments to the stack

The mips.linux.syscall template was only handling 4 syscall arguments
and silently discarded the remaining ones. Push the arguments to the stack
instead.

$ shellcraft -f asm mips.linux.syscall SYS_sendto 3 0x123456 0x100 0 0xabcdefff 0x10

Fixes #2153

* Fix mips syscall doctest

* Update CHANGELOG

Co-authored-by: Peace-Maker <[email protected]>
  • Loading branch information
Arusekk and peace-maker committed Jul 9, 2023
1 parent 8d10485 commit 1399c7a
Show file tree
Hide file tree
Showing 475 changed files with 1,976 additions and 1,959 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,12 @@ The table below shows which release corresponds to each branch, and what date th
- [#2202][2202] Fix `remote` and `listen` in sagemath
- [#2117][2117] Add -p (--prefix) and -s (--separator) arguments to `hex` command
- [#2221][2221] Add shellcraft.sleep template wrapping SYS_nanosleep
- [#2219][2219] Fix passing arguments on the stack in shellcraft syscall template

[2202]: https://github.com/Gallopsled/pwntools/pull/2202
[2117]: https://github.com/Gallopsled/pwntools/pull/2117
[2221]: https://github.com/Gallopsled/pwntools/pull/2221
[2219]: https://github.com/Gallopsled/pwntools/pull/2219

## 4.11.0 (`beta`)

Expand Down
8 changes: 4 additions & 4 deletions pwnlib/data/syscalls/generate.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
target = regs[index]
register_arguments[target] = arg
elif arg is not None:
stack_arguments[index] = arg
stack_arguments[name] = arg
# The argument is not a register. It is a string value, and we
# are expecting a string value
Expand Down Expand Up @@ -100,15 +100,15 @@
target = regs[index]
register_arguments[target] = arg
elif arg is not None:
stack_arguments[target] = arg
stack_arguments[name] = arg
# Some syscalls have different names on various architectures.
# Determine which syscall number to use for the current architecture.
for syscall in {syscalls!r}:
if hasattr(pwnlib.constants, syscall):
break
else:
raise Exception("Could not locate any syscalls: %r" % syscalls)
raise Exception("Could not locate any syscalls: %r" % {syscalls!r})
%>
/* {name}(${{', '.join(syscall_repr)}}) */
%for name, arg in string_arguments.items():
Expand Down Expand Up @@ -249,7 +249,7 @@ def generate_one(target):
# Mako is unable to use *vararg and *kwarg, so we just stub in
# a whole bunch of additional arguments.
if argname == 'vararg':
for j in range(5):
for j in range(6):
argname = 'vararg_%i' % j
argument_names.append(argname)
argument_names_.append(argname)
Expand Down
14 changes: 7 additions & 7 deletions pwnlib/shellcraft/templates/common/linux/syscalls/_llseek.asm
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import pwnlib.constants
import pwnlib.shellcraft
import six
%>
<%docstring>_llseek(vararg_0, vararg_1, vararg_2, vararg_3, vararg_4) -> str
<%docstring>_llseek(vararg_0, vararg_1, vararg_2, vararg_3, vararg_4, vararg_5) -> str

Invokes the syscall _llseek.

Expand All @@ -16,7 +16,7 @@ Arguments:
Returns:
long
</%docstring>
<%page args="vararg_0=None, vararg_1=None, vararg_2=None, vararg_3=None, vararg_4=None"/>
<%page args="vararg_0=None, vararg_1=None, vararg_2=None, vararg_3=None, vararg_4=None, vararg_5=None"/>
<%
abi = pwnlib.abi.ABI.syscall()
stack = abi.stack
Expand All @@ -26,8 +26,8 @@ Returns:
can_pushstr = []
can_pushstr_array = []

argument_names = ['vararg_0', 'vararg_1', 'vararg_2', 'vararg_3', 'vararg_4']
argument_values = [vararg_0, vararg_1, vararg_2, vararg_3, vararg_4]
argument_names = ['vararg_0', 'vararg_1', 'vararg_2', 'vararg_3', 'vararg_4', 'vararg_5']
argument_values = [vararg_0, vararg_1, vararg_2, vararg_3, vararg_4, vararg_5]

# Load all of the arguments into their destination registers / stack slots.
register_arguments = dict()
Expand All @@ -48,7 +48,7 @@ Returns:
target = regs[index]
register_arguments[target] = arg
elif arg is not None:
stack_arguments[index] = arg
stack_arguments[name] = arg

# The argument is not a register. It is a string value, and we
# are expecting a string value
Expand Down Expand Up @@ -76,15 +76,15 @@ Returns:
target = regs[index]
register_arguments[target] = arg
elif arg is not None:
stack_arguments[target] = arg
stack_arguments[name] = arg

# Some syscalls have different names on various architectures.
# Determine which syscall number to use for the current architecture.
for syscall in ['SYS__llseek']:
if hasattr(pwnlib.constants, syscall):
break
else:
raise Exception("Could not locate any syscalls: %r" % syscalls)
raise Exception("Could not locate any syscalls: %r" % ['SYS__llseek'])
%>
/* _llseek(${', '.join(syscall_repr)}) */
%for name, arg in string_arguments.items():
Expand Down
14 changes: 7 additions & 7 deletions pwnlib/shellcraft/templates/common/linux/syscalls/_newselect.asm
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import pwnlib.constants
import pwnlib.shellcraft
import six
%>
<%docstring>_newselect(vararg_0, vararg_1, vararg_2, vararg_3, vararg_4) -> str
<%docstring>_newselect(vararg_0, vararg_1, vararg_2, vararg_3, vararg_4, vararg_5) -> str

Invokes the syscall _newselect.

Expand All @@ -16,7 +16,7 @@ Arguments:
Returns:
long
</%docstring>
<%page args="vararg_0=None, vararg_1=None, vararg_2=None, vararg_3=None, vararg_4=None"/>
<%page args="vararg_0=None, vararg_1=None, vararg_2=None, vararg_3=None, vararg_4=None, vararg_5=None"/>
<%
abi = pwnlib.abi.ABI.syscall()
stack = abi.stack
Expand All @@ -26,8 +26,8 @@ Returns:
can_pushstr = []
can_pushstr_array = []

argument_names = ['vararg_0', 'vararg_1', 'vararg_2', 'vararg_3', 'vararg_4']
argument_values = [vararg_0, vararg_1, vararg_2, vararg_3, vararg_4]
argument_names = ['vararg_0', 'vararg_1', 'vararg_2', 'vararg_3', 'vararg_4', 'vararg_5']
argument_values = [vararg_0, vararg_1, vararg_2, vararg_3, vararg_4, vararg_5]

# Load all of the arguments into their destination registers / stack slots.
register_arguments = dict()
Expand All @@ -48,7 +48,7 @@ Returns:
target = regs[index]
register_arguments[target] = arg
elif arg is not None:
stack_arguments[index] = arg
stack_arguments[name] = arg

# The argument is not a register. It is a string value, and we
# are expecting a string value
Expand Down Expand Up @@ -76,15 +76,15 @@ Returns:
target = regs[index]
register_arguments[target] = arg
elif arg is not None:
stack_arguments[target] = arg
stack_arguments[name] = arg

# Some syscalls have different names on various architectures.
# Determine which syscall number to use for the current architecture.
for syscall in ['SYS__newselect']:
if hasattr(pwnlib.constants, syscall):
break
else:
raise Exception("Could not locate any syscalls: %r" % syscalls)
raise Exception("Could not locate any syscalls: %r" % ['SYS__newselect'])
%>
/* _newselect(${', '.join(syscall_repr)}) */
%for name, arg in string_arguments.items():
Expand Down
14 changes: 7 additions & 7 deletions pwnlib/shellcraft/templates/common/linux/syscalls/_sysctl.asm
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import pwnlib.constants
import pwnlib.shellcraft
import six
%>
<%docstring>_sysctl(vararg_0, vararg_1, vararg_2, vararg_3, vararg_4) -> str
<%docstring>_sysctl(vararg_0, vararg_1, vararg_2, vararg_3, vararg_4, vararg_5) -> str

Invokes the syscall _sysctl.

Expand All @@ -16,7 +16,7 @@ Arguments:
Returns:
long
</%docstring>
<%page args="vararg_0=None, vararg_1=None, vararg_2=None, vararg_3=None, vararg_4=None"/>
<%page args="vararg_0=None, vararg_1=None, vararg_2=None, vararg_3=None, vararg_4=None, vararg_5=None"/>
<%
abi = pwnlib.abi.ABI.syscall()
stack = abi.stack
Expand All @@ -26,8 +26,8 @@ Returns:
can_pushstr = []
can_pushstr_array = []

argument_names = ['vararg_0', 'vararg_1', 'vararg_2', 'vararg_3', 'vararg_4']
argument_values = [vararg_0, vararg_1, vararg_2, vararg_3, vararg_4]
argument_names = ['vararg_0', 'vararg_1', 'vararg_2', 'vararg_3', 'vararg_4', 'vararg_5']
argument_values = [vararg_0, vararg_1, vararg_2, vararg_3, vararg_4, vararg_5]

# Load all of the arguments into their destination registers / stack slots.
register_arguments = dict()
Expand All @@ -48,7 +48,7 @@ Returns:
target = regs[index]
register_arguments[target] = arg
elif arg is not None:
stack_arguments[index] = arg
stack_arguments[name] = arg

# The argument is not a register. It is a string value, and we
# are expecting a string value
Expand Down Expand Up @@ -76,15 +76,15 @@ Returns:
target = regs[index]
register_arguments[target] = arg
elif arg is not None:
stack_arguments[target] = arg
stack_arguments[name] = arg

# Some syscalls have different names on various architectures.
# Determine which syscall number to use for the current architecture.
for syscall in ['SYS__sysctl']:
if hasattr(pwnlib.constants, syscall):
break
else:
raise Exception("Could not locate any syscalls: %r" % syscalls)
raise Exception("Could not locate any syscalls: %r" % ['SYS__sysctl'])
%>
/* _sysctl(${', '.join(syscall_repr)}) */
%for name, arg in string_arguments.items():
Expand Down
6 changes: 3 additions & 3 deletions pwnlib/shellcraft/templates/common/linux/syscalls/accept.asm
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Returns:
target = regs[index]
register_arguments[target] = arg
elif arg is not None:
stack_arguments[index] = arg
stack_arguments[name] = arg

# The argument is not a register. It is a string value, and we
# are expecting a string value
Expand Down Expand Up @@ -78,15 +78,15 @@ Returns:
target = regs[index]
register_arguments[target] = arg
elif arg is not None:
stack_arguments[target] = arg
stack_arguments[name] = arg

# Some syscalls have different names on various architectures.
# Determine which syscall number to use for the current architecture.
for syscall in ['SYS_accept']:
if hasattr(pwnlib.constants, syscall):
break
else:
raise Exception("Could not locate any syscalls: %r" % syscalls)
raise Exception("Could not locate any syscalls: %r" % ['SYS_accept'])
%>
/* accept(${', '.join(syscall_repr)}) */
%for name, arg in string_arguments.items():
Expand Down
6 changes: 3 additions & 3 deletions pwnlib/shellcraft/templates/common/linux/syscalls/accept4.asm
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ Returns:
target = regs[index]
register_arguments[target] = arg
elif arg is not None:
stack_arguments[index] = arg
stack_arguments[name] = arg

# The argument is not a register. It is a string value, and we
# are expecting a string value
Expand Down Expand Up @@ -79,15 +79,15 @@ Returns:
target = regs[index]
register_arguments[target] = arg
elif arg is not None:
stack_arguments[target] = arg
stack_arguments[name] = arg

# Some syscalls have different names on various architectures.
# Determine which syscall number to use for the current architecture.
for syscall in ['SYS_accept4']:
if hasattr(pwnlib.constants, syscall):
break
else:
raise Exception("Could not locate any syscalls: %r" % syscalls)
raise Exception("Could not locate any syscalls: %r" % ['SYS_accept4'])
%>
/* accept4(${', '.join(syscall_repr)}) */
%for name, arg in string_arguments.items():
Expand Down
6 changes: 3 additions & 3 deletions pwnlib/shellcraft/templates/common/linux/syscalls/access.asm
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ Returns:
target = regs[index]
register_arguments[target] = arg
elif arg is not None:
stack_arguments[index] = arg
stack_arguments[name] = arg

# The argument is not a register. It is a string value, and we
# are expecting a string value
Expand Down Expand Up @@ -77,15 +77,15 @@ Returns:
target = regs[index]
register_arguments[target] = arg
elif arg is not None:
stack_arguments[target] = arg
stack_arguments[name] = arg

# Some syscalls have different names on various architectures.
# Determine which syscall number to use for the current architecture.
for syscall in ['SYS_access']:
if hasattr(pwnlib.constants, syscall):
break
else:
raise Exception("Could not locate any syscalls: %r" % syscalls)
raise Exception("Could not locate any syscalls: %r" % ['SYS_access'])
%>
/* access(${', '.join(syscall_repr)}) */
%for name, arg in string_arguments.items():
Expand Down
6 changes: 3 additions & 3 deletions pwnlib/shellcraft/templates/common/linux/syscalls/acct.asm
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ Returns:
target = regs[index]
register_arguments[target] = arg
elif arg is not None:
stack_arguments[index] = arg
stack_arguments[name] = arg

# The argument is not a register. It is a string value, and we
# are expecting a string value
Expand Down Expand Up @@ -76,15 +76,15 @@ Returns:
target = regs[index]
register_arguments[target] = arg
elif arg is not None:
stack_arguments[target] = arg
stack_arguments[name] = arg

# Some syscalls have different names on various architectures.
# Determine which syscall number to use for the current architecture.
for syscall in ['SYS_acct']:
if hasattr(pwnlib.constants, syscall):
break
else:
raise Exception("Could not locate any syscalls: %r" % syscalls)
raise Exception("Could not locate any syscalls: %r" % ['SYS_acct'])
%>
/* acct(${', '.join(syscall_repr)}) */
%for name, arg in string_arguments.items():
Expand Down
6 changes: 3 additions & 3 deletions pwnlib/shellcraft/templates/common/linux/syscalls/add_key.asm
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ Returns:
target = regs[index]
register_arguments[target] = arg
elif arg is not None:
stack_arguments[index] = arg
stack_arguments[name] = arg

# The argument is not a register. It is a string value, and we
# are expecting a string value
Expand Down Expand Up @@ -80,15 +80,15 @@ Returns:
target = regs[index]
register_arguments[target] = arg
elif arg is not None:
stack_arguments[target] = arg
stack_arguments[name] = arg

# Some syscalls have different names on various architectures.
# Determine which syscall number to use for the current architecture.
for syscall in ['SYS_add_key']:
if hasattr(pwnlib.constants, syscall):
break
else:
raise Exception("Could not locate any syscalls: %r" % syscalls)
raise Exception("Could not locate any syscalls: %r" % ['SYS_add_key'])
%>
/* add_key(${', '.join(syscall_repr)}) */
%for name, arg in string_arguments.items():
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ Returns:
target = regs[index]
register_arguments[target] = arg
elif arg is not None:
stack_arguments[index] = arg
stack_arguments[name] = arg

# The argument is not a register. It is a string value, and we
# are expecting a string value
Expand Down Expand Up @@ -76,15 +76,15 @@ Returns:
target = regs[index]
register_arguments[target] = arg
elif arg is not None:
stack_arguments[target] = arg
stack_arguments[name] = arg

# Some syscalls have different names on various architectures.
# Determine which syscall number to use for the current architecture.
for syscall in ['SYS_adjtimex']:
if hasattr(pwnlib.constants, syscall):
break
else:
raise Exception("Could not locate any syscalls: %r" % syscalls)
raise Exception("Could not locate any syscalls: %r" % ['SYS_adjtimex'])
%>
/* adjtimex(${', '.join(syscall_repr)}) */
%for name, arg in string_arguments.items():
Expand Down
Loading

0 comments on commit 1399c7a

Please sign in to comment.