VNCTF2021 WriteUp

拿了个第一,好

图片[1]-VNCTF2021 WriteUp-魔法少女雪殇

[VNCTF 2021]Ez_game

F12进控制台,找js

图片[2]-VNCTF2021 WriteUp-魔法少女雪殇

可疑字段,怀疑是flag明文

复制出来在控制台打出,即可

图片[3]-VNCTF2021 WriteUp-魔法少女雪殇

[VNCTF 2021]Check_In

签到

[VNCTF 2021]冰冰好像藏着秘密

rar下载后解压报错,binwalk+dd指令直接分解

图片[4]-VNCTF2021 WriteUp-魔法少女雪殇

文件名叫FFT,所以根据这个进行搜索

找到这类文章

https://www.jb51.net/article/144193.htm

撰写exp即可

import cv2
import numpy as np
from matplotlib import pyplot as plt
 
img = cv2.imread('FFT.png',0)
ff = np.fft.fft2(img)
xf = np.fft.fftshift(ff)
magnitude_spectrum = 20*np.log(np.abs(xf))
 
plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('1'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(magnitude_spectrum, cmap = 'gray')
plt.title('2'), plt.xticks([]), plt.yticks([])
plt.show()
图片[5]-VNCTF2021 WriteUp-魔法少女雪殇

[VNCTF 2021]interesting_fishing

开局一个bin,不知道,直接nodepad++打开

图片[6]-VNCTF2021 WriteUp-魔法少女雪殇

打开后莫名其妙的一堆base64,含有qq的解密都是意义不明的东西

图片[7]-VNCTF2021 WriteUp-魔法少女雪殇

继续往下看,下面仍有三个可以进行解密的base64

图片[8]-VNCTF2021 WriteUp-魔法少女雪殇

第一个解密,意义不明,但是可以看见crazyman,出题人的信息

图片[9]-VNCTF2021 WriteUp-魔法少女雪殇

第二个解密,发现一个连接,打开后是图片,猜测是第二部分所需的图片

先不管,

第三个base64段非常长,所以单独复制出来解密,可以看出rar!的文件头,直接保存为rar后缀即可

图片[10]-VNCTF2021 WriteUp-魔法少女雪殇
图片[11]-VNCTF2021 WriteUp-魔法少女雪殇

解压后,漫无目的的寻找,在vcxproj的文件里下发现这个

图片[12]-VNCTF2021 WriteUp-魔法少女雪殇

根据目录去寻找该文件

图片[13]-VNCTF2021 WriteUp-魔法少女雪殇

nodepad++打开

图片[14]-VNCTF2021 WriteUp-魔法少女雪殇

可以看到base64加密段,进行解密

\u-65432?\u-65420?\u-65420?\u-65424?\u-65421?\u-65478?\u-65489?\u-65489?\u-65418?\u-65426?\u-65437?\u-65420?\u-65434?\u-65491?\u-65486?\u-65487?\u-65485?\u-65491?\u-65487?\u-65486?\u-65483?\u-65481?\u-65488?\u-65482?\u-65487?\u-65487?\u-65486?\u-65485?\u-65490?\u-65437?\u-65425?\u-65421?\u-65490?\u-65439?\u-65424?\u-65491?\u-65426?\u-65439?\u-65426?\u-65430?\u-65431?\u-65426?\u-65433?\u-65490?\u-65427?\u-65415?\u-65423?\u-65437?\u-65428?\u-65425?\u-65419?\u-65436?\u-65490?\u-65437?\u-65425?\u-65427?\u-65489?\u-65456?\u-65415?\u-65425?\u-65426?\u-65433?\u-65415?\u-65439?\u-65426?\u-65433?\u-65499?\u-65486?\u-65488?\u-65421?\u-65420?\u-65425?\u-65422?\u-65435?\u-65421?\u-65499?\u-65486?\u-65488?\u-65428?\u-65425?\u-65417?\u-65499?\u-65486?\u-65488?\u-65425?\u-65426?\u-65499?\u-65486?\u-65488?\u-65434?\u-65425?\u-65422?\u-65435?\u-65431?\u-65433?\u-65426?\u-65499?\u-65486?\u-65488?\u-65433?\u-65425?\u-65425?\u-65436?\u-65421?\u-65499?\u-65486?\u-65488?\u-65439?\u-65427?\u-65431?\u-65436?\u-65499?\u-65486?\u-65488?\u-65458?\u-65425?\u-65422?\u-65420?\u-65432?\u-65499?\u-65486?\u-65488?\u-65461?\u-65425?\u-65422?\u-65435?\u-65439?\u-65426?\u-65499?\u-65486?\u-65488?\u-65469?\u-65457?\u-65450?\u-65463?\u-65468?\u-65491?\u-65487?\u-65479?\u-65499?\u-65486?\u-65488?\u-65424?\u-65439?\u-65422?\u-65439?\u-65426?\u-65425?\u-65431?\u-65439?\u-65490?\u-65422?\u-65439?\u-65422?

意义不明,但是还感觉像utf,于是脑洞人,对其进行65536-后面数字,获得ascii,获得网址

https://vnctf-213-1257061123.cos.ap-nanjing-myqcloud.com/Pyongyang%20stores%20low%20on%20foreign%20goods%20amid%20North%20Korean%20COVID-19%20paranoia.rar

进行下载

图片[15]-VNCTF2021 WriteUp-魔法少女雪殇

获得提示,进行爆破

密码为9705

图片[16]-VNCTF2021 WriteUp-魔法少女雪殇

获得docx,直接查看无果,解压

发现个hideinfo.xml

图片[17]-VNCTF2021 WriteUp-魔法少女雪殇

意义不明,尝试零宽隐写

图片[18]-VNCTF2021 WriteUp-魔法少女雪殇

获得第一部分

第二部分是有第二个base解密的网址获得的图片

图片[19]-VNCTF2021 WriteUp-魔法少女雪殇

直接oursecret出了

图片[20]-VNCTF2021 WriteUp-魔法少女雪殇

[VNCTF 2021]Do_you_like_Rhythm_Doctor

开局下载一个格式为节奏医生的谱面

导入后报错

图片[21]-VNCTF2021 WriteUp-魔法少女雪殇

不过可以直接解压获得rdlevel文件,直接导入创作谱面

图片[22]-VNCTF2021 WriteUp-魔法少女雪殇

意义不明,不知道要干什么,问了出题人后,出题人说flag就在谱面文件,所以那就直接txt打开谱面进行分析

图片[23]-VNCTF2021 WriteUp-魔法少女雪殇

bar为进度条,beat为没八拍一个,row为轨道,y值不明,重点是pluseType,表示两种不同的note形式

由于有过出音游题经验,顺理成章理解为每个轨道的两种note定位为专有的0和1,这样进行转换即可。

脚本:

from json import load
file = open('main.rdlevel','r',encoding='UTF-8')
jsons = load(file)
rows = [[],[],[],[]]
for i in jsons['events']:
    if 'pulseType' in i:
        rows[i['row']].append(1 if i['pulseType'] == 'Wave' else 0)
print(rows)

输出的二进制转换为字符串即可

[VNCTF 2021]HAPPYNEWYEAR

图片[24]-VNCTF2021 WriteUp-魔法少女雪殇

不知道是啥。。。。但是给了hint,看hint

根据网址找到对应的谜语

图片[25]-VNCTF2021 WriteUp-魔法少女雪殇

对照进行解密,获得密码:

f87840bdddcc01e4

解码后是一个png,开始以为是LSB,鼓捣半天没结果,又是问出题人,stegpy爆破,彳亍

那就爆破,参考密码本:

https://github.com/Misclife/CTFpics-1

exp:

import os
from subprocess import Popen,PIPE
import sys
def carkcccc(pic):
        file = open('top3000.txt', 'r')
        line = file.readline()
        while line:
            cmd = ["stegpy", "-p", pic]
            subp = Popen([sys.executable, '-c', 'import pty, sys; pty.spawn(sys.argv[1:])', *cmd], stdin=PIPE, stdout=PIPE,stderr=PIPE)
            print(subp.stdout.read(len("Enter password (will not be echoed):")))
            #print(line)
            obj = subp.stdin.write((line + '\n').encode('utf-8'))
            subp.stdin.flush()
            print('result:')
            print(subp.stdout.readlines()[1])
            print('\n')
            line = file.readline()
​
if __name__ == "__main__":
    carkcccc('happynewyear.png')

获得密码:

tyinfo

图片[26]-VNCTF2021 WriteUp-魔法少女雪殇

[VNCTF 2021]Crackme2

调用了Native层函数stringFromJNI(),打开了JNI_OnLoad,没有更换native函数,同时初始化了一个128位的数字

下面是AES加密函数

__int64 __fastcall sub_42944(_DWORD *key, const char *input, size_t len, __int64 a4, unsigned int *a5)
{
  sub_42AE0(key, a4, v17);
  if ( *a5 )
  {
    v18 = 0;
    do
    {
        // ECB模式
      sub_42CBC(key, &v13[v18], v14 + v18, v17);
      v18 += key[3];
    }
    while ( v18 < *a5 );
  }
  operator delete[](v13);
  operator delete[](v17);
  return v14;
}
from Crypto.Cipher import AES
key = [114, 59, 255, 100, 203, 160, 225, 150, 176, 95, 92, 246, 23, 176, 18, 249,]
print(len(key))
aes = AES.new(key=bytes(key),mode=AES.MODE_ECB)
​
str = bytes([0xB2, 0x82, 0x16, 0xEE, 0x5E, 0xCD, 0x5F, 0xFA, 0xFF,0x82, 0x54, 0xE6, 0xB, 0x4B, 0xAE, 0xAA])
print(aes.decrypt(str))

[VNCTF 2021]FilpGame

成功结果为word_40301c全部为-1,长度为0x20,flag为输入的md5

图片[27]-VNCTF2021 WriteUp-魔法少女雪殇

v4+16*v5为递增数列,根据数组,反转位为

(v5-1,v4)(v5,v4)(v5,v4-1)(v5,v4+1)(v5+1,v4)

cnt为奇数时翻转,由于v4、v5都是uint32,范围为0~15

综上所述

当v5=2时,0号字必须是-1,这样v5=1时只会出现有限数量的方案,进行dfs

#include <string.h>
#include <math.h>
#include "defs.h"
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
uint16_t itter[] = {48885, 35772, 41193, 29456, 55568, 41901, 52406, 19934, 13388, 15318, 26385, 34447, 7290, 33829, 27405, 6988};
int32_t d_402140[]={0,0,-1,1,0};
int32_t d_40212c[]={-1,0,0,0,1};
​
char StoH(uint32_t a);
void pArray(const char *name,uint8_t *v,size_t len);
​
void dfs(uint16_t *state,size_t start,size_t i,char *flag){
    if(i==16){
        if(start>=1&&state[start-1]!=0xffff){
            return;
        }
        start+=1;
        i=0;
    }
    if(start==16){
        if(state[start-1]==0xffff){
            printf("%ld: %s\n",strlen(flag),flag);
            fflush(stdout);
            exit(0);
        }
        return;
    }
    if(strlen(flag)>214)return;
    uint16_t *nstate = (uint16_t*)alloca(sizeof(itter));
    memcpy(nstate,state,sizeof(itter));
    uint32_t v12,v13;
    for(size_t j=0;j<5;j++){
        v12=d_40212c[j]+i;
        v13=d_402140[j]+start;
        if(v12<=0xf&&v13<=0xf){
            nstate[v13]^=1<<(15-v12);
        }
    }
    uint16_t *nnstate=(uint16_t*)alloca(sizeof(itter));
    char *nsflag = (char*)alloca(len+1);
    memcpy(nsflag,flag,len+1);
    memcpy(nnstate,state,sizeof(itter));
    dfs(nnstate,start,i+1,nsflag);
    char *sflag=(char*)alloca(len+3);
    memcpy(sflag,flag,len+1);
    sflag[len]=StoH(i);
    sflag[len+1]=StoH(start);
    sflag[len+2]=0;
    dfs(nstate,start,i+1,sflag);
}
void pArray(const char *name,uint8_t *v,size_t len) 
{
    printf("--------%s--------\n",name);
    for(size_t i=0;i<len;i++){
        printf("0x%02X,",v[i]);
    }
    printf("\n----------------\n");
}
char StoH(uint32_t a){
    if(a<=9)return a+'0';
    else return a+55;
}
​
int main(){
    char flag[]="";
    dfs(itter,0,0,flag);
    return 0;
}

最终直接输出

import sys
import hashlib
import base64
​
print(hashlib.md5(b'2050608090A0B0C0D02131417191A1B1527282B2D2E2F213234363B3D36494C4D4E415456575C5D5E50626566686C6F6071787B7C72838587898C8D81949596999B9C9F95A8AAAEA0B1B3B4B7B1C2C3C4C6C9CBCEC0D4D7D9DBDCDED0E1E3E4E5E6E8E9ECEEEFE3F7F8FBF').hexdigest())

[VNCTF 2021]notsudoku

在前面要补齐16个字节

data = []
with open('2.pyc','rb') as f:
    data = f.read()
struct = []
with open('notsudoku/struct','rb') as f:
    struct = f.read()
with open('2_2.pyc','wb') as f:
    f.write(struct[:16]+data)

百度搜索到有关于九宫格的解法

https://blog.csdn.net/weixin_40368377/article/details/78628358

其中题目中间还有着md5进行验证的鬼东西,,必须符合才可以,,,麻了

图片[28]-VNCTF2021 WriteUp-魔法少女雪殇

根据上述文章进行修改解题

exp:

import hashlib
​
flag = ""
i=0
​
def sudoku_rule(n,sudoku):
    tx = n//2
    ty = 0
    for i in range(n * n):
        sudoku[ty][tx] = i + 1
        tx = tx+1
        ty = ty-1
        if ty<0 and tx>=n:      #条件(4)
            tx = tx-1
            ty = ty+2
        elif ty<0:              #条件(3)
            ty = n-1
        elif tx>=n:             #条件(2)
            tx = 0
        elif sudoku[ty][tx]!=0: #条件(5)
            tx = tx-1
            ty = ty+2
​
    return sudoku
​
sudoku = [[0 for i in range(5)] for i in range(5)]
s = sudoku_rule(5,sudoku)
for j in range(25):
    for x in range(5):
        try:
            a = i
            b = s[i].index(j+1)
            flag+=str(a)
            flag+=str(b)
            i=0
            break
        except:
            i+=1
x = str(hashlib.new('md5', bytes((flag), encoding='utf8')).hexdigest())
print(x)

[VNCTF_202021]Questionnaire

问卷

© 版权声明
THE END
喜欢就支持一下吧
点赞3 分享
评论 共3条
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情
    • 头像套神Mumuzi1
    • 头像帅帅0
    • 头像mochu70