Re
SU_BBRE
分析汇编,函数 fun2 为 rc4,密钥:suctf,密文:0x2f,0x5a,0x57,0x65,0x14,0x8f,0x69,0xcd,0x93,0x29,0x1a,0x55,0x18,0x40,0xe4,0x5e
解密:
|
|
fun1 解密:
|
|
fun1 调用由 scrtpy 溢出调用,后三位为地址:0x40223d,ASCLL:="@
flag:We1com3ToReWorld="@AndPWNT00
SU_minesweeper
逻辑比较清楚,先读入输入,偏移 6 位后转换成 16 进制数,再依据二进制转换成雷区。 给了雷区的一些约束,那么 z3 求解即可
扫雷
输入文件 in.txt
|
|
构造方程
|
|
解方程
|
|
|
|
验证结果
|
|
创建位图
|
|
映射
|
|
App
好多校验
copy 到目录的文件
|
|
Unidbg call so
应该有其他东西,不是静态的,模拟执行 call 出来的结果 check 是在匹配那个 base64
|
|
Frida hook
- 改端口,把签名校验 hook 掉,然后会调用 start 函数,检测到 hook 后程序终止
日志:
|
|
|
|
Harmony

这个辅助定位

转 uint32,数据都标好了,太友善了

定位到 v5,sub_57B0 传入输入和密文

就在这里加密,开逆
第一个

第二个

第三个

第四个

第五个

第六个


|
|
Pwn
SU_BABY
交互
|
|
SU_text
✨ 分析
checksec 查看。保护全开
IDA 分析。部分函数已重命名
向 buf 中输入最多 0xfff 个字节,随后逐字节去解析。解析第一个字节,如果是 1 则进入 add_delete,如果是 2 则进入 show_edit
沙箱中允许了这些,一看就知道最后是利用 orw 获取 flag
add_delete 函数中,继续解析一字节,如果是 0x10,进入 add,如果是 0x11,进入 delete
add 中创建 chunk,不能太大也不能太小,显然是 largebin attack
delete 函数正常
首先解析一字节,是要操作 chunk 的 index,继续解析一字节,如果是 0x10,进入 mov_show,如果是 0x11,进入 xor_or
mov_show 这里有一些操作,与 vm 很像。值得看的是 a1_mov1
将 chunk+a1 位置的一个值赋值为一个自己输入的值
show 可以泄露信息,可以用来泄露 libcbase,elfbase,stack,heap
xor_or 函数中也有一堆类似 vm 的操作
这些操作都是逐字节完成,在进行这些操作后,就会将 a2 指针加 1
而之前 a1_mov1 中 a1 有限制,不能超过那个 chunk 的大小,但是是以 a2 为基准的,通过上面的 xor 操作增加 a2 指针后,并没有对 a2 指针进行归位操作,就导致 a2+a1 可以超过 chunk 大小,来到下一个 chunk,将下一个 chunk 中的地址赋值为想要的地址,就导致了堆溢出
所以可以 largebin attack,修改 mp_.tcache_bins 为一个大值,再利用 tcache attack 修改栈上的返回地址完成 orw 利用
✨ 解题
先是定义一些函数,方便后续利用
然后 add 了两个 chunk,上面那个 chunk 是为了后面改下面那个 chunk 创建的。同时创建 chunk 也是为了能够 show,因为 show 需要先有一个 chunk
下面就是一些 show,狠狠地 show 出 stack,show 出 heap,show 出 libcbase
0x250000 是远程的那个段到_rtld_global 段的距离,我本地是 0x3b000,这个 blind 很简单,只需要往大写,然后就会 show 不出来,缩小,直到能 show 出来,就是_rtld_global 段
从图里可以看到偏移
从_rtld_global 开始正向偏移有堆和栈
负向偏移有 libc
接下来正常构造 largebin attack
利用 xor 增加 chunk 的指针,以完成溢出,修改 largebin 第四个字段为想要修改的 mp_.tcache_bins – 0x20 地址
完成 largebin attack,接下来是 tcache attack
释放两个 chunk 进 tcache,fd 修改为 stack
取出来后,chunk 就来到了栈上,修改返回地址,完成 rop,需要注意一下的是这里将栈降低了很多,因为在返回地址附近由于其他函数会修改 canary 等等报错
✨exp
|
|
Web
photogallery
正常上传一次观察发包记录,有一个 unzip.php 文件,利用之前羊城杯时候的源码泄露漏洞获取源码

unzip.php
|
|
正常处理过后的文件名和路径无从得知,但是这里是先解压再移动,这里利用解压函数 ZipArchive 的超长文件名报错,让上传的文件在 upload/suimages/留下写 php 的文件
|
|

然后读取
|
|

ezk8s on aliyun
读取一下源码
|
|

|
|
main.py
|
|
audit.py
|
|
麻烦的沙箱绕过,不想看了,其实不用绕,打一个 SSRF 去找阿里云元数据

Ezblog
注册个 admin 进去读源码

app.py
|
|
/Admin 路由下面有原型链污染,关于_set 方法示例
|
|
模板编译时的变量
在 flask 中如使用 render_template 渲染一个模板实际上经历了多个阶段的处理,其中一个阶段是对模板中的 Jinja 语法进行解析转化为 AST,而在语法树的根部即 Lib/site-packages/jinja2/compiler.py 中 CodeGenerator 类的 visit_Template 方法纯在一段有趣的逻辑
该逻辑会向输出流写入一段拼接的代码(输出流中代码最终会被编译进而执行),在生成代码的时候有一个可控变量 exported_names,他是 runtime(https://github.com/pallets/jinja/blob/main/src/jinja2/runtime.py#L45) 里面的一个数组,所以我们完全可以通过 pydash.set_() 来进行覆盖,从而达到 rce。该变量为 .runtime 模块(即 Lib/site-packages/jinja2/runtime.py)中导入的变量 exported 和 async_exported 组合后得到,这就意味着我们可以通过污染 .runtime 模块中这两个变量实现 RCE。由于这段逻辑是模板文件解析过程中必经的步骤之一,所以这就意味着只要渲染任意的文件均能通过污染这两属性实现 RCE。
loader 被过滤

spec 内置属性在 Python 3.4 版本引入,其包含了关于类加载时的信息,本身是定义在 Lib/importlib/_bootstrap.py 的类 ModuleSpec,显然因为定义在 importlib 模块下的 py 文件,所以可以直接采用 <模块名>.__spec__.__init__.__globals__['sys'] 获取到 sys 模块
从 0 试到 2 发现 2 可以,最后的 payload
|
|

然后/readflag,不理解为什么上面那个 import os 写法不行
|
|
