[VNCTF 2021] notsudoku wp

10 篇文章 0 订阅

这个题目之前比赛写的时候就是一脸懵。比赛之后看了大神们的wp才知道还是我太弱了,学习的太少了。

1.查壳

下载附件后先查壳。在这里插入图片描述
发现带有upx壳,我么先脱壳。
在这里插入图片描述

2.将python打包的exe文件转化为pyc文件

通过观察文件图标可以发现,这个文件是使用python打包的一个exe文件我们需要使用pyinstxtractor.py将python打包的.exe文件还原成.py文件

python pyinstxtractor.py notsudoku.exe 
 //注意:要将被还原文件和 pyinstxtractor.py放在同一文件夹下哦!

在这里插入图片描述
转化出来后会得到一个notsudoku.exe_extracted文件夹在这里插入图片描述
红圈标出的就是等下要还原的文件。

3.将文件还原成可阅读的.py文件

使用010editor打开上图红圈标记的文件
在这里插入图片描述

notsudoku.exe_extracted文件夹找到struct文件也用010editor打开在这里插入图片描述
在这里插入图片描述
新建一页:复制上图红圈里的内容到新建的页面中。再将2文件的所有内容复制到新建的页面中 ,保存并命名为xxx.pyc文件

3.2 使用uncompyle6对.pyc文件进行反编译。

使用这条命令

uncompyle6.exe 111.pyc > 111.py

在这里插入图片描述
这样就得到了可以直接阅读的.py 文件。

4.代码分析

通过分析代码可以看出,这个题其实就是一个五阶幻方。

import time, sys, hashlib

class:

    def __init__(self):
        self.= {}
        self.= []
        self.= ''
        self.= []
        self.= 65

    def(self, えひ):

        def(f):
            self.[えひ] = f
            return f

        returndef(self,):
        return self..get()

    def(self):= 0
        while True:= self.[][0]= self.[][1]= self.[][2]= self.()(,)+= 1=()

@い.('し')
def f(a, b):
    if a == 1:.+= b


@い.('す')
def f(a, b):
    if a == 1:
        print(.)
    else:
        if a == 2:
            print(.)
        else:
            if a == 3:
                print((.flag), end='')
            else:
                print(a, end='')


@い.('せ')
def f(a, b):
    sys.exit()


@い.('そ')
def f(a, b):.= input()  #输入flag


@い.('た')
def f(a, b):
    time.sleep(a)


@い.('ち')
def f(a, b):
    if len(.) % 2 != 0:
        sys.exit()
    for i in.:
        if ord(i) > 52 or ord(i) < 48:
            sys.exit()

    x = str(hashlib.new('md5', bytes((.), encoding='utf8')).hexdigest())#对输入的flag进行MD5操作
    if x[:6] != 'e3a912':   #对MD5后的flag前六位进行判断,判断是否为正确的flag
        sys.exit().flag = x


@い.('と')
def f(a, b):               #对五阶幻方进行赋值,从1开始赋值到25结束= 0
    for i in range(0, len(.), 2):#这里也可以看出输入的flag其实就是坐标,变量a是横坐标,变量b是纵坐标。flag每两位是一组+= 1                      
        a = int(.[i])
        b = int(.[(i + 1)]).[a][b] = ふ


@い.('つ')
def f(a, b):                #对赋值了的五阶幻方进行判断。判断是否为正确的五阶幻方。其实,这里也就是给出了五阶幻方中的几个值方便之后逆向破解。
    if.[0][1] != 24 or.[4][3] != 2:
        sys.exit()
    if.[0][2] != 1 or.[2][3] != 20:
        sys.exit()
    if.[1][0] != 23 or.[3][4] != 3:
        sys.exit()


@い.('て')
def f(a, b):= 0
    if b == -1:
        for i in range(5):+=.[a][i]

        if!=.:
            sys.exit()
    else:
        for i in range(5):+=.[i][b]

        if!=.:
            sys.exit().= [
 [
  'す', 'welcome baby~ ', 0],
 [
  'す', 'input your flag~:', 0],
 [
  'そ', 0, 0],
 [
  'す', 'your input is:', 0],
 [
  'す', 1, 0],
 [
  'す', "let's check......", 0],
 [
  'た', 0.5, 0],
 [
  'し', 1, [[0 for i in range(5)]]],
 [
  'し', 1, [[0 for i in range(5)]]],
 [
  'し', 1, [[0 for i in range(5)]]],
 [
  'し', 1, [[0 for i in range(5)]]],
 [
  'し', 1, [[0 for i in range(5)]]],
 [
  'ち', 0, 0],
 [
  'と', 0, 0],
 [
  'つ', 0, 0],
 [
  'て', 0, -1],
 [
  'て', 1, -1],
 [
  'て', 2, -1],
 [
  'て', 3, -1],
 [
  'て', 4, -1],
 [
  'て', 0, 0],
 [
  'て', 0, 1],
 [
  'て', 0, 2],
 [
  'て', 0, 3],
 [
  'て', 0, 4],
 [
  'す', 'Goodjob!', 0],
 [
  'す', 'The flag is vnctf{', 0],
 [
  'す', 3, 0],
 [
  'す', '}', 0],
 [
  'せ', 0, 0]].()

解出来的五阶幻方是这样子的
在这里插入图片描述
附上解密脚本:

#include<cstdio>
#include<cmath>
#include<string>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<vector>
#include<queue>
#include<map>
using namespace std;
int main()
{
	int a[100][100];
	for (int i = 0; i <= 4; i++)
	{
		for (int j = 0; j <= 4; j++)
		{
			cin >> a[i][j];
		}
	}
	int k = 1;
	while (k <= 25) 
	{
		for (int i = 0; i <= 4; i++)
		{
			for (int j = 0; j <= 4; j++)
			{
				if (a[i][j] == k)
				{
					cout << i << j;
					k++;
				}

			}
		}
	}
	return 0;
	system("pause");
}
//这里的数字需要自己输入哦我比较懒就没有直接给数组初始化了
//嘻嘻,其实我就是菜忘记怎么二维数组初始化了,有会的大佬欢迎在评论区教我!!

在这里插入图片描述
将输出的数字MD5就得到了flag:e3a912c1e911ad82544af0c3d753f44f
最终就是vnctf{e3a912c1e911ad82544af0c3d753f44f}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值