• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Gallopsled / pwntools / 3797606986

pending completion
3797606986

push

github-actions

GitHub
Merge branch 'dev' into rop_raw_list

3931 of 6599 branches covered (59.57%)

102 of 102 new or added lines in 15 files covered. (100.0%)

12074 of 16876 relevant lines covered (71.55%)

0.72 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

83.7
/pwnlib/rop/srop.py
1
# -*- coding: utf-8 -*-
2
r"""
1✔
3
Sigreturn ROP (SROP)
4

5
Sigreturn is a syscall used to restore the entire register context
6
from memory pointed at by ESP.
7

8
We can leverage this during ROP to gain control of registers for which
9
there are not convenient gadgets.  The main caveat is that *all* registers
10
are set, including ESP and EIP (or their equivalents).  This means that
11
in order to continue after using a sigreturn frame, the stack pointer
12
must be set accordingly.
13

14
i386 Example:
15

16
    Let's just print a message out using SROP.
17

18
    >>> message = "Hello, World\\n"
19

20
    First, we'll create our example binary.
21
    It just reads some data onto the stack, and invokes
22
    the ``sigreturn`` syscall.
23
    We also make an ``int 0x80`` gadget available, followed
24
    immediately by ``exit(0)``.
25

26
    >>> context.clear(arch='i386')
27
    >>> assembly =  'setup: sub esp, 1024\n'
28
    >>> assembly += 'read:'      + shellcraft.read(constants.STDIN_FILENO, 'esp', 1024)
29
    >>> assembly += 'sigreturn:' + shellcraft.sigreturn()
30
    >>> assembly += 'int3:'      + shellcraft.trap()
31
    >>> assembly += 'syscall: '  + shellcraft.syscall()
32
    >>> assembly += 'exit: '     + 'xor ebx, ebx; mov eax, 1; int 0x80;'
33
    >>> assembly += 'message: '  + ('.asciz "%s"' % message)
34
    >>> binary = ELF.from_assembly(assembly)
35

36
    Let's construct our frame to have it invoke a ``write``
37
    syscall, and dump the message to stdout.
38

39
    >>> frame = SigreturnFrame(kernel='amd64')
40
    >>> frame.eax = constants.SYS_write
41
    >>> frame.ebx = constants.STDOUT_FILENO
42
    >>> frame.ecx = binary.symbols['message']
43
    >>> frame.edx = len(message)
44
    >>> frame.esp = 0xdeadbeef
45
    >>> frame.eip = binary.symbols['syscall']
46

47
    Let's start the process, send the data, and check the message.
48

49
    >>> p = process(binary.path)
50
    >>> p.send(bytes(frame))
51
    >>> p.recvline()
52
    b'Hello, World\n'
53
    >>> p.poll(block=True)
54
    0
55

56
amd64 Example:
57

58
    >>> context.clear()
59
    >>> context.arch = "amd64"
60
    >>> assembly =  'setup: sub rsp, 1024\n'
61
    >>> assembly += 'read:'      + shellcraft.read(constants.STDIN_FILENO, 'rsp', 1024)
62
    >>> assembly += 'sigreturn:' + shellcraft.sigreturn()
63
    >>> assembly += 'int3:'      + shellcraft.trap()
64
    >>> assembly += 'syscall: '  + shellcraft.syscall()
65
    >>> assembly += 'exit: '     + 'xor rdi, rdi; mov rax, 60; syscall;'
66
    >>> assembly += 'message: '  + ('.asciz "%s"' % message)
67
    >>> binary = ELF.from_assembly(assembly)
68
    >>> frame = SigreturnFrame()
69
    >>> frame.rax = constants.SYS_write
70
    >>> frame.rdi = constants.STDOUT_FILENO
71
    >>> frame.rsi = binary.symbols['message']
72
    >>> frame.rdx = len(message)
73
    >>> frame.rsp = 0xdeadbeef
74
    >>> frame.rip = binary.symbols['syscall']
75
    >>> p = process(binary.path)
76
    >>> p.send(bytes(frame))
77
    >>> p.recvline()
78
    b'Hello, World\n'
79
    >>> p.poll(block=True)
80
    0
81

82
arm Example:
83

84
    >>> context.clear()
85
    >>> context.arch = "arm"
86
    >>> assembly =  'setup: sub sp, sp, 1024\n'
87
    >>> assembly += 'read:'      + shellcraft.read(constants.STDIN_FILENO, 'sp', 1024)
88
    >>> assembly += 'sigreturn:' + shellcraft.sigreturn()
89
    >>> assembly += 'int3:'      + shellcraft.trap()
90
    >>> assembly += 'syscall: '  + shellcraft.syscall()
91
    >>> assembly += 'exit: '     + 'eor r0, r0; mov r7, 0x1; swi #0;'
92
    >>> assembly += 'message: '  + ('.asciz "%s"' % message)
93
    >>> binary = ELF.from_assembly(assembly)
94
    >>> frame = SigreturnFrame()
95
    >>> frame.r7 = constants.SYS_write
96
    >>> frame.r0 = constants.STDOUT_FILENO
97
    >>> frame.r1 = binary.symbols['message']
98
    >>> frame.r2 = len(message)
99
    >>> frame.sp = 0xdead0000
100
    >>> frame.pc = binary.symbols['syscall']
101
    >>> p = process(binary.path)
102
    >>> p.send(bytes(frame))
103
    >>> p.recvline()
104
    b'Hello, World\n'
105
    >>> p.wait_for_close()
106
    >>> p.poll(block=True)
107
    0
108

109
Mips Example:
110

111
    >>> context.clear()
112
    >>> context.arch = "mips"
113
    >>> context.endian = "big"
114
    >>> assembly =  'setup: sub $sp, $sp, 1024\n'
115
    >>> assembly += 'read:'      + shellcraft.read(constants.STDIN_FILENO, '$sp', 1024)
116
    >>> assembly += 'sigreturn:' + shellcraft.sigreturn()
117
    >>> assembly += 'syscall: '  + shellcraft.syscall()
118
    >>> assembly += 'exit: '     + shellcraft.exit(0)
119
    >>> assembly += 'message: '  + ('.asciz "%s"' % message)
120
    >>> binary = ELF.from_assembly(assembly)
121
    >>> frame = SigreturnFrame()
122
    >>> frame.v0 = constants.SYS_write
123
    >>> frame.a0 = constants.STDOUT_FILENO
124
    >>> frame.a1 = binary.symbols['message']
125
    >>> frame.a2 = len(message)
126
    >>> frame.sp = 0xdead0000
127
    >>> frame.pc = binary.symbols['syscall']
128
    >>> p = process(binary.path)
129
    >>> p.send(bytes(frame))
130
    >>> p.recvline()
131
    b'Hello, World\n'
132
    >>> p.poll(block=True)
133
    0
134

135
Mipsel Example:
136

137
    >>> context.clear()
138
    >>> context.arch = "mips"
139
    >>> context.endian = "little"
140
    >>> assembly =  'setup: sub $sp, $sp, 1024\n'
141
    >>> assembly += 'read:'      + shellcraft.read(constants.STDIN_FILENO, '$sp', 1024)
142
    >>> assembly += 'sigreturn:' + shellcraft.sigreturn()
143
    >>> assembly += 'syscall: '  + shellcraft.syscall()
144
    >>> assembly += 'exit: '     + shellcraft.exit(0)
145
    >>> assembly += 'message: '  + ('.asciz "%s"' % message)
146
    >>> binary = ELF.from_assembly(assembly)
147
    >>> frame = SigreturnFrame()
148
    >>> frame.v0 = constants.SYS_write
149
    >>> frame.a0 = constants.STDOUT_FILENO
150
    >>> frame.a1 = binary.symbols['message']
151
    >>> frame.a2 = len(message)
152
    >>> frame.sp = 0xdead0000
153
    >>> frame.pc = binary.symbols['syscall']
154
    >>> p = process(binary.path)
155
    >>> p.send(bytes(frame))
156
    >>> p.recvline()
157
    b'Hello, World\n'
158
    >>> p.poll(block=True)
159
    0
160

161
"""
162
from __future__ import absolute_import
1✔
163
from __future__ import division
1✔
164

