2020虎符杯逆向题解

Author Avatar
Xzhah 4月 22, 2020
  • 在其它设备中阅读本文章

enc

这个题需要记录两点:

1.碰到一时识别不了的加密算法尝试用angr莽?

2.rc6算法特点:很多ROL?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from angr import *
from claripy import *
#timestamp=1575018225 0x5de0def1
flag = BVS('flag', 8 * 16)
result = BVV(b'\xae\xed\x13\x5c\xbd\xd2\xa1\x74\x9c\x4c\x5e\x02\xd3\x28\x9b\x60', 8 * 16)
disasm = BVV(b'794c87696d24d16e7b9e3dddad778c93', 8 * 32)
p = Project('task.exe', auto_load_libs=False)
#p.hook(0x403610, SIM_PROCEDURES['libc']['srand']())
#p.hook(0x4035ef, SIM_PROCEDURES['libc']['rand']())
#p.hook(0x405128, SIM_PROCEDURES['libc']['malloc']())
#p.hook(0x4035e4, SIM_PROCEDURES['libc']['calloc']())
st = p.factory.full_init_state(addr=0x40154d, add_options={options.SYMBOLIC_WRITE_ADDRESSES,
options.REGION_MAPPING,
options.SYMBOL_FILL_UNCONSTRAINED_REGISTERS})
st.memory.store(st.regs.ebp, BVV(0, 32))
st.memory.store(st.regs.ebp - 0x24, flag)
st.memory.store(st.regs.ebp - 0x54, disasm)
sim = p.factory.simgr(st)
sim.explore(find=0x401558)
f = sim.one_found
f.solver.add(f.memory.load(f.regs.ebp - 0x24, 16) == result)
print(f.solver.eval(flag, cast_to=bytes))

game

python字节码可以参考

https://zhuanlan.zhihu.com/p/45101508

https://docs.python.org/3.5/library/dis.html#python-bytecode-instructions

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
from z3 import *
def get_models(s):
while s.check() == sat:
m = s.model()
yield m
s.add(Or([sym() != m[sym] for sym in m.decls()]))

def first_enc(input,input2):
inpt=input[:]
for i in range(len(inpt)):
inpt[i]=input[i]^input2[i]
return inpt
arr0 = [249,91,149,113,16,91,53,41]
arr1 = [43,1,6,69,20,62,6,44,24,113,6,35,0,3,6,44,20,22,127,60]
arr2 = [ 90, 100, 87, 109, 86, 108, 86, 105, 90, 104, 88, 102]
arr = [BitVec('arr[%d]'%i, 32) for i in range(39)]
s = Solver()
s.add(arr[0]==ord('f'))
s.add(arr[1]==ord('l'))
s.add(arr[2]==ord('a'))
s.add(arr[3]==ord('g'))
s.add(arr[4]==ord('{'))
s.add(arr[5]==ord('5'))
s.add(arr[38]==ord('}'))
for i in range(len(arr)):
s.add(arr[i]<128)
s.add(arr[i]>32)
a = arr[6:30:3]

for i in range(len(a)):
s.add((a[i]*17684+372511)%257==arr0[i])
b = arr[-2:33:-1]*5
c = first_enc(b,arr[7:27])

for i in range(len(c)):
s.add(c[i]==arr1[i])
p = 0
for i in range(28,34):
s.add((arr[i]+107)/16+77 ==arr2[p])
s.add((arr[i]+117)%16+99==arr2[p+1])
p+=2
print s.check()
for m in get_models(s):
serial = [m[arr[i]].as_long() for i in range(39)]
key = ''
for _ in serial: key += chr(_)
print key

