Repository: Gallopsled/pwntools

Issue:
pwn.shellcraft.linkat second argument is incorrect
https://github.com/Gallopsled/pwntools/blob/bd12d1874f17e1fd6a9b26411ccc7ccd6c31f4cb/pwnlib/shellcraft/templates/common/linux/syscalls/linkat.asm#L30

`from` should be `from_`. The current implementation makes it not possible to pass a string.


Discussion:
I would be happy to create a PR, but it's not clear if something is wrong with some auto-generator (located where?) or if the correct fix is to just directly patch this file.
I believe it was sth like pwnlib/shellcraft/data/generator.py; I think that the argument name strings should be without the underscore, too, only the python variables conflicting with python keywords

Resolving patch:
diff --git a/pwnlib/data/syscalls/generate.py b/pwnlib/data/syscalls/generate.py
--- a/pwnlib/data/syscalls/generate.py
+++ b/pwnlib/data/syscalls/generate.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python2
+#!/usr/bin/env python3
 from __future__ import division
 import argparse
 import keyword
@@ -137,6 +137,7 @@ def can_be_string(arg):
     if arg.type == 'void' and arg.derefcnt == 1:
         return True
 
+
 def can_be_array(arg):
     if arg.type == 'char' and arg.derefcnt == 2:
         return True
@@ -160,11 +161,13 @@ def fix_bad_arg_names(func, arg):
 def get_arg_default(arg):
     return 0
 
+
 def fix_rt_syscall_name(name):
     if name.startswith('rt_'):
         return name[3:]
     return name
 
+
 def fix_syscall_names(name):
     # Do not use old_mmap
     if name == 'SYS_mmap':
@@ -180,6 +183,7 @@ def main(target):
         with context.local(arch=arch):
             generate_one(target)
 
+
 def generate_one(target):
     SYSCALL_NAMES = [c for c in dir(constants) if c.startswith('SYS_')]
 
@@ -214,46 +218,50 @@ def generate_one(target):
 
         # Set up the argument string for Mako
         argument_names = []
+        argument_names_ = []
         argument_defaults = []
 
+        string_arguments = []
+        array_arguments = []
+        arg_docs = []
+
         #
 
         for arg in function.args:
-            argname = fix_bad_arg_names(function, arg)
+            argname_ = fix_bad_arg_names(function, arg)
+            argname = argname_.rstrip('_')
             default = get_arg_default(arg)
 
+            if can_be_array(arg):
+                array_arguments.append(argname)
+
+            if can_be_string(arg):
+                string_arguments.append(argname)
+
+            argtype = str(arg.type) + ('*' * arg.derefcnt)
+            arg_docs.append(
+                '    {argname_}({argtype}): {argname}'.format(
+                    argname_=argname_,
+                    argname=argname,
+                    argtype=argtype,
+                ))
+
             # 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):
                     argname = 'vararg_%i' % j
                     argument_names.append(argname)
+                    argument_names_.append(argname)
                     argument_defaults.append('%s=%s' % (argname, None))
                 break
 
             argument_names.append(argname)
-            argument_defaults.append('%s=%s' % (argname, default))
+            argument_names_.append(argname_)
+            argument_defaults.append('%s=%s' % (argname_, default))
 
         arguments_default_values = ', '.join(argument_defaults)
-        arguments_comma_separated = ', '.join(argument_names)
-
-        string_arguments = []
-        array_arguments = []
-        arg_docs = []
-
-        for arg in function.args:
-
-            if can_be_array(arg):
-                array_arguments.append(arg.name)
-
-            if can_be_string(arg):
-                string_arguments.append(arg.name)
-
-            argname = arg.name
-            argtype = str(arg.type) + ('*' * arg.derefcnt)
-            arg_docs.append(
-                '    {argname}({argtype}): {argname}'.format(argname=argname,
-                                                             argtype=argtype))
+        arguments_comma_separated = ', '.join(argument_names_)
 
         return_type = str(function.type) + ('*' * function.derefcnt)
         arg_docs = '\n'.join(arg_docs)
@@ -282,6 +290,7 @@ def generate_one(target):
         with open(os.path.join(target, name + '.asm'), 'wt') as f:
             f.write('\n'.join(map(str.strip, lines)) + '\n')
 
+
 if __name__ == '__main__':
     p = argparse.ArgumentParser()
     p.add_argument('target_directory')


Test patch: