-
Notifications
You must be signed in to change notification settings - Fork 1.7k
/
link.asm
102 lines (89 loc) · 3.4 KB
/
link.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
<%
import collections
import pwnlib.abi
import pwnlib.constants
import pwnlib.shellcraft
import six
%>
<%docstring>link(from_, to) -> str
Invokes the syscall link.
See 'man 2 link' for more information.
Arguments:
from(char*): from
to(char*): to
Returns:
int
</%docstring>
<%page args="from_=0, to=0"/>
<%
abi = pwnlib.abi.ABI.syscall()
stack = abi.stack
regs = abi.register_arguments[1:]
allregs = pwnlib.shellcraft.registers.current()
can_pushstr = ['from', 'to']
can_pushstr_array = []
argument_names = ['from_', 'to']
argument_values = [from_, to]
# Load all of the arguments into their destination registers / stack slots.
register_arguments = dict()
stack_arguments = collections.OrderedDict()
string_arguments = dict()
dict_arguments = dict()
array_arguments = dict()
syscall_repr = []
for name, arg in zip(argument_names, argument_values):
if arg is not None:
syscall_repr.append('%s=%r' % (name, arg))
# If the argument itself (input) is a register...
if arg in allregs:
index = argument_names.index(name)
if index < len(regs):
target = regs[index]
register_arguments[target] = arg
elif arg is not None:
stack_arguments[index] = arg
# The argument is not a register. It is a string value, and we
# are expecting a string value
elif name in can_pushstr and isinstance(arg, (six.binary_type, six.text_type)):
if isinstance(arg, six.text_type):
arg = arg.encode('utf-8')
string_arguments[name] = arg
# The argument is not a register. It is a dictionary, and we are
# expecting K:V paris.
elif name in can_pushstr_array and isinstance(arg, dict):
array_arguments[name] = ['%s=%s' % (k,v) for (k,v) in arg.items()]
# The arguent is not a register. It is a list, and we are expecting
# a list of arguments.
elif name in can_pushstr_array and isinstance(arg, (list, tuple)):
array_arguments[name] = arg
# The argument is not a register, string, dict, or list.
# It could be a constant string ('O_RDONLY') for an integer argument,
# an actual integer value, or a constant.
else:
index = argument_names.index(name)
if index < len(regs):
target = regs[index]
register_arguments[target] = arg
elif arg is not None:
stack_arguments[target] = arg
# Some syscalls have different names on various architectures.
# Determine which syscall number to use for the current architecture.
for syscall in ['SYS_link']:
if hasattr(pwnlib.constants, syscall):
break
else:
raise Exception("Could not locate any syscalls: %r" % syscalls)
%>
/* link(${', '.join(syscall_repr)}) */
%for name, arg in string_arguments.items():
${pwnlib.shellcraft.pushstr(arg, append_null=(b'\x00' not in arg))}
${pwnlib.shellcraft.mov(regs[argument_names.index(name)], abi.stack)}
%endfor
%for name, arg in array_arguments.items():
${pwnlib.shellcraft.pushstr_array(regs[argument_names.index(name)], arg)}
%endfor
%for name, arg in stack_arguments.items():
${pwnlib.shellcraft.push(arg)}
%endfor
${pwnlib.shellcraft.setregs(register_arguments)}
${pwnlib.shellcraft.syscall(syscall)}