165
from collections import namedtuple
1✔
166

167
from pwnlib.abi import ABI
1✔
168
from pwnlib.context import LocalContext
1✔
169
from pwnlib.context import context
1✔
170
from pwnlib.log import getLogger
1✔
171
from pwnlib.util.packing import flat
1✔
172
from pwnlib.util.packing import pack
1✔
173
from pwnlib.util.packing import unpack_many
1✔
174

175
log = getLogger(__name__)
1✔
176

177
registers = {
1✔
178
# Reference : http://lxr.free-electrons.com/source/arch/x86/include/asm/sigcontext.h?v=2.6.28#L138
179
        'i386' : {0: 'gs', 4: 'fs', 8: 'es', 12: 'ds', 16: 'edi', 20: 'esi', 24: 'ebp', 28: 'esp',
180
                  32: 'ebx', 36: 'edx', 40: 'ecx', 44: 'eax', 48: 'trapno', 52: 'err', 56: 'eip',
181
                  60: 'cs', 64: 'eflags', 68: 'esp_at_signal', 72: 'ss', 76: 'fpstate'},
182
# Reference : https://www.cs.vu.nl/~herbertb/papers/srop_sp14.pdf
183
        'amd64': {0: 'uc_flags', 8: '&uc', 16: 'uc_stack.ss_sp', 24: 'uc_stack.ss_flags',
184
                  32: 'uc_stack.ss_size', 40: 'r8', 48: 'r9', 56: 'r10', 64: 'r11', 72: 'r12',
185
                  80: 'r13', 88: 'r14', 96: 'r15', 104: 'rdi', 112: 'rsi', 120: 'rbp', 128: 'rbx',
186
                  136: 'rdx', 144: 'rax', 152: 'rcx', 160: 'rsp', 168: 'rip', 176: 'eflags',
187
                  184: 'csgsfs', 192: 'err', 200: 'trapno', 208: 'oldmask', 216: 'cr2',
188
                  224: '&fpstate', 232: '__reserved', 240: 'sigmask'},
189
# Reference : http://lxr.free-electrons.com/source/arch/arm/include/uapi/asm/sigcontext.h#L15
190
        'arm' : {0: 'uc_flags', 4: 'uc_link', 8: 'uc_stack.ss_sp', 12: 'uc_stack.ss_flags',
191
                 16: 'uc_stack.ss_size', 20: 'trap_no', 24: 'error_code', 28: 'oldmask', 32: 'r0',
192
                 36: 'r1', 40: 'r2', 44: 'r3', 48: 'r4', 52: 'r5', 56: 'r6', 60: 'r7', 64: 'r8',
193
                 68: 'r9', 72: 'r10', 76: 'fp', 80: 'ip', 84: 'sp', 88: 'lr', 92: 'pc', 96: 'cpsr',
194
                 100: 'fault_address', 104: 'uc_sigmask', 108: '__unused', 112: 'uc_regspace',
195
                 232: 'VFPU-magic', 236: 'VFPU-size'},
196
# Reference : http://lxr.free-electrons.com/source/arch/mips/include/uapi/asm/sigcontext.h#L15
197
        'mips': {0: 'sf_ass0', 4: 'sf_ass1', 8: 'sf_ass2', 12: 'sf_ass3', 16: 'sf_ass4', 20: 'sf_pad0',
198
                 24: 'sf_pad1', 28: 'sc_regmask', 32: 'sc_status', 36: 'pc', 44: 'padding', 52: 'at', 60: 'v0',
199
                 68: 'v1', 76: 'a0', 84: 'a1', 92: 'a2', 100: 'a3', 108: 't0', 116: 't1', 124: 't2',
200
                 132: 't3', 140: 't4', 148: 't5', 156: 't6', 164: 't7', 172: 's0', 180: 's1', 188: 's2',
201
                 196: 's3', 204: 's4', 212: 's5', 220: 's6', 228: 's7', 236: 't8', 244: 't9', 252: 'k0',
202
                 260: 'k1', 268: 'gp', 276: 'sp', 284: 's8', 292: 'ra'},
203
        'mipsel': {0: 'sf_ass0', 4: 'sf_ass1', 8: 'sf_ass2', 12: 'sf_ass3', 16: 'sf_ass4', 20: 'sc_regmask',
204
                   24: 'sc_status', 32: 'pc', 40: 'padding', 48: 'at', 56: 'v0', 64: 'v1', 72: 'a0',
205
                   80: 'a1', 88: 'a2', 96: 'a3', 104: 't0', 112: 't1', 120: 't2', 128: 't3', 136: 't4',
206
                   144: 't5', 152: 't6', 160: 't7', 168: 's0', 176: 's1', 184: 's2', 192: 's3', 200: 's4',
207
                   208: 's5', 216: 's6', 224: 's7', 232: 't8', 240: 't9', 248: 'k0', 256: 'k1', 264: 'gp',
208
                   272: 'sp', 280: 's8', 288: 'ra'},
209
        'aarch64': {312: 'x0', 320: 'x1', 328: 'x2', 336: 'x3',
210
                    344: 'x4',  352: 'x5', 360: 'x6', 368: 'x7',
211
                    376: 'x8', 384: 'x9', 392: 'x10', 400: 'x11',
212
                    408: 'x12', 416: 'x13', 424: 'x14', 432: 'x15',
213
                    440: 'x16', 448: 'x17', 456: 'x18', 464: 'x19',
214
                    472: 'x20', 480: 'x21', 488: 'x22', 496: 'x23',
215
                    504: 'x24', 512: 'x25', 520: 'x26', 528: 'x27',
216
                    536: 'x28', 544: 'x29', 552: 'x30', 560: 'sp',
217
                    568: 'pc', 592: 'magic'}
218
}
219

