复现一下2021CISCN

rsa

题目:

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
from flag import text,flag
import md5
from Crypto.Util.number import long_to_bytes,bytes_to_long,getPrime

assert md5.new(text).hexdigest() == flag[6:-1]

msg1 = text[:xx]
msg2 = text[xx:yy]
msg3 = text[yy:]

msg1 = bytes_to_long(msg1)
msg2 = bytes_to_long(msg2)
msg3 = bytes_to_long(msg3)

p1 = getPrime(512)
q1 = getPrime(512)
N1 = p1*q1
e1 = 3
print pow(msg1,e1,N1)


print (e1,N1)

p2 = getPrime(512)
q2 = getPrime(512)
N2 = p2*q2
e2 = 17
e3 = 65537
print pow(msg2,e2,N2)
print pow(msg2,e3,N2)
print (e2,N2)
print (e3,N2)

p3 = getPrime(512)
q3 = getPrime(512)
N3 = p3*q3
print pow(msg3,e3,N3)
print (e3,N3)
print p3>>200

给出的out文件

1
2
3
4
5
6
7
8
9
19105765285510667553313898813498220212421177527647187802549913914263968945493144633390670605116251064550364704789358830072133349108808799075021540479815182657667763617178044110939458834654922540704196330451979349353031578518479199454480458137984734402248011464467312753683234543319955893
(3, 123814470394550598363280518848914546938137731026777975885846733672494493975703069760053867471836249473290828799962586855892685902902050630018312939010564945676699712246249820341712155938398068732866646422826619477180434858148938235662092482058999079105450136181685141895955574548671667320167741641072330259009L)
54995751387258798791895413216172284653407054079765769704170763023830130981480272943338445245689293729308200574217959018462512790523622252479258419498858307898118907076773470253533344877959508766285730509067829684427375759345623701605997067135659404296663877453758701010726561824951602615501078818914410959610
91290935267458356541959327381220067466104890455391103989639822855753797805354139741959957951983943146108552762756444475545250343766798220348240377590112854890482375744876016191773471853704014735936608436210153669829454288199838827646402742554134017280213707222338496271289894681312606239512924842845268366950
(17, 111381961169589927896512557754289420474877632607334685306667977794938824018345795836303161492076539375959731633270626091498843936401996648820451019811592594528673182109109991384472979198906744569181673282663323892346854520052840694924830064546269187849702880332522636682366270177489467478933966884097824069977L)
(65537, 111381961169589927896512557754289420474877632607334685306667977794938824018345795836303161492076539375959731633270626091498843936401996648820451019811592594528673182109109991384472979198906744569181673282663323892346854520052840694924830064546269187849702880332522636682366270177489467478933966884097824069977L)
59213696442373765895948702611659756779813897653022080905635545636905434038306468935283962686059037461940227618715695875589055593696352594630107082714757036815875497138523738695066811985036315624927897081153190329636864005133757096991035607918106529151451834369442313673849563635248465014289409374291381429646
(65537, 113432930155033263769270712825121761080813952100666693606866355917116416984149165507231925180593860836255402950358327422447359200689537217528547623691586008952619063846801829802637448874451228957635707553980210685985215887107300416969549087293746310593988908287181025770739538992559714587375763131132963783147L)
7117286695925472918001071846973900342640107770214858928188419765628151478620236042882657992902

首先是msg1,低加密指数攻击,给c开三次方就可以解出来了,但是谨慎一点,还是使用循环爆破来解比较稳妥。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from gmpy2 import iroot
from Crypto.Util import number
n = 123814470394550598363280518848914546938137731026777975885846733672494493975703069760053867471836249473290828799962586855892685902902050630018312939010564945676699712246249820341712155938398068732866646422826619477180434858148938235662092482058999079105450136181685141895955574548671667320167741641072330259009
c = 19105765285510667553313898813498220212421177527647187802549913914263968945493144633390670605116251064550364704789358830072133349108808799075021540479815182657667763617178044110939458834654922540704196330451979349353031578518479199454480458137984734402248011464467312753683234543319955893

e = 0x3
k = 0
while 1:
res=iroot(c+k*n,e)
if(res[1]==True):
print(number.long_to_bytes(res[0]))
break
k=k+1
# b' \nO wild West Wind, thou breath of Autum'

然后是msg2,共模攻击

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

#扩展欧几里得算法
def exgcd(m, n, x, y):
if n == 0:
x = 1
y = 0
return (m, x, y)
a1 = b = 1
a = b1 = 0
c = m
d = n
q = int(c / d)
r = c % d
while r:
c = d
d = r
t = a1
a1 = a
a = t - q * a
t = b1
b1 = b
b = t - q * b
q = int(c / d)
r = c % d
x = a
y = b
return (d, x, y)

c1=54995751387258798791895413216172284653407054079765769704170763023830130981480272943338445245689293729308200574217959018462512790523622252479258419498858307898118907076773470253533344877959508766285730509067829684427375759345623701605997067135659404296663877453758701010726561824951602615501078818914410959610
c2=91290935267458356541959327381220067466104890455391103989639822855753797805354139741959957951983943146108552762756444475545250343766798220348240377590112854890482375744876016191773471853704014735936608436210153669829454288199838827646402742554134017280213707222338496271289894681312606239512924842845268366950
e1 = 17
e2 = 65537
n=111381961169589927896512557754289420474877632607334685306667977794938824018345795836303161492076539375959731633270626091498843936401996648820451019811592594528673182109109991384472979198906744569181673282663323892346854520052840694924830064546269187849702880332522636682366270177489467478933966884097824069977
ans=exgcd(e1,e2,0,0)
s1=ans[1]
s2=ans[2]

#powmod()函数,分数取模也可以直接算
m=(gmpy2.powmod(c1,s1,n)*gmpy2.powmod(c2,s2,n))%n
print(long_to_bytes(m))
# b"n's being,\nThou, from whose unseen presence the leaves dead\nAre driven, like ghosts from an enchanter fleeing,\nYellow, a"

最后一个倒是挺迷惑人的,给出了错误的方向,右移200位,再左移的话,和不告诉我们没有区别……

然后,我找到了这首诗:

不知道msg3的范围,字符串循环爆破即可。

1
2
3
4
5
6
7
8
9
10
11
12
e = 65537
n = 113432930155033263769270712825121761080813952100666693606866355917116416984149165507231925180593860836255402950358327422447359200689537217528547623691586008952619063846801829802637448874451228957635707553980210685985215887107300416969549087293746310593988908287181025770739538992559714587375763131132963783147
c = 59213696442373765895948702611659756779813897653022080905635545636905434038306468935283962686059037461940227618715695875589055593696352594630107082714757036815875497138523738695066811985036315624927897081153190329636864005133757096991035607918106529151451834369442313673849563635248465014289409374291381429646

string = b"nd black, and pale, and hectic red,\nPestilence-stricken multitudes: O thou,\nWho chariotest to their dark wintry bed\n\nThe winged seeds, where they lie cold and low,\nEach like a corpse within its grave, until\nThine azure sister of the Spring shall blow\n\nHer clarion o'er the dreaming earth, and fill\n(Driving sweet buds like flocks to feed in air)\nWith living hues and odours plain and hill:\n\nWild Spirit, which art moving everywhere;\nDestroyer and preserver; hear, oh hear!"
for i in range(len(string)):
fake_m = bytes_to_long(string[:i])
fake_c = pow(fake_m,e,n)
if fake_c == c:
print(string[:i])
break
# b'nd black, and pale, and hectic red,\nPestilence-stricken multitudes: O thou,\nWho chariotest to their dark wintry bed\n'

python3的生成md5代码:

1
2
3
4
5
6
7
8
9
10
11
import hashlib
msg1 = b' \nO wild West Wind, thou breath of Autum'
msg2 = b"n's being,\nThou, from whose unseen presence the leaves dead\nAre driven, like ghosts from an enchanter fleeing,\nYellow, a"
msg3 = b'nd black, and pale, and hectic red,\nPestilence-stricken multitudes: O thou,\nWho chariotest to their dark wintry bed\n'
text = msg1+msg2+msg3
print(text)

crypto = hashlib.md5()
flag = crypto.hexdigest()
print(flag)
# d41d8cd98f00b204e9800998ecf8427e

python2的生成md5代码:

1
2
3
4
5
import md5
text = b" \nO wild West Wind, thou breath of Autumn's being,\nThou, from whose unseen presence the leaves dead\nAre driven, like ghosts from an enchanter fleeing,\nYellow, and black, and pale, and hectic red,\nPestilence-stricken multitudes: O thou,\nWho chariotest to their dark wintry bed\n"
flag = md5.new(text).hexdigest()
print(flag)
# 3943e8843a19149497956901e5d98639

如果比赛就一个一个的试……

glass

先用jeb查看一下,直接查看没有发现任何加密函数,有点懵,然后发现上面有一个.lib文件

用jd-gui可以查看有一个so文件,

直接解压.apk文件,然后在lib-> armeabi-v7a -> 处找到.so文件,用ida32就能查看这个checkflag函数

可以发现是RC4加密,可以查看我之前的一个博客,还有当时参考的大佬的一篇文章

sub_FFC函数是RC4加密的准备工作,数组S的置换以及生成密钥流

在经历了标准的RC4加密后,经过了第二个加密函数,39作为二参传入加密函数

其中有两个for循环,第二个for循环根据xor的特性,照搬不动即可

第一个for循环,可以转换成以下的代码:

1
2
3
data[i] = data[i] ^ data[i+2]
data[i+2] = data[i+2] ^ data[i+1]
data[i+1] = data[i+1] ^ data[i]

最终结果是要与unk_497C数组做对比

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
#include <stdio.h>
#include <stdlib.h>

void rc4_init(unsigned char*s,unsigned char*key,unsigned long len)
{
int i=0;
int j=0;
unsigned char k[256]={};
unsigned char temp = 0;
for(i=0;i<256;i++)
{
s[i]=i; //0-255赋给s
k[i]=key[i%len]; //将k重新计算
}
for(i=0;i<256;i++)
{
j=(j+s[i]+k[i])%256; //给j赋值
temp=s[i];
s[i]=s[j];
s[j]=temp; //s[i]和s[j]交换
}
}

void rc4_crypt(unsigned char*s,unsigned char*data,unsigned long len)
{
int i=0,j=0,t=0;
unsigned long k=0;
unsigned char temp;
for(k=0;k<len;k++)
{
i=(i+1)%256; //固定方式生成的i
j=(j+s[i])%256; //固定方式生成的j
temp=s[i];
s[i]=s[j];
s[j]=temp; //交换s[i]和s[j]
t=(s[i]+s[j])%256; //固定方式生成的t
data[k]^=s[t]; //来作为s的下标和data进行异或运算
}
}

int main()
{
unsigned char s[256]={0};
int i=0,j=0;
char key[256] = "12345678";
unsigned char data[512]={0xA3, 0x1A, 0xE3, 0x69, 0x2F, 0xBB, 0x1A, 0x84, 0x65, 0xC2, 0xAD, 0xAD, 0x9E, 0x96, 0x05, 0x02,0x1F, 0x8E, 0x36, 0x4F, 0xE1, 0xEB, 0xAF, 0xF0, 0xEA, 0xC4, 0xA8, 0x2D, 0x42, 0xC7, 0x6E, 0x3F,0xB0, 0xD3, 0xCC, 0x78, 0xF9, 0x98, 0x3F, 0x00};

unsigned long data_len = 39;
unsigned long key_len = 8;
for(i=0;i<39;i+=key_len)
{
for (j = 0; (key_len & ~(key_len >> 31)) != j && i + j < 39; ++j)
{
data[i+j] = data[i+j] ^ key[j];
}
}
for(i=0;i<data_len;i+=3)
{
//向右循环回去
data[i+1] = data[i] ^ data[i+1];
data[i+2] = data[i+1] ^ data[i+2];
data[i] = data[i+2] ^ data[i];
}
rc4_init(s,(unsigned char*)key,key_len);//初始化得到s
rc4_crypt(s,(unsigned char*)data,data_len);//解密
for(i=0;i<39;i++)
{
printf("%c",data[i]);
}
return 0;
}
//CISCN{6654d84617f627c88846c172e0f4d46c}

脚本来源