sudoku

119次阅读
没有评论

sudoku

拿到程序之后 发现是一个顶着python图标的exe程序

capoo@DESKTOP-4JQA10R:/mnt/c/Users/15589/Desktop$ strings sudoku.exe | grep -i pyz | head
Installing PYZ: could not get sys.path object!
Failed to append PYZ entry to sys.path!

发现里面封装了pyz,直接用pyinstxtractor.py反编译

python pyinstxtractor.py sudoku.exe

反编译之后发现一个sudoku.pyc文件初步怀疑是真正的源码,直接交给网站逆向

在线Python pyc文件编译与反编译

得到下面的代码

# uncompyle6 version 3.9.2
# Python bytecode version base 3.8.0 (3413)
# Decompiled from: Python 3.6.12 (default, Feb  9 2021, 09:19:15) 
# [GCC 8.3.0]
# Embedded file name: sudoku.py
import numpy as np

def check(lst):
    check = [i for i in range(1, 17)]
    return sorted(lst) == check


def check_line(input_array):
    for i in range(16):
        if not check(input_array[i]):
            return             return False
        return True


def check_boxes(board):
    for i in range(0, 16, 4):
        for j in range(0, 16, 4):
            nums = board[i][j[:j + 4]] + board[i + 1][j[:j + 4]] + board[i + 2][j[:j + 4]] + board[i + 3][j[:j + 4]]
not check(nums)            return             return False
        else:
            return True


def check_column(input_array):
    array = np.transpose(input_array)
    for i in range(16):
        if not check(array[i]):
            return             return False
        return True


def check_sudoku(input_array):
    return check_line(input_array) and check_column(input_array) and check_boxes(input_array)


def fill(m, input_value):
    k = 0
    for i in range(16):
        for j in range(16):
            if m[i][j] == 0:
                m[i][j] = int(input_value[k], 16) + 1
                k = k + 1
        else:
            return True


sudoku = [
 [
  4, 6, 14, 1, 0, 16, 12, 5, 9, 8, 0, 2, 15, 3, 10, 0],
 [
  9, 8, 3, 12, 15, 4, 7, 10, 0, 13, 16, 6, 11, 14, 1, 2],
 [
  5, 15, 7, 2, 13, 1, 6, 14, 3, 0, 10, 12, 8, 9, 0, 4],
 [
  10, 11, 13, 16, 8, 3, 9, 2, 1, 15, 0, 4, 6, 12, 5, 7],
 [
  14, 10, 4, 3, 6, 5, 15, 16, 8, 0, 13, 7, 1, 2, 9, 11],
 [
  15, 13, 16, 11, 9, 2, 10, 8, 6, 14, 3, 1, 4, 7, 0, 5],
 [
  7, 9, 1, 8, 0, 14, 4, 3, 2, 5, 11, 10, 16, 13, 15, 6],
 [
  12, 2, 6, 5, 1, 0, 13, 7, 15, 9, 4, 0, 14, 8, 3, 10],
 [
  3, 14, 2, 9, 5, 0, 16, 13, 7, 0, 1, 15, 12, 4, 11, 8],
 [
  8, 1, 5, 15, 4, 6, 11, 9, 12, 3, 2, 14, 13, 10, 7, 0],
 [
  16, 12, 0, 7, 14, 8, 2, 15, 13, 4, 9, 11, 3, 5, 6, 1],
 [
  6, 4, 11, 13, 7, 12, 3, 0, 10, 16, 5, 8, 9, 15, 2, 0],
 [
  13, 5, 15, 10, 16, 7, 14, 12, 4, 1, 6, 9, 2, 11, 8, 3],
 [
  1, 3, 0, 6, 10, 15, 5, 4, 11, 2, 8, 13, 7, 16, 14, 9],
 [
  11, 7, 9, 14, 2, 13, 8, 6, 16, 10, 12, 3, 5, 1, 0, 15],
 [
  2, 16, 8, 4, 3, 9, 1, 0, 14, 7, 15, 5, 0, 6, 0, 12]]