220
defaults = {
1✔
221
    "i386" : {"cs": 0x73, "ss": 0x7b},
222
    "i386_on_amd64": {"cs": 0x23, "ss": 0x2b},
223
    "amd64": {"csgsfs": 0x33},
224
    "arm": {"trap_no": 0x6, "cpsr": 0x40000010, "VFPU-magic": 0x56465001, "VFPU-size": 0x120},
225
    "mips": {},
226
    "aarch64": {"magic": 0x0000021046508001},
227
}
228

229
instruction_pointers = {
1✔
230
    'i386': 'eip',
231
    'amd64': 'rip',
232
    'arm': 'pc',
233
    'mips': 'pc',
234
    'aarch64': 'pc',
235
}
236

237
stack_pointers = {
1✔
238
    'i386': 'esp',
239
    'amd64': 'rsp',
240
    'arm': 'sp',
241
    'mips': 'sp',
242
    'aarch64': 'sp',
243
}
244

245
# # XXX Need to add support for Capstone in order to extract ARM and MIPS
246
# XXX as the SVC code may vary.
247
syscall_instructions = {
1✔
248
    'amd64': ['syscall'],
249
    'i386': ['int 0x80'],
250
    'arm': ['svc 0'],
251
    'aarch64': ['svc 0'],
252
    'thumb': ['svc 0'],
253
    'mips': ['syscall']
254
}
255

