一、战队信息
名称:NYNUSEC战队
排名:第五名
二、解题情况
三、解题过程
注:以下所有内容为比赛题目答案及解析,不涉及其他方面,仅做解题方法分享
Web
FakeUpload1
首先随便上传一个图片上去
然后可以发现查看图片的路径是http://10.75.1.71:58002/reader.php?filename=pics/GIFINFO.jpg
可以发现是明显的读文件,所以直接读flag.php
view-source:http://10.75.1.71:58002/reader.php?filename=flag.php
得到flag
flag{ff96523b1124e8645bf4ff223b537f23}
Misc
PNGCracker3
打开压缩包就一个文件ctf.png
,打开文件提示出错了
于是丢到010 Editor
里
发现前面是png
文件,后面是zip
于是直接丢到foremost
里,分离出png和一个压缩包
png文件打开提示错误
于是尝试修复宽高
得到宽高为 1243,885
import os
import binascii
import struct
crcbp = open("ctf.png", "rb").read() #打开图片
for i in range(2000):
for j in range(2000):
data = crcbp[12:16] + \
struct.pack('>i', i)+struct.pack('>i', j)+crcbp[24:29]
crc32 = binascii.crc32(data) & 0xffffffff
if(crc32 == 0x46a4fdc1): #图片当前CRC
print(i, j)
print('hex:', hex(i), hex(j))
用010修改高度为885
得到一个password
正好拿去给压缩包当解压密码
cr4ckthisP4ssworD!@#
然后得到了
丢到Stegsolve.jar
然后发现Red
,Green
,Blue
通道存在隐写
提取出来得到flag
flag{3bfdf2004fb06399b58998e597781fca}
ZIPCracker2[三血]
打开压缩包,发现俩文件都需要密码
但是什么信息都没给,于是盲猜伪加密
用ZipCenOp.jar
直接去除伪加密
打开piazzolla.zip
摆明了要明文攻击
于是尝试用WinRar
给piazzolla.jpg
压缩
然后用ARCHPR
来明文攻击
得到解压密码:crQ2#!
打开flag.txt
得到flag
flag{310fbb0e6f812d2588689257afa6437d}
xpxp1
根据附件大小为512mb,且格式为raw格式,推断出其为内存取证题。首先利用Volatility内存取证工具对可能包含flag的文件进行搜索、分析进程、分析历史命令等信息,并根据线索按图索骥,得到以下数据。
使用cmdline
参数得到:
用grep搜一下flag
相关的文件
同理再搜一下letter
相关的文件
一共得到了egg1
,egg2
,egg3
,egg4
,egg5
,flagData.zip
,exp
,letter_PixelReplacement.png
8个文件
将文件提取出来
egg1
Do you know what the Chinese meaning of ankle is? flag is that.
Remember to convert the answer to a 32-bit lowercase MD5 value.
翻译一下
你知道脚踝的中文意思是什么吗?标志就是这样。
请记住将答案转换为 32 位小写 MD5 值。
egg2
听说对图片,有一种加密方式,叫做图像像素置换加密。置换加密算法是一种最简单的加密算法,原理就是将字母表中的字符替换成另一个字母表中的字符。那么像素置换加密是怎么样的呢。好像有一个工具集成了这个加密。但是我忘记了。据说放到邮箱草稿里面了。
egg3
egg4
你知道异或加密吗。异或是对两个运算元的一种逻辑分析类型,符号为XOR或EOR。据说在电脑某处放了部分代码,内容是对一个文件进行异或,但是有个letter不知到放到哪里了,好像是某个彩蛋吧。你能解出来吗。
egg5
According to Homer's epic, the hero Achilles is the precious son of the mortal Polus and the beautiful fairy Thetis.
It is said that her mother Tethys carried him upside down into the Styx river when he was just born, so that he could be invulnerable.
Unfortunately, due to the rapid flow of the Ming River, his mother didn't dare to let go of his heel.
The heel held by his mother was accidentally exposed outside the water, so the heel was the most vulnerable place, leaving the only "dead hole" in his body, so he buried the disaster.
When he grew up, Achilles fought bravely. When he went to attack the city of Troy (the story of Trojan horse slaughtering the city), the brave Achilles singled out the Trojan general Hector, killed him and dragged his body to demonstrate.
But later, after conquering Troy, Achilles was attacked by an arrow by Hector's brother-in-law Paris and hit his ankle - the hero fell to the ground and died at the moment of shaking.
ankle, ankle, I love ankle.The password is ??k1eAn???
翻译一下
根据荷马史诗,英雄阿喀琉斯是凡人波卢斯和美丽仙女忒提斯的宝贝儿子。
据说,在他刚出生的时候,她的母亲特提斯就将他倒挂在冥河中,这样他就可以刀枪不入了。
可惜,明河水流急促,他的母亲不敢放开他的脚后跟。
妈妈握着的脚后跟不小心暴露在了水里,所以脚后跟是最脆弱的地方,留下了他身上唯一的“死穴”,于是埋下了祸患。
长大后,阿喀琉斯勇敢地战斗。当他去攻打特洛伊城(特洛伊木马屠城的故事)时,勇敢的阿喀琉斯单挑特洛伊将军赫克托尔,将他杀死并拖着他的尸体进行示威。
但后来,在征服特洛伊后,阿喀琉斯被赫克托耳的姐夫帕里斯一箭射中脚踝——英雄倒在地上,在颤抖的瞬间死亡。
脚踝,脚踝,我爱脚踝。密码是??k1eAn???
exp
f = open('./flag.zip', 'rb').read()
new = open('./fffflllaag.dat', 'ab')
letter = ''
secret = int(letter,16)
print(secret)
for i in f:
n = int(i) ^ secret
new.write(int(n).to_bytes(1, 'big'))
letter_PixelReplacement.png
分析脚本代码,结合egg4的提示可以发现dat文件是由flag文件异或后生成的。
但是目前letter未知,根据egg2
、egg3
的像素置换15
的提示推断其使用了像素置换加密。
而替换后的文件就是letter_PixelReplacement.png
现在想要解密,就需要找到一个工具,根据egg2
所说好像有一个工具集成了这个加密。但是我忘记了。据说放到邮箱草稿里面了。
需要找到邮箱草稿
,But,找了半天并没有找到,干脆去google一下,搜了一下关键词还真找到了。
https://github.com/ffffffff0x/BerylEnigma
V2
通过工具像素置换解密得到letter='A'
于是写脚本将flag.zip
取出
f = open('./fffflllaag.dat', 'rb').read()
a = bytearray()
letter = 'A'
secret = int(letter, 16)
for i in f:
n = int(i) ^ secret
a.append(n)
print(a)
with open('flag.zip', 'wb') as f:
f.write(a)
打开压缩包后发现需要密码,根据egg5
结尾的提示
The password is ??k1eAn???
猜测规律password应该是:Ank1eAnk1e
打开压缩包得到
The answer to egg1 is : You are the only weakness in my body
This is also the answer to flag
再根据egg1
的提示,将You are the only weakness in my body
取md5后全小写就是flag
flag{47155018947fbed1987313fe2d02e0bb}
数据流中的秘密3[二血]
拿到题目,是个流量包。
打开大致看一遍,有一堆安卓相关的东东,如sdcard
、scrcpy
、手机型号等。
于是右键解析为ADB CS
,在2号数据流里面发现一个rar包,被拆成了0x10000
+0x10000
+0xb575
三个包,然后前两个包又有两个分包。
数据流前4字节是固定标识DATA
,4~8字节是小端序数据长度,8字节以后是数据。
提取五条数据流合并得到完整的rar文件,发现需要密码。
看14号数据流发现00 00 00 01 67
头,结合scrcpy
可猜测是h264
视频数据。
从文件头开始提取出文件(因为h264容错性很牛逼,所以没完全正确提取也问题不大)。打开发现是四张图片来回滚动。
拼合得到一个二维码。
用工具扫码得到一串文本695c630e-523c-4098-8ff8-0bac8f8b22d7
,用来当密码打开压缩包,发现确实是压缩包密码。
解压得到一个图片和一个几乎空的.git
索引。
图片文件尾有一段base32
。
写个脚本解码。
a = "KRUGKIDXNBSWK3BA4KAI3YUARXRIBDHCQGROFANE4KA2HYUARXRIDIXCQGROFAEN4KAI3YUARTRIDIPCQCG6FAEM4KAI3YUBUHRIBDHCQGROFANC4KAIZYUBULRIBDPCQGROFAEM4KAI3YUBULRIDIPCQCG6FAEM4KA2FYUARXRIDJHCQCG6FANB4KA2HYUARTRIDJHCQGROFAEN4KAI3YUARXRIDIXCQGROFANE4KA2JYUARXRIDJHCQGROFAEM4KA2JYUBUTRIDIPCQCG6FANB4KAI3YUBUTRIDIXCQGSOFAND4KA2DYUARXRIDJHCQCGOFAEN4KA2FYUBUHRIDIXCQCGOFANC4KAIZYUBULRIDIPCQGROFAEN4KAI3YUBUHRIBDPCQCG6FANB4KAIZYUARXRIDIXCQCG6FANB4KAI3YUARTRIDIXCQGROFANE4KAIZYUBUHRIDIXCQGROFANC4KA2HYUARTRIDIXCQCGOFANB4KAI3YUBUTRIDIPCQCGOFANB4KAIZYUBULRIDIPCQCG6FANC4KAI3YUARXRIDIXCQGROFANC4KA2FYUBUTRIDIPCQCG6FANC4KA2DYUBUPRIDJHCQCG6FAND4KAIZYUBULRIBDPCQCGOFAEN4KA2FYUARXRIBDHCQGROFANC4KAI3YUARTRIDIXCQCG6FAEM4KAI3YUARXRIDIXCQGQ6FAEN4KA2HYUBUTRIDIXCQGR6FANC4KA2FYUBUTRIDIPCQCGOFANC4KA2DYUBULRIBDPCQGROFANDOR2XE3TTFQQG433UNBUW4ZZANFZSAZLWMVZCA3TFO4XA===="
from base64 import b32decode
print(b32decode(a).decode())
得到如下文本:
The wheel turns, nothing is ever new.
其中含有不可见字符。
去看.git
索引,有个指向github.com/KuroLabs/stegcloak
的源,还有个密码just4fun
。
打开stegcloak
发现是个文本隐写工具,用上面的密码解上面的含不可见字符的文本,得到flag。
flag{487745369bbcd1e2d663b9fd136d01d0}
Crypto
NumberGame3
拿到题目,发现三组n, e, c
。
n1:12671827609071157026977398418260127577729239910356059636353714138256023623770344437013038456629652805253619484243190436122472172086809006270535958920503788271745182898308583012315393657937467583278528574109842696210193482837553369816110424840884683667932711439417044144625891738594098963618068866281205254024287936360981926173192169919836661589685119695804443529730259703940744061684219737502099455504322939948562185702662485642366411258841082322583213825076942399375712892608077960687636100621655314604756871227708407963698548718981737143081639214928707030543449473132959887760171345393471397998907576088643495456531
e1:65537
c1:5268497051283009363591890965286255308367378505062739645805302950184343652292967525985407935922935972883557494557593439711003227737116083417992112594428400382187113609935251268634230537282408994938066541612999550555591607744019286392765549844400176442415480559773688439693874264657925123598756193286897112566420847480601040372338338442932524410598834393630019038536173336696498743879160879377504894526001205060753543289059104874467150194596404490638065573974570258671195173327475871936431769234701590572816592485898568463143587137721883610069616008902637316459660001435171054741347142470208082183171637233299493273737
n2:18090800828995898324812976370950614944724424095669490324214928162454640462382724191043785592350299626782376411935499259428970532102686361824967300649916495702138825182857737210486173137998811993244590794690070307872074705348982970060304389842338043432383690934814892283936018142382990267868341375956549210694354065317328612440672169232803362481090661368782599819926970968509827001203936933692777821117679448168400620234261164018167404541446201828349880887526076468982840569645753428057937172715073817332736878737709704495317549386111938639861221307607948775421897063976457107356574428602380790814162110473018856344871
e2:4097
c2:2326267610355516153575986453727161366266816656017644910981028690283132055217271939475840618294311986463011398892570340626131158223217558335139831985973737748812636360601010312490160903427322848411507157238373313053959092326875136396134997877757316339153327290508806645882428114647041522287934007579220769189583249469879165078254248922442084985860374461188259818592181294686890335242981199427715392978546977718475462727987012437677290341463732660152302257234030751774759466703002189003437204934438026047163828083902584763527752033035438078609950665211243112982373167722458975172667665849715372158378299319548194854914
n3:14016899139767071357961567514373780608355222973882916699129907806456201886114368147540489514960479836424236595826190295819765979835270500889626994048655508134450908075698567925938340322498944878806273261377551132596295484579752118097281084614987064680928168918147910522922020462762688924459558896249968804885885853885632349539590507675397376494346489972596290270168847103345561743327300964196811506510943971437325302822974593782292850499524055338033832053610217461760698628614971171144300450574522839157187874548994036357212297166759231255765155759405207408315314182166142015547345744054533749334516820850300569790673
e3:1048577
c3:1507157402302225700443994264641838312753363380677759942918832857396550216927941389943122383728949792984913155517202501504817319345830153748955731880333992875210194306712098593166605310784068299411946792264365247471197716329666415403718297430110977954951479772565341847358286252098930408452594561104228639615640815799731581302607522977457874347224189202268831547055389518214072278766864028489294466057175201908756749666131546163372443691718757198229262989973810951064160488114367967684657242385568733678188829354802025582496625272334309487028498614869964712744826603931510547381997149345221530469380732265014466170524
尝试gcd
一下几个n
,发现n1
和n2
,n2
和n3
有公约数,所以那肯定三个n
的p
就能出来了,然后反推q
就能正常解rsa了。
n1=12671827609071157026977398418260127577729239910356059636353714138256023623770344437013038456629652805253619484243190436122472172086809006270535958920503788271745182898308583012315393657937467583278528574109842696210193482837553369816110424840884683667932711439417044144625891738594098963618068866281205254024287936360981926173192169919836661589685119695804443529730259703940744061684219737502099455504322939948562185702662485642366411258841082322583213825076942399375712892608077960687636100621655314604756871227708407963698548718981737143081639214928707030543449473132959887760171345393471397998907576088643495456531
e1=65537
c1=5268497051283009363591890965286255308367378505062739645805302950184343652292967525985407935922935972883557494557593439711003227737116083417992112594428400382187113609935251268634230537282408994938066541612999550555591607744019286392765549844400176442415480559773688439693874264657925123598756193286897112566420847480601040372338338442932524410598834393630019038536173336696498743879160879377504894526001205060753543289059104874467150194596404490638065573974570258671195173327475871936431769234701590572816592485898568463143587137721883610069616008902637316459660001435171054741347142470208082183171637233299493273737
n2=18090800828995898324812976370950614944724424095669490324214928162454640462382724191043785592350299626782376411935499259428970532102686361824967300649916495702138825182857737210486173137998811993244590794690070307872074705348982970060304389842338043432383690934814892283936018142382990267868341375956549210694354065317328612440672169232803362481090661368782599819926970968509827001203936933692777821117679448168400620234261164018167404541446201828349880887526076468982840569645753428057937172715073817332736878737709704495317549386111938639861221307607948775421897063976457107356574428602380790814162110473018856344871
e2=4097
c2=2326267610355516153575986453727161366266816656017644910981028690283132055217271939475840618294311986463011398892570340626131158223217558335139831985973737748812636360601010312490160903427322848411507157238373313053959092326875136396134997877757316339153327290508806645882428114647041522287934007579220769189583249469879165078254248922442084985860374461188259818592181294686890335242981199427715392978546977718475462727987012437677290341463732660152302257234030751774759466703002189003437204934438026047163828083902584763527752033035438078609950665211243112982373167722458975172667665849715372158378299319548194854914
n3=14016899139767071357961567514373780608355222973882916699129907806456201886114368147540489514960479836424236595826190295819765979835270500889626994048655508134450908075698567925938340322498944878806273261377551132596295484579752118097281084614987064680928168918147910522922020462762688924459558896249968804885885853885632349539590507675397376494346489972596290270168847103345561743327300964196811506510943971437325302822974593782292850499524055338033832053610217461760698628614971171144300450574522839157187874548994036357212297166759231255765155759405207408315314182166142015547345744054533749334516820850300569790673
e3=1048577
c3=1507157402302225700443994264641838312753363380677759942918832857396550216927941389943122383728949792984913155517202501504817319345830153748955731880333992875210194306712098593166605310784068299411946792264365247471197716329666415403718297430110977954951479772565341847358286252098930408452594561104228639615640815799731581302607522977457874347224189202268831547055389518214072278766864028489294466057175201908756749666131546163372443691718757198229262989973810951064160488114367967684657242385568733678188829354802025582496625272334309487028498614869964712744826603931510547381997149345221530469380732265014466170524
from gmpy2 import gcd, invert, powmod
from Crypto.Util.number import long_to_bytes
p = gcd(n1, n2)
# print p
q = n1 / p
# print q
phi = (p - 1) * (q - 1)
d = invert(e1, phi)
print long_to_bytes(powmod(c1, d, n1))
q = n2 / p
phi = (p - 1) * (q - 1)
d = invert(e2, phi)
print long_to_bytes(powmod(c2, d, n2))
p = gcd(n2, n3)
# print p
q = n3 / p
phi = (p - 1) * (q - 1)
d = invert(e3, phi)
print long_to_bytes(powmod(c3, d, n3))
# flag{fb72574404901f5a37f88431b42b4872}
flag{fb72574404901f5a37f88431b42b4872}
Reverse
crackme2_apk1
jadx
打开,很容易看出调用链check -> encode
,check
判断flag长度和头尾,然后encode
后和目标数组比较就完事。
然后看encode
函数,是个按字节加密的,没有前后影响的情况,那就直接每字节爆破就完事。
package com.example.hooktest.hook
import com.highcapable.yukihookapi.YukiHookAPI
import com.highcapable.yukihookapi.annotation.xposed.InjectYukiHookWithXposed
import com.highcapable.yukihookapi.hook.log.loggerI
import com.highcapable.yukihookapi.hook.xposed.proxy.IYukiHookXposedInit
@InjectYukiHookWithXposed
class Main : IYukiHookXposedInit {
override fun onHook() = YukiHookAPI.encase {
loadApp("com.example.CrackMe2") {
"$packageName.MainActivity".hook {
injectMember {
method {
name = "onCreate"
}
afterHook {
val target = charArrayOf(
'\u00cd',
'R',
't',
'z',
30.toChar(),
'\b',
'\b',
'\u00e0',
'W',
';',
24.toChar(),
'\u0099',
'\u00af',
'=',
29.toChar(),
'\u0094',
21.toChar(),
'%',
'g',
'[',
'd',
'S',
31.toChar(),
';',
'\u00dc',
'\u00a2',
'F',
'6',
'\u00d3',
'\u00fd',
'\u00be',
'3'
)
val encode = method {
name="encode"
}.get(instance)
var flag = byteArrayOf(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
var i = 0
while (i < 32) {
val rst = (encode.call(String(flag), "happygame") as String).toCharArray()
if (rst[i] == target[i]) {
loggerI(msg = flag[i].toString())
i++
continue
} else {
flag[i] = (flag[i] + 1).toByte()
}
}
loggerI(msg = String(flag))
}
}
}
}
}
}
flag{2fd3d38b20b7bae1f6ed0d70a7df345e}
meikyu2[一血]
打开题目的main.py
,看着感觉像是读取地图然后输入线路走迷宫的题。
其中地图标识分别有START, END, WALL, ROAD
,尝试读取地图,发现大小是10201
,所以应该是101*101
的图。
with open('data', 'rb') as f:
data = f.read()
map_ = list(data)
cipher = list(b'suta-to')
print(len(map_)) # 101 * 101
尝试按101*101
输出,可以猜测START=83, END=69, WALL=35, ROAD=32
。
with open('data', 'rb') as f:
data = f.read()
map_ = list(data)
cipher = list(b'suta-to')
print(len(map_)) # 101 * 101
for i, ch in enumerate(map_):
if i % 101 == 0:
print()
map_[i] = ch ^ cipher[i % len(cipher)]
print(map_[i], end=' ')
print()
# # START 83, END 69, WALL 35, ROAD 32
那就写个dfs去搜路径就完事。
def dfs(x, y, lx, ly):
if map_[x * 101 + y] == 69:
return True, ""
if x + 1 < 101 and map_[(x + 1) * 101 + y] != 35 and x + 1 != lx:
rst, road = dfs(x+1, y, x, y)
if rst:
return True, "下"+road
if x - 1 >= 0 and map_[(x - 1) * 101 + y] != 35 and x - 1 != lx:
rst, road = dfs(x-1, y, x, y)
if rst:
return True, "上"+road
if y + 1 < 101 and map_[x * 101 + y + 1] != 35 and y + 1 != ly:
rst, road = dfs(x, y+1, x, y)
if rst:
return True, "右"+road
if y - 1 >= 0 and map_[x * 101 + y - 1] != 35 and y - 1 != ly:
rst, road = dfs(x, y-1, x, y)
if rst:
return True, "左"+road
return False, ""
with open('data', 'rb') as f:
data = f.read()
map_ = list(data)
cipher = list(b'suta-to')
print(len(map_)) # 101 * 101
for i, ch in enumerate(map_):
if i % 101 == 0:
print()
map_[i] = ch ^ cipher[i % len(cipher)]
print(map_[i], end=' ')
print()
# # START 83, END 69, WALL 35, ROAD 32
print(dfs(1, 0, 0, 0))
然后现在就是路径格式应该是长啥样的问题了,先去看了下mylib.pyd
文件,看了好久没找到什么头绪,后来在util.dll
里面的run_decoded_map_0
函数发现了解析路径的逻辑。
那就把上面的路径用wsad
替换一下,然后md5
一波(main.py
文件里面有写flag格式)交一下看看,结果真就是flag。
from hashlib import md5
def dfs(x, y, lx, ly):
if map_[x * 101 + y] == 69:
return True, ""
if x + 1 < 101 and map_[(x + 1) * 101 + y] != 35 and x + 1 != lx:
rst, road = dfs(x+1, y, x, y)
if rst:
return True, "s"+road
if x - 1 >= 0 and map_[(x - 1) * 101 + y] != 35 and x - 1 != lx:
rst, road = dfs(x-1, y, x, y)
if rst:
return True, "w"+road
if y + 1 < 101 and map_[x * 101 + y + 1] != 35 and y + 1 != ly:
rst, road = dfs(x, y+1, x, y)
if rst:
return True, "d"+road
if y - 1 >= 0 and map_[x * 101 + y - 1] != 35 and y - 1 != ly:
rst, road = dfs(x, y-1, x, y)
if rst:
return True, "a"+road
return False, ""
with open('data', 'rb') as f:
data = f.read()
map_ = list(data)
cipher = list(b'suta-to')
print(len(map_)) # 101 * 101
for i, ch in enumerate(map_):
if i % 101 == 0:
print()
map_[i] = ch ^ cipher[i % len(cipher)]
print(map_[i], end=' ')
print()
# # START 83, END 69, WALL 35, ROAD 32
print(dfs(1, 0, 0, 0))
print(f"flag{{{md5(dfs(1, 0, 0, 0)[1].encode()).hexdigest()}}}")
flag{3f48672b213770d9de5c3d50369840a3}