1# coding=utf-8
2# Copyright 2018 Sascha Schirra
3#
4# Redistribution and use in source and binary forms, with or without
5# modification, are permitted provided that the following conditions are met:
6#
7# 1. Redistributions of source code must retain the above copyright notice, this
8# list of conditions and the following disclaimer.
9#
10# 2. Redistributions in binary form must reproduce the above copyright notice,
11# this list of conditions and the following disclaimer in the documentation
12# and/or other materials provided with the distribution.
13#
14# 3. Neither the name of the copyright holder nor the names of its contributors
15# may be used to endorse or promote products derived from this software without
16# specific prior written permission.
17#
18# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" A ND
19# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29from ropper.common.abstract import *
30from ropper.common.enum import Enum
31from ropper.common.error import NotSupportedError
32from ropper.search import Searcher, Searcherx86, SearcherARM, SearcherMIPS
33from re import compile
34from capstone import *
35from . import gadget
36try:
37    import sys
38    import archinfo
39except:
40    pass
41
42# Optional keystone support
43try:
44    import keystone
45except:
46    pass
47
48def byte_regexp(bitmask, bitvalues):
49    r = b'['
50    for value in range(256):
51        if value & bitmask == bitvalues:
52            # Generates unencoded string (bytes) in both Python 2 and 3.
53            r += bytes(bytearray([value]))
54    r += b']'
55    return r
56
57class Endianess(Enum):
58    _enum_ = 'LITTLE BIG'
59
60class Architecture(AbstractSingleton):
61
62    def __init__(self, arch, mode, addressLength, align, endianess=Endianess.LITTLE, branch_delay_slot=False):
63        super(Architecture, self).__init__()
64        self._name = 'raw'
65        self._arch = arch
66        self._mode = mode
67        self._info = None
68
69        self._ksarch = (None,None)
70
71        self._addressLength = addressLength
72        self._align = align
73
74        self._endings = {}
75        self._badInstructions = []
76        self._categories = {}
77        self._maxInvalid = 1
78
79        self._endianess = endianess
80
81        self._searcher = Searcher()
82
83        self._initGadgets()
84        self._initBadInstructions()
85        self._initCategories()
86
87        self._initEndianess(endianess)
88        self._hasBranchDelaySlot = branch_delay_slot
89
90        self._endings[gadget.GadgetType.ALL] = self._endings[
91            gadget.GadgetType.ROP] + self._endings[gadget.GadgetType.JOP] + self._endings[gadget.GadgetType.SYS]
92
93    def _initGadgets(self):
94        self._endings[gadget.GadgetType.ROP] = []
95        self._endings[gadget.GadgetType.JOP] = []
96        self._endings[gadget.GadgetType.SYS] = []
97
98    def _initBadInstructions(self):
99        pass
100
101    def _initCategories(self):
102        pass
103
104    def _initEndianess(self, endianess):
105        if endianess == Endianess.BIG:
106            for key in self.endings:
107                tmp = []
108                for pattern, size in self.endings[key]:
109                    tmp.append((pattern[::-1], size))
110                self.endings[key] = tmp
111
112    @property
113    def info(self):
114        return self._info
115
116
117    @property
118    def ksarch(self):
119        return self._ksarch
120
121    @property
122    def arch(self):
123        return self._arch
124
125    @property
126    def align(self):
127        return self._align
128
129    @property
130    def mode(self):
131        return self._mode
132
133    @property
134    def addressLength(self):
135        return self._addressLength
136
137    @property
138    def endings(self):
139        return self._endings
140
141    @property
142    def badInstructions(self):
143        return self._badInstructions
144
145    @property
146    def searcher(self):
147        return self._searcher
148
149    @property
150    def maxInvalid(self):
151        return self._maxInvalid
152
153    @property
154    def endianess(self):
155        return self._endianess
156
157    @property
158    def hasBranchDelaySlot(self):
159        return self._hasBranchDelaySlot
160
161    def getRegisterName(self, reg):
162        if self.info is None:
163            return reg
164        info = self.info.registers.get(reg)
165        if not info:
166            return reg
167        return self.info.translate_register_name(info[0], info[1]*8)
168
169    def __str__(self):
170        return self._name
171
172    def __repr__(self):
173        return repr(str(self))
174
175
176class ArchitectureX86(Architecture):
177
178    def __init__(self):
179        super(ArchitectureX86, self).__init__( CS_ARCH_X86, CS_MODE_32, 4, 1)
180        self._name = 'x86'
181        self._maxInvalid = 6
182        if 'keystone' in globals():
183            self._ksarch = (keystone.KS_ARCH_X86, keystone.KS_MODE_32)
184
185        if 'archinfo' in globals():
186            self._info = archinfo.ArchX86()
187
188        self._searcher = Searcherx86()
189        self._pprs = [b'[\x58-\x5f]{2}\xc3', # pop reg; pop reg; ret
190                        b'\x83\xc4\x04[\x58-\x5f]\xc3', # add esp, 4; pop reg; ret
191                        b'[\x58-\x5f]\x83\xc4\x04\xc3', # pop reg; add esp, 4; ret
192                        b'\x83\xc4\x08\xc3',            # add esp, 8; ret;
193                        b'\xff\x54\x24[\x08\x14\x1c\x2c\x44\x50]',            # call [esp+n]
194                        b'\xff\x64\x24[\x08\x14\x1c\x2c\x44\x50]',            # jmp [esp+n]
195                        b'\xff\x65[\x0c\x24\x30\xfc\xf4\xe8]',                            # jmp [ebp+n]
196                        b'\xff\x55[\x0c\x24\x30\xfc\xf4\xe8]'                             # call [ebp+n]
197                        ]
198
199    @property
200    def pprs(self):
201        return self._pprs
202
203    def _initGadgets(self):
204        super(ArchitectureX86, self)._initGadgets()
205        self._endings[gadget.GadgetType.ROP] = [(b'\xc3', 1),                           # ret
206                                                (b'\xc2[\x00-\xff]{2}', 3)]             # ret xxx
207
208        self._endings[gadget.GadgetType.SYS] = [(b'\xcd\x80', 2),                           # int 0x80
209                                                (b'\x0f\x05',2),                            # syscall
210                                                (b'\x0f\x34',2),                            # sysenter
211                                                (b'\x65\xff\x15\x10\x00\x00\x00', 7)]       # call gs:[10]
212
213        self._endings[gadget.GadgetType.JOP] = [(
214            b'\xff[\x20\x21\x22\x23\x26\x27]', 2),                                      # jmp [reg]
215            (b'\xf2\xff[\x20\x21\x22\x23\x26\x27]', 3),                                      # bnd jmp [reg]
216            (b'\xff[\xe0\xe1\xe2\xe3\xe4\xe6\xe7]', 2),                                 # jmp reg
217            (b'\xf2\xff[\xe0\xe1\xe2\xe3\xe4\xe6\xe7]', 3),                                 # bnd jmp reg
218            (b'\xff[\x10\x11\x12\x13\x16\x17]', 2),                                     # call [reg]
219            (b'\xf2\xff[\x10\x11\x12\x13\x16\x17]', 3),                                     # bnd call [reg]
220            (b'\xff[\xd0\xd1\xd2\xd3\xd4\xd6\xd7]', 2),                                 # call reg
221            (b'\xf2\xff[\xd0\xd1\xd2\xd3\xd4\xd6\xd7]', 3),                                 # bnd call reg
222            (b'\xff[\x14\x24]\x24', 3),                                                 # call/jmp [esp]
223            (b'\xf2\xff[\x14\x24]\x24', 4),                                                 # bnd call/jmp [esp]
224            (b'\xff[\x55\x65]\x00', 3),                                                 # call/jmp [ebp]
225            (b'\xf2\xff[\x55\x65]\x00', 4),                                             # bnd call/jmp [ebp]
226            (b'\xff[\xa0\xa1\xa2\xa3\xa6\xa7][\x00-\x0ff]{4}', 6),                      # jmp [reg+value]
227            (b'\xf2\xff[\xa0\xa1\xa2\xa3\xa6\xa7][\x00-\x0ff]{4}', 7),                  # bnd jmp [reg+value]
228            (b'\xff\xa4\x24[\x00-\xff]{4}', 7),
229            (b'\xf2\xff\xa4\x24[\x00-\xff]{4}', 8),
230            (b'\xff[\x50-\x53\x55-\x57][\x00-\xff]{1}', 3),                             # call [reg + value]
231            (b'\xf2\xff[\x50-\x53\x55-\x57][\x00-\xff]{1}', 4),                             # call [reg + value]
232            (b'\xff[\x60-\x63\x65-\x67][\x00-\xff]{1}', 3),                             # jmp [reg + value]
233            (b'\xf2\xff[\x60-\x63\x65-\x67][\x00-\xff]{1}', 4),                             # jmp [reg + value]
234            #(b'\xe9[\x00-\xff]{4}', 5),                                                 # jmp value
235            #(b'\xe8[\x00-\xff]{4}', 5),                                                 # call value
236            (b'\xff[\x90\x91\x92\x93\x94\x96\x97][\x00-\x0ff]{4}', 6)]
237
238    def _initBadInstructions(self):
239        self._badInstructions = ['enter','loop','loopne','int3', 'db', 'ret', 'jmp']
240
241    def _initCategories(self):
242        self._categories = {
243                gadget.Category.STACK_PIVOT : (('^sub (?P<dst>.sp), (?P<src>[x0-9a-fA-F]+)$','^add (?P<dst>.sp), (?P<src>[x0-9a-fA-F]+)$','^mov (?P<dst>.sp), .+ ptr \[(?P<src>...)\]$','^mov (?P<dst>.sp), (?P<src>...)$','^xchg (?P<dst>.sp), (?P<src>...)$','^xchg (?P<dst>...), (?P<src>.sp)$','ret.+'),('mov','call','jmp')),
244                gadget.Category.LOAD_MEM : (('mov (?P<dst>...), .+ ptr \[(?P<src>...)\]',),('mov','call','jmp')),
245                gadget.Category.WRITE_MEM : (('^mov .+ ptr \[(?P<dst>...)\], (?P<src>...)$',),('mov','call','jmp')),
246                gadget.Category.LOAD_REG : (('pop (?P<dst>...)',),('mov','call','jmp')),
247                gadget.Category.JMP : (('^jmp (?P<dst>...)$',),()),
248                gadget.Category.CALL : (('^call (?P<dst>...)$',),('mov','call','jmp')),
249                gadget.Category.INC_REG : (('^inc (?P<dst>...)$', '^add (?P<dst>e?..), 1$'),('mov','call','jmp')),
250                gadget.Category.CLEAR_REG : (('^xor (?P<dst>...), (?P<src>...)$',),('mov','call','jmp')),
251                gadget.Category.SUB_REG : (('^sub (?P<dst>...), (?P<src>...)$',),('mov','call','jmp')),
252                gadget.Category.ADD_REG : (('^add (?P<dst>...), (?P<src>...)$',),('mov','call','jmp')),
253                gadget.Category.XCHG_REG : (('^xchg (?P<dst>...), (?P<src>...)$',),('mov','call','jmp')),
254                gadget.Category.PUSHAD : (('^pushal$',),('mov','call','jmp')),
255                gadget.Category.NEG_REG : (('^neg (?P<dst>...)$',),('mov','call','jmp')),
256                gadget.Category.SYSCALL : (('^int (?P<dst>0x80)$',),('mov','call','jmp'))}
257
258
259
260class ArchitectureX86_64(ArchitectureX86):
261
262    def __init__(self):
263        super(ArchitectureX86_64, self).__init__()
264        self._name = 'x86_64'
265        self._maxInvalid = 8
266        if 'keystone' in globals():
267            self._ksarch = (keystone.KS_ARCH_X86, keystone.KS_MODE_64)
268
269        self._endings[gadget.GadgetType.SYS] = [(b'\x0f\x05',2),
270                                                (b'\x0f\x05\xc3',3)]                            # syscall
271
272        self._mode = CS_MODE_64
273        if 'archinfo' in globals():
274            self._info = archinfo.ArchAMD64()
275
276        self._addressLength = 8
277        self._pprs = [b'[\x58-\x5f]{2}\xc3', # pop reg; pop reg; ret
278                        b'\x83\xc4\x08[\x58-\x5f]\xc3', # add esp, 4; pop reg; ret
279                        b'[\x58-\x5f]\x83\xc4\x08\xc3', # pop reg; add esp, 4; ret
280                        b'\x83\xc4\x10\xc3'             # add esp, 8; ret;
281                        ]
282        self._pprs.append(b'\x41?[\x58-\x5f]\x48\x83\xc4\x08\xc3')
283        self._pprs.append(b'\x48\x83\xc4\x08\x41?[\x58-\x5f]\xc3')
284        self._pprs.append(b'(\x41?[\x58-\x5f]){2}\xc3')
285        self._pprs.append(b'\x48\x83\xc4\x10\xc3')
286
287    def _initBadInstructions(self):
288        super(ArchitectureX86_64, self)._initBadInstructions()
289        self._badInstructions.append('jrcxz')
290
291    def _initCategories(self):
292        self._categories = {
293                gadget.Category.STACK_PIVOT : (('^mov (?P<dst>.sp), .+ ptr \[(?P<src>...)\]$','^mov (?P<dst>.sp), (?P<src>...)$','^xchg (?P<dst>.sp), (?P<src>...)$','^xchg (?P<dst>...), (?P<src>.sp)$','ret.+'),('mov','call','jmp')),
294                gadget.Category.LOAD_MEM : (('mov (?P<dst>r..), .+ ptr \[(?P<src>r..)\]',),('mov','call','jmp')),
295                gadget.Category.WRITE_MEM : (('^mov .+ ptr \[(?P<dst>r..)\], (?P<src>r..)$',),('mov','call','jmp')),
296                gadget.Category.LOAD_REG : (('pop (?P<dst>r..)',),('mov','call','jmp')),
297                gadget.Category.JMP : (('^jmp (?P<dst>r..)$',),()),
298                gadget.Category.CALL : (('^call (?P<dst>r..)$',),('mov','call','jmp')),
299                gadget.Category.INC_REG : (('^inc (?P<dst>...)$', '^add (?P<dst>[er]?..), 1$'),('mov','call','jmp')),
300                gadget.Category.CLEAR_REG : (('^xor (?P<dst>...), (?P<src>...)$',),('mov','call','jmp')),
301                gadget.Category.SUB_REG : (('^sub (?P<dst>...), (?P<src>...)$',),('mov','call','jmp')),
302                gadget.Category.ADD_REG : (('^add (?P<dst>...), (?P<src>...)$',),('mov','call','jmp')),
303                gadget.Category.XCHG_REG : (('^xchg (?P<dst>...), (?P<src>...)$',),('mov','call','jmp')),
304                gadget.Category.PUSHAD : (('^pushal$',),('mov','call','jmp')),
305                gadget.Category.NEG_REG : (('^neg (?P<dst>...)$',),('mov','call','jmp')),
306                gadget.Category.SYSCALL : (('^syscall$',),('mov','call','jmp'))}
307
308
309
310
311
312
313class ArchitectureMips(Architecture):
314
315    def __init__(self, endianess=Endianess.LITTLE):
316        super(ArchitectureMips,self).__init__(CS_ARCH_MIPS, CS_MODE_32, 4, 4, endianess, branch_delay_slot=True)
317        self._name = 'MIPS'
318
319        if 'keystone' in globals():
320            self._ksarch = (keystone.KS_ARCH_MIPS, keystone.KS_MODE_MIPS32)
321
322        if 'archinfo' in globals():
323            self._info = archinfo.ArchMIPS32()
324
325        self._searcher = SearcherMIPS()
326
327    def _initGadgets(self):
328        super(ArchitectureMips, self)._initGadgets()
329        self._endings[gadget.GadgetType.ROP] = []
330        self._endings[gadget.GadgetType.JOP] = [(b'\x09\xf8\x20\x03', 4), # jalr t9
331                                                (b'\x08\x00\x20\x03', 4), # jr t9
332                                                (b'\x08\x00\xe0\x03', 4)] # jr ra
333
334
335class ArchitectureMipsBE(ArchitectureMips):
336
337    def __init__(self):
338        super(ArchitectureMipsBE, self).__init__(Endianess.BIG)
339        self._name = 'MIPSBE'
340        self._mode |= CS_MODE_BIG_ENDIAN
341        if 'keystone' in globals():
342            self._ksarch = (self._ksarch[0], self._ksarch[1] + keystone.KS_MODE_BIG_ENDIAN)
343
344class ArchitectureMips64(ArchitectureMips):
345
346    def __init__(self, endianess=Endianess.LITTLE):
347        super(ArchitectureMips64, self).__init__(endianess)
348        self._name = 'MIPS64'
349
350        if 'keystone' in globals():
351            self._ksarch = (keystone.KS_ARCH_MIPS, keystone.KS_MODE_64)
352
353        self._mode = CS_MODE_MIPS64
354        if 'archinfo' in globals():
355            self._info = archinfo.ArchMIPS64()
356
357        self._addressLength = 8
358
359    def _initGadgets(self):
360        super(ArchitectureMips64, self)._initGadgets()
361
362
363class ArchitectureMips64BE(ArchitectureMips64):
364
365    def __init__(self):
366        super(ArchitectureMips64BE, self).__init__(Endianess.BIG)
367        self._name = 'MIPS64BE'
368        self._mode |= CS_MODE_BIG_ENDIAN
369        if 'keystone' in globals():
370            self._ksarch = (self._ksarch[0], self._ksarch[1] + keystone.KS_MODE_BIG_ENDIAN)
371
372class ArchitectureArm(Architecture):
373
374    def __init__(self, endianess=Endianess.LITTLE):
375        super(ArchitectureArm,self).__init__(CS_ARCH_ARM, CS_MODE_ARM, 4, 4, endianess)
376        self._searcher = SearcherARM()
377        self._name = 'ARM'
378
379        if 'archinfo' in globals():
380            self._info = archinfo.ArchARM()
381        if 'keystone' in globals():
382            self._ksarch = (keystone.KS_ARCH_ARM, keystone.KS_MODE_ARM)
383
384    def _initGadgets(self):
385        super(ArchitectureArm, self)._initGadgets()
386        self._endings[gadget.GadgetType.ROP] = [(b'[\x01-\xff]\x80\xbd\xe8', 4)] # pop {[reg]*,pc}
387        self._endings[gadget.GadgetType.JOP] = [(b'[\x10-\x1e]\xff\x2f\xe1', 4), # bx <reg>
388                                                (b'[\x30-\x3e]\xff\x2f\xe1', 4), # blx <reg>
389                                                (b'[\x00-\x0f]\xf0\xa0\xe1', 4), # mov pc, <reg>
390                                                (b'\x01\x80\xbd\xe8', 4)] # ldm sp! ,{pc}
391
392
393class ArchitectureArmBE(ArchitectureArm):
394
395    def __init__(self):
396        super(ArchitectureArmBE, self).__init__(Endianess.BIG)
397        self._name = 'ARMBE'
398        self._mode |= CS_MODE_BIG_ENDIAN
399        if 'keystone' in globals():
400            self._ksarch = (self._ksarch[0], self._ksarch[1] + keystone.KS_MODE_BIG_ENDIAN)
401
402    def _initEndianess(self, endianess):
403        super(ArchitectureArmBE, self)._initEndianess(endianess)
404        self._endings[gadget.GadgetType.ROP] = [(b'\xe8\xbd\x80[\x01-\xff]', 4)] # pop {[reg]*,pc}
405        self._endings[gadget.GadgetType.JOP] = [(b'\xe1\x2f\xff[\x10-\x1e]', 4), # bx <reg>
406                                                (b'\xe1\x2f\xff[\x30-\x3e]', 4), # blx <reg>
407                                                (b'\xe1\xa0\xf0[\x00-\x0f]', 4), # mov pc, <reg>
408                                                (b'\xe8\xdb\x80\x01', 4)] # ldm sp! ,{pc}
409
410class ArchitectureArmThumb(Architecture):
411
412    def __init__(self):
413        super(ArchitectureArmThumb, self).__init__(CS_ARCH_ARM, CS_MODE_THUMB, 4, 2)
414        self._searcher = SearcherARM()
415        self._name = 'ARMTHUMB'
416        self._maxInvalid = 2
417
418        if 'archinfo' in globals():
419            self._info = archinfo.ArchARM()
420
421        if 'keystone' in globals():
422            self._ksarch = (keystone.KS_ARCH_ARM, keystone.KS_MODE_THUMB)
423
424    def _initGadgets(self):
425        super(ArchitectureArmThumb, self)._initGadgets()
426        self._endings[gadget.GadgetType.ROP] = [(b'[\x00-\xff]\xbd', 2)] # pop {[regs]*,pc}
427        self._endings[gadget.GadgetType.JOP] = [(b'[\x00-\x7f]\x47', 2), # bx <reg>
428                                                (b'[\x80\x88\x90\x98\xa0\xa8\xb0\xb8\xc0\xc8\xd0\xd8\xe0\xe8\xf0\xf8]\x47', 2) # blx <reg>
429                                                ]
430
431
432
433
434class ArchitectureArm64(Architecture):
435
436    def __init__(self):
437        super(ArchitectureArm64, self).__init__(CS_ARCH_ARM64, CS_MODE_ARM, 8, 4)
438        self._name = 'ARM64'
439
440        if 'archinfo' in globals():
441            self._info = archinfo.ArchAArch64()
442        if 'keystone' in globals():
443            self._ksarch = (keystone.KS_ARCH_ARM64, keystone.KS_MODE_LITTLE_ENDIAN)
444
445    def _initGadgets(self):
446        super(ArchitectureArm64, self)._initGadgets()
447        self._endings[gadget.GadgetType.ROP] = [(b'[\x00\x20\x40\x60\x80\xa0\xc0\xe0][\x00-\x02]\x5f\xd6', 4), # ret <reg>
448                                                (b'[\x00\x20\x40\x60\x80]\x03\x5f\xd6', 4), # ret <reg> (x24 - x28)
449                                                (b'\xc0\x03\x5f\xd6', 4)] # ret
450
451        self._endings[gadget.GadgetType.JOP] = [(b'[\x00\x20\x40\x60\x80\xa0\xc0\xe0][\x00-\x02]\x1f\xd6', 4), # br <reg>
452                                                (b'[\x00\x20\x40\x60\x80]\x03\x1f\xd6', 4), # br <reg>
453                                                (b'[\x00\x20\x40\x60\x80\xa0\xc0\xe0][\x00-\x02]\\?\xd6', 4), # blr <reg>
454                                                (b'[\x00\x20\x40\x60\x80]\x03\\?\xd6', 4)] # blr <reg>
455
456
457
458class ArchitecturePPC(Architecture):
459
460    def __init__(self):
461        super(ArchitecturePPC, self).__init__(CS_ARCH_PPC, CS_MODE_32 + CS_MODE_BIG_ENDIAN, 4, 4)
462        self._name = 'PPC'
463
464        if 'keystone' in globals():
465            self._ksarch = (keystone.KS_ARCH_PPC, keystone.KS_MODE_32)
466
467    def _initGadgets(self):
468        super(ArchitecturePPC, self)._initGadgets()
469        self._endings[gadget.GadgetType.ROP] = [(b'\x4e\x80\x00\x20', 4)] # blr
470        self._endings[gadget.GadgetType.JOP] = [(b'\x4e\x80\x04[\x20-\x21]', 4)] # bctr, bctrl
471        self._endings[gadget.GadgetType.SYS] = [(b'\x44\x00\x00\x02', 4)] # sc
472
473
474class ArchitecturePPC64(ArchitecturePPC):
475
476    def __init__(self):
477
478        Architecture.__init__(self, CS_ARCH_PPC, CS_MODE_64 + CS_MODE_BIG_ENDIAN, 8, 4)
479        self._name = 'PPC64'
480
481        if 'keystone' in globals():
482            self._ksarch = (keystone.KS_ARCH_PPC, keystone.KS_MODE_64)
483
484class ArchitectureSPARC(Architecture):
485
486    def __init__(self):
487        super(ArchitectureSPARC, self).__init__(CS_ARCH_SPARC, CS_MODE_32 + CS_MODE_BIG_ENDIAN, 4, 4,
488						branch_delay_slot=True)
489        self._name = 'SPARC'
490
491        if 'keystone' in globals():
492            self._ksarch = (keystone.KS_ARCH_SPARC, keystone.KS_MODE_32)
493
494    def _initGadgets(self):
495        super(ArchitectureSPARC, self)._initGadgets()
496        self._endings[gadget.GadgetType.ROP] = []
497        self._endings[gadget.GadgetType.JOP] = []
498        self._endings[gadget.GadgetType.SYS] = []
499
500
501class ArchitectureSPARC64(ArchitectureSPARC):
502
503    def __init__(self):
504
505        Architecture.__init__(self, CS_ARCH_SPARC, CS_MODE_V9 + CS_MODE_BIG_ENDIAN, 8, 4, branch_delay_slot=True)
506        self._name = 'SPARC64'
507
508        if 'keystone' in globals():
509            self._ksarch = (keystone.KS_ARCH_SPARC, keystone.KS_MODE_64)
510
511    def _initGadgets(self):
512        super(ArchitectureSPARC, self)._initGadgets()
513        self._endings[gadget.GadgetType.ROP] = [
514            (byte_regexp(0b11000001, 0b10000001) + b'[\xc8-\xcf][\x00-\xff][\x00-\xff]', 4), # return
515            (byte_regexp(0b11000001, 0b10000001) + b'[\xe8-\xef][\x00-\xff][\x00-\xff]', 4)] # restore
516        self._endings[gadget.GadgetType.JOP] = [
517            (byte_regexp(0b11000001, 0b10000001) + b'[\xc0-\xc7][\x00-\xff][\x00-\xff]', 4)] # jmpl (ret, retl)
518        self._endings[gadget.GadgetType.SYS] = [(b'\x91\xd0\x20\x6d', 4)] # ta 0x6d
519
520
521
522x86 = ArchitectureX86()
523x86_64 = ArchitectureX86_64()
524MIPS = ArchitectureMips()
525MIPSBE = ArchitectureMipsBE()
526MIPS64 = ArchitectureMips64()
527MIPS64BE = ArchitectureMips64BE()
528ARM = ArchitectureArm()
529ARMBE = ArchitectureArmBE()
530ARMTHUMB = ArchitectureArmThumb()
531ARM64 = ArchitectureArm64()
532PPC = ArchitecturePPC()
533PPC64 = ArchitecturePPC64()
534SPARC64 = ArchitectureSPARC64()
535
536def getArchitecture(archString):
537    arch = globals().get(archString, None)
538
539    if isinstance(arch, Architecture):
540        return arch
541
542    raise NotSupportedError('Architecture is not supported: ' + archString + '\nSupported architectures are: x86, x86_64, MIPS, MIPS64, ARM, ARMTHUMB, ARM64, PPC, PPC64, SPARC64')
543