CISCN 2020 初赛部分题解

就说自己做出来的。

Misc 电脑被黑

菜狗不小心删除了一些数据,您能帮他找到丢失的数据吗?

取证题。给了一个Linux EXT磁盘映像。特别巧,我电脑上装了个DiskGenius。直接拉进去恢复。找到了一个flag.txt。恢复出来,用记事本打开是乱码。里面有一个程序Demo。

IDA逆向F5一下,发现是对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
int __cdecl main(int argc, const char **argv, const char **envp)
{
  char c; // ST26_1
  char v6; // [rsp+27h] [rbp-19h]
  FILE *fw; // [rsp+28h] [rbp-18h]
  FILE *fr; // [rsp+30h] [rbp-10h]
  char v5; // [rsp+3Eh] [rbp-2h]
  char v4; // [rsp+3Fh] [rbp-1h]

  _main();
  fr = fopen("flag.txt", "rb");
  fw = fopen("dec.txt", "rb+");
  v4 = 34;
  for ( v5 = 0; ; v5 = (v5 + 2) & 0xF )
  {
    v6 = fgetc(fr);
    if ( v6 == -1 )
      break;
    c = (v4 ^ v6) - v5;
    printf("%c", (unsigned int)c);
    fputc(c, fw);
    v4 += 34;
  }
  fclose(fr);
  fclose(fw);
  return 0;
}

异或改回去即可得Flag。
代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<cstdio>
using namespace std;
int main(){
    FILE* fr=fopen("flag.txt","rb");
    FILE* fw=fopen("dec.txt","rb+");
    char v4=34,v5=0;
    while(1){
        char v6=fgetc(fr);
        if(v6==-1)break;
        char c=(v6^v4)-v5;
        printf("%c",c);
        fputc(c,fw);
        v4+=34;
        v5=(v5+2)&0xf;
    }
    fclose(fr);
    fclose(fw);
}

Crypto bd

数学在密码学里面很重要的!现在知道吃亏了吧!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from secret import flag
from Crypto.Util.number import *

m = bytes_to_long(flag)

p = getPrime(512)
q = getPrime(512)
N = p * q
phi = (p-1) * (q-1)
while True:
    d = getRandomNBitInteger(200)
    if GCD(d, phi) == 1:
        e = inverse(d, phi)
        break

c = pow(m, e, N)

print(c, e, N, sep='\n')

# 37625098109081701774571613785279343908814425141123915351527903477451570893536663171806089364574293449414561630485312247061686191366669404389142347972565020570877175992098033759403318443705791866939363061966538210758611679849037990315161035649389943256526167843576617469134413191950908582922902210791377220066
# 46867417013414476511855705167486515292101865210840925173161828985833867821644239088991107524584028941183216735115986313719966458608881689802377181633111389920813814350964315420422257050287517851213109465823444767895817372377616723406116946259672358254060231210263961445286931270444042869857616609048537240249
# 86966590627372918010571457840724456774194080910694231109811773050866217415975647358784246153710824794652840306389428729923771431340699346354646708396564203957270393882105042714920060055401541794748437242707186192941546185666953574082803056612193004258064074902605834799171191314001030749992715155125694272289

参考https://ctf-wiki.github.io/ctf-wiki/crypto/asymmetric/rsa/rsa_d_attack-zh/。
在 d 比较小($d<\frac{1}{3}N^{\frac{1}{4}}$)时,攻击者可以使用 Wiener's Attack 来获得私钥。 直接把脚本拉过来跑d。得d=1485313191830359055093545745451584299495272920840463008756233。 再n,e,d跑p,q。参考https://err0rzz.github.io/2017/11/14/CTF%E4%B8%ADRSA%E5%A5%97%E8%B7%AF/

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
import random  
 
def gcd(a, b):  
   if a < b:  
     a, b = b, a  
   while b != 0:  
     temp = a % b  
     a = b  
     b = temp  
   return a  
 
def getpq(n,e,d):  
    p = 1  
    q = 1  
    while p==1 and q==1:  
        k = d * e - 1  
        g = random.randint ( 0 , n )  
        while p==1 and q==1 and k % 2 == 0:  
            k /= 2  
            y = pow(g,k,n)  
            if y!=1 and gcd(y-1,n)>1:  
                p = gcd(y-1,n)  
                q = n/p  
    return p,q  
 
def main():  
 
    n = 86966590627372918010571457840724456774194080910694231109811773050866217415975647358784246153710824794652840306389428729923771431340699346354646708396564203957270393882105042714920060055401541794748437242707186192941546185666953574082803056612193004258064074902605834799171191314001030749992715155125694272289
    e = 46867417013414476511855705167486515292101865210840925173161828985833867821644239088991107524584028941183216735115986313719966458608881689802377181633111389920813814350964315420422257050287517851213109465823444767895817372377616723406116946259672358254060231210263961445286931270444042869857616609048537240249
    d = 1485313191830359055093545745451584299495272920840463008756233
    p,q = getpq(n,e,d)  
    print "p: "+str(p)
    print "q: "+str(q)
 
if __name__ == '__main__':  
    main()

最后跑明文。参考https://xz.aliyun.com/t/6459

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import binascii
import gmpy2
n=86966590627372918010571457840724456774194080910694231109811773050866217415975647358784246153710824794652840306389428729923771431340699346354646708396564203957270393882105042714920060055401541794748437242707186192941546185666953574082803056612193004258064074902605834799171191314001030749992715155125694272289
p=7854850701841988188661901463022799285216997125881448777534908110883806494299965162678132451275942969907800531217872020483098944139172026712063940511717257
q=11071705106626529257369300808350271388196407564419199111627001501149570364651837364794751508113141729956372125544279571695229382891671575778315012542095577
e=46867417013414476511855705167486515292101865210840925173161828985833867821644239088991107524584028941183216735115986313719966458608881689802377181633111389920813814350964315420422257050287517851213109465823444767895817372377616723406116946259672358254060231210263961445286931270444042869857616609048537240249
c=37625098109081701774571613785279343908814425141123915351527903477451570893536663171806089364574293449414561630485312247061686191366669404389142347972565020570877175992098033759403318443705791866939363061966538210758611679849037990315161035649389943256526167843576617469134413191950908582922902210791377220066


phi=(p-1)*(q-1)
d=gmpy2.invert(e,phi)
m=pow(c,d,n)
print(hex(m))
print(binascii.unhexlify(hex(m)[2:].strip("L")))

得flag。

CISCN 2020 初赛部分题解》有3个想法

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注