256
class SigreturnFrame(dict):
1✔
257
    r"""
258
    Crafts a sigreturn frame with values that are loaded up into
259
    registers.
260

261
    Arguments:
262
        arch(str):
263
            The architecture. Currently ``i386`` and ``amd64`` are
264
            supported.
265

266
    Examples:
267

268
        Crafting a SigreturnFrame that calls mprotect on amd64
269

270
        >>> context.clear(arch='amd64')
271
        >>> s = SigreturnFrame()
272
        >>> unpack_many(bytes(s))
273
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0]
274
        >>> assert len(s) == 248
275
        >>> s.rax = 0xa
276
        >>> s.rdi = 0x00601000
277
        >>> s.rsi = 0x1000
278
        >>> s.rdx = 0x7
279
        >>> assert len(bytes(s)) == 248
280
        >>> unpack_many(bytes(s))
281
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6295552, 4096, 0, 0, 7, 10, 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0]
282

283
        Crafting a SigreturnFrame that calls mprotect on i386
284

285
        >>> context.clear(arch='i386')
286
        >>> s = SigreturnFrame(kernel='i386')
287
        >>> unpack_many(bytes(s))
288
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 115, 0, 0, 123, 0]
289
        >>> assert len(s) == 80
290
        >>> s.eax = 125
291
        >>> s.ebx = 0x00601000
292
        >>> s.ecx = 0x1000
293
        >>> s.edx = 0x7
294
        >>> assert len(bytes(s)) == 80
295
        >>> unpack_many(bytes(s))
296
        [0, 0, 0, 0, 0, 0, 0, 0, 6295552, 7, 4096, 125, 0, 0, 0, 115, 0, 0, 123, 0]
297

298
        Crafting a SigreturnFrame that calls mprotect on ARM
299

300
        >>> s = SigreturnFrame(arch='arm')
301
        >>> unpack_many(bytes(s))
302
        [0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1073741840, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1447448577, 288]
303
        >>> s.r0 = 125
304
        >>> s.r1 = 0x00601000
305
        >>> s.r2 = 0x1000
306
        >>> s.r3 = 0x7
307
        >>> assert len(bytes(s)) == 240
308
        >>> unpack_many(bytes(s))
309
        [0, 0, 0, 0, 0, 6, 0, 0, 125, 6295552, 4096, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1073741840, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1447448577, 288]
310

311
        Crafting a SigreturnFrame that calls mprotect on MIPS
312

313
        >>> context.clear()
314
        >>> context.endian = "big"
315
        >>> s = SigreturnFrame(arch='mips')
316
        >>> unpack_many(bytes(s))
317
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
318
        >>> s.v0 = 0x101d
319
        >>> s.a0 = 0x00601000
320
        >>> s.a1 = 0x1000
321
        >>> s.a2 = 0x7
322
        >>> assert len(bytes(s)) == 296
323
        >>> unpack_many(bytes(s))
324
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4125, 0, 0, 0, 6295552, 0, 4096, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
325

326
        Crafting a SigreturnFrame that calls mprotect on MIPSel
327

328
        >>> context.clear()
329
        >>> context.endian = "little"
330
        >>> s = SigreturnFrame(arch='mips')
331
        >>> unpack_many(bytes(s))
332
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
333
        >>> s.v0 = 0x101d
334
        >>> s.a0 = 0x00601000
335
        >>> s.a1 = 0x1000
336
        >>> s.a2 = 0x7
337
        >>> assert len(bytes(s)) == 292
338
        >>> unpack_many(bytes(s))
339
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4125, 0, 0, 0, 6295552, 0, 4096, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
340

341
        Crafting a SigreturnFrame that calls mprotect on Aarch64
342

343
        >>> context.clear()
344
        >>> context.endian = "little"
345
        >>> s = SigreturnFrame(arch='aarch64')
346
        >>> unpack_many(bytes(s))
347
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1179680769, 528]
348
        >>> s.x8 = 0xe2
349
        >>> s.x0 = 0x4000
350
        >>> s.x1 = 0x1000
351
        >>> s.x2 = 0x7
352
        >>> assert len(bytes(s)) == 600
353
        >>> unpack_many(bytes(s))
354
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16384, 0, 4096, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 226, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1179680769, 528]
355
    """