input_value = input("Please input the value to fill the blank:\n")
fill(sudoku, input_value)
if check_sudoku(sudoku):
    print("You done it!\nGive you!\nhgame{%s}" % input_value)
else:
    print("You lose my game!")

发现是一个数独程序,其中flag就是我们输入用来填充数独的数字 用16进制表示
这里直接给出payload

from z3 import *

# 初始数独
sudoku = [
 [4, 6, 14, 1, 0, 16, 12, 5, 9, 8, 0, 2, 15, 3, 10, 0],
 [9, 8, 3, 12, 15, 4, 7, 10, 0, 13, 16, 6, 11, 14, 1, 2],
 [5, 15, 7, 2, 13, 1, 6, 14, 3, 0, 10, 12, 8, 9, 0, 4],
 [10, 11, 13, 16, 8, 3, 9, 2, 1, 15, 0, 4, 6, 12, 5, 7],
 [14, 10, 4, 3, 6, 5, 15, 16, 8, 0, 13, 7, 1, 2, 9, 11],
 [15, 13, 16, 11, 9, 2, 10, 8, 6, 14, 3, 1, 4, 7, 0, 5],
 [7, 9, 1, 8, 0, 14, 4, 3, 2, 5, 11, 10, 16, 13, 15, 6],
 [12, 2, 6, 5, 1, 0, 13, 7, 15, 9, 4, 0, 14, 8, 3, 10],
 [3, 14, 2, 9, 5, 0, 16, 13, 7, 0, 1, 15, 12, 4, 11, 8],
 [8, 1, 5, 15, 4, 6, 11, 9, 12, 3, 2, 14, 13, 10, 7, 0],
 [16, 12, 0, 7, 14, 8, 2, 15, 13, 4, 9, 11, 3, 5, 6, 1],
 [6, 4, 11, 13, 7, 12, 3, 0, 10, 16, 5, 8, 9, 15, 2, 0],
 [13, 5, 15, 10, 16, 7, 14, 12, 4, 1, 6, 9, 2, 11, 8, 3],
 [1, 3, 0, 6, 10, 15, 5, 4, 11, 2, 8, 13, 7, 16, 14, 9],
 [11, 7, 9, 14, 2, 13, 8, 6, 16, 10, 12, 3, 5, 1, 0, 15],
 [2, 16, 8, 4, 3, 9, 1, 0, 14, 7, 15, 5, 0, 6, 0, 12]]

# 创建 16x16 的整数变量网格
X = [[Int("x_%s_%s" % (i, j)) for j in range(16)] for i in range(16)]

# 创建求解器
s = Solver()

# 约束:每个单元格在 1 到 16 之间
s.add([And(X[i][j] >= 1, X[i][j] <= 16) for i in range(16) for j in range(16)])

# 约束:已知格子固定
for i in range(16):
    for j in range(16):
        if sudoku[i][j] != 0:
            s.add(X[i][j] == sudoku[i][j])

# 约束:每行不同
for i in range(16):
    s.add(Distinct(X[i]))

# 约束:每列不同
for j in range(16):
    s.add(Distinct([X[i][j] for i in range(16)]))

# 约束:每个 4x4 宫不同
for i0 in range(0, 16, 4):
    for j0 in range(0, 16, 4):
        s.add(Distinct([X[i0 + di][j0 + dj] for di in range(4) for dj in range(4)]))

# 求解
if s.check() == sat:
    m = s.model()
    # 提取空白格的值(按顺序)
    solution = [[m.evaluate(X[i][j]).as_long() for j in range(16)] for i in range(16)]
    
    # 按原数独 0 的顺序收集
    blank_values = []
    for i in range(16):
        for j in range(16):
            if sudoku[i][j] == 0:
                blank_values.append(solution[i][j])
    
    # 转成十六进制字符(0~F)
    hex_str = ''.join(hex(v - 1)[2:].upper() for v in blank_values)
    print("Flag: hgame{" + hex_str + "}")
else:
    print("No solution")

正文完
 0
评论(没有评论)