NCTF2022-复现

NCTF2022-复现

比赛题目

NCTF2022

比赛总结

本次比赛,web还是一无所获,自己还是差的很多。反观misc,这次比赛六道杂项题,做出来两道,然后在核对大佬们的wp后发现自己的思路完全正确,可惜的是自己不会写脚本。总的,本次比赛收获挺大的,做misc的思路更上了一步。个人感觉,这次misc是我做过最有意思的一次,非常好玩。

Misc

Signin

程序设计实验作业,但是签到题(听zys说建议把终端字体调小一点并且只需要输入一串来自35年前的神秘秘籍

神秘秘籍:上上下下左右左右ba,可以直接得到flag
在这里插入图片描述NCTF{VVe1c0m3_T0_NCTF_2022!!!}

另一种解法
在这里插入图片描述这道题,ida不太会用,先把参考的wp留着。

只因因

给了网站http://www.ncbi.nlm.nih.gov/BLAST/查询基因序列
在这里插入图片描述
在这里插入图片描述
简写 CFTR md5加密得到flag

NCTF{254e72a3768938792446548561412d43}

炉边聚会

听说炉石传说快关服了,zys很难过,决定在最后的时间里再组一套卡组玩玩,你能找到藏在里面的flag吗?

这题一开始做的时候不知道是什么东西,后来实在没思路就看着说明,搜了搜炉石传说,发现这段字符应该就是炉石的套牌代码,一下子就觉得只要找到卡组,flag肯定就没问题了。自己还装了一个炉石,结果代码复制进去完全没反应,然后搜的时候弹出了很多卡组代码的组成原理,于是就开始漫长的学习卡组代码的组成原理。

参考:炉石传说卡组代码是什么原理?代码是如何对应卡牌的?

<?php
function read_varint(&$data) {
    $shift = 0;
    $result = 0;
    do {
        $c = array_shift($data);
        $result |= ($c & 0x7f) << $shift;
        $shift += 7;
    }
    while ($c & 0x80);
    return $result;
}

function parse_deck($data) {
    $reserve = read_varint($data);
    if ($reserve != 0) {
        printf("Invalid deckstring");
        die;
    }
    $version = read_varint($data);
    if ($version != 1) {
        printf("Unsupported deckstring version %s", $version);
        die;
    }
    $format = read_varint($data);
    $heroes = [];
    $num_heroes = read_varint($data);
    for ($i = 0; $i < $num_heroes; $i++) {
        $heroes[] = read_varint($data);
    }
    $cards = [];
    $num_cards_x1 = read_varint($data);
    for ($i = 0; $i < $num_cards_x1; $i++) {
        $card_id = read_varint($data);
        $cards[] = [$card_id, 1];
    }
    $num_cards_x2 = read_varint($data);
    for ($i = 0; $i < $num_cards_x2; $i++) {
        $card_id = read_varint($data);
        $cards[] = [$card_id, 2];
    }
    $num_cards_xn = read_varint($data);
    for ($i = 0; $i < $num_cards_xn; $i++) {
        $card_id = read_varint($data);
        $count = read_varint($data);
        $cards[] = [$card_id, $count];
    }
    return [$cards, $heroes, $format];
}

$deckstring = "AAEDAZoFKIwGngXIBrwFzgnQBfIHygf0CIgJkAi+BogJ1gjMCPIHtgeeBeAD6AfyB7YHvgbgA+AD4AO2B7wFkgnMCMwI+ga2B/QImgi6BJAIiAn2BOIJAAA=";
#这是一个非常有趣的萨满卡组
$binary = base64_decode($deckstring);
$hex = bin2hex($binary);
$arr = str_split($hex, 2);
$arr = array_map("hexdec", $arr);
$arr = parse_deck($arr);
var_dump($arr);

执行结果

array(3) {
  [0] =>
  array(40) {
    [0] =>
    array(2) {
      [0] =>
      int(780)
      [1] =>
      int(1)
    }
    [1] =>
    array(2) {
      [0] =>
      int(670)
      [1] =>
      int(1)
    }
    [2] =>
    array(2) {
      [0] =>
      int(840)
      [1] =>
      int(1)
    }
    [3] =>
    array(2) {
      [0] =>
      int(700)
      [1] =>
      int(1)
    }
    [4] =>
    array(2) {
      [0] =>
      int(1230)
      [1] =>
      int(1)
    }
    [5] =>
    array(2) {
      [0] =>
      int(720)
      [1] =>
      int(1)
    }
    [6] =>
    array(2) {
      [0] =>
      int(1010)
      [1] =>
      int(1)
    }
    [7] =>
    array(2) {
      [0] =>
      int(970)
      [1] =>
      int(1)
    }
    [8] =>
    array(2) {
      [0] =>
      int(1140)
      [1] =>
      int(1)
    }
    [9] =>
    array(2) {
      [0] =>
      int(1160)
      [1] =>
      int(1)
    }
    [10] =>
    array(2) {
      [0] =>
      int(1040)
      [1] =>
      int(1)
    }
    [11] =>
    array(2) {
      [0] =>
      int(830)
      [1] =>
      int(1)
    }
    [12] =>
    array(2) {
      [0] =>
      int(1160)
      [1] =>
      int(1)
    }
    [13] =>
    array(2) {
      [0] =>
      int(1110)
      [1] =>
      int(1)
    }
    [14] =>
    array(2) {
      [0] =>
      int(1100)
      [1] =>
      int(1)
    }
    [15] =>
    array(2) {
      [0] =>
      int(1010)
      [1] =>
      int(1)
    }
    [16] =>
    array(2) {
      [0] =>
      int(950)
      [1] =>
      int(1)
    }
    [17] =>
    array(2) {
      [0] =>
      int(670)
      [1] =>
      int(1)
    }
    [18] =>
    array(2) {
      [0] =>
      int(480)
      [1] =>
      int(1)
    }
    [19] =>
    array(2) {
      [0] =>
      int(1000)
      [1] =>
      int(1)
    }
    [20] =>
    array(2) {
      [0] =>
      int(1010)
      [1] =>
      int(1)
    }
    [21] =>
    array(2) {
      [0] =>
      int(950)
      [1] =>
      int(1)
    }
    [22] =>
    array(2) {
      [0] =>
      int(830)
      [1] =>
      int(1)
    }
    [23] =>
    array(2) {
      [0] =>
      int(480)
      [1] =>
      int(1)
    }
    [24] =>
    array(2) {
      [0] =>
      int(480)
      [1] =>
      int(1)
    }
    [25] =>
    array(2) {
      [0] =>
      int(480)
      [1] =>
      int(1)
    }
    [26] =>
    array(2) {
      [0] =>
      int(950)
      [1] =>
      int(1)
    }
    [27] =>
    array(2) {
      [0] =>
      int(700)
      [1] =>
      int(1)
    }
    [28] =>
    array(2) {
      [0] =>
      int(1170)
      [1] =>
      int(1)
    }
    [29] =>
    array(2) {
      [0] =>
      int(1100)
      [1] =>
      int(1)
    }
    [30] =>
    array(2) {
      [0] =>
      int(1100)
      [1] =>
      int(1)
    }
    [31] =>
    array(2) {
      [0] =>
      int(890)
      [1] =>
      int(1)
    }
    [32] =>
    array(2) {
      [0] =>
      int(950)
      [1] =>
      int(1)
    }
    [33] =>
    array(2) {
      [0] =>
      int(1140)
      [1] =>
      int(1)
    }
    [34] =>
    array(2) {
      [0] =>
      int(1050)
      [1] =>
      int(1)
    }
    [35] =>
    array(2) {
      [0] =>
      int(570)
      [1] =>
      int(1)
    }
    [36] =>
    array(2) {
      [0] =>
      int(1040)
      [1] =>
      int(1)
    }
    [37] =>
    array(2) {
      [0] =>
      int(1160)
      [1] =>
      int(1)
    }
    [38] =>
    array(2) {
      [0] =>
      int(630)
      [1] =>
      int(1)
    }
    [39] =>
    array(2) {
      [0] =>
      int(1250)
      [1] =>
      int(1)
    }
  }
  [1] =>
  array(1) {
    [0] =>
    int(666)
  }
  [2] =>
  int(3)
}

其它wp脚本
这个要先转换为8位的二进制,根据卡组编码规则,把代码转为十六进制,再转二进制

fflag=['10001100','00000110','10011110','00000101','11001000','00000110','10111100','00000101','11001110','00001001','11010000','00000101','11110010','00000111','11001010','00000111','11110100','00001000','10001000','00001001','10010000','00001000','10111110','00000110','10001000','00001001','11010110','00001000','11001100','00001000','11110010','00000111','10110110','00000111','10011110','00000101','11100000','00000011','11101000','00000111','11110010','00000111','10110110','00000111','10111110','00000110','11100000','00000011','11100000','00000011','11100000','00000011','10110110','00000111','10111100','00000101','10010010','00001001','11001100','00001000','11001100','00001000','11111010','00000110','10110110','00000111','11110100','00001000','10011010','00001000','10111010','00000100','10010000','00001000','10001000','00001001','11110110','00000100','11100010','00001001','00000000','00000000']
for i in range(40):
    flag=fflag[2*i+1]+fflag[2*i][1:-1]+fflag[2*i][-1]
    fla=int(flag,2)
    fl=fla//10
    print(chr(fl),end='')

脚本三;可以直接出

from hearthstone.deckstrings import Deck

deck = Deck.from_deckstring('AAEDAZoFKIwGngXIBrwFzgnQBfIHygf0CIgJkAi+BogJ1gjMCPIHtgeeBeAD6AfyB7YHvgbgA+AD4AO2B7wFkgnMCMwI+ga2B/QImgi6BJAIiAn2BOIJAAA=')

for card in deck.cards:
    flag_part = int(card[0] / 10)
    print(chr(flag_part), end='')
NCTF{HearthStone_C0de_S000_FunnY_ri9ht?}

zystego

可以分离出一个zip,爆破密码
在这里插入图片描述
flag.txt是假的
在这里插入图片描述somethin里有一堆不认识的东西,开头可以拿去搜一下,发现是PGP的私钥,然后这里就不会了,一直学PGP没搞懂,到底加密后的是什么,就给我个密钥怎么解。现在看了wp才发现,fd.png里还有东西。
fd.png右边一列奇怪的东西
请添加图片描述

提取RGB
看wp,可以用lsb找,但我一直找不出来,只能用脚本(但别说脚本真的香)

from PIL import Image

im = Image.open('fd.png')
pix = im.load()
width = im.size[0]
height = im.size[1]
for x in range(height):
    for y in range(width-3,width):
        r,g,b = pix[y,x]
        print(r,g,b)

在这里插入图片描述

from PIL import Image

im = Image.open('fd.png')
pix = im.load()
width = im.size[0]
height = im.size[1]
for x in range(height):
    for y in range(width-3,width):
        r, g, b = pix[y,x]
        #print(r,g,b)
        if r%10 == 0:
            print(0,end='')
        else:
            print(1,end='')
        if g%10 == 0:
            print(0,end='')
        else:
            print(1,end='')
        if b%10 == 0:
            print(0,end='')
        else:
            print(1,end='')

在这里插入图片描述到这里我也不认识了(要学的东西还多)
一个dct算法,末尾是key

import numpy as np
import cv2

丁真 = np.float32(cv2.imread(r"fd.png",1))

for i in range(64):
    for j in range(64):
        for 芝士 in range(3):
            小马珍珠 = 丁真[:, :, 芝士]
            雪豹 = cv2.dct(小马珍珠[8*i:8*i+8, 8*j:8*j+8])
            print(雪豹[7,7])
import numpy as np
import cv2

丁真 = np.float32(cv2.imread(r"fd.png",1))

for i in range(64):
    for j in range(64):
        for 芝士 in range(3):
            小马珍珠 = 丁真[:, :, 芝士]
            雪豹 = cv2.dct(小马珍珠[8*i:8*i+8, 8*j:8*j+8])
            # print(雪豹[7,7])
            if(雪豹[7,7] > 10):
                print(1,end='')
            elif(雪豹[7,7] < -10):
                print(0,end='')

得到一个zip,即为加密文件
在这里插入图片描述
在这里插入图片描述

key:%$#%$#jhgasdfg76342t

NCTF{zys_1s_s0_V3g3T@13lE_qwq}

qrssssssss

有什么东西掩盖住了zys的双眼,好像在给他指明方向!(flag括号内的内容只有26位

这题,512个二维码,一开始以为会组成什么东西,扫完发现NCTF{}有这东西,那一想,二维码按顺序扫描,flag不就出来了。然后发现每个二维码名字是时间,于是想到会不会按时间顺序就能扫出来了。

这个脚本才让我明白这题的原理,时间竟然是非预期

from PIL import Image
import pyzbar.pyzbar as pyzbar
import os

def qrcode_parse_content(img_path):
    '''
    单张图片的二维码解析
    '''
    img = Image.open(img_path)

    #使用pyzbar解析二维码图片内容
    barcodes = pyzbar.decode(img)

    #打印解析结果,从结果上可以看出,data是识别到的二维码内容,rect是二维码所在的位置
    # print(barcodes)
    # [Decoded(data=b'http://www.h3blog.com', type='QRCODE', rect=Rect(left=7, top=7, width=244, height=244), polygon=[Point(x=7, y=7), Point(x=7, y=251), Point(x=251, y=251), Point(x=251, y=7)])]

    result = []
    for barcode in barcodes:
        barcode_content = barcode.data.decode('utf-8')
        result.append(barcode_content)

    return result

def load_imgs(folder):
    '''
    加载文件夹下的图片
    '''
    imgs = []
    for img_path in os.listdir(folder):
        ext = os.path.splitext(img_path)
        if len(ext) > 1 and is_img(ext[1]):
            imgs.append(img_path)

    return imgs

def is_img(ext):
    '''
    判断文件后缀是否是图片
    '''
    ext = ext.lower()
    if ext == '.jpg':
        return True
    elif ext == '.png':
        return True
    elif ext == '.jpeg':
        return True
    elif ext == '.bmp':
        return True
    else:
        return False

if __name__ == "__main__":

    imgs = load_imgs('./') # 打开图片文件夹,我这里是当前程序运行目录
    contents = []
    # for img in imgs:
    #     contents.extend(qrcode_parse_content(img))
    #     print( img)
    # file = './result.txt' # 写入文件路径,我这里程序当前运行目录下的result.txt
    # with open(file,'w',encoding='utf-8') as f:
    #     for c in contents:
    #         f.write(c + '\n')
    for img in imgs:
        print(qrcode_parse_content(img)[0],end='')
e1b19411bCT3ef91e-T6--5115-b-eNe5-01e-1-0}1a15-0e91e50N15-eTa3-0e}8bC16ee11feeeeb7{ae1eeNbC7Ta1T-5bFb--398a515-NbTfbb-8-7ef-}0C-Te4eF501f{6a51e4be--5-Fb0}Fb-5{b97ef8a-{fa11bC9fee-3-e9N{1-51T1NN01C41883{577-1e-T1603{C{-17-NNeC0f-0C39711514{9117F--6-F-e05a7517C3b4-F{F71f}-1fe70-34-{7805C}b{bCf1f-aT{e3aFe-f-0bT6C17000N78e-76}af7-}4N-907}03187b113T9eaeF--13ebeN71b-C9Te1eF-680-468675F17410674N910F51b1511--80FF565165-19}beT}N17N-1758e-}1a8-4C-0057e-5b7b0}5}{7eaN-{-b}36b}7eb0-606{15b4b01971T-59388-Te351eFC044417af

在这里插入图片描述二维码纠错级别LMQH
参考文章:如何一眼看出二维码的纠错等级
另一种方法

脚本输出二维码内容和修改时间

# coding: UTF-8
from PIL import Image
import pyzbar.pyzbar as pyzbar
import os

def qrcode_parse_content(img_path):
    '''
    单张图⽚的⼆维码解析
    '''
    img = Image.open(img_path)
    #使⽤pyzbar解析⼆维码图⽚内容
    barcodes = pyzbar.decode(img)
    #打印解析结果,从结果上可以看出,data是识别到的⼆维码内容,rect是⼆维码所在的位置
    # print(barcodes)
    # [Decoded(data=b'http://www.h3blog.com', type='QRCODE', rect=Rect(left=7, t
    result = []
    for barcode in barcodes:
        barcode_content = barcode.data.decode('utf-8')
        result.append(barcode_content)
    return result

def load_imgs(folder):
    '''
    加载⽂件夹下的图⽚
    '''
    imgs = []
    for img_path in os.listdir(folder):
        ext = os.path.splitext(img_path)
        if len(ext) > 1 and is_img(ext[1]):
            imgs.append(img_path)
    return imgs

def is_img(ext):
    '''
    判断⽂件后缀是否是图⽚
    '''
    ext = ext.lower()
    if ext == '.jpg':
        return True
    elif ext == '.png':
        return True
    elif ext == '.jpeg':
        return True
    elif ext == '.bmp':
        return True
    else:
        return False

if __name__ == "__main__":
    # path = "C:/Users/KG/Desktop/1/"
    path = 'C://Users/LENOVO/Desktop/NCTF2022/qrssssssss/qrssssssss/'
    imgs = load_imgs(path)  # 打开图⽚⽂件夹,我这⾥是当前程序运⾏⽬录
    contents = []
    for img in imgs:
        print(img, end='\t')
        old_name = img[:15]
        # print(old_name)
        print(qrcode_parse_content(path + img)[0], end='\t')
        print(os.path.getatime(path + img), end='\t')
        print(os.path.getctime(path + img), end='\t')
        print(os.path.getmtime(path + img))
    # new_name = old_name+'_'+qrcode_parse_content(path+img)[0]+'.png'
    # print(old_name+'_'+new_name+'.png')
    # print(qrcode_parse_content(path+img))
    # os.rename(path+img, path+new_name)
    # contents.extend(qrcode_parse_content(path+img))

脚本输出二维码的纠错级别

from PIL import Image
import pyzbar.pyzbar as pyzbar
import os

def qrcode_parse_content(img_path):
    '''
    单张图⽚的⼆维码解析
    '''
    img = Image.open(img_path)
    #使⽤pyzbar解析⼆维码图⽚内容
    barcodes = pyzbar.decode(img)
    #打印解析结果,从结果上可以看出,data是识别到的⼆维码内容,rect是⼆维码所在的位置
    # print(barcodes)
    # [Decoded(data=b'http://www.h3blog.com', type='QRCODE', rect=Rect(left=7, t
    result = []
    for barcode in barcodes:
        barcode_content = barcode.data.decode('utf-8')
        result.append(barcode_content)
    return result

def load_imgs(folder):
    '''
    加载⽂件夹下的图⽚
    '''
    imgs = []
    for img_path in os.listdir(folder):
        ext = os.path.splitext(img_path)
        if len(ext) > 1 and is_img(ext[1]):
            imgs.append(img_path)

    return imgs

def is_img(ext):
    '''
    判断文件后缀是否是图片
    '''
    ext = ext.lower()
    if ext == '.jpg':
        return True
    elif ext == '.png':
        return True
    elif ext == '.jpeg':
        return True
    elif ext == '.bmp':
        return True
    else:
        return False

def get_level(i):
    img = Image.open(i)
    if img.load()[10, 170] == 0 and img.load()[30, 170] == 0:
        return(i, 'L')
    if img.load()[10, 170] == 0 and img.load()[30, 170] == 255:
        return(i, 'M')
    if img.load()[10, 170] == 255 and img.load()[30, 170] == 0:
        return(i, 'Q')
    if img.load()[10, 170] == 255 and img.load()[30, 170] == 255:
        return(i, 'H')

if __name__ == "__main__":
    path = "C://Users/LENOVO/Desktop/NCTF2022/qrssssssss/qrssssssss/"
    # path = 'C://Users/KG/Downloads/qrssssssss/'
    imgs = load_imgs(path) # 打开图⽚⽂件夹,我这⾥是当前程序运⾏⽬录
    contents = []

    for img in imgs:
        old_name = img[:15]
        print(old_name,end='\t')
        print(qrcode_parse_content(path+img)[0],end='\t')
        print(get_level(path+img)[1],end='\t')
        print(os.path.getatime(path+img),end='\t')
        print(os.path.getctime(path+img),end='\t')
        print(os.path.getmtime(path+img))
        # new_name = old_name+'_'+qrcode_parse_content(path+img)[0]+'.png'
        # print(old_name+'_'+new_name+'.png')
        # print(qrcode_parse_content(path+img))
        # os.rename(path+img, path+new_name)

按纠错顺序排序即可得到flag

NCTF{737150-eeb-465-e91-110a8fb}

qrssssssss_revenge

LMQH

这道就是纯LMQH来排序了,没有非预期

NCTF{62130783efd44b3692b4ddbecf}

参考:

南邮-NCTF2022 WRITE UP

Scr1w战队wp(比赛群里师傅发的)

如何一眼看出二维码的纠错等级

### NCTF Web Challenges and Resources NCTF (National Cybersecurity Talent Competition) is a well-known competition that focuses on cybersecurity skills, including web security challenges. These challenges are designed to test participants' abilities in identifying vulnerabilities within web applications and exploiting them ethically. The website mentioned in the reference provides access to various Capture The Flag (CTF) competitions where contestants can engage with different types of challenges, such as web-based ones[^1]. Participants often encounter tasks involving SQL injection, cross-site scripting (XSS), command injection, insecure deserialization, and more advanced techniques like bypassing authentication mechanisms or exploiting server-side request forgery (SSRF). For those interested specifically in NCTF's web-related content, it’s recommended to explore past challenge archives from official sources when available. Additionally, there exist several platforms hosting similar CTF-style exercises which could serve as supplementary material: #### Example Code for Testing XSS Vulnerability Below demonstrates how one might check whether an input field allows reflected Cross-Site Scripting attacks. ```javascript // Simple payload used during testing phase alert('This shows potential vulnerability'); ``` Such scripts should only execute under conditions indicating improper sanitization processes at play—highlighting areas needing remediation efforts before deployment into production environments.
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

slawgut

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值