[NewStarCTF 2023]PZthon
本文最后更新于 171 天前,其中的信息可能已经过时,如有错误可以直接在文章下留言

这一题,是 Reverse 方向的,很像广州大学第三届方班预备班 X 网安学会 CTF 新生赛 Reverse 里面的一题,后面再复盘那一题

用 IDA 打开给的 PZthon.exe 文件,没什么关键函数,直接 shift + F12 看 Strings Window,发现字符串数据非常多,没什么特别的字符串,要说特别的就下面这几个

为什么说像广州大学新生赛的那一题,像就像在这里,当时做那一题时这也有图里面的这两种字符串,星期、月份还有 26 个大小写字母都出现了,当时作为小白啥也不懂,以为是关键数据,这困惑了我很久。好吧,现在也是小白,图中的这些字符串我现在也不明白为啥会出现。这题反正也是没思路,因为广州大学新生赛那一题我也还没搞懂呢。直接看 Writeup

NewStarCTF 2023 Week2 官方 WriteUp(转载)-CSDN 博客

Writeup 说如图这些是 Python 的痕迹,考点也就是 py 打包成的 exe,其实题目的标题也有提示了。学习了一下,是指将 python 的.py 源代码文件打包成.exe 可执行文件,作用呢是可以使我们的程序在没有安装 Python 解释器的环境中运行。需要依靠类似 PyInstaller 等工具。

第一次接触这种类型的题目,所以啥也不会也正常吧。

所以按照 Writeup,我们要做的,就是依据.exe 文件获得它的 python 源代码吧,毕竟 flag 的线索大概率在源代码里,利用到解包工具 pyinstxtractor,又是第一次接触,不过安装使用都不难,Writeup 里面给了下载链接,直接解包

在同级目录下可以找到 PZthon.exe_extracted 文件夹,在里面找到 PZthon.pyc,该文件就是 python 文件的字节码文件。

那什么又是.pyc 文件呢?

python 运行经过了两步操作:

  • 将源代码编译成为 “字节码”
  • 转发 “字节码” 到 “虚拟机”

可以理解为翻译,把 print(hello world) 翻译成字节码,字节码会保存在后缀名是.pyc 的文件里,这文件其实就是编译后的.py 源代码。

这些字节码相较于源代码,运行起来速度要快得多。为什么?

  • pyc 文件是由.py 文件经过编译后生成的字节码文件在下一次运行程序时,如果在上次保存了字节码之后没有修改过源代码了,Python 就会加载.pyc 文件并且跳过编译这个步骤,就省去了编译的过程,节省了时间。其加载速度就相对于之前的.py 文件有所提高,而且还可以实现源码隐藏,以及一定程度上的反编译。因此,不同版本的 python 可能运行不了同一个.pyc 文件。

在这里又牵扯到 “字节码” 和 “虚拟机” 两个概念,就不多扩展先。这两个概念其实 Java 语言里面也是有的,而且 Java 也有类似.pyc 的字节码文件.class,后面是会遇到 Java 的反编译题目的

所以.pyc 文件确实是可以反编译回 python 的源代码的,我们直接用 pycdc 反编译,得到如下代码

def hello():
art = '\n ___ \n // ) ) / / // ) ) // | | / / // | | \\ / / \\ / / \n //___/ / / / // //__| | / / //__| | \\ / \\ / / \n / ____ / / / // ____ / ___ | / / / ___ | / / \\/ / \n // / / // / / // | | / / // | | / /\\ / / \n// / /___ ((____/ / // | | / /____/ / // | | / / \\ / / \n \n / / // / / || / / // / / / / /__ ___/ || / | / / // ) ) \n / / //____ || / / //____ / / / / || / | / / // / / \n / / / ____ || / / / ____ / / / / || / /||/ / // / / \n / / // ||/ / // / / / / ||/ / | / // / / \n / /____/ / //____/ / | / //____/ / / /____/ / / / | / | / ((___/ / \n'
print(art)
return bytearray(input('Please give me the flag: ').encode())
enc = [
115,
121,
116,
114,
110,
76,
37,
96,
88,
116,
113,
112,
36,
97,
65,
125,
103,
37,
96,
114,
125,
65,
39,
112,
70,
112,
118,
37,
123,
113,
69,
79,
82,
84,
89,
84,
77,
76,
36,
112,
99,
112,
36,
65,
39,
116,
97,
36,
102,
86,
37,
37,
36,
104]
data = hello()
for i in range(len(data)):
data[i] = data[i] ^ 21
if bytearray(enc) == data:
print('WOW!!')
else:
print('I believe you can do it!')
input('To be continue...')