356

357
    arch = None
1✔
358
    frame = None
1✔
359
    size  = 0
1✔
360
    _regs = []
1✔
361
    endian = None
1✔
362

363
    @LocalContext
1✔
364
    def __init__(self):
1✔
365
        if context.kernel is None and context.arch == 'i386':
1!
366
            log.error("kernel architecture must be specified")
×
367

368
        self.arch = context.arch
1✔
369
        self.endian = context.endian
1✔
370
        self._regs = [self.registers[i] for i in sorted(self.registers.keys())]
1✔
371
        self.update({r:0 for r in self._regs})
1✔
372
        self.size = len(bytes(self))
1✔
373
        self.update(defaults[self.arch])
1✔
374

375
        if context.arch == 'i386' and context.kernel == 'amd64':
1✔
376
            self.update(defaults['i386_on_amd64'])
1✔
377

378
    def __setitem__(self, item, value):
1✔
379
        if item not in self._regs:
1!
380
            log.error("Unknown register %r (not in %r)" % (item, self._regs))
×
381
        if self.arch == "arm" and item == "sp" and (value & 0x7):
1!
382
            log.warn_once("ARM SP should be aligned to an 8-byte boundary")
×
383
        if self.arch == "aarch64" and item == "sp" and (value & 0xf):
1!
384
            log.warn_once("AArch64 SP should be aligned to a 16-byte boundary")
