From 923679b3b8f871338f1f7d9b3aa85dece89b3a00 Mon Sep 17 00:00:00 2001 From: Arusekk Date: Sun, 14 Jun 2020 12:46:52 +0200 Subject: [PATCH 1/4] Refactor encoders Fix code style and python 3 compatibility, reduce code duplication. --- pwnlib/encoders/encoder.py | 2 +- pwnlib/encoders/i386/delta.py | 21 ++++++++++++--------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/pwnlib/encoders/encoder.py b/pwnlib/encoders/encoder.py index 5225f5293..13b64764e 100644 --- a/pwnlib/encoders/encoder.py +++ b/pwnlib/encoders/encoder.py @@ -15,7 +15,7 @@ log = getLogger(__name__) class Encoder(object): - _encoders = collections.defaultdict(lambda: []) + _encoders = collections.defaultdict(list) #: Architecture which this encoder works on arch = None diff --git a/pwnlib/encoders/i386/delta.py b/pwnlib/encoders/i386/delta.py index e3d272917..653a91e5c 100644 --- a/pwnlib/encoders/i386/delta.py +++ b/pwnlib/encoders/i386/delta.py @@ -4,7 +4,6 @@ import six import collections from random import choice -from random import randint from pwnlib.asm import asm from pwnlib.asm import disasm @@ -56,26 +55,30 @@ class i386DeltaEncoder(Encoder): blacklist = set(raw) def __call__(self, raw_bytes, avoid, pcreg=''): - table = collections.defaultdict(lambda: []) + table = collections.defaultdict(list) endchar = bytearray() - not_bad = lambda x: six.int2byte(x) not in avoid - not_bad_or_term = lambda x: not_bad(x) and x != self.terminator + avoid = frozenset(bytearray(avoid)) + avoid_or_term = {self.terminator} | avoid - for i in filter(not_bad_or_term, range(0, 256)): + for i in range(256): + if i in avoid_or_term: + continue endchar.append(i) - for j in filter(not_bad, range(0, 256)): + for j in range(256): + if j in avoid: + continue table[(j - i) & 0xff].append(bytearray([i, j])) res = bytearray(self.raw) for c in bytearray(raw_bytes): - l = len(table[c]) - if l == 0: + choices = table[c] + if not choices: print('No encodings for character %02x' % c) return None - res += table[c][randint(0, l - 1)] + res.extend(choice(choices)) res.append(self.terminator) res.append(choice(endchar)) From a6cc5a0407a76020324f9035f856d076a5ae2d3f Mon Sep 17 00:00:00 2001 From: Arusekk Date: Sun, 14 Jun 2020 14:39:16 +0200 Subject: [PATCH 2/4] Refactor ARM encoder Lots of whitespace changes. Best to view with git diff -w --- .../arm/alphanumeric/ARM_Instructions.py | 154 ++- pwnlib/encoders/arm/alphanumeric/__init__.py | 2 +- .../arm/alphanumeric/alphanum_byte.py | 58 +- pwnlib/encoders/arm/alphanumeric/builder.py | 897 +++++++++--------- 4 files changed, 538 insertions(+), 573 deletions(-) diff --git a/pwnlib/encoders/arm/alphanumeric/ARM_Instructions.py b/pwnlib/encoders/arm/alphanumeric/ARM_Instructions.py index 9c25a919d..f737deb6a 100755 --- a/pwnlib/encoders/arm/alphanumeric/ARM_Instructions.py +++ b/pwnlib/encoders/arm/alphanumeric/ARM_Instructions.py @@ -1,4 +1,5 @@ from __future__ import division +import six # +------------------------------------------------------------------------+ # | ARM Instructions | @@ -18,122 +19,85 @@ LSR = 11 # (EOR/SUB/RSB)(PL/MI){S} rd, rn, #imm -# ==================================== +# ==================================== def dpimm(op, cond, s, d, n, imm): - if type(imm) == int: - x = chr(imm & 0xff) - else: - x = imm - x += chr((d << 4) & 0xff) - if s: - if op == EOR: - x += chr(0x30 | n) - if op == SUB: - x += chr(0x50 | n) - if op == RSB: - x += chr(0x70 | n) - else: - if op == SUB: - x += chr(0x40 | n) - if op == RSB: - x += chr(0x60 | n) - if cond == PL: - x += "\x52" - else: - x += "\x42" - return x - + x = bytearray() + if isinstance(imm, six.integer_types): + x.append(imm & 0xff) + else: + x.append(imm) + x.append((d << 4) & 0xff) + x.append(op << 5 | s << 4 | n) + x.append(cond << 4 | 2) + return bytes(x) + # (EOR/SUB/RSB)PL{S} rd, rn, ra ROR #imm -# ====================================== +# ====================================== def dpshiftimm(op, s, d, n, a, imm): - x = chr(0x60 | a) - x += chr(((d << 4)| (imm >> 1)) & 0xff) - if s: - if op == EOR: - x += chr(0x30 | n) - if op == SUB: - x += chr(0x50 | n) - if op == RSB: - x += chr(0x70 | n) - else: - if op == SUB: - x += chr(0x40 | n) - if op == RSB: - x += chr(0x60 | n) - return x + "\x50" + x = bytearray() + x.append(0x60 | a) + x.append(((d << 4)| (imm >> 1)) & 0xff) + x.append(op << 5 | s << 4 | n) + x.append(PL << 4) + return bytes(x) # (EOR/SUB/RSB)PL{S} rd, rn, ra (ROR/LSR) rb -# ========================================== +# ========================================== def dpshiftreg(op, s, d, n, a, shift, b): - x = '' - if shift == LSR: - x += chr(0x30 | a) - else: - x += chr(0x70 | a) - x += chr(((d << 4) | b) & 0xff) - if s != 0: - if op == EOR: - x += chr(0x30 | n) - if op == SUB: - x += chr(0x50 | n) - if op == RSB: - x += chr(0x70 | n) - else: - if op == SUB: - x += chr(0x40 | n) - if op == RSB: - x += chr(0x60 | n) - return x + "\x50" + x = bytearray() + if shift == LSR: + x.append(0x30 | a) + else: + x.append(0x70 | a) + x.append(((d << 4) | b) & 0xff) + x.append(op << 5 | s << 4 | n) + x.append(PL << 4) + return bytes(x) # (LDR/STR)(PL/MI)B rd, [rn, #-imm] -# ================================= +# ================================= def lsbyte(op, cond, d, n, imm): - if type(imm) == int: - x = chr(imm & 0xff) - else: - x = imm - x += chr((d << 4) & 0xff) -# x = chr(imm) + chr((d << 4) & 0xff) - if op == STR: - x += chr(0x40 | n) - else: - x += chr(0x50 | n) - if cond == PL: - x += "\x55" - else: - x += "\x45" - return x + x = bytearray() + if isinstance(imm, six.integer_types): + x.append(imm & 0xff) + else: + x.append(imm) + x.append((d << 4) & 0xff) + if op == STR: + x.append(0x40 | n) + else: + x.append(0x50 | n) + x.append(cond << 4 | 5) + return bytes(x) # STMPLFD rd, (Register List)^ -# ============================ +# ============================ def smul(d, reglH, reglL): - return chr(reglL) + chr(reglH) + chr(0x40 | d) + "\x59" + return bytes(bytearray((reglL, reglH, 0x40 | d, 0x59))) # LDMPLDB rn!, (Register List) -# ============================ +# ============================ def lmul(n, reglH, reglL): - return chr(reglL) + chr(reglH) + chr(0x30 | n) + "\x59" + return bytes(bytearray((reglL, reglH, 0x30 | d, 0x59))) # SWI(PL/MI) 0x9f0002 -# ============== +# ============== def swi(cond): - x = "\x02\x00\x9f" - if cond == MI: - x += "\x4f" - else: - x += "\x5f" - return x + x = bytearray(b"\x02\x00\x9f") + x.append(cond << 4 | 0xf) + return bytes(x) # BMI 0xfffff4 -# ============ +# ============ def bmi(): - return "\xf4\xff\xff\x4b" + return b"\xf4\xff\xff\x4b" # STRPLB rd, [!rn, -(rm ROR #imm)] with P=0 i.e. post-indexed addressing mode -# =========================================================================== +# =========================================================================== def sbyteposti(d, n, m, imm): - x = chr(0x60 | m) - x += chr(((d << 4) | (imm >> 1)) & 0xff) - x += chr(0x40 | n) - x += "\x56" - return x + x = bytearray() + x.append(0x60 | m) + x.append(((d << 4) | (imm >> 1)) & 0xff) + x.append(0x40 | n) + x.append(PL << 4 | 6) + return bytes(x) diff --git a/pwnlib/encoders/arm/alphanumeric/__init__.py b/pwnlib/encoders/arm/alphanumeric/__init__.py index 5e8072c65..426265fc6 100644 --- a/pwnlib/encoders/arm/alphanumeric/__init__.py +++ b/pwnlib/encoders/arm/alphanumeric/__init__.py @@ -32,7 +32,7 @@ def __call__(self, input, avoid, pcreg=None): enc_dec_loop = b.encDecoderLoopBuilder(dec_loop) dec = b.DecoderBuilder(dec_loop, self.icache_flush) - output,dec = b.buildInit(dec); + output, dec = b.buildInit(dec) output += dec output += enc_dec_loop diff --git a/pwnlib/encoders/arm/alphanumeric/alphanum_byte.py b/pwnlib/encoders/arm/alphanumeric/alphanum_byte.py index 7a0a86397..1f05492fd 100755 --- a/pwnlib/encoders/arm/alphanumeric/alphanum_byte.py +++ b/pwnlib/encoders/arm/alphanumeric/alphanum_byte.py @@ -7,46 +7,46 @@ # | ALPHANUMERIC MANIPULATIONS FUNCTIONS | # +------------------------------------------------------------------------+ -ALPHANUMERIC_BYTES = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" +ALPHANUMERIC_BYTES = bytearray(b"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz") # return 1 if the byte is alphanumeric # ==================================== def alphanumeric_check(c): - if type(c) == int: - c = chr(c & 0xff) - return c.isalnum() + if isinstance(c, six.integer_types): + return c in ALPHANUMERIC_BYTES + return c.isalnum() # return a random alphanumeric byte # ================================= def alphanumeric_get_byte(): - return ord(random_funcs.randel(ALPHANUMERIC_BYTES)) + return random_funcs.randel(ALPHANUMERIC_BYTES) -# return a randomly selected alphanumeric byte less than max -# ========================================================== -#CSE author actually returns a byte <= max, not strictly < max +# return a randomly selected alphanumeric byte less than max +# ========================================================== +# CSE author actually returns a byte <= max, not strictly < max def alphanumeric_get_byte_ltmax(max): - sz = 0 - while sz < len(ALPHANUMERIC_BYTES) and ord(ALPHANUMERIC_BYTES[sz]) <= max: - sz += 1 - return ord(random_funcs.randel(ALPHANUMERIC_BYTES[:sz])) + sz = 0 + while sz < len(ALPHANUMERIC_BYTES) and ord(ALPHANUMERIC_BYTES[sz]) <= max: + sz += 1 + return random_funcs.randel(ALPHANUMERIC_BYTES[:sz]) -# generate an alphanumeric offset such that c+offset is also alphanumeric -# ======================================================================= +# generate an alphanumeric offset such that c+offset is also alphanumeric +# ======================================================================= def off_gen(c): - if c >= 0 and c <= 0x4a: - max = 16 * 7 + 10 - c - while True: - x = alphanumeric_get_byte_ltmax(max) - if alphanumeric_check(c + x): - return x - return 0 - -# return an alphanumeric value ret such that c XOR ret is also alphanumeric -# ========================================================================= + if c >= 0 and c <= 0x4a: + max = 16 * 7 + 10 - c + while True: + x = alphanumeric_get_byte_ltmax(max) + if alphanumeric_check(c + x): + return x + return 0 + +# return an alphanumeric value ret such that c XOR ret is also alphanumeric +# ========================================================================= def alphanumeric_get_complement(c): - c &= 0xff; - while True: - ret = alphanumeric_get_byte() - if alphanumeric_check(c ^ ret): - return ret + c &= 0xff + while True: + ret = alphanumeric_get_byte() + if alphanumeric_check(c ^ ret): + return ret diff --git a/pwnlib/encoders/arm/alphanumeric/builder.py b/pwnlib/encoders/arm/alphanumeric/builder.py index e350f1c13..2434afbac 100755 --- a/pwnlib/encoders/arm/alphanumeric/builder.py +++ b/pwnlib/encoders/arm/alphanumeric/builder.py @@ -2,453 +2,454 @@ from __future__ import division from . import alphanum_byte -from . import ARM_Instructions +from .ARM_Instructions import ( + EOR, + SUB, + RSB, + MI, + PL, + LDR, + STR, + LDM, + STM, + ROR, + LSR, + dpimm, + dpshiftimm, + dpshiftreg, + swi, + bmi, + lmul, + lsbyte, + sbyteposti, +) from . import random_funcs -#+---------------------------------------------------+*/ -#| Builder Functions |*/ -#+---------------------------------------------------+*/ - -EOR = 1 -SUB = 2 -RSB = 3 -MI = 4 -PL = 5 -LDR = 6 -STR = 7 -LDM = 8 -STM = 9 -ROR = 10 -LSR = 11 - -class builder: - - def __init__(self): - self.I = 0 - self.size = 0 - self.i = 0 - self.j = 0 - self.k = 0 - self.x = 0 - self.addr = 0 - self.addr_offset = 0 - - def enc_data_builder(self, input): - if len(input) == 0: - return '' - output = '' - arr = [1,2,3,4,5,6,7,8,9] - self.I = random_funcs.randel(arr) - for _, ab in enumerate(bytearray(input)): - b = ab & 0x0f - e0 = random_funcs.enc_data_msn(b, self.I) - e0 = e0 << 4 - ef = e0 | b - d = ((ab & 0xf0) ^ e0) >> 4 - c0 = random_funcs.enc_data_msn(d, self.I) << 4 - cd = c0 | d - output += chr(cd & 0xff) - output += chr(ef & 0xff) - #Last two bytes to stop the decoder_loop*/ - max = 0x30 | self.I - output += chr(alphanum_byte.alphanumeric_get_byte()) - output += chr(alphanum_byte.alphanumeric_get_byte_ltmax(max)) - return output - - def DecoderLoopBuilder(self, icache_flush): - dec_loop = '' - # Select p,s,t and q */ - arr = [3, 7] - p = random_funcs.randel(arr) - if p == 3: - s = 7 - else: - s = 3 - t = 6 - arr2 = [8, 9] - q = random_funcs.randel(arr2) - - # Add the instructions*/ - if icache_flush != 0: - dec_loop += ARM_Instructions.swi(MI) - - rsalnum = alphanum_byte.alphanumeric_get_byte() - - if icache_flush != 0: - #EORMIS rp, r4, #(randomly selected alphanumeric value)*/ - dec_loop += ARM_Instructions.dpimm(EOR, MI, 1, p, 4, rsalnum) - - if icache_flush == 1: - dist = 0x2c - else: - dist = 0x28 - - offset = alphanum_byte.off_gen(dist + 0x04) - - #SUBPL rs, r4, #(dist+0x04+offset)*/ - dec_loop += ARM_Instructions.dpimm(SUB, PL, 0, s, 4, chr(dist + 0x04 + offset)) - - #SUBPL rs, pc, rs LSR r4*/ - dec_loop += ARM_Instructions.dpshiftreg(SUB, 0, s, 0x0f, s, LSR, 4) - - #EORPLS rt, r4, rs LSR r4*/ - dec_loop += ARM_Instructions.dpshiftreg(EOR, 1, t, 4, s, LSR, 4) - - #EORMIS rp, r4, #rsalnum*/ - rsalnum = alphanum_byte.alphanumeric_get_byte() - dec_loop += ARM_Instructions.dpimm(EOR, MI, 1, p, 4, rsalnum) - - #LDRPLB rp, [rs, #(-offset)]*/ - dec_loop += ARM_Instructions.lsbyte(LDR, PL, p, s, offset) - - #SUBPL rs, rs, r5 LSR r4*/ - dec_loop += ARM_Instructions.dpshiftreg(SUB, 0, s, s, 5, LSR, 4) - - #LDRPLB rq, [rs, #(-offset)]*/ - dec_loop += ARM_Instructions.lsbyte(LDR, PL, q, s, offset) - - #EORPLS rp, rq, rp ROR #28*/ - dec_loop += ARM_Instructions.dpshiftimm(EOR, 1, p, q, p, 28) - - #STRPLB rp, [rt, #(-offset)]*/ - dec_loop += ARM_Instructions.lsbyte(STR, PL, p, t, offset) - - #SUBPL rt, rt, r5 LSR r4*/ - dec_loop += ARM_Instructions.dpshiftreg(SUB, 0, t, t, 5, LSR, 4) - - #SUBPL rs, rs, r5 LSR r4*/ - dec_loop += ARM_Instructions.dpshiftreg(SUB, 0, s, s, 5, LSR, 4) - - #RSBPLS rq, rq, #0x3I*/ - dec_loop += ARM_Instructions.dpimm(RSB, PL, 1, q, q, 0x30 | self.I) - - #BMI 0xfffff4*/ - dec_loop += ARM_Instructions.bmi() - - #STRPLB r4, [rt, #-(offset+1)]*/ - dec_loop += ARM_Instructions.lsbyte(STR, PL, 4, t, offset + 1) - - if icache_flush == 1: - #SWIPL 0x9f0002*/ - dec_loop += ARM_Instructions.swi(PL) - return dec_loop - - def encDecoderLoopBuilder(self, input): - output = '' - if len(input) == 0: - return output - for p in input: - if not alphanum_byte.alphanumeric_check(p): - output += chr(alphanum_byte.alphanumeric_get_byte()) - else: - output += p - return output - - def DecoderBuilder(self, input, icache_flush): - if len(input) == 0: - return '' - output = '' - - #Register selections*/ - arr = [4,6] - self.addr = random_funcs.randel(arr) - arr2 = [3, 5, 7] - self.i = random_funcs.randel(arr2) - arr3 = [0, 0] - q = 0 - for p in range(3): - if arr2[p] != self.i: - arr3[q] = arr2[p] - q += 1 - self.j = random_funcs.randel(arr3) - for p in range(2): - if arr3[p] != self.j: - self.k = arr3[p] - break - - self.x = alphanum_byte.off_gen(0x01) - offset = 0x91 - if icache_flush != 0: - output += self.algo1(input, 0, 3) - output += self.gap_traverse(0x1e) - output += self.algo1(input, 33, 5) - else: - output += self.gap_traverse(0x19) - output += self.algo1(input, 25, 5) - output += self.gap_traverse(0x0f) - if icache_flush != 0: - output += self.algo1(input, 53, 15) - else: - output += self.algo1(input, 45, 11) - #trucate the last instruction, which increments raddr by 1, from the output*/ - output = output[:-4] - self.size -= 4 - #Setting r0, r1, r2 for parameter passing*/ - #SUBPLS ri, ri, #x*/ - output += ARM_Instructions.dpimm(SUB, PL, 1, self.i, self.i, self.x) - #SUBPL r4, ri, ri LSR ri*/ - output += ARM_Instructions.dpshiftreg(SUB, 0, 4, self.i, self.i, LSR, self.i) - #SUBPL r6, ri, ri LSR ri*/ - output += ARM_Instructions.dpshiftreg(SUB, 0, 6, self.i, self.i, LSR, self.i) - #SUBPL r5, rj, r4 ROR r6*/ - output += ARM_Instructions.dpshiftreg(SUB, 0, 5, self.j, 4, ROR, 6) - - self.size += 4 * 4 - - if icache_flush: - arr4 = [3,7] - m = random_funcs.randel(arr4) - - c = alphanum_byte.off_gen(24) - arr5 = [2,4,6,8,10,12,14,16,18] - arr6 = [4,6] - arr7 = [1,2,4,8] - reglH = 0x40 | random_funcs.randel(arr7) - #SUBPL rm, sp, #(c+24) */ - output += ARM_Instructions.dpimm(SUB, PL, 0, m, 13, c + 24) - - #Store 4 0x00*/ - #STRPLB random_funcs.randel(arr6), [!rm, -(r5 ROR #random_funcs.randel(arr5))]*/ - output += ARM_Instructions.sbyteposti(random_funcs.randel(arr6), m, 5, random_funcs.randel(arr5)) - output += ARM_Instructions.sbyteposti(random_funcs.randel(arr6), m, 5, random_funcs.randel(arr5)) - output += ARM_Instructions.sbyteposti(random_funcs.randel(arr6), m, 5, random_funcs.randel(arr5)) - output += ARM_Instructions.sbyteposti(random_funcs.randel(arr6), m, 5, random_funcs.randel(arr5)) - - #Store 4 0xff*/ - #STRPLB r5, [!rm, -(r5 ROR #random_funcs.randel(arr5))]*/ - output += ARM_Instructions.sbyteposti(5, m, 5, random_funcs.randel(arr5)) - output += ARM_Instructions.sbyteposti(5, m, 5, random_funcs.randel(arr5)) - output += ARM_Instructions.sbyteposti(5, m, 5, random_funcs.randel(arr5)) - output += ARM_Instructions.sbyteposti(5, m, 5, random_funcs.randel(arr5)) - - #Store 4 0x00*/ - #STRPLB random_funcs.randel(arr6), [!rm, -(r5 ROR #random_funcs.randel(arr5))]*/ - output += ARM_Instructions.sbyteposti(random_funcs.randel(arr6), m, 5, random_funcs.randel(arr5)) - output += ARM_Instructions.sbyteposti(random_funcs.randel(arr6), m, 5, random_funcs.randel(arr5)) - output += ARM_Instructions.sbyteposti(random_funcs.randel(arr6), m, 5, random_funcs.randel(arr5)) - output += ARM_Instructions.sbyteposti(random_funcs.randel(arr6), m, 5, random_funcs.randel(arr5)) - - #SUBPL rm, sp, #c*/ - output += ARM_Instructions.dpimm(SUB, PL, 0, m, 13, c) - - #LDMPLDB rm!, {r0, r1, r2, r6, r8/9/10/11, r14}*/ - output += ARM_Instructions.lmul(m, reglH, 0x47) - - #SUBPLS rm, r5, r4 ROR rm*/ - output += ARM_Instructions.dpshiftreg(SUB, 1, m, 5, 4, ROR, m) - - self.size += 4 * 16 - return output - - def algo1(self, input, begin_inp, iter): - if len(input) == 0: - return '' - output = '' - offset = 0x91 - for p in range(begin_inp, begin_inp + iter): - y = ord(input[p]) - if alphanum_byte.alphanumeric_check(y): - #SUBPL raddr, raddr, rj ROR rk*/ - output += ARM_Instructions.dpshiftreg(SUB, 0, self.addr, self.addr, self.j, ROR, self.k) - self.size += 4 - continue - if y >= 0x80: - if alphanum_byte.alphanumeric_check(~y): - #EORPLS rk, rj, #~y*/ - output += ARM_Instructions.dpimm(EOR, PL, 1, self.k, self.j, ~y) - #STRMIB rk, [raddr, #(-offset)]*/ - output += ARM_Instructions.lsbyte(STR, MI, self.k, self.addr, offset) - #SUBMIS rk, ri, #x*/ - output += ARM_Instructions.dpimm(SUB, MI, 1, self.k, self.i, self.x) - #SUBPL raddr, raddr, rj ROR rk*/ - output += ARM_Instructions.dpshiftreg(SUB, 0, self.addr, self.addr, self.j, ROR, self.k) - - self.size += 4 * 4 - continue - - a = alphanum_byte.alphanumeric_get_complement(~y) - b = (a ^ ~y) & 0xff - #EORPLS rk, rj, #a*/ - output += ARM_Instructions.dpimm(EOR, PL, 1, self.k, self.j, a) - #EORMIS rk, rk, #b*/ - output += ARM_Instructions.dpimm(EOR, MI, 1, self.k, self.k, b) - #STRMIB rk, [raddr, #(-offset)]*/ - output += ARM_Instructions.lsbyte(STR, MI, self.k, self.addr, offset) - #SUBMIS rk, ri, #x*/ - output += ARM_Instructions.dpimm(SUB, MI, 1, self.k, self.i, self.x) - #SUBPL raddr, raddr, rj ROR rk*/ - output += ARM_Instructions.dpshiftreg(SUB, 0, self.addr, self.addr, self.j, ROR, self.k) - - self.size += 4 * 5 - continue - if self.x > y: - z1 = self.x - y - if alphanum_byte.alphanumeric_check(z1): - #SUBPL rk, ri, #z*/ - output += ARM_Instructions.dpimm(SUB, PL, 0, self.k, self.i, z1) - #STRPLB rk, [raddr, #(-offset)]*/ - output += ARM_Instructions.lsbyte(STR, PL, self.k, self.addr, offset) - #SUBPL raddr, raddr, rj ROR rk*/ - output += ARM_Instructions.dpshiftreg(SUB, 0, self.addr, self.addr, self.j, ROR, self.k) - - self.size += 4 * 3 - continue - z2 = self.x + y - if alphanum_byte.alphanumeric_check(z2): - #RSBPL rk, ri, #z*/ - output += ARM_Instructions.dpimm(RSB, PL, 0, self.k, self.i, z2) - #STRPLB rk, [raddr, #(-offset)]*/ - output += ARM_Instructions.lsbyte(STR, PL, self.k, self.addr, offset) - #SUBPL raddr, raddr, rj ROR rk*/ - output += ARM_Instructions.dpshiftreg(SUB, 0, self.addr, self.addr, self.j, ROR, self.k) - - self.size += 4 * 3 - continue - z3 = self.x ^ y - if alphanum_byte.alphanumeric_check(z3): - #EORPLS rk, ri, #z*/ - output += ARM_Instructions.dpimm(EOR, PL, 1, self.k, self.i, z3) - #STRPLB rk, [raddr, #(-offset)]*/ - output += ARM_Instructions.lsbyte(STR, PL, self.k, self.addr, offset) - #SUBPL raddr, raddr, rj ROR rk*/ - output += ARM_Instructions.dpshiftreg(SUB, 0, self.addr, self.addr, self.j, ROR, self.k) - - self.size += 4 * 3 - continue - a2 = alphanum_byte.alphanumeric_get_complement(z3) - b2 = a2 ^ z3 - #EORPLS rk, ri, #a*/ - output += ARM_Instructions.dpimm(EOR, PL, 1, self.k, self.i, a2) - #EORPLS rk, rk, #b*/ - output += ARM_Instructions.dpimm(EOR, PL, 1, self.k, self.k, b2) - #STRPLB rk, [raddr, #(-offset)]*/ - output += ARM_Instructions.lsbyte(STR, PL, self.k, self.addr, offset) - #SUBPL raddr, raddr, rj ROR rk*/ - output += ARM_Instructions.dpshiftreg(SUB, 0, self.addr, self.addr, self.j, ROR, self.k) - - self.size += 4 * 4 - - - return output - - def gap_traverse(self, gap): - output = '' - g = alphanum_byte.off_gen(gap) - h = g + gap - #SUBPL rj, ri, #x*/ - output += ARM_Instructions.dpimm(SUB, PL, 0, self.j, self.i, self.x) - #EORPLS rk, rj, #g*/ - output += ARM_Instructions.dpimm(EOR, PL, 1, self.k, self.j, g) - #SUBPL rk, rk, #h*/ - output += ARM_Instructions.dpimm(SUB, PL, 0, self.k, self.k, h) - #SUBPL raddr, raddr, rk LSR rj*/ - output += ARM_Instructions.dpshiftreg(SUB, 0, self.addr, self.addr, self.k, LSR, self.j) - #SUBPL rj, ri, #(x+1)*/ - output += ARM_Instructions.dpimm(SUB, PL, 0, self.j, self.i, self.x + 1) - - self.size += 4 * 5 - return output - - - def buildInit(self, input): - if len(input) == 0: - return ('', input) - output = '' - - #Select values of v and w*/ - total = 0x70 - arr1 = [0x30, 0x34, 0x38] - v1 = random_funcs.randel(arr1) - v2 = random_funcs.randel(arr1) - - topv = ((total - (v1 + v2)) // 4) + 1 - - w1 = random_funcs.randel(arr1) - w2 = random_funcs.randel(arr1) - - topw = ((total - (w1 + w2)) // 4) + 2 - - arrop = [EOR, SUB, RSB] - arrcond = [PL, MI] - arrs = [0, 1] - arrd = [3, 5, 7] - arrn = [1, 2, 3, 4, 5, 6, 7, 8, 9] - p = 1 - while p <= ((total-8) // 4): - op = random_funcs.randel(arrop) - cond = random_funcs.randel(arrcond) - if op == EOR: - s = 1 - else: - s = random_funcs.randel(arrs) - d = random_funcs.randel(arrd) - n = random_funcs.randel(arrn) - if p == topv or p == topw: - output += ARM_Instructions.dpimm(op, cond, s, d, n, self.x) - else: - output += ARM_Instructions.dpimm(op, cond, s, d, n, alphanum_byte.alphanumeric_get_byte()) - p += 1 - - #SUBPL ri, pc, #v1*/ - output += ARM_Instructions.dpimm(SUB, PL, 0, self.i, 15, v1) - #SUBMI ri, pc, #w1*/ - output += ARM_Instructions.dpimm(SUB, MI, 0, self.i, 15, w1) - #LDRPLB ri, [ri, #(-v2)]*/ - output += ARM_Instructions.lsbyte(LDR, PL, self.i, self.i, v2) - #LDRMIB ri, [ri, #(-w2)]*/ - output += ARM_Instructions.lsbyte(LDR, MI, self.i, self.i, w2) - - output += self.algo2() - - #SUBPL rj, ri, #(x+1)*/ - output += ARM_Instructions.dpimm(SUB, PL, 0, self.j, self.i, self.x + 1) - #Initializer built!!*/ - - #Replace 0x91s in decoder with addr_offset*/ - input_new = '' - for p in input: - if p == "\x91": - input_new += chr(self.addr_offset) - else: - input_new += p - return (output, input_new) - - def algo2(self): - output = '' - self.size += 4 - #SUBMIS rk, ri, #x*/ - output += ARM_Instructions.dpimm(SUB, MI, 1, self.k, self.i, self.x) - #SUBPLS rk, ri, #x*/ - output += ARM_Instructions.dpimm(SUB, PL, 1, self.k, self.i, self.x) - #SUBPL rj, ri, #x*/ - output += ARM_Instructions.dpimm(SUB, PL, 0, self.j, self.i, self.x) - - quo = (self.size - 4) // 0x7a - if quo >= 1: - for p in range(quo): - #SUBPL rj, rj, #0x7a*/ - output += ARM_Instructions.dpimm(SUB, PL, 0, self.j, self.j, 0x7a) - - rem = (self.size - 4) % 0x7a - if rem >= 1 and rem <= 0x4a: - self.addr_offset = alphanum_byte.off_gen(rem) - #SUBPL rj, rj, #(offset+rem)*/ - output += ARM_Instructions.dpimm(SUB, PL, 0, self.j, self.j, self.addr_offset + rem) - - if rem >= 0x4b and rem < 0x7a: - if alphanum_byte.alphanumeric_check(rem): - self.addr_offset = alphanum_byte.alphanumeric_get_byte() - #SUBPL rj, rj, #(rem)*/ - output += ARM_Instructions.dpimm(SUB, PL, 0, self.j, self.j, rem) - #SUBPL rj, rj, #(offset)*/ - output += ARM_Instructions.dpimm(SUB, PL, 0, self.j, self.j, self.addr_offset) - else: - self.addr_offset = alphanum_byte.off_gen(rem - 0x5a) - #SUBPL rj, rj, #0x5a*/ - output += ARM_Instructions.dpimm(SUB, PL, 0, self.j, self.j, 0x5a) - #SUBPL rj, rj, #(offset + (rem - 0x5a))*/ - output += ARM_Instructions.dpimm(SUB, PL, 0, self.j, self.j, self.addr_offset + rem - 0x5a) - - #SUBPL raddr, pc, rj ROR rk*/ - output += ARM_Instructions.dpshiftreg(SUB, 0, self.addr, 15, self.j, ROR, self.k) - return output + +# +---------------------------------------------------+ +# | Builder Functions | +# +---------------------------------------------------+ + +class builder(object): + def __init__(self): + self.I = 0 + self.size = 0 + self.i = 0 + self.j = 0 + self.k = 0 + self.x = 0 + self.addr = 0 + self.addr_offset = 0 + + def enc_data_builder(self, input): + if not input: + return b'' + output = bytearray() + self.I = random_funcs.randel(range(1, 10)) + for ab in bytearray(input): + b = ab & 0x0f + e0 = random_funcs.enc_data_msn(b, self.I) + e0 = e0 << 4 + ef = e0 | b + d = ((ab & 0xf0) ^ e0) >> 4 + c0 = random_funcs.enc_data_msn(d, self.I) << 4 + cd = c0 | d + output.append(cd & 0xff) + output.append(ef & 0xff) + # Last two bytes to stop the decoder_loop + max = 0x30 | self.I + output.append(alphanum_byte.alphanumeric_get_byte()) + output.append(alphanum_byte.alphanumeric_get_byte_ltmax(max)) + return bytes(output) + + def DecoderLoopBuilder(self, icache_flush): + dec_loop = b'' + # Select p,s,t and q + arr = [3, 7] + p = random_funcs.randel(arr) + if p == 3: + s = 7 + else: + s = 3 + t = 6 + arr2 = [8, 9] + q = random_funcs.randel(arr2) + + # Add the instructions + if icache_flush != 0: + dec_loop += swi(MI) + + rsalnum = alphanum_byte.alphanumeric_get_byte() + + if icache_flush != 0: + # EORMIS rp, r4, #(randomly selected alphanumeric value) + dec_loop += dpimm(EOR, MI, 1, p, 4, rsalnum) + + if icache_flush == 1: + dist = 0x2c + else: + dist = 0x28 + + offset = alphanum_byte.off_gen(dist + 0x04) + + # SUBPL rs, r4, #(dist+0x04+offset) + dec_loop += dpimm(SUB, PL, 0, s, 4, dist + 0x04 + offset) + + # SUBPL rs, pc, rs LSR r4 + dec_loop += dpshiftreg(SUB, 0, s, 0x0f, s, LSR, 4) + + # EORPLS rt, r4, rs LSR r4 + dec_loop += dpshiftreg(EOR, 1, t, 4, s, LSR, 4) + + # EORMIS rp, r4, #rsalnum + rsalnum = alphanum_byte.alphanumeric_get_byte() + dec_loop += dpimm(EOR, MI, 1, p, 4, rsalnum) + + # LDRPLB rp, [rs, #(-offset)] + dec_loop += lsbyte(LDR, PL, p, s, offset) + + # SUBPL rs, rs, r5 LSR r4 + dec_loop += dpshiftreg(SUB, 0, s, s, 5, LSR, 4) + + # LDRPLB rq, [rs, #(-offset)] + dec_loop += lsbyte(LDR, PL, q, s, offset) + + # EORPLS rp, rq, rp ROR #28 + dec_loop += dpshiftimm(EOR, 1, p, q, p, 28) + + # STRPLB rp, [rt, #(-offset)] + dec_loop += lsbyte(STR, PL, p, t, offset) + + # SUBPL rt, rt, r5 LSR r4 + dec_loop += dpshiftreg(SUB, 0, t, t, 5, LSR, 4) + + # SUBPL rs, rs, r5 LSR r4 + dec_loop += dpshiftreg(SUB, 0, s, s, 5, LSR, 4) + + # RSBPLS rq, rq, #0x3I + dec_loop += dpimm(RSB, PL, 1, q, q, 0x30 | self.I) + + # BMI 0xfffff4 + dec_loop += bmi() + + # STRPLB r4, [rt, #-(offset+1)] + dec_loop += lsbyte(STR, PL, 4, t, offset + 1) + + if icache_flush == 1: + # SWIPL 0x9f0002 + dec_loop += swi(PL) + return dec_loop + + def encDecoderLoopBuilder(self, input): + output = bytearray() + for p in input: + if not alphanum_byte.alphanumeric_check(p): + output.append(alphanum_byte.alphanumeric_get_byte()) + else: + output.append(p) + return bytes(output) + + def DecoderBuilder(self, input, icache_flush): + if not input: + return b'' + output = b'' + + # Register selections + arr = [4, 6] + self.addr = random_funcs.randel(arr) + arr2 = [3, 5, 7] + self.i = random_funcs.randel(arr2) + arr3 = [0, 0] + q = 0 + for p in arr2: + if p != self.i: + arr3[q] = p + q += 1 + self.j = random_funcs.randel(arr3) + for p in arr3: + if p != self.j: + self.k = p + break + + self.x = alphanum_byte.off_gen(0x01) + if icache_flush != 0: + output += self.algo1(input, 0, 3) + output += self.gap_traverse(0x1e) + output += self.algo1(input, 33, 5) + else: + output += self.gap_traverse(0x19) + output += self.algo1(input, 25, 5) + output += self.gap_traverse(0x0f) + if icache_flush != 0: + output += self.algo1(input, 53, 15) + else: + output += self.algo1(input, 45, 11) + # trucate the last instruction, which increments raddr by 1, from the output + output = output[:-4] + self.size -= 4 + # Setting r0, r1, r2 for parameter passing + # SUBPLS ri, ri, #x + output += dpimm(SUB, PL, 1, self.i, self.i, self.x) + # SUBPL r4, ri, ri LSR ri + output += dpshiftreg(SUB, 0, 4, self.i, self.i, LSR, self.i) + # SUBPL r6, ri, ri LSR ri + output += dpshiftreg(SUB, 0, 6, self.i, self.i, LSR, self.i) + # SUBPL r5, rj, r4 ROR r6 + output += dpshiftreg(SUB, 0, 5, self.j, 4, ROR, 6) + + self.size += 4 * 4 + + if icache_flush: + arr4 = [3, 7] + m = random_funcs.randel(arr4) + + c = alphanum_byte.off_gen(24) + arr5 = range(2, 20, 2) + arr6 = [4, 6] + arr7 = [1, 2, 4, 8] + reglH = 0x40 | random_funcs.randel(arr7) + # SUBPL rm, sp, #(c+24) + output += dpimm(SUB, PL, 0, m, 13, c + 24) + + # Store 4 0x00 + # STRPLB random_funcs.randel(arr6), [!rm, -(r5 ROR #random_funcs.randel(arr5))] + output += sbyteposti(random_funcs.randel(arr6), m, 5, random_funcs.randel(arr5)) + output += sbyteposti(random_funcs.randel(arr6), m, 5, random_funcs.randel(arr5)) + output += sbyteposti(random_funcs.randel(arr6), m, 5, random_funcs.randel(arr5)) + output += sbyteposti(random_funcs.randel(arr6), m, 5, random_funcs.randel(arr5)) + + # Store 4 0xff + # STRPLB r5, [!rm, -(r5 ROR #random_funcs.randel(arr5))] + output += sbyteposti(5, m, 5, random_funcs.randel(arr5)) + output += sbyteposti(5, m, 5, random_funcs.randel(arr5)) + output += sbyteposti(5, m, 5, random_funcs.randel(arr5)) + output += sbyteposti(5, m, 5, random_funcs.randel(arr5)) + + # Store 4 0x00 + # STRPLB random_funcs.randel(arr6), [!rm, -(r5 ROR #random_funcs.randel(arr5))] + output += sbyteposti(random_funcs.randel(arr6), m, 5, random_funcs.randel(arr5)) + output += sbyteposti(random_funcs.randel(arr6), m, 5, random_funcs.randel(arr5)) + output += sbyteposti(random_funcs.randel(arr6), m, 5, random_funcs.randel(arr5)) + output += sbyteposti(random_funcs.randel(arr6), m, 5, random_funcs.randel(arr5)) + + # SUBPL rm, sp, #c + output += dpimm(SUB, PL, 0, m, 13, c) + + # LDMPLDB rm!, {r0, r1, r2, r6, r8/9/10/11, r14} + output += lmul(m, reglH, 0x47) + + # SUBPLS rm, r5, r4 ROR rm + output += dpshiftreg(SUB, 1, m, 5, 4, ROR, m) + + self.size += 4 * 16 + return output + + def algo1(self, input, begin_inp, iter): + if not input: + return b'' + output = b'' + offset = 0x91 + for p in range(begin_inp, begin_inp + iter): + y = ord(input[p]) + if alphanum_byte.alphanumeric_check(y): + # SUBPL raddr, raddr, rj ROR rk + output += dpshiftreg(SUB, 0, self.addr, self.addr, self.j, ROR, self.k) + self.size += 4 + continue + if y >= 0x80: + if alphanum_byte.alphanumeric_check(~y): + # EORPLS rk, rj, #~y + output += dpimm(EOR, PL, 1, self.k, self.j, ~y) + # STRMIB rk, [raddr, #(-offset)] + output += lsbyte(STR, MI, self.k, self.addr, offset) + # SUBMIS rk, ri, #x + output += dpimm(SUB, MI, 1, self.k, self.i, self.x) + # SUBPL raddr, raddr, rj ROR rk + output += dpshiftreg(SUB, 0, self.addr, self.addr, self.j, ROR, self.k) + + self.size += 4 * 4 + continue + + a = alphanum_byte.alphanumeric_get_complement(~y) + b = (a ^ ~y) & 0xff + # EORPLS rk, rj, #a + output += dpimm(EOR, PL, 1, self.k, self.j, a) + # EORMIS rk, rk, #b + output += dpimm(EOR, MI, 1, self.k, self.k, b) + # STRMIB rk, [raddr, #(-offset)] + output += lsbyte(STR, MI, self.k, self.addr, offset) + # SUBMIS rk, ri, #x + output += dpimm(SUB, MI, 1, self.k, self.i, self.x) + # SUBPL raddr, raddr, rj ROR rk + output += dpshiftreg(SUB, 0, self.addr, self.addr, self.j, ROR, self.k) + + self.size += 4 * 5 + continue + if self.x > y: + z1 = self.x - y + if alphanum_byte.alphanumeric_check(z1): + # SUBPL rk, ri, #z + output += dpimm(SUB, PL, 0, self.k, self.i, z1) + # STRPLB rk, [raddr, #(-offset)] + output += lsbyte(STR, PL, self.k, self.addr, offset) + # SUBPL raddr, raddr, rj ROR rk + output += dpshiftreg(SUB, 0, self.addr, self.addr, self.j, ROR, self.k) + + self.size += 4 * 3 + continue + z2 = self.x + y + if alphanum_byte.alphanumeric_check(z2): + # RSBPL rk, ri, #z + output += dpimm(RSB, PL, 0, self.k, self.i, z2) + # STRPLB rk, [raddr, #(-offset)] + output += lsbyte(STR, PL, self.k, self.addr, offset) + # SUBPL raddr, raddr, rj ROR rk + output += dpshiftreg(SUB, 0, self.addr, self.addr, self.j, ROR, self.k) + + self.size += 4 * 3 + continue + z3 = self.x ^ y + if alphanum_byte.alphanumeric_check(z3): + # EORPLS rk, ri, #z + output += dpimm(EOR, PL, 1, self.k, self.i, z3) + # STRPLB rk, [raddr, #(-offset)] + output += lsbyte(STR, PL, self.k, self.addr, offset) + # SUBPL raddr, raddr, rj ROR rk + output += dpshiftreg(SUB, 0, self.addr, self.addr, self.j, ROR, self.k) + + self.size += 4 * 3 + continue + a2 = alphanum_byte.alphanumeric_get_complement(z3) + b2 = a2 ^ z3 + # EORPLS rk, ri, #a + output += dpimm(EOR, PL, 1, self.k, self.i, a2) + # EORPLS rk, rk, #b + output += dpimm(EOR, PL, 1, self.k, self.k, b2) + # STRPLB rk, [raddr, #(-offset)] + output += lsbyte(STR, PL, self.k, self.addr, offset) + # SUBPL raddr, raddr, rj ROR rk + output += dpshiftreg(SUB, 0, self.addr, self.addr, self.j, ROR, self.k) + + self.size += 4 * 4 + return output + + def gap_traverse(self, gap): + output = b'' + g = alphanum_byte.off_gen(gap) + h = g + gap + # SUBPL rj, ri, #x + output += dpimm(SUB, PL, 0, self.j, self.i, self.x) + # EORPLS rk, rj, #g + output += dpimm(EOR, PL, 1, self.k, self.j, g) + # SUBPL rk, rk, #h + output += dpimm(SUB, PL, 0, self.k, self.k, h) + # SUBPL raddr, raddr, rk LSR rj + output += dpshiftreg(SUB, 0, self.addr, self.addr, self.k, LSR, self.j) + # SUBPL rj, ri, #(x+1) + output += dpimm(SUB, PL, 0, self.j, self.i, self.x + 1) + + self.size += 4 * 5 + return output + + def buildInit(self, input): + if not input: + return (b'', input) + output = b'' + + # Select values of v and w + total = 0x70 + arr1 = [0x30, 0x34, 0x38] + v1 = random_funcs.randel(arr1) + v2 = random_funcs.randel(arr1) + + topv = ((total - (v1 + v2)) // 4) + 1 + + w1 = random_funcs.randel(arr1) + w2 = random_funcs.randel(arr1) + + topw = ((total - (w1 + w2)) // 4) + 2 + + arrop = [EOR, SUB, RSB] + arrcond = [PL, MI] + arrs = [0, 1] + arrd = [3, 5, 7] + arrn = range(1, 10) + p = 1 + while p <= ((total - 8) // 4): + op = random_funcs.randel(arrop) + cond = random_funcs.randel(arrcond) + if op == EOR: + s = 1 + else: + s = random_funcs.randel(arrs) + d = random_funcs.randel(arrd) + n = random_funcs.randel(arrn) + if p == topv or p == topw: + output += dpimm(op, cond, s, d, n, self.x) + else: + output += dpimm(op, cond, s, d, n, alphanum_byte.alphanumeric_get_byte()) + p += 1 + + # SUBPL ri, pc, #v1 + output += dpimm(SUB, PL, 0, self.i, 15, v1) + # SUBMI ri, pc, #w1 + output += dpimm(SUB, MI, 0, self.i, 15, w1) + # LDRPLB ri, [ri, #(-v2)] + output += lsbyte(LDR, PL, self.i, self.i, v2) + # LDRMIB ri, [ri, #(-w2)] + output += lsbyte(LDR, MI, self.i, self.i, w2) + + output += self.algo2() + + # SUBPL rj, ri, #(x+1) + output += dpimm(SUB, PL, 0, self.j, self.i, self.x + 1) + # Initializer built!! + + # Replace 0x91s in decoder with addr_offset + input_new = b'' + for p in input: + if p == b"\x91": + input_new.append(self.addr_offset) + else: + input_new += p + return (output, input_new) + + def algo2(self): + output = b'' + self.size += 4 + # SUBMIS rk, ri, #x + output += dpimm(SUB, MI, 1, self.k, self.i, self.x) + # SUBPLS rk, ri, #x + output += dpimm(SUB, PL, 1, self.k, self.i, self.x) + # SUBPL rj, ri, #x + output += dpimm(SUB, PL, 0, self.j, self.i, self.x) + + quo = (self.size - 4) // 0x7a + if quo >= 1: + for p in range(quo): + # SUBPL rj, rj, #0x7a + output += dpimm(SUB, PL, 0, self.j, self.j, 0x7a) + + rem = (self.size - 4) % 0x7a + if rem >= 1 and rem <= 0x4a: + self.addr_offset = alphanum_byte.off_gen(rem) + # SUBPL rj, rj, #(offset+rem) + output += dpimm(SUB, PL, 0, self.j, self.j, self.addr_offset + rem) + + if rem >= 0x4b and rem < 0x7a: + if alphanum_byte.alphanumeric_check(rem): + self.addr_offset = alphanum_byte.alphanumeric_get_byte() + # SUBPL rj, rj, #(rem) + output += dpimm(SUB, PL, 0, self.j, self.j, rem) + # SUBPL rj, rj, #(offset) + output += dpimm(SUB, PL, 0, self.j, self.j, self.addr_offset) + else: + self.addr_offset = alphanum_byte.off_gen(rem - 0x5a) + # SUBPL rj, rj, #0x5a + output += dpimm(SUB, PL, 0, self.j, self.j, 0x5a) + # SUBPL rj, rj, #(offset + (rem - 0x5a)) + output += dpimm(SUB, PL, 0, self.j, self.j, self.addr_offset + rem - 0x5a) + + # SUBPL raddr, pc, rj ROR rk + output += dpshiftreg(SUB, 0, self.addr, 15, self.j, ROR, self.k) + return output From 133de1d1da1d63c326916cf6879127f178d5a0f6 Mon Sep 17 00:00:00 2001 From: Arusekk Date: Sun, 14 Jun 2020 16:09:44 +0200 Subject: [PATCH 3/4] Fix ARM encoders duplication --- .../arm/alphanumeric/ARM_Instructions.py | 2 +- pwnlib/encoders/arm/alphanumeric/__init__.py | 6 +- .../arm/alphanumeric/alphanum_byte.py | 5 +- pwnlib/encoders/arm/alphanumeric/builder.py | 97 ++++++++----------- pwnlib/encoders/encoder.py | 23 ++--- 5 files changed, 56 insertions(+), 77 deletions(-) diff --git a/pwnlib/encoders/arm/alphanumeric/ARM_Instructions.py b/pwnlib/encoders/arm/alphanumeric/ARM_Instructions.py index f737deb6a..5717087b6 100755 --- a/pwnlib/encoders/arm/alphanumeric/ARM_Instructions.py +++ b/pwnlib/encoders/arm/alphanumeric/ARM_Instructions.py @@ -78,7 +78,7 @@ def smul(d, reglH, reglL): # LDMPLDB rn!, (Register List) # ============================ def lmul(n, reglH, reglL): - return bytes(bytearray((reglL, reglH, 0x30 | d, 0x59))) + return bytes(bytearray((reglL, reglH, 0x30 | n, 0x59))) # SWI(PL/MI) 0x9f0002 # ============== diff --git a/pwnlib/encoders/arm/alphanumeric/__init__.py b/pwnlib/encoders/arm/alphanumeric/__init__.py index 426265fc6..34d990c49 100644 --- a/pwnlib/encoders/arm/alphanumeric/__init__.py +++ b/pwnlib/encoders/arm/alphanumeric/__init__.py @@ -14,8 +14,8 @@ class ArmEncoder(Encoder): arch = 'arm' - blacklist = {chr(c) for c in range(256) if chr(c) in (string.ascii_letters + string.digits)} - icache_flush = 1 + blacklist = set((string.ascii_letters + string.digits).encode()) + icache_flush = True def __call__(self, input, avoid, pcreg=None): # If randomization is disabled, ensure that the seed @@ -41,7 +41,7 @@ def __call__(self, input, avoid, pcreg=None): finally: random.setstate(state) - return output.encode() + return output class ThumbEncoder(ArmEncoder): arch = 'thumb' diff --git a/pwnlib/encoders/arm/alphanumeric/alphanum_byte.py b/pwnlib/encoders/arm/alphanumeric/alphanum_byte.py index 1f05492fd..5af195e1d 100755 --- a/pwnlib/encoders/arm/alphanumeric/alphanum_byte.py +++ b/pwnlib/encoders/arm/alphanumeric/alphanum_byte.py @@ -1,6 +1,7 @@ from __future__ import division from __future__ import absolute_import +import six from . import random_funcs # +------------------------------------------------------------------------+ @@ -13,7 +14,7 @@ # ==================================== def alphanumeric_check(c): if isinstance(c, six.integer_types): - return c in ALPHANUMERIC_BYTES + return c&0xff in ALPHANUMERIC_BYTES return c.isalnum() @@ -27,7 +28,7 @@ def alphanumeric_get_byte(): # CSE author actually returns a byte <= max, not strictly < max def alphanumeric_get_byte_ltmax(max): sz = 0 - while sz < len(ALPHANUMERIC_BYTES) and ord(ALPHANUMERIC_BYTES[sz]) <= max: + while sz < len(ALPHANUMERIC_BYTES) and ALPHANUMERIC_BYTES[sz] <= max: sz += 1 return random_funcs.randel(ALPHANUMERIC_BYTES[:sz]) diff --git a/pwnlib/encoders/arm/alphanumeric/builder.py b/pwnlib/encoders/arm/alphanumeric/builder.py index 2434afbac..2298cd16c 100755 --- a/pwnlib/encoders/arm/alphanumeric/builder.py +++ b/pwnlib/encoders/arm/alphanumeric/builder.py @@ -76,16 +76,16 @@ def DecoderLoopBuilder(self, icache_flush): q = random_funcs.randel(arr2) # Add the instructions - if icache_flush != 0: + if icache_flush: dec_loop += swi(MI) rsalnum = alphanum_byte.alphanumeric_get_byte() - if icache_flush != 0: + if icache_flush: # EORMIS rp, r4, #(randomly selected alphanumeric value) dec_loop += dpimm(EOR, MI, 1, p, 4, rsalnum) - if icache_flush == 1: + if icache_flush: dist = 0x2c else: dist = 0x28 @@ -135,7 +135,7 @@ def DecoderLoopBuilder(self, icache_flush): # STRPLB r4, [rt, #-(offset+1)] dec_loop += lsbyte(STR, PL, 4, t, offset + 1) - if icache_flush == 1: + if icache_flush: # SWIPL 0x9f0002 dec_loop += swi(PL) return dec_loop @@ -172,7 +172,7 @@ def DecoderBuilder(self, input, icache_flush): break self.x = alphanum_byte.off_gen(0x01) - if icache_flush != 0: + if icache_flush: output += self.algo1(input, 0, 3) output += self.gap_traverse(0x1e) output += self.algo1(input, 33, 5) @@ -180,7 +180,7 @@ def DecoderBuilder(self, input, icache_flush): output += self.gap_traverse(0x19) output += self.algo1(input, 25, 5) output += self.gap_traverse(0x0f) - if icache_flush != 0: + if icache_flush: output += self.algo1(input, 53, 15) else: output += self.algo1(input, 45, 11) @@ -213,24 +213,18 @@ def DecoderBuilder(self, input, icache_flush): # Store 4 0x00 # STRPLB random_funcs.randel(arr6), [!rm, -(r5 ROR #random_funcs.randel(arr5))] - output += sbyteposti(random_funcs.randel(arr6), m, 5, random_funcs.randel(arr5)) - output += sbyteposti(random_funcs.randel(arr6), m, 5, random_funcs.randel(arr5)) - output += sbyteposti(random_funcs.randel(arr6), m, 5, random_funcs.randel(arr5)) - output += sbyteposti(random_funcs.randel(arr6), m, 5, random_funcs.randel(arr5)) + for _ in range(4): + output += sbyteposti(random_funcs.randel(arr6), m, 5, random_funcs.randel(arr5)) # Store 4 0xff # STRPLB r5, [!rm, -(r5 ROR #random_funcs.randel(arr5))] - output += sbyteposti(5, m, 5, random_funcs.randel(arr5)) - output += sbyteposti(5, m, 5, random_funcs.randel(arr5)) - output += sbyteposti(5, m, 5, random_funcs.randel(arr5)) - output += sbyteposti(5, m, 5, random_funcs.randel(arr5)) + for _ in range(4): + output += sbyteposti(5, m, 5, random_funcs.randel(arr5)) # Store 4 0x00 # STRPLB random_funcs.randel(arr6), [!rm, -(r5 ROR #random_funcs.randel(arr5))] - output += sbyteposti(random_funcs.randel(arr6), m, 5, random_funcs.randel(arr5)) - output += sbyteposti(random_funcs.randel(arr6), m, 5, random_funcs.randel(arr5)) - output += sbyteposti(random_funcs.randel(arr6), m, 5, random_funcs.randel(arr5)) - output += sbyteposti(random_funcs.randel(arr6), m, 5, random_funcs.randel(arr5)) + for _ in range(4): + output += sbyteposti(random_funcs.randel(arr6), m, 5, random_funcs.randel(arr5)) # SUBPL rm, sp, #c output += dpimm(SUB, PL, 0, m, 13, c) @@ -249,8 +243,19 @@ def algo1(self, input, begin_inp, iter): return b'' output = b'' offset = 0x91 - for p in range(begin_inp, begin_inp + iter): - y = ord(input[p]) + + def op(oper, arg): + nonlocal output + # (EORPLS|SUBPL|SBRPL). rk, ri, #arg + output += dpimm(oper, PL, oper == EOR, self.k, self.i, arg) + # STRPLB rk, [raddr, #(-offset)] + output += lsbyte(STR, PL, self.k, self.addr, offset) + # SUBPL raddr, raddr, rj ROR rk + output += dpshiftreg(SUB, 0, self.addr, self.addr, self.j, ROR, self.k) + + self.size += 4 * 3 + + for y in bytearray(input[begin_inp:begin_inp + iter]): if alphanum_byte.alphanumeric_check(y): # SUBPL raddr, raddr, rj ROR rk output += dpshiftreg(SUB, 0, self.addr, self.addr, self.j, ROR, self.k) @@ -289,48 +294,25 @@ def algo1(self, input, begin_inp, iter): z1 = self.x - y if alphanum_byte.alphanumeric_check(z1): # SUBPL rk, ri, #z - output += dpimm(SUB, PL, 0, self.k, self.i, z1) - # STRPLB rk, [raddr, #(-offset)] - output += lsbyte(STR, PL, self.k, self.addr, offset) - # SUBPL raddr, raddr, rj ROR rk - output += dpshiftreg(SUB, 0, self.addr, self.addr, self.j, ROR, self.k) - - self.size += 4 * 3 + op(SUB, z1) continue z2 = self.x + y if alphanum_byte.alphanumeric_check(z2): # RSBPL rk, ri, #z - output += dpimm(RSB, PL, 0, self.k, self.i, z2) - # STRPLB rk, [raddr, #(-offset)] - output += lsbyte(STR, PL, self.k, self.addr, offset) - # SUBPL raddr, raddr, rj ROR rk - output += dpshiftreg(SUB, 0, self.addr, self.addr, self.j, ROR, self.k) - - self.size += 4 * 3 + op(RSB, z2) continue z3 = self.x ^ y if alphanum_byte.alphanumeric_check(z3): # EORPLS rk, ri, #z - output += dpimm(EOR, PL, 1, self.k, self.i, z3) - # STRPLB rk, [raddr, #(-offset)] - output += lsbyte(STR, PL, self.k, self.addr, offset) - # SUBPL raddr, raddr, rj ROR rk - output += dpshiftreg(SUB, 0, self.addr, self.addr, self.j, ROR, self.k) - - self.size += 4 * 3 + op(EOR, z3) continue a2 = alphanum_byte.alphanumeric_get_complement(z3) b2 = a2 ^ z3 - # EORPLS rk, ri, #a - output += dpimm(EOR, PL, 1, self.k, self.i, a2) - # EORPLS rk, rk, #b - output += dpimm(EOR, PL, 1, self.k, self.k, b2) - # STRPLB rk, [raddr, #(-offset)] - output += lsbyte(STR, PL, self.k, self.addr, offset) - # SUBPL raddr, raddr, rj ROR rk - output += dpshiftreg(SUB, 0, self.addr, self.addr, self.j, ROR, self.k) - - self.size += 4 * 4 + # EORPLS rk, rk, #a + output += dpimm(EOR, PL, 1, self.k, self.k, a2) + # EORPLS rk, ri, #b + op(EOR, b2) + self.size += 4 return output def gap_traverse(self, gap): @@ -406,13 +388,13 @@ def buildInit(self, input): # Initializer built!! # Replace 0x91s in decoder with addr_offset - input_new = b'' - for p in input: - if p == b"\x91": + input_new = bytearray() + for p in bytearray(input): + if p == 0x91: input_new.append(self.addr_offset) else: - input_new += p - return (output, input_new) + input_new.append(p) + return (output, bytes(input_new)) def algo2(self): output = b'' @@ -424,13 +406,12 @@ def algo2(self): # SUBPL rj, ri, #x output += dpimm(SUB, PL, 0, self.j, self.i, self.x) - quo = (self.size - 4) // 0x7a + quo, rem = divmod(self.size - 4, 0x7a) if quo >= 1: for p in range(quo): # SUBPL rj, rj, #0x7a output += dpimm(SUB, PL, 0, self.j, self.j, 0x7a) - rem = (self.size - 4) % 0x7a if rem >= 1 and rem <= 0x4a: self.addr_offset = alphanum_byte.off_gen(rem) # SUBPL rj, rj, #(offset+rem) diff --git a/pwnlib/encoders/encoder.py b/pwnlib/encoders/encoder.py index 13b64764e..7aa112576 100644 --- a/pwnlib/encoders/encoder.py +++ b/pwnlib/encoders/encoder.py @@ -62,12 +62,10 @@ def encode(raw_bytes, avoid=None, expr=None, force=0, pcreg=''): """ orig_avoid = avoid - avoid = set(avoid or '') + avoid = set(avoid or b'') if expr: - for char in all_chars: - if re.search(expr, char): - avoid.add(char) + avoid |= set(b''.join(re.findall(expr, all_chars))) if not (force or avoid & set(raw_bytes)): return raw_bytes @@ -90,26 +88,25 @@ def encode(raw_bytes, avoid=None, expr=None, force=0, pcreg=''): return v - avoid_errmsg = '' if orig_avoid and expr: avoid_errmsg = '%r and %r' % (orig_avoid, expr) elif expr: avoid_errmsg = repr(expr) else: - avoid_errmsg = ''.join(avoid) + avoid_errmsg = repr(bytearray(avoid)) args = (context.arch, avoid_errmsg, hexdump(raw_bytes)) msg = "No encoders for %s which can avoid %s for\n%s" % args msg = msg.replace('%', '%%') log.error(msg) -all_chars = list(chr(i) for i in range(256)) -re_alphanumeric = r'[^A-Za-z0-9]' -re_printable = r'[^\x21-\x7e]' -re_whitespace = r'\s' -re_null = r'\x00' -re_line = r'[\s\x00]' +all_chars = bytes(bytearray(range(256))) +re_alphanumeric = br'[^A-Za-z0-9]' +re_printable = br'[^\x21-\x7e]' +re_whitespace = br'\s' +re_null = br'\x00' +re_line = br'[\s\x00]' @LocalContext def null(raw_bytes, *a, **kw): @@ -163,4 +160,4 @@ def scramble(raw_bytes, *a, **kw): Accepts the same arguments as :func:`encode`. """ - return encode(raw_bytes, force=1, *a, **kw) + return encode(raw_bytes, force=True, *a, **kw) From a1a10c41333ac1b61ccf8b55ba3af45baf11cbf4 Mon Sep 17 00:00:00 2001 From: Arusekk Date: Sun, 14 Jun 2020 16:23:01 +0200 Subject: [PATCH 4/4] No nonlocal in py2 --- pwnlib/encoders/arm/alphanumeric/builder.py | 33 ++++++++++----------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/pwnlib/encoders/arm/alphanumeric/builder.py b/pwnlib/encoders/arm/alphanumeric/builder.py index 2298cd16c..84e826337 100755 --- a/pwnlib/encoders/arm/alphanumeric/builder.py +++ b/pwnlib/encoders/arm/alphanumeric/builder.py @@ -241,36 +241,35 @@ def DecoderBuilder(self, input, icache_flush): def algo1(self, input, begin_inp, iter): if not input: return b'' - output = b'' + output = [] offset = 0x91 def op(oper, arg): - nonlocal output # (EORPLS|SUBPL|SBRPL). rk, ri, #arg - output += dpimm(oper, PL, oper == EOR, self.k, self.i, arg) + output.append(dpimm(oper, PL, oper == EOR, self.k, self.i, arg)) # STRPLB rk, [raddr, #(-offset)] - output += lsbyte(STR, PL, self.k, self.addr, offset) + output.append(lsbyte(STR, PL, self.k, self.addr, offset)) # SUBPL raddr, raddr, rj ROR rk - output += dpshiftreg(SUB, 0, self.addr, self.addr, self.j, ROR, self.k) + output.append(dpshiftreg(SUB, 0, self.addr, self.addr, self.j, ROR, self.k)) self.size += 4 * 3 for y in bytearray(input[begin_inp:begin_inp + iter]): if alphanum_byte.alphanumeric_check(y): # SUBPL raddr, raddr, rj ROR rk - output += dpshiftreg(SUB, 0, self.addr, self.addr, self.j, ROR, self.k) + output.append(dpshiftreg(SUB, 0, self.addr, self.addr, self.j, ROR, self.k)) self.size += 4 continue if y >= 0x80: if alphanum_byte.alphanumeric_check(~y): # EORPLS rk, rj, #~y - output += dpimm(EOR, PL, 1, self.k, self.j, ~y) + output.append(dpimm(EOR, PL, 1, self.k, self.j, ~y)) # STRMIB rk, [raddr, #(-offset)] - output += lsbyte(STR, MI, self.k, self.addr, offset) + output.append(lsbyte(STR, MI, self.k, self.addr, offset)) # SUBMIS rk, ri, #x - output += dpimm(SUB, MI, 1, self.k, self.i, self.x) + output.append(dpimm(SUB, MI, 1, self.k, self.i, self.x)) # SUBPL raddr, raddr, rj ROR rk - output += dpshiftreg(SUB, 0, self.addr, self.addr, self.j, ROR, self.k) + output.append(dpshiftreg(SUB, 0, self.addr, self.addr, self.j, ROR, self.k)) self.size += 4 * 4 continue @@ -278,15 +277,15 @@ def op(oper, arg): a = alphanum_byte.alphanumeric_get_complement(~y) b = (a ^ ~y) & 0xff # EORPLS rk, rj, #a - output += dpimm(EOR, PL, 1, self.k, self.j, a) + output.append(dpimm(EOR, PL, 1, self.k, self.j, a)) # EORMIS rk, rk, #b - output += dpimm(EOR, MI, 1, self.k, self.k, b) + output.append(dpimm(EOR, MI, 1, self.k, self.k, b)) # STRMIB rk, [raddr, #(-offset)] - output += lsbyte(STR, MI, self.k, self.addr, offset) + output.append(lsbyte(STR, MI, self.k, self.addr, offset)) # SUBMIS rk, ri, #x - output += dpimm(SUB, MI, 1, self.k, self.i, self.x) + output.append(dpimm(SUB, MI, 1, self.k, self.i, self.x)) # SUBPL raddr, raddr, rj ROR rk - output += dpshiftreg(SUB, 0, self.addr, self.addr, self.j, ROR, self.k) + output.append(dpshiftreg(SUB, 0, self.addr, self.addr, self.j, ROR, self.k)) self.size += 4 * 5 continue @@ -309,11 +308,11 @@ def op(oper, arg): a2 = alphanum_byte.alphanumeric_get_complement(z3) b2 = a2 ^ z3 # EORPLS rk, rk, #a - output += dpimm(EOR, PL, 1, self.k, self.k, a2) + output.append(dpimm(EOR, PL, 1, self.k, self.k, a2)) # EORPLS rk, ri, #b op(EOR, b2) self.size += 4 - return output + return b''.join(output) def gap_traverse(self, gap): output = b''