我一开始写的脚本是这样的,但是一直报错,’ord () expected string of length 1, but int found‘,但是我打印了一次 date,发现 date 里面也没数字啊

enc = [0x73, 0x79, 0x74, 0x72, 0x6e, 0x4c, 0x25, 0x60, 0x58, 0x74, 0x71, 0x70, 0x24, 0x61, 0x41, 0x7d, 0x67, 0x25, 0x60,
0x72, 0x7d, 0x41, 0x27, 0x70, 0x46, 0x70, 0x76, 0x25, 0x7b, 0x71, 0x45, 0x4f, 0x52, 0x54, 0x59, 0x54, 0x4d, 0x4c,
0x24, 0x70, 0x63, 0x70, 0x24, 0x41, 0x27, 0x74, 0x61, 0x24, 0x66, 0x56, 0x25, 0x25, 0x24, 0x68]
date=bytearray(enc)
#在这里print(date)的话结果是bytearray(b"sytrnL%`Xtqp$aA}g%`r}A\'pFpv%{qEORTYTML$pcp$A\'ta$fV%%$h")
for i in range(len(enc)):
date[i]=chr(ord(date[i])^21)
print(date)

后面问了学校的大佬,才又又又学到了小知识,像这种 bytes,bytearray,long_to_bytes 的函数,最终输出来的字节串,里面的数据都是以 int 的形式存储的,但是输出出来会以 b”some string” 的形式显现出来,我觉得可以用以下 python 代码来解释就可以明白了

enc = [0x73, 0x79, 0x74, 0x72, 0x6e, 0x4c, 0x25, 0x60, 0x58, 0x74, 0x71, 0x70, 0x24, 0x61, 0x41, 0x7d, 0x67, 0x25, 0x60,
0x72, 0x7d, 0x41, 0x27, 0x70, 0x46, 0x70, 0x76, 0x25, 0x7b, 0x71, 0x45, 0x4f, 0x52, 0x54, 0x59, 0x54, 0x4d, 0x4c,
0x24, 0x70, 0x63, 0x70, 0x24, 0x41, 0x27, 0x74, 0x61, 0x24, 0x66, 0x56, 0x25, 0x25, 0x24, 0x68]
date=bytearray(enc)
print(date)
#输出结果为 bytearray(b"sytrnL%`Xtqp$aA}g%`r}A\'pFpv%{qEORTYTML$pcp$A\'ta$fV%%$h")
print(date[0])
#输出结果为数字115
date[0]=65
print(date)
#输出结果为 bytearray(b"AytrnL%`Xtqp$aA}g%`r}A\'pFpv%{qEORTYTML$pcp$A\'ta$fV%%$h")

这里看明明输出是 b”sytrnL%`Xtqp$aA} g%`r} A\’pFpv%{qEORTYTML$pcp$A\’ta$fV%%$h”,但是打印出来 date [0] 却是 115,也就是字母 s 在 Ascii 码表中对应的值,把它直接改为 A 在 Ascii 码表中对应的值 65,就显现出 A 了。

所以改进脚本如下

enc = [0x73, 0x79, 0x74, 0x72, 0x6e, 0x4c, 0x25, 0x60, 0x58, 0x74, 0x71, 0x70, 0x24, 0x61, 0x41, 0x7d, 0x67, 0x25, 0x60,
0x72, 0x7d, 0x41, 0x27, 0x70, 0x46, 0x70, 0x76, 0x25, 0x7b, 0x71, 0x45, 0x4f, 0x52, 0x54, 0x59, 0x54, 0x4d, 0x4c,0x24, 0x70, 0x63, 0x70, 0x24, 0x41, 0x27, 0x74, 0x61, 0x24, 0x66, 0x56, 0x25, 0x25, 0x24, 0x68]
date=bytearray(enc)
for i in range(len(enc)):
date[i]=(date[i])^21
print(date)
#输出结果为 bytearray(b'flag{Y0uMade1tThr0ughT2eSec0ndPZGALAXY1eve1T2at1sC001}')

因此 flag 即为 flag {Y0uMade1tThr0ughT2eSec0ndPZGALAXY1eve1T2at1sC001}

文末附加内容
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