01
Web样题---网上商城
第一步:目录扫描,发现存在git源码泄露
第二步:使用githacker下载源码
第三步:审计代码,发现上传SVG文件,存在XXE漏洞。
第四步:经进一步代码审计,可以发现文件上传后,保存路径为/concat/user_feedback/时间_文件名。
第五步:使用SVG文件格式上传文件,触发XXE漏洞,实现任意文件读取。
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg [
<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd" >]>
<svg>&xxe;</svg>
第六步:进行任意文件读取测试,取消勾选URL-Encode。
第七步:由于保存文件名只精确到秒,因此将并发数设置为1,避免条件竞争覆盖文件。
第八步:对文件内容进行分析,发现apache2.conf配置文件中存在特殊文件扩展格式可解析成php代码。
第九步:只要文件名包含.ph(ar|p|tml)-cgi就可以当做php来执行。
第十步:由于文件名黑名单过滤,仅可以使用.phar-cgi。
第十一步:根据返回时间,构造文件名220827042041_1.phar-cgi.jpg。
第十二步:拿到shell并在根路径找到flag。
02
Misc样题---小明的困惑
第一步:查看图片,用winhex打开,发现有个zip的压缩包,提取后,发现需要解压密码。
第二步:继续查看图片,发现图片高度不对,修改后,发现在图片右下角有“find_st”字符。
第三步:继续查找,发现还有lsb隐写,用zsteg,进行查看,找到“eg_information”。
第四步:将两部分拼接后“find_steg_information”,解开压缩包,得到一个flag.txt。
第五步:打开flag.txt没有发现文档中有flag,继续观察发现段落存在不一样的,有一行间隔和两行间隔。
第六步:统计每行间隔得到如下信息:
“1211112212212221121121111122111112212221112221121211212212211212”
第七步:替换“1”为“0”,“2”为“1”后,hex后得到“CnH0n9Ke”。
第八步:按照该题目提示flag格式为找到的信息内容的md5值。
03
Crypto样题---Repair
第一步:题目给了公钥和私钥,乍一看可以直接解密,但打开私钥发现,其实私钥大部分的位置都被污染了,无法使用。公钥倒是完好,可以从公钥中提出n和e,参考命令如下:
openssl rsa -in public_key.pem -pubin -modulus -text
第二步:但是仅有n、e、c是无法做题的,因为n不能直接分解,所以我们还需要看看私钥给我们留下了什么。根据资料,我们得知RSA的私钥通常以PKCS#1的模式进行存储,简单地说如下所示:
RSAPrivateKey ::= SEQUENCE {
version Version,
modulus INTEGER, -- n
publicExponent INTEGER, -- e
privateExponent INTEGER, -- d
prime1 INTEGER, -- p
prime2 INTEGER, -- q
exponent1 INTEGER, -- d mod (p-1)
exponent2 INTEGER, -- d mod (q-1)
coefficient INTEGER, -- (inverse of q) mod p
otherPrimeInfos OtherPrimeInfos OPTIONAL
第三步:将现在已经被污染的私钥base64解码后,按照上边的格式展开,得到如下内容:
308204a2020100
0282010100
(n)fffffffffffffffffffffffffffffffffffffffff7f7ffeffdfbffffffffffffffffeffffffffffffffffbffffffffeffff7fffffd6efddfffffffffffffffffffffffff2ffffffff6fffffffffffffffffdffffffffffffffffffffffffffffffffffdffffffffeffffdffdfffffffffdffefffeffffffffbffffffffffffffbfefffffdfff7ffdfffeff7ffdfdffffffffffffffff7fdffffffffffdfffffffdf6dffff7fffffdffffff7dffffbffffffeffffffbffffff7fff7ffbfbfffffffffffffffff7ffffdfffeffffffffffffffffffffffdfedffffffffff7f7df7ffffffdffbfffffffbff7ffffff7ffeffffffeefffffffffdefdffffffefffff
0202
(e)07ff
02820100
(d)3fffdffffdffffffffffbfbfffffffffffdffffbfffffffffffffffffffffff7ffffffff7ffffeffffefffafebdfffbffffffdffffffffffdffffffffffffff7ffdfffdffffffff7ffff7ffffffff7fffffffffffffffffffffff7fffdfffffffffffffffffffffeffff6ffffdf7ffffffffff7fffffffbbeeffffffdfffdfffffffffffffffbffffffdff7ffffffffdb7f7fbffffffbff7feffefffffffffffff77fdfffffffffbffffffffffffdfffffff7feffdff7ffbffffdffbffffdfffeffffffd5ffffffffeffdfffffffffffeffffffffdfffffffffffffffdff7ffffffffffff77bfffffbff7fffdffffffffffffffdfffffffffffff7feffffffdf
02818100
(p)fffffffdffbfdedffffeffffffffffdffefbdffffffbffffffffdffbff7ffffffbfffffffffffdfffffbffffffefffffffffffffffffdffffd7fbfffffffffffffffffffbffffffffdfffffffffeffffdfffffdfff7ffffffffffffffff7fffbffeffffdffffbfffefffffffffffffffffffebffdfffffffffffffffffffffff
02818100
(q)effffdf9afbffffffffffbffffffffff7ff7fffffdffffbfffffffff5efffffffffefffffffdffffefffffeffffffffffffdfffffdfffbf7fffebfffdffdfffefbfbffffffffffffffffffeffbffdffffefff7fffffdfffeffffeeffff7ffffbf7fefffffffffffffbdfffffffffffffdffffffffffdffbf7fffffffffffffff
028180
(dp)3fcf3d13d09db27c4bcf3e6c9cd7000393b23c013b572f222c438d747919b02fb190b4745bfc1e357ae00304d00508e6ab3052d110d143eca416cc9ce9e2e83bb02e9f2d0a6f0c3d27304dbe4b3effffffffffffefffffbfffff7fffffffffffff7fffffffffff87694293e5b20f7555a726f0ec8e4cfa5b5cd60dc9fbfcd079
02818100
(dq)ffdffffffffffffffffffbffdffffffffdffffdfeffeffffffffffffffffffdfffffdfffff7fffdfffffbffdfeffff7fefffffffffffffddd6efffffffffffdafbb7ffffffffffeefffffffffffffdfffffffffffffffdeffffffff7ffffffff7d7fffefffffdbfffffffffffffcfffff6f7df7effffffffffffffffffffff7f
028180
(coeff)2dfff9fff7fffffffefd7efffdffefeffff7fffffffffddffeffdfffffffffffffffbffffbfffffffffbffb7ffffffffffbffffffb7fffffdffdfffffffffffffffffeffffffffffffffff7ffffaff9ffff7fffffdfffff7ffffffffffffffffffffffffffffffffffffdffffffffffff6efdffbfffffffff7fffffffffbe7ff
第四步:可以看到,除了dp以外其他内容基本已经无法使用,dp只缺少其中的200位,因此可以尝试使用coppersmith方法去解。由于coppersmith方法需要未知变量系数为1,我们这里尝试推导一下:
由于dp <= p-1,所以k<e,coppersmith方法通过遍历1~e寻找k。现在假设k已知,那么有
第五步:构造出系数为1的同余方程,可以使用coppersmith方法解题,脚本如下:
from sage.all import *
from Crypto.Util.number import long_to_bytes
n = 0xddcf1173762e044574e63da04c2b1bacfbea68db06f5cf82ed5aeb7c4843389247c844b17dd1f39e64d0e96c6819996c8152ec73996a01dcb09fe2e734fa4935b7286e092617153fd458a4c21ab0d15d4579537bbbbae497fabf5a6f313096259ddec6d97be756ba5eef4eddfdce94c9f065e4db6cdcd0f660bf4fec19b279be03662cc304b31da4d836835c0db868c6b1bebbe10c3c69163819bbbeb9775f87e5a6854f774086486771dc40e983bde3548a447c8fad3960752836fcaf35c9d8bc9e6b8d6bc146eb9c586ece0a87b0c28e52c4f0687859cc12764f07f97f41f4cba146d46b06f68ee32b051cde2192c401708ca41ecfdfa352b9eb70ab88c4a1
e = 0x7e1
c = 21937511599879658320245010473944633925441787086897923606876234732036931509216263512735849774912874332764680814074885868221096593579769994309521779662420688416030965621074818794048969093563299478047199730115706099503699196289472943487035669305421975335593633326266487073958890132494638557837758042694553188726181931946054967736538139663513504164190622590765169647373885641456707747064760653756155807054248508047151555258302911989208736925836417322590284513984093853904173719307586288192548409151059606320079026308755374099292761095053520917571479099153696348154897607299141818107752381426356962818744112864871794394236
s1 = 0x3fcf3d13d09db27c4bcf3e6c9cd7000393b23c013b572f222c438d747919b02fb190b4745bfc1e357ae00304d00508e6ab3052d110d143eca416cc9ce9e2e83bb02e9f2d0a6f0c3d27304dbe4b3e
s2 = 0x87694293e5b20f7555a726f0ec8e4cfa5b5cd60dc9fbfcd079
invE = 19088282082615487819382474692750934693327753686845107715450035767922662190508316824413339628917969892571991893838408173397543228279801635804343053526361273689324554216799590283829867261341643996143581891161369519775596800255392601468124726255830520148240431211305299051119143348966960578911798907620083927339541056909951868528737888423601089140170994358698933479699594754041840517148422475098771787153578074734546469755065713563057579689420740989403600077544960009058169876770234872048560387334609409518229765677065232764432473280130830897935835014740520871023089211052786637551582683715573382185224000747282700481728
invpow = 5959368854985348381144147611476094163287536927984940568808008634001167843278056401585141872858458133948528655009714902012155203639867942921495219511697484265371767405000059008674319166690090809538821421018935188367195829347823399852810934549927030603827885573773432473846453673753721015355137735965518906115058199982588167836573626472294246623515294424437811803135051328469191388951319107553215694944110710837580172889491536487455698613948142340445627147090097818438060549621214596238011552756726330871615791878675680926880512423651169080845033569579587448649022534547627396297582516872579072030272820514119251502958
def coppersmith(k):
PolynomialRing(Zmod(n)) =
f = (s1 << 400) * invpow + x + s2 * invpow + (k - 1) * invE * invpow # make monic
x0 = f.small_roots(X=2 ** 200, beta=0.44, epsilon=1/32)
return x0
for k in range(1, e):
print (k)
x0 = coppersmith(k)
if len(x0) != 0:
x = Integer(x0[0])
dp = (s1 << 400) + (x << 200) + s2
p = (e*dp - 1) // k + 1
if p != -1:
q = n // p
assert n == p * q
phi = (p-1)*(q-1)
d = inverse_mod(e,phi)
print (d)
print (long_to_bytes(pow(c,d,n)))
break
第六步:invE、invpow分别是计算好的invert(e, n)和invert(2200,n),最终求出k=516,代码运行时间约15分钟。
04
Reverse样题---贪吃蛇游戏
第一步:输入以下命令,执行程序。
py -2 game.pyc
第二步:对pyc进行反编译,本地可以使用uncompyle6。
# uncompyle6 version 3.7.4
# Python bytecode 2.7 (62211)
# Decompiled from: Python 2.7.17
# [GCC 7.5.0]
import marshal, types, time
ll = types.FunctionType(marshal.loads(('YwEAAAABAAAABQAAAEMAAABzNAAAAHQAAGoBAHQCAGoDAHQEAGQBAIMBAGoFAHwAAGoGAGQCAIMBnAIMBAIMBAHQHAIMAAIMCAFMoAwAAAE50BAAAAHpsaWJ0BgAAAGJhc2U2NCgIAAAAdAUAAAB0eXBlnc3QMAAAARnVuY3Rpb25UeXBldAcAAABtYXJzaGFsdAUAAABsb2Fkc3QKAAAAX19pbXBvcnRfX3QKnAAAAZGVjb21wcmVzc3QGAAAAZGVjb2RldAcAAABnbG9iYWxzKAEAAAB0AQAAAHMoAAAAACgAAAAAncwcAAAA8c3RkaW4+dAoAAABsb2FkTGFtYmRhAQAAAHQAAAAAn').decode('base64')), globals())
i0 = ll('eJxLZoACJiB2BuJiLiBRwsCQwsjQzMgQrAES9ythA5JFiXkp+bkajCB5kKL4+Mzcgvyikvh4DZABnCKKYHUjYFJekZObZlXCA2DmJuUkpiXaMEKMZGAC+nBJhn')
i1 = ll('eJxLZoACJiB2BuJiLiBRwsCQwsjQzMgQrAES9ythA5LJpUXFqcUajCB5kKL4+Mzcgvyikvh4DZABnCKKYHUjYFJekZObZlXCA2DmJuUkpiXaMEKMZGADEORJ1n')
f0 = ll('eJxLZmRgYABhJiB2BuJiXiBRw8CQxcCQwsjQzMgQrAGS8ssEEgwaIJUl7CAiMzc1v7QEIsAMJMozn8zTASkBEMUiJTXFJSmaeXQkHiJ2TmJuUkmgHVg5SAQBjWRD5n')
f1 = ll('eJxLZmRgYIBhZyAu5gISNQwMWQwMzQwMwRogcT8wWcIKJNJTS5IzIFxmIFGemacBpBjARDE7kLApnLknJzLMr4QCxcxJzk1IS7cDKQSoAvuUPJw==n')
f2 = ll('eJx1kL1uwkAQhOfOBsxPQZUmL+DOEnWUBghEQQbFIESVglUkY5ECX+lHoMz7Jrt7HCgSOWlGO/rmn1tbtIwBBY1b9zdYYkEFlcRqiAQoWxaginDJhjcUBijNQy+O24jxgfzsHdTxOFB8DtoqPoK7HPcXnngCPFZ1BfcUGsdMA/lpc/fEqeUBq21Mp0L0rv/3grX/f5aELlbryVYzbXZnub7j42K5dcxslym7vunJby/zubrK1pMX9apPLOTraReqe9T3SlWd9ieakfl17OTb36OpFE/CDQDE5vHv7K/FKBNmA==n')
f3 = ll('eJxVj00KAjEMhV+b8Q9040IZT9C9WxHEvRvBC1iFUhhk2sUIIwgexLWn1KQzI9qSl/DlhaZHDSDjnII4tR3ix1IBVyK1GXitImt/0l1JDSSih1rAZfIZyI4x9BRIkeKA8SLeF1Dl9clIHG+c9OakdZ35OnT/o+yiciZI2Hgvpt702Pt925Nx/HFZwSGbIYqaL87FS5aKSIgi5JbZR/F1WTrkZmk4QByypE64p1nap6X4g8LaaoZ3zFGfzFVE/UBTuovhA==n')
f4 = ll('eJw1zDsKgEAMBNCJilb2drZ7AEuxsbfxBOIHFFkWNqWdF3eyYJEXkgxZcwB/jazYkkdwUeAVCAcVnW3F4MjTt7ISZyWVUS7KEsPtN7cW9e2ddLeKTIXk7gkSsSB91O/2g9uToLBELO0otH2W6Ez8=n')
f5 = ll('eJxdjr0OwjAMhM9J+as6M7HTF0AsiKV7F54ACJUKVaiSjOnEi2MbISQGf4rtu3OuMwBSBVfDFQdGnBhzwMAgNMsER1s58+wJ3Hlm4Ai/z33YGE+A1IrNljnBBtiLYT1ZSf2sr6lMt19u+ZPYQkGDJqA0jnycfap7+lBT/C2bveJ/UkEQ7KqByTGMbPKNQSpojiPMTEzqNKup2aKlnShramopJW5g2ipyUMn')
f6 = ll('eJxdjTEOglAQRB98iMbEKxhLbkBjaLSwsrHWBEUJCRKULTT5VFzc3W9nMS+zk93ZqwNS1UK1VQ17nRQ0CVcQUsTvljO4vWjEmSIRP8A4PXn3MlHKOea4DlxyzWMsOjXUHK/bpVXb1TWy855kF2gN9SPo2nDD9+At8Zdm4YZorNIFXTFTI335aPS1UWtie28QV3xx4pn')
f7 = ll('eJxtjz8LwjAQxV/S1mrRxcnZKat/qyAuOrv0E4ilIJRS2hsUCg7OfmcvubZTIe/97nKPcHkEADpdnWPWPjYCGj0Kj0fjIfHwVqiWIbzxbJ6SHEleQ1yf8ocQHFLSJqgKN+nTYVUUEGndNCiRG8UY3M7F7nabb7TrAS7AVrQSw4CDaCreBo7CfJPvdy/nZeummZuyY3bHBWh2ynmtJncXaRLLaJem6HaqGiVlMVn6Zn+Azn/L1k=n')
f8 = ll('eJwljr0KAkEMhCf3o2hrIb7BlWIhFiKC1jYWViKHe+qKnHob0GKt7sVNcsV8ZDeTSc45gJ5oINqInwkkQgTvQAvRdgwmO0BK2xxl+uTUTxBwugUtxT8EZIiHKZ4o21dZE7FLRe4yD+nMLixlchvG+0KU7nPxR6EVjhSVDoKazt86MqG6uasr5WrI3SucCNbJPEp685keIy576aqktThVs3r0kf48s8r4c9OgajnL3SnIej8MrDz9aqLXJhPzwMNaURT4R/aUC0Xn')
a1 = ll('eJxLZmRgYIBhZyAuZgESKYwMwRpMQIZfCUhcWwNIMGiAmGB+DoQPIorZgYRNcUlKZp5dCQeInZOYnm5SSaAdWDFIBALI0C1U=n')
a2 = ll('eJxLZmRgYIBhZyAuZgESKYwMwRpMQIZfCUhcWQNIMGiAmGB+DoQPIorZgYRNcUlKZp5dCQeInZOYnm5SSaAdWDFIBALBMC00=n')
a3 = ll('eJw1zjkLAkEMBeA33vetoJ3d9monWtgIgoXai5hVPFiFmU6t/OMmD4TJxySZI0cHIKUx0Fho+KsinDpKCpCEZbrKQHCQPKTAtQkqQMqQCqbJSY6XOSoOpFpuQFqSN8wAfh7cufbmDboAlX4defxt19bt1nsCkWNKFL+qBnuvI2ZfxisqUHeqMx3dMJHdMRPXlzSOf0c8mqkW1DWrnHSWQfBON539Ssiz8+r0x9nkEsy44nDyG76jDXdzv0ARDwqiQ==n')
a4 = ll('eJxLZmRgYIBhZyAuZgESKYwMwRpMQIZfCUhcRQNIMGiAmGB+DoQPIorZgYRNcUlKZp5dCQeInZOYnm5SSaAdWDFIBALCJC04=n')
a5 = ll('eJxNzTELwjAQBeCXS4r6TzKJP6DUgruLq0s1S7BKIRkqJP/dd3Hp8D4ex3H3NAA6xjEXJo2kAHeHnalAF1aI6FINg8BIsZxTZdM5lM2/95i2PXCNBPBCvzeubLOR4yvp2bX6bS3P+LyppR/qUQ/wMea99nnt6PMA26l/SKxQ/XGxkyn')
a6 = ll('eJwlzLsKwkAQheF/L0afw2qr4AOENOnT2NpEgyDGENgtFHbfPTNrcT6G4cw8DHCQeMkgiWchw81TnDMVSHMWTDdnytGTHu+Ea9G4MAkHPkxXaS9L1t/qrbtXlX1TiUehiml9rn046L9PnPk+99qJ+cewNnxxM9n')
a7 = ll('eJwlzLEKwjAQxvF/rhF9jk6Zig8gXdy7uLq0FqFYRUiGFpJ39y4O34/j+O4eDjhovOaqia2S4e4pnjiKUhuLJjiw8hex5Cbdgd0NQCHaeROnOydZbda9+q+u/aMSjcolpXj59Otm8ju9pHnvrRfvS8AMMnqhM6n')
a8 = ll('eJxLZmRgYABhJiB2BuJiPiBRw8CQwsgglsLEkM3EEKzBDBTyy2QFkplAzKABJkCaSkBEjgZcsJgdnSNgUl6Rk5tmVcIDYOYm5SSmJdmDFIBUAVDAM/Q==n')
a9 = ll('eJxLZmRgYIBhZyAuZgESKYwMwRpMQIZfCUhcQQNIMGiAmGB+DoQPIorZgYRNcUlKZp5dCQeInZOYnm5SSaAdWDFIBAK+VC0o=n')
m0 = ll('eJw1jTELwjAUhC9Jq/0VzhldBAfr4u7i6mYpFFSKCXRJp/7x3rsi5L5Avnsvrx0AS8PcmNQSGSg8nDsWjBJQKS42nxwzMQSog09b/gsrs9AGP6LjhHr3tMfSn7TpH+yebfYtJHGXH7eknTpGAkPbEJeVun+F5V/Bw1Wpl0B7cCYGsZOw==n')
m1 = ll('eJw1zUEKAjEMBdCfdMQreIRuRwU3Mhv3bjzCDAOCitCAm7rqxU1+cZGX0v408wbAvy5e5eQYUAUmnqAnNHdASvsJLhSVUBpryoPG6Km5ZfPaah/hBnXXf29jbsbdDjl0W2Tdd6IN+6JwdkLJ1zsWW+2vin/HOMRIklkJ38AF2QGOk=n')
m2 = ll('eJxNjj8LAjEMxV96fz+Fk0NHdT5c3F1cD5c7BEHlsAWXdrov7kuKICS/0LyXpFMP4JcnZrgSEUgMnQXJIDVKLtcHokAWZKvsVUm0eGjr1rC3GCplBW/03Xpy2hM5bj4sXnjh7p4cUz30pO6+fiKouxtn6ny8MehcH4MU7GtydgCB0xhDjfX8ey8mAzrYqyka18AW5IIKw=n')
def snake(w):
r = i0()
c = i1()
f0(w)
d = (0, 1)
p = [(5, 5)]
pl = 1
s = 0
l = None
while 1:
p, d, pl, l, s, w, c, r = m2(p, d, pl, l, s, w, c, r)
time.sleep(0.4)
return
i1().wrapper(snake)
第三步:可以看到反汇编后,代码进行了混淆,其中可以`ll`函数应该是用来做解包的,将其转换成pyc。
import marshal
src = marshal.loads(('YwEAAAABAAAABQAAAEMAAABzNAAAAHQAAGoBAHQCAGoDAHQEAGQBAIMBAGoFAHwAAGoGAGQCAIMBnAIMBAIMBAHQHAIMAAIMCAFMoAwAAAE50BAAAAHpsaWJ0BgAAAGJhc2U2NCgIAAAAdAUAAAB0eXBlnc3QMAAAARnVuY3Rpb25UeXBldAcAAABtYXJzaGFsdAUAAABsb2Fkc3QKAAAAX19pbXBvcnRfX3QKnAAAAZGVjb21wcmVzc3QGAAAAZGVjb2RldAcAAABnbG9iYWxzKAEAAAB0AQAAAHMoAAAAACgAAAAAncwcAAAA8c3RkaW4+dAoAAABsb2FkTGFtYmRhAQAAAHQAAAAAn').decode('base64'))
f = open("ll.pyc", "wb")
f.write(bytearray([0x03,0xf3,0x0d,0x0a,0xce,0xea,0xe5,0x61]))
marshal.dump(src, f)
f.close()
第四步:然后继续反汇编,可以看出是先base64decode再zlib解压。
return types.FunctionType(marshal.loads(__import__('zlib').decompress(s.decode('base64'))), globals())
第五步:把其他代码逐一解码,脚本如下。
import marshal
def reconstruct(s, file_name):
src = marshal.loads(__import__('zlib').decompress(s.decode('base64')))
f = open("{}.pyc".format(file_name), "wb")
f.write(bytearray([0x03,0xf3,0x0d,0x0a,0xce,0xea,0xe5,0x61]))
marshal.dump(src, f)
f.close()
第六步:最终可以在a3代码里面找到flag。
# uncompyle6 version 3.7.4
# Python bytecode 2.7 (62211)
# Decompiled from: Python 2.7.17
# [GCC 7.5.0]
f = ['C', 'n', 'H', 'o', 'n', 'g', 'K', 'e{', 'S', 'n', 'a', 'k', 'e', '_', '5', 'n', '4', 'k', '3', '_', 'f', '4', 'n', '!', '?', '}']
return f[(pl / 5 % len(f))]
05
APK样题---三位一体
第一步:用jadx打开 apk 文件,静态分析。
java 代码有混淆
assets 中有一个文件 "square.html",里面的内嵌的 javascript 代码也有混淆
java 代码有加载一个 so、有一个 native 方法 calcTriangle
第二步:根据运行界面,主要就是找 Submit 后校验的代码,由于有混淆,在 MainActivity 没有看到直接的校验逻辑,以无法混淆的关键类名为特征来寻找,界面的弹出提示 "invalid flag" 用的是 Toast,全文搜索 Toast。
第三步:顺着第一个 "invalid flag" 提示语,找到了按钮点击事件处理,分析代码,可见正则表达式是关键,既用来校验了 flag 的字符串格式,又用来提取 3 个子字符串(见 3 个 matcher.group)。提取的 3 个子串,再传给 3 个计算方法(其中一个是 calcTriangle,由运行界面可推其它两个应也是 "calc形状 命名",只是混淆了),只是这 3 个方法并没有返回值,主判断逻辑(即校验输入的 flag 是否正确)也不在这。
三个方法:mainActivity.m547n、mainActivity.calcTriangle、mainActivity.m546m
第四步:上图第 25 行从f1796c点进去,下图确认了那3个都是TextView。
第五步:全文搜索 Toast,顺着提示语 "Congratulations!!!",找到了主判断逻辑:合并 3 个 TextView 控件的字符串值,与 "jiexlivwg2bh3lfet43h645d863b61ef" 作比较。结合前面正则处,是同样的 3 个 TextView,这里是直接取值合并,那么设置值的地方就在提取子串后分别传入的那 3 个没有返回值的方法了。
第六步:结合三个方法进行三位一体,拿到flag,详解其中mainActivity.m546m方法如下:
☆分析代码,入参 str (正则中的 c段)被转换成 bytes 然后逐字节参与循环异或计算,然后又被转换进制处理,最后写入 TextView。
☆☆C0482d 是个字符串处理的工具类,m1251b 是字符串转换成字节数组。
☆☆☆算法的输入输出是对称的,所以直接将上面反编译的代码挎出来,修改几行加个 main。
public class Circle {
public static final class C0482d {
public static final char[] f1793a = "0123456789ABCDEF".toCharArray();
public static int m1250a(char c) {
if ('0' <= c && c <= '9') {
return c - '0';
}
char c2 = 'A';
if ('A' > c || c > 'F') {
c2 = 'a';
if ('a' > c || c > 'f') {
return -1;
}
}
return (c - c2) + 10;
}
public static byte[] m1251b(String str) {
int length = str.length();
if (length % 2 == 0) {
byte[] bArr = new byte[(length / 2)];
for (int i = 0; i < length; i += 2) {
int a = m1250a(str.charAt(i));
int a2 = m1250a(str.charAt(i + 1));
if (a == -1 || a2 == -1) {
StringBuilder sb = new StringBuilder();
sb.append("contains illegal character for hexBinary:");
sb.append(str);
throw new IllegalArgumentException(sb.toString());
}
bArr[i / 2] = (byte) ((a * 16) + a2);
}
return bArr;
}
StringBuilder sb2 = new StringBuilder();
sb2.append("hexBinary needs to be even-length:");
sb2.append(str);
throw new IllegalArgumentException(sb2.toString());
}
}
public static final void m546m(String str) {
try {
byte[] b = C0482d.m1251b(str);
byte[] bytes = "circle".getBytes();
for (int i = 0; i < 6; i++) {
int length = (b.length - i) - 1;
b[length] = (byte) (b[length] ^ bytes[i]);
}
// TextView textView = this.f882m.f1796c;
StringBuilder sb = new StringBuilder(b.length * 2);
for (byte b2 : b) {
char[] cArr = C0482d.f1793a;
sb.append(cArr[(b2 >> 4) & 15]);
sb.append(cArr[b2 & 15]);
}
// textView.setText(sb.toString());
System.out.println(sb.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// 645d863b61ef 即最后要比较的值
m546m("645d863b61ef");
}
}
☆☆☆☆运行得到 **0131E549088C**,最终根据正则,拼装还原flag。
原文始发于微信公众号(数字人才创研院):2023领航杯 · CTF竞赛样题与WP
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论