UNCTF2022 writeup

题量太多了,比赛结束之后又要做一遍…

注:最后给出的均为题目解出的flag,提交时需将格式修改为UNCTF{}

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(由于当时做题的时候我导出两个数据之后,循环仍然跑的s,发现两串的出来的相同,因此在写wp的时候写的4051C0,然后直接去跑脚本了,所以在wp中写出了错误的思路,感谢查看wp的师傅提出来的问题,该段文字为修改后的,下图为当时写的脚本,直接复制了循环过程)
在这里插入图片描述

双击unk_405040,导出数据,写个脚本处理一下

s = '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 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 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 06 00 00 00 00 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 06 00 00 00 00 00 00 00 09 00 00 00 00 00 00 00 00 00 00 00 00 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 01 00 00 00 04 00 00 00 00 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}

我小心海也绝非鳝类

在这里插入图片描述

能看清Il的出题人都是好出题人好人一生平安。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

尝试做了一个小时没做出来,等官解了

  • 12
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值