HITCON2017 writeup

Reverse

Sakura

一个大函数、稍微IDA里标一下函数名然后grep出来调用顺序到文件,然后把栈上那些变量按顺序填入d = dict()然后直接z3

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
import z3
x = [z3.BitVec(i, 16) for i in range(400)]
s = z3.Solver()
'''
pEnd = get_end_pointer_2rp((__int64)&v904);
if ( sum != 17 )
'''
l = open('haha','r').read().split(')\n')
for token in l:
if 'rp(' not in token: break
print token
pos = token.index('rp(')
cparameter = int(token[pos-1:pos],10)
pos = token.index('&v')+1
print token[pos+2:token.index(';')-2]
oparameter = int(token[pos+1:token.index(';')-1],10)
pos = token.index('!= ')
final = int(token[pos+3:],10)
flag = 0
sum = 0
for i in range(cparameter):
p = d[oparameter+i*2]*20+d[oparameter+i*2+1]
s.add(x[p]>0)
s.add(x[p]<=9)
s.add((flag>>x[p])&1!=1)
flag |= 1<<x[p]
sum+=x[p]
s.add(sum==final)
print s.check()
if s.check() == z3.sat:
m = s.model()
print m
flag = map(lambda sym: m[sym], x)
print flag

跑出来

1
[None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, 9, 2, None, None, None, None, 4, 1, None, None, None, None, 9, 1, None, 1, 7, None, 3, 7, 8, 1, 9, 2, None, None, 6, 3, 8, None, 4, 6, 8, 3, None, 2, 9, 6, 1, 8, None, None, 8, 1, None, 7, 1, None, 9, 8, 3, 7, None, None, None, None, 8, 9, None, 9, 2, None, None, None, None, 9, 3, 6, None, 9, 1, 5, None, None, None, None, None, 8, 1, None, 1, 2, None, None, None, 8, 2, 1, 6, None, 2, 8, 4, 3, None, None, None, None, 3, 1, None, 1, 2, None, None, None, None, 4, 9, 8, None, 9, 3, 1, None, 3, 7, None, None, 2, 9, 3, 4, 1, None, None, None, 3, 7, 9, 2, None, 6, 2, None, 1, 9, 2, 8, 3, 7, None, 1, 2, None, 7, 1, 2, 8, None, 1, 7, 2, None, None, None, None, 1, 9, None, None, None, None, None, None, 9, 2, None, None, None, None, 9, 1, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, 1, 4, None, 6, 5, None, None, None, 2, 7, 1, None, 4, 9, None, None, None, None, 4, 1, 8, 3, 5, 7, 9, 2, None, None, 8, 9, 6, 4, 1, 2, 7, 5, None, 1, 2, 5, None, 1, 3, None, 7, 3, None, 9, 1, None, None, 5, 3, None, 3, 7, None, 7, 6, None, 7, 2, None, 8, 6, None, None, 8, 6, None, None, None, 2, 6, None, None, None, None, 9, 4, 8, None, 5, 1, 2, None, None, None, 5, 3, None, None, None, 3, 6, None, None, None, 5, 7, None, 1, 8, None, 8, 6, None, None, None, 5, 2, None, None, None, 5, 1, None, 4, 8, None, 4, 9, None, 5, 3, 8, None, 8, 5, None, 6, 9, None, None, 8, 5, None, 1, 7, 8, 6, 3, 2, 9, 4, None, None, 7, 3, 6, 1, 5, 2, 8, 4, None, None, None, 3, 1, None, 7, 4, None, None, None, None, None, None, 3, 5, None, 1, 2, 3, None]

然后"".join(['0' if x==None else str(x) for x in a])
得到答案0000000000000000000000000092000041000091017037819200638046830296180081071098370000890920000936091500000810120008216028430000310120000498093103700293410003792062019283701207128017200001900000092000091000000000000000000000000014065000271049000041835792008964127501250130730910053037076072086008600026000094805120005300036000570180860005200051048049053808506900850178632940073615284000310740000003501230

Seccomp

bpf reverse
首先用工具把汇编导出来,然后观察了一阵发现一共有几个pattern,写一个脚本让流程看的更清楚一点

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
import struct
def parse():
s = open('dis.txt', 'rb').read()
s = s.replace('\r', '').split('\n')
o = []
for i in s:
t = i.split('\t')[1].split(' ')
o.append(map(lambda x: x.replace(',', ''), t))
return o

def run(ins):
def is_match(src,seq):
seq_c = 0
for k in range(len(seq)):
if src[k][0] == seq[k]:
seq_c +=1
if seq_c==len(seq):
return True,[src[0][1],src[-1][1]]
return False,[]
def opd(s):
if s.startswith('[') and s.endswith(']'):
i = int(s[1:-1])
if i == 0:
return 0x1337
return x[(i - 16) / 4]
elif s.startswith('#'):
t = s[1:]
if t.startswith('0x'):
return int(t, 16)
else:
return int(t, 10)
elif s.startswith('M[') and s.endswith(']'):
return M[int(s[2:-1])]
elif s == 'x':
return X
else:
print s
raise Exception('wtf')
def p16(a):
return struct.pack(">H",a)
idx = 17
key = []
while idx < len(ins):
i = ins[idx]
op = i[0]
if op == 'ld':
seq = ['ld','jeq','ld','mul','tax','div','mul','neg','add','jeq','ld','st']
res = is_match(ins[idx:idx+len(seq)],seq)
if res[0]:
#print "%s = %s * %d %% 0x10001"%(res[1][1],res[1][0],opd(ins[idx+3][1]))
key.append(struct.pack(">H",opd(ins[idx+3][1])))
idx+=len(seq)
continue
seq = ['ld','add','and','st']
res = is_match(ins[idx:idx+len(seq)],seq)
if res[0]:
#print "%s = (%s + %d) & 0xffff"%(res[1][1],res[1][0],opd(ins[idx+1][1]))
key.append(struct.pack(">H",opd(ins[idx+1][1])))
idx+=len(seq)
continue
seq = ['ld','ldx','xor','st']
res = is_match(ins[idx:idx+len(seq)],seq)
if res[0]:
#print "%s = %s ^ %s"%(res[1][1],res[1][0],ins[idx+1][1])
idx+=len(seq)
continue
seq = ['ld','ldx','add','and','st']
res = is_match(ins[idx:idx+len(seq)],seq)
if res[0]:
#print "%s = (%s + %s) & 0xffff"%(res[1][1],res[1][0],ins[idx+1][1])
idx+=len(seq)
continue
seq = ['ld','ldx','stx','st']
res = is_match(ins[idx:idx+len(seq)],seq)
if res[0]:
#print "swap(%s,%s)"%(res[1][1],res[1][0])
idx+=len(seq)
continue
print idx,"error"
exit()
elif op=='ldx':
enc = p16(opd(ins[idx][1])^opd(ins[idx+3+12][1]))+p16(opd(ins[idx][1])^opd(ins[idx+3+8][1]))+p16(opd(ins[idx][1])^opd(ins[idx+3+4][1]))+p16(opd(ins[idx][1])^opd(ins[idx+3][1]))
print "d = '%s'.decode('hex')"%enc.encode('hex')
idx+=31
print 'key = "%s"'%"".join(key)[:16]
print "cipher = IDEA.new(key,IDEA.MODE_ECB,)\na.append(cipher.decrypt(d)[::-1])"
key = []
continue
print ins[idx]
print "error"
exit()
ins = parse()
run(ins)

会发现输入是4个word输出4个word,然后8轮这样的算法,确定是IDEA,改一下上面的脚本输出解密代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
M[0] = M[0] * 26465 % 0x10001
M[1] = (M[1] + 27750) & 0xffff
M[2] = (M[2] + 24421) & 0xffff
M[3] = M[3] * 27489 % 0x10001
M[4] = M[0] ^ M[2]
M[5] = M[1] ^ M[3]
M[4] = M[4] * 26207 % 0x10001
M[5] = (M[4] + M[5]) & 0xffff
M[5] = M[5] * 24927 % 0x10001
M[4] = (M[4] + M[5]) & 0xffff
M[0] = M[0] ^ M[5]
M[1] = M[1] ^ M[4]
M[2] = M[2] ^ M[5]
M[3] = M[3] ^ M[4]
swap(M[2],M[1])

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
from CryptoPlus.Cipher import IDEA
a = []
d = 'bda9a256044419b0'.decode('hex')
key = "galf_ekaf_a_ma_I"
cipher = IDEA.new(key,IDEA.MODE_ECB,)
a.append(cipher.decrypt(d)[::-1])
d = '888c2d1a2d5580cd'.decode('hex')
key = "ver_yr7_n0_emoC_"
cipher = IDEA.new(key,IDEA.MODE_ECB,)
a.append(cipher.decrypt(d)[::-1])
d = 'a0a7aab80005558d'.decode('hex')
key = "nikxxf_siht_esre"
cipher = IDEA.new(key,IDEA.MODE_ECB,)
a.append(cipher.decrypt(d)[::-1])
d = 'dff79b5d009e1498'.decode('hex')
key = "!selur_pmocces_g"
cipher = IDEA.new(key,IDEA.MODE_ECB,)
a.append(cipher.decrypt(d)[::-1])
d = '8fd875f0c7ef4e09'.decode('hex')
key = "galf_ekaf_a_ma_I"
cipher = IDEA.new(key,IDEA.MODE_ECB,)
a.append(cipher.decrypt(d)[::-1])
print "hitcon{%s}"%"".join(a)

hitcon{w0w_y0u_are_Master-0F-secc0mp///>_w_<///

家徒四壁~Everlasting Imaginative Void~

debug

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
0x000000e719e62000 0x000000e719e63000 r-xp	/tmp/void-1b63cbab5d58da4294c2f97d6b60f568
0x000000e71a062000 0x000000e71a063000 r--p /tmp/void-1b63cbab5d58da4294c2f97d6b60f568
0x000000e71a063000 0x000000e71a064000 rw-p /tmp/void-1b63cbab5d58da4294c2f97d6b60f568

=> 0xe719e62935: call 0xe719e62284
0xe719e6293a: push 0xa
0xe719e6293c: pop rax
0xe719e6293d: push rdi


=> 0xe719e62284: pop rdi
0xe719e62285: mov al,BYTE PTR [rdi+0x200715]
0xe719e6228b: cmp al,0x21
0xe719e6228d: jne 0xe719e62297

!

RAX: 0xe71a062e48 --> 0x1c
RBX: 0x7f52f7cb1168 --> 0xe719e62000 --> 0x10102464c457f
RCX: 0x4
RDX: 0x1
RSI: 0x0
RDI: 0x7f52f7cb0948 --> 0x0
RBP: 0x7ffe684992c0 --> 0x7f52f7a845f8 --> 0x7f52f7a85c40 --> 0x0
RSP: 0x7ffe684991f0 --> 0xe719e6293a --> 0x3aef816657580a6a
RIP: 0xe719e62284 --> 0x3c00200715878a5f
R8 : 0x4
R9 : 0x3
R10: 0x7ffe68499218 --> 0x7f52f7cb09d8 --> 0x7f52f7a8a000 --> 0x10102464c457f
R11: 0x3
R12: 0xe71a062dd0 --> 0xe719e626b0 (cmp BYTE PTR [rip+0x200969],0x0 # 0xe71a063020)
R13: 0x1
R14: 0x7ffe68499200 --> 0x7f52f7cb1168 --> 0xe719e62000 --> 0x10102464c457f
R15: 0x0
EFLAGS: 0x202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
=> 0xe719e62284: pop rdi
0xe719e62285: mov al,BYTE PTR [rdi+0x200715]
0xe719e6228b: cmp al,0x21
0xe719e6228d: jne 0xe719e62297
[------------------------------------stack-------------------------------------]
0000| 0x7ffe684991f0 --> 0xe719e6293a --> 0x3aef816657580a6a


sys_mprotect(0xe719e62000,0x1000)
RSI: 0x1000
RDI: 0xe719e62000 --> 0x10102464c457f




0xe719e62284: pop rdi
0xe719e62285: mov al,BYTE PTR [rdi+0x200715]
0xe719e6228b: cmp al,0x21
0xe719e6228d: jne 0xe719e62297
0xe719e6228f: call rdi
0xe719e62291: add rdi,0x15
0xe719e62295: jmp rdi
0xe719e62297: ret

.eh_frame:000000000000094F xor ecx, ecx
.eh_frame:0000000000000951 add di, 0FEF9h
.eh_frame:0000000000000956 push rdi
.eh_frame:0000000000000957 push rdi
.eh_frame:0000000000000958 pop rsi
.eh_frame:0000000000000959 pop rbx
.eh_frame:000000000000095A
.eh_frame:000000000000095A loc_95A: ; CODE XREF: .eh_frame:0000000000000965j
.eh_frame:000000000000095A mov cl, [rsi]
.eh_frame:000000000000095C test cl, cl
.eh_frame:000000000000095E js short loc_967
.eh_frame:0000000000000960 inc rsi
.eh_frame:0000000000000963 rep movsb
.eh_frame:0000000000000965 jmp short loc_95A
.eh_frame:0000000000000967 ; ---------------------------------------------------------------------------
.eh_frame:0000000000000967
.eh_frame:0000000000000967 loc_967: ; CODE XREF: .eh_frame:000000000000095Ej
.eh_frame:0000000000000967 add bx, 17h
.eh_frame:000000000000096B jmp rbx

0xe719e6285f: mov rsi,rbx
0xe719e62862: sub si,0xc7
0xe719e62867: add rbx,0x2007e1
0xe719e6286e: movdqu xmm1,XMMWORD PTR [rbx];input
0xe719e62872: movdqu xmm0,XMMWORD PTR [rsi];0xfffe07e803fdc148 0xdb312074ed8548ff
0xe719e62876: pxor xmm1,xmm0
0xe719e6287a: push 0xa
0xe719e6287c: pop rdi
0xe719e6287d: add rsi,0x10
0xe719e62881: movdqu xmm0,XMMWORD PTR [rsi]
0xe719e62885: dec edi
0xe719e62887: test edi,edi
0xe719e62889: je 0xe719e62894
0xe719e6288b: js 0xe719e6289b negative
=> 0xe719e6288d: aesenc xmm1,xmm0
0xe719e62892: jmp 0xe719e6287d
0xe719e62894: aesenclast xmm1,xmm0
0xe719e62899: jmp 0xe719e6287d
0xe719e6289b: ucomisd xmm0,xmm1
0xe719e6289f: je 0xe719e628a2
0xe719e628a1: ret


_mm_aesenclast_si128
_mm_aesenc_si128


aesenc xmm1,xmm0 0x10 times
aesenclast xmm1,xmm0
cmp xmm0,xmm1

0xe719e628a2: neg edi
0xe719e628a4: push rdi
0xe719e628a5: pop rax
0xe719e628a6: add rsi,0x10
0xe719e628aa: call 0xe719e62948

0xe719e62948: push 0x7
0xe719e6294a: pop rdx
0xe719e6294b: syscall
0xe719e6294d: pop rdi
0xe719e6294e: ret

gdb-peda$ x/10gx $rsi
0xe719e62798: 0xfffe07e803fdc148,0xdb312074ed8548ff ; init

0xe719e627a8: 0x0000000000841f0f,0x8944f6894cea894c
0xe719e627b8: 0xc38348dc14ff41ff,0x8348ea75dd394801
0xe719e627c8: 0x5d415c415d5b08c4,0x2e6690c35f415e41
0xe719e627d8: 0x0000000000841f0f,0x08ec83480000c3f3
0xe719e627e8: 0x000000c308c48348,0x6800732500020001
0xe719e627f8: 0x73257b6e6f637469,0x3b031b0100000a7d
0xe719e62808: 0x0000000700000040,0x0000008cfffffdbc
0xe719e62818: 0x000000b4fffffdcc,0x0000005cfffffdec
0xe719e62828: 0x000000ccffffff1c,0x000000ecffffff57
0xe719e62838: 0x0000010cffffff6c,0x00000154ffffffdc
0xe719e62848: 0x47cf6d49120447e7,0x2846fb67171be9b0 ; final

hex(0xe719e6285f-0x000000e719e62000)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>
#include <string.h>
#include <tmmintrin.h>
#include <wmmintrin.h>

int main () {
__int64_t a[2] = {0,0};
__int64_t round_key[] = {0xfffe07e803fdc148,0xdb312074ed8548ff,0x0000000000841f0f,0x8944f6894cea894c,0xc38348dc14ff41ff,0x8348ea75dd394801,0x5d415c415d5b08c4,0x2e6690c35f415e41,0x0000000000841f0f,0x08ec83480000c3f3,0x000000c308c48348,0x6800732500020001,0x73257b6e6f637469,0x3b031b0100000a7d,0x0000000700000040,0x0000008cfffffdbc,0x000000b4fffffdcc,0x0000005cfffffdec,0x000000ccffffff1c,0x000000ecffffff57};
__int64_t final[] = {0x47cf6d49120447e7^0x0000010cffffff6c,0x2846fb67171be9b0^0x00000154ffffffdc};
__m128i mfinal = _mm_load_si128((__m128i *)final);
for (int i=0;i<9;i++)
{
__int64_t* b = &round_key[(9-i)*2];
__m128i key = _mm_load_si128((__m128i *)b);
printf("Round key %d: %016llx %016llx\n",9-i,b[0],b[1]);
mfinal = _mm_aesdec_si128(mfinal,_mm_aesimc_si128(key));
}
__m128i key = _mm_load_si128((__m128i *)&round_key);
mfinal = _mm_aesdeclast_si128(mfinal,(key));
_mm_storeu_si128(a, mfinal);
printf("%llx %llx",a[0],a[1]);
return 0;
}

天衣無縫~Fantastic Seamless Textile~

https://gist.github.com/pzread/2ae0bb3aa5fe0dc69fcf3257c41db944
https://github.com/radare/radare2/pull/8796