vm

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
def c_char(c):
assert(len(c)==1)
tmp = ord(c)
if tmp >= 128:
tmp -= 256
return tmp
def disam(code):
count=0
print hex(len(code))
while(count<len(code)):
opcode=ord(code[count])
if opcode==1:
print '%4x: input and %s'%(count,"push")
count+=1
elif opcode==2:
print '%4x: putc and %s'%(count,"pop")
count+=1
elif opcode==3:
print '%4x: nop '%(count)
count+=1
elif opcode==4:
print '%4x: %s'%(count,"push {:#x}".format(ord(code[count+1])))
count+=2
elif opcode==7:
print '%4x: %s'%(count,"push memory[{:#x}]".format(ord(code[count+1])))
count+=2
elif opcode==8:
print "%4x: %s" % (count, "pop memory[{:#x}]".format(ord(code[count+1])))
count+=2
elif opcode==6:
print "%4x: %s" % (count, "pop reg[{:#x}]".format(ord(code[count+1])))
count+=2
elif opcode==5:
print "%4x: %s" % (count, "push reg[{:#x}]".format(ord(code[count+1])))
count+=2
elif opcode==0x13:
print "%4x: %s" % (count, "if stack[top]==stack[top-1] goto {:#x} stack-2".format(count+ord(code[count+1])))
count+=2
elif opcode==0x14:
print "%4x: %s" % (count, "if stack[top]!=stack[top-1] goto {:#x} stack-2".format(count+ord(code[count+1])))
count+=2
elif opcode==0x15:
print "%4x: %s" % (count, "if stack[top]>stack[top-1] goto {:#x} stack-2".format(count+ord(code[count+1])))
count+=2
elif opcode==0x16:
print "%4x: %s" % (count, "if stack[top]<=stack[top-1] goto {:#x} stack-2".format(count+ord(code[count+1])))
count+=2
elif opcode==0x17:
print "%4x: %s" % (count, "if stack[top]<stack[top-1] goto {:#x} stack-2".format(count+ord(code[count+1])))
count+=2
elif opcode==0x18:
print "%4x: %s" % (count, "if stack[top]>=stack[top-1] goto {:#x} stack-2".format(count+ord(code[count+1])))
count+=2
elif opcode==0xa:
print "%4x: %s" % (count, "push stack[top-1]-stack[top] stack-1")
count+=1
elif opcode==0xb:
print "%4x: %s" % (count, "push stack[top]*stack[top-1] stack-1")
count+=1
elif opcode==0xc:
print "%4x: %s" % (count, "push stack[top-1]/stack[top] stack-1")
count+=1
elif opcode==0xd:
print "%4x: %s" % (count, "push stack[top-1]%stack[top] stack-1")
count+=1
elif opcode==0xe:
print "%4x: %s" % (count, "push stack[top-1]^stack[top] stack-1")
count+=1
elif opcode==0x11:
print "%4x: %s" % (count, "stack[top]=-stack[top]")
count+=1
elif opcode==9:
print "%4x: %s" % (count, "push stack[top-1]+stack[top] stack-1")
count+=1
elif opcode==0x19:
print "%4x: %s" % (count, "stack[top]= memory[stack[top]]")
count+=1
elif opcode==0x12:
print "%4x: %s" % (count, "stack[top]=~stack[top]")
count+=1
elif opcode==0xf:
print "%4x: %s" % (count, "push stack[top]&stack[top-1] stack-1")
count+=1
elif opcode==0x10:
print "%4x: %s" % (count, "push stack[top]|stack[top-1] stack-1")
count+=1
elif opcode==0x1b:
print "%4x: %s" % (count, "stack[top]=regs[stack[top]]")
count+=1
elif opcode==0x1a:
print "%4x: %s" % (count, "memory[stack[top]]=[stack[top-1]]")
count+=1
elif opcode==0x1c:
print "%4x: %s" % (count, "reg[stack[top]]=[stack[top-1]]")
count+=1
elif opcode==0x1d:
print "%4x: %s" % (count, "jmp {:#x}".format((count+c_char(code[count+1]))))
count+=2
else:
print hex(opcode)
break

with open("code", "rb") as f:
code = f.read()
disam(code)