×
385
        super(SigreturnFrame, self).__setitem__(item, value)
1✔
386

387
    def __setattr__(self, attr, value):
1✔
388
        if attr in SigreturnFrame.__dict__:
1✔
389
            super(SigreturnFrame, self).__setattr__(attr, value)
1✔
390
        else:
391
            self.set_regvalue(attr, value)
1✔
392

393
    def __getattr__(self, attr):
1✔
394
        if attr in self:
×
395
            return self[attr]
×
396
        raise AttributeError(attr)
×
397

398
    def __bytes__(self):
1✔
399
        frame = b""
1✔
400
        with context.local(arch=self.arch):
1✔
401
            for register_offset in sorted(self.register_offsets):
1✔
402
                if len(frame) < register_offset:
1✔
403
                    frame += b"\x00"*(register_offset - len(frame))
1✔
404
                frame += pack(self[self.registers[register_offset]])
1✔
405
        return frame
1✔
406

407
    def __str__(self):
1✔
408
        return str(self.__bytes__())
×
409

410
    def __len__(self):
1✔
411
        return self.size
1✔
412

413
    def __flat__(self):
1✔
414
        return bytes(self)
×
415

416
    @property
1✔
417
    def registers(self):
1✔
418
        if self.arch == "mips" and self.endian == "little":
1✔
419
            return registers["mipsel"]
1✔
420
        return registers[self.arch]
1✔
421

422
    @property
1✔
423
    def register_offsets(self):
1✔
424
        if self.arch == "mips" and self.endian == "little":
1✔
425
            return registers["mipsel"]
1✔
426
        return registers[self.arch].keys()
1✔
427

428
    @property
1✔
429
    def arguments(self):
1✔
430
        # Skip the register used to hold the syscall number
431
        return ABI.syscall(arch=self.arch).register_arguments[1:]
1✔
432

433
    @arguments.setter
1✔
434
    def arguments(self, a):
1✔
435
        for arg, reg in zip(a, self.arguments):
×
436
            setattr(self, reg, arg)
×
437

438
    @property
1✔
439
    def sp(self):
1✔
440
        return self[stack_pointers[self.arch]]
1✔
441

442
    @sp.setter
1✔
443
    def sp(self, v):
1✔
444
        self[stack_pointers[self.arch]] = v
1✔
445

446
    @property
1✔
447
    def pc(self):
1✔
448
        return self[instruction_pointers[self.arch]]
×
449

450
    @pc.setter
1✔
451
    def pc(self, v):
1✔
452
        self[instruction_pointers[self.arch]] = v
1✔
453

454
    @property
1✔
455
    def syscall(self):
1✔
456
        return self[self.syscall_register]
×
457

458
    @syscall.setter
1✔
459
    def syscall(self, v):
1✔
460
        self[self.syscall_register] = v
1✔
461

462
    @property
1✔
463
    def syscall_register(self):
1✔
464
        return ABI.syscall(arch=self.arch).syscall_register
1✔
465

466
    def set_regvalue(self, reg, val):
1✔
467
        """
468
        Sets a specific ``reg`` to a ``val``
469
        """
470
        self[reg] = val
1✔
471

472
    def get_spindex(self):
1✔
473
        return self._regs.index(stack_pointers[self.arch])
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc