Skip to content

2024年全国大学生信息安全竞赛安徽省赛 # WriteUp

作者:乔不思

CRYPTO1 RSAROLL

下载得到文件

{920139713,19}
704796792
752211152
274704164
18414022
368270835
483295235
。。。。

1.文件的第一行

很可能是公钥(n,e),

其中n:920139713, e = 19。

2.接下来的数字列表应该是加密后的密文

要解决这个问题

1.因子分解n以获得p和q

2.计算欧拉函数p(n)=(p-1)(q-1)

3.计算私钥d=e^(-1)modp(n)4.对每个密文c进行解密:m=c^dmodn5.将解密后的数字转换为字符

python
from Crypto.Util.number import inverse, long_to_bytes

def factorize(n):
    for i in range(2, int(n**0.5) + 1):
        if n % i == 0:
            return i, n // i
    return None

n = 920139713
e = 19

p, q = factorize(n)
phi = (p - 1) * (q - 1)
d = inverse(e, phi)

ciphertext = [  704796792, 752211152, 274704164, 18414022, 368270835, 483295235, 263072905, 459788476, 483295235, 459788476, 663551792, 475206804, 459788476, 428313374, 475206804, 459788476, 425392137, 704796792, 458265677, 341524652, 483295235, 534149509, 425392137, 428313374, 425392137, 341524652, 458265677, 263072905, 483295235, 828509797, 341524652, 425392137, 475206804, 428313374, 483295235, 475206804, 459788476, 306220148] 

plaintext = ""
for c in ciphertext:
    m = pow(c, d, n)
    plaintext += long_to_bytes(m).decode('ascii', errors='ignore')

print(plaintext)

得到flag

CRYPTO2 RSA_GCD

下载附件,解压得到两个txt文件

这两个文件attach1.txt和attach2.txt

包含了两组RSA加密的数据:

1.两个文件都包含公钥(n,e)和密文c

2.两个文件使用了相同的公钥指数e=65537

3.两个文件的模数n是不同的:attach1.txt的n=23220619839642624...attach2.txt 的 n =22642739016943309...

4.密文c也是不同的。

这种情况下,我们可以尝试使用最大公约数(GCD)攻击来破解RSA。这种攻击方法适用于两个不同的RSA公钥共享一个质因子的情况。

攻击步骤如下:

1.计算两个模数n1和n2的最大公约数。

2.如果GCD(n1,n2)不等于1,那么我们找到了一个共同的质因子 p。

3.使用 p 来分解 n1 和 n2,得到另一个质因子 q。

4.有了p和q,我们就可以计算出私钥 d。

5.使用私钥d来解密密文c。

python
import math

def gcd(a, b):
    while b:
        a, b = b, a % b
    return a

def main():
    n1 = 23220619839642624127208804329329079289273497927351564011985292026254914394833691542552890810511751239656361686073628273309390314881604580204429708461587512500636158161303419916259271078173864800267063540526943181173708108324471815782985626723198144643256432774984884880698594364583949485749575467318173034467846143380574145455195152793742611717169602237969286580028662721065495380192815175057945420182742366791661416822623915523868590710387635935179876275147056396018527260488459333051132720558953142984038635223793992651637708150494964785475065404568844039983381403909341302098773533325080910057845573898984314246089
    n2 = 22642739016943309717184794898017950186520467348317322177556419830195164079827782890660385734113396507640392461790899249329899658620250506845740531699023854206947331021605746078358967885852989786535093914459120629747240179425838485974008209140597947135295304382318570454491064938082423309363452665886141604328435366646426917928023608108470382196753292656828513681562077468846105122812084765257799070754405638149508107463233633350462138751758913036373169668828888213323429656344812014480962916088695910177763839393954730732312224100718431146133548897031060554005592930347226526561939922660855047026581292571487960929911
    e = 65537
    c1 = 9700614748413503291260966231863562117502096284616216707445276355274869086619796527618473213422509996843430296526594113572675840559345077344419098900818709577642324900405582499683604786981144099878021784567540654040833912063141709913653416394888766281465200682852378794478801329251224801006820925858507273130504236563822120838520746270280731121442839412258397191963036040553539697846535038841541209050503061001070909725806574230090246041891486506980939294245537252610944799573920844235221096956391095716111629998594075762507345430945523492775915790828078000453705320783486744734994213028476446922815870053311973844961
    c2 = 20513108670823938405207629835395350087127287494963553421797351726233221750526355985253069487753150978011340115173042210284965521215128799369083065796356395285905154260709263197195828765397189267866348946188652752076472172155755940282615212228370367042435203584159326078238921502151083768908742480756781277358357734545694917591921150127540286087770229112383605858821811640935475859936319249757754722093551370392083736485637225052738864742947137890363135709796410008845576985297696922681043649916650599349320818901512835007050425460872675857974069927846620905981374869166202896905600343223640296138423898703137236463508 

    p = gcd(n1, n2)
    if p > 1:
        q1 = n1 // p
        q2 = n2 // p

        phi1 = (p - 1) * (q1 - 1)
        phi2 = (p - 1) * (q2 - 1)
        d1 = pow(e, -1, phi1)
        d2 = pow(e, -1, phi2)
        

        m1 = pow(c1, d1, n1)
        m2 = pow(c2, d2, n2)
        
        print("解密后的消息1:", m1)
        print("解密后的消息2:", m2)
        
        # 将 m1 和 m2 转换为字符串
        try:
            message1 = bytes.fromhex(hex(m1)[2:]).decode('utf-8')
            message2 = bytes.fromhex(hex(m2)[2:]).decode('utf-8')
            print("解密后的文本消息1:", message1)
            print("解密后的文本消息2:", message2)
        except:
            print("...")
    else:
        print("...")




if __name__ == "__main__":
    main()

得到结果

解密后的消息1: 584734024210053001694699533881960229862347256375
解密后的消息2: 6121411568964967526691207501160753713595005
解密后的文本消息1: flag{336BB5172ADE227
解密后的文本消息2: FE68BAA44FDA73F3B}

拼接得到完整flag

CRYPTO3 easycrypt

下载附件得到提图片

image-20240928193131547

php加密函数,

加密函数的步骤如下:

1.反转输入字符串

2.对每个字符的ASCII码加1

3.将结果进行base64编码

4.再次反转字符串

5.应用ROT13加密

改成python如下

python
import base64

def decode(s):
    # 1. 解除ROT13加密
    def rot13(text):
        return ''.join([chr((ord(c) - 97 + 13) % 26 + 97) if c.isalpha() and c.islower() else 
                        chr((ord(c) - 65 + 13) % 26 + 65) if c.isalpha() and c.isupper() else c
                        for c in text])
    
    o = rot13(s)
    

    o = o[::-1]
    

    o = base64.b64decode(o).decode('utf-8')

    result = ''.join([chr(ord(c) - 1) for c in o])

    return result[::-1]

encrypted = "a1zLbgQsCESEIqRLwuQAyMwLyq2L5VwBxqGA3RQAyumZ0tmMvSGM2ZwB4tws"
decrypted = decode(encrypted)
print(decrypted)

得到flag

flag:

# MISC1 Forgeten password

hint 内存取证题

windows上安装[volatility3]

获取内存镜像的基本信息

img

根据hint小明总是喜欢password记录下来,用editbox显示出有关编辑控件的信息,得到密码password*&!@wxcq12

img

用密码直接交不对,那么应该是压缩包之类的密码了 查找压缩包并导出

img

editbox得到的密码解压压缩包拿到flag

MISC2 你是黑客吗

image-20240928192016415

下载下来是一个压缩包,需要密码,根据题目描述,密码可能是100-1000 之间的素数数量

写出py代码

python
def is_prime(n):
    if n < 2:
        return False
    for i in range(2, int(n**0.5) + 1):
        if n % i == 0:
            return False
    return True

primes = [num for num in range(101, 1000) if is_prime(num)]

print("100到1000之间的所有质数:")
print(primes)
print(f"总共有 {len(primes)} 个质数")

得到 143

尝试之后不行

想 可能是 所有素数之和

添加代码

python
# 计算质数的和
prime_sum = sum(primes)
print(f"这些质数的和为: {prime_sum}")

得到结果

一张图片

使用hxd打开查看源代码,发现其中存在base64字符串,于是复制字符串使用base64编码得到一张二维码,扫码得到flag

image-20240928201444418

Reverse2 NSCTF Rverse 400

下载得到Revesre03.exe,排查发现是一个pyinstaller打包的程序

⽤到了 PyInstaller Extractor 这个⼯具, 下载来后直接 执⾏ python pyinstxtractor.py Revesre03.exe 可以得到源⽂件。

打 开 Revesre03.exe_extracted/Revesre03 就能够得到源代码了

image-20240928195142630

这是⼀段 Python 代码并嵌⼊了⼀段 C 的注释,

buf ⾥的 flag 并不是真正的 flag。

将 C 语⾔提取出来编译运⾏发现 encode 之后的 buf 和上⾯的 data 很像,尤其 是⾸尾是完全⼀样的,既然 encode(buf) ≈ data ,

那么 decode(data) ≈ buf ,所以猜测对 data 进⾏逆向解码就是真正的 flag。

python
data = \
"\x1c\x7a\x16\x77\x10\x2a\x51\x1f\x4c\x0f\x5b\x1d\x42\x2f
\x4b\x7e\x4a\x7a\x4a\x7b" +\
"\x49\x7f\x4a\x7f\x1e\x78\x4c\x75\x10\x28\x18\x2b\x48\x7e
\x46\x23\x12\x24\x11\x72" +\
"\x4b\x2e\x1b\x7e\x4f\x2b\x12\x76\x0b"
flag = ""
for i in range(len(data)-1):
 flag += chr(ord(data[i]) ^ ord(data[i+1]))
print flag

Reverse3 Crackme

使用IDA打开

image-20240928201640574

可以确认判断条件位于if语句中,决定是否调用MessageBoxA输出正确提示。接下来分析sub_401630函数:

image-20240928201703308

函数主体部分首先使用srand生成随机数,然后令v4=rand[0]%10,再将v2和v3对应的某一位数值进行比对。

srand函数是随机数发生器的初始化函数,与rand()配合使用产生伪随机数序列。rand()函数通过系统给定的种子生成随机序列,而srand()可以改变种子值。

对于本题的逻辑,由于初始以10作为种子,rand[0]为0x47(71);以1作为种子,rand[0]为0x29(41),模10后都令v4=1,所以v4的值不会变化,始终为1。

确定v4后,判断逻辑变得清晰:a2的每一个值与v3+96的第n*10+1个值进行比对。

向上查找,发现:

image-20240928201833206

这里有一个strcpy函数,将内存中的一串字符串赋值到v2+96。进一步分析可知,此处的v2+96就是v3+96。因此,只需将这个字符串每隔十个字符取出(直到取到320为止),就可以得到最终的flag

python
s = ";f1K3{c5:efl21t4;1t1zaxpim9}5+?gtux;=vc9v{v7+buhU{bT=-am2q}=fh[xk{y?xrqe{?}l5-sd2-Mo+:j{9=sY[dalvpx?z3{?no{[k5ll{zjsu5[kfla+r6Zg72o0skq6cGl5cw[=d?3v9q5-vkjSv{4sqtg=f0cz{+jurjfl[tb]lrfF1;2}udhb?0g8{om:T4dh;z:oz-Dn=m=ux;o[gs9{+zqx+sq-dsxctcvykUs2oddrt43pwv:f0;njkrb9los6g0{ih?rqantfx$sslqd:rvqixr;j{?o:sn+[i[yA11;gsmr8lm0?3};+iv+Tf:4Gtv2:-20upi0]7?77=;qzx{m-W;0vtueh]ko8d?=w:fbhd{E:;19?p=k:b+}doht6wpEq-z]2qbV1}dh416qw9:xm[;ed;:ecb-0:ni-s4u2kf6]2wn45amzjrun=ofkx-=hmgo-lz;j909=rmo7xcj4le0hxs[i]-vjl[?o12:sv4upio7ma1hRy7556+57krev:hLQ+1cx65z5v5];6n=[p83;n={zm{k2p"
flag=''
for i in range(len(s)//10):
    flag+=s[i*10+1]
    if(i*10==320):
        break
print(flag)

比赛成绩 b47e52c9-3039-489e-a8d7-31b6ede59991

个人省排25,还算不错了