Misc

数学天才

Challenge

森莫?要爆零了!那来签个到吧。

hint:试炼一和试练二两个一起看解压葵花宝典

Solution

数学天才.txt给出的提示如下:

小伙子,我看你骨骼清奇,必是旷世奇才,那就考验一下你的悟性吧!
试炼一:斜下对角线的数字,是打开葵花宝典的密钥。
试炼二:为师不想要死,为师喜欢$。
试炼三:你是第60位前来考核的人员,想想该怎么读懂葵花宝典呢?

sdpcctf2025-1

题目给的图片是一个杀手数独(Killer Sudoku),要求实现:

  1. 标准数独的规则(行、列和3×3方块不能重复)
  2. Killer Sudoku特有的笼子(cage)约束
  3. 使用回溯算法寻找解决方案
python
# 初始化问题N = 9sudoku = [[0,0,0,0,0,3,0,8,0],          [3,0,0,1,0,0,0,0,0],          [6,0,0,0,0,0,3,0,0],          [0,0,0,0,6,0,7,0,0],          [0,0,0,9,0,0,0,0,4],          [0,6,0,0,0,5,0,0,0],          [0,0,8,0,0,0,4,0,9],          [0,7,0,3,0,0,0,0,0],          [0,0,4,0,9,0,0,0,0]] cages = [    (6,[(0,0),(0,1)]),    (6,[(0,2),(0,3)]),    (25,[(0,4),(0,5),(1,5),(2,5)]),    (23,[(0,6),(0,7),(1,6),(1,7)]),    (11,[(0,8),(1,8)]),    (24,[(1,0),(2,0),(3,0),(4,0)]),    (17,[(1,1),(2,1)]),    (10,[(1,2),(1,3),(2,3)]),    (12,[(1,4),(2,4)]),    (14,[(2,6),(2,7),(3,6),(3,7)]),    (9,[(2,8),(3,8)]),    (14,[(2,2),(3,2)]),    (6,[(3,1),(4,1)]),    (16,[(3,3),(4,2),(4,3)]),    (19,[(3,4),(3,5),(4,4),(5,3),(5,4)]),    (19,[(4,5),(4,6),(5,5)]),    (14,[(4,7),(5,7)]),    (22,[(4,8),(5,8),(6,8),(7,8)]),    (9,[(5,0),(6,0)]),    (19,[(5,1),(5,2),(6,1),(6,2)]),    (5,[(5,6),(6,6)]),    (26,[(6,3),(7,3),(8,3),(8,4)]),    (6,[(6,4),(7,4)]),    (14,[(6,5),(7,5),(7,6)]),    (9,[(6,7),(7,7)]),    (10,[(7,0),(8,0)]),    (19,[(7,1),(7,2),(8,1),(8,2)]),    (12,[(8,5),(8,6)]),    (9,[(8,7),(8,8)]),] # 创建cage_map,将每个单元格映射到它的笼子cage_map = {}for cage_sum, cells in cages:    for cell in cells:        cage_map[cell] = (cage_sum, cells) def print_sudoku(board):    """打印数独"""    for i in range(N):        if i % 3 == 0 and i != 0:            print("-" * 22)        for j in range(N):            if j % 3 == 0 and j != 0:                print(" |", end="")            print(f"{board[i][j]:2d}", end="")        print()    print() def is_valid(board, row, col, num):    """检查在指定位置放置数字是否合法"""    # 检查行    for x in range(N):        if board[row][x] == num:            return False        # 检查列     for x in range(N):        if board[x][col] == num:            return False        # 检查3x3方块    start_row, start_col = 3 * (row // 3), 3 * (col // 3)    for i in range(3):        for j in range(3):            if board[start_row + i][start_col + j] == num:                return False        # 检查笼子约束    cage_sum, cage_cells = cage_map[(row, col)]    current_sum = num        # 计算当前笼子中已经填充的数字之和    for cell_row, cell_col in cage_cells:        if board[cell_row][cell_col] != 0:            current_sum += board[cell_row][cell_col]        # 如果已填充的数字之和超过了笼子的和,则不合法    if current_sum > cage_sum:        return False        # 如果这是最后一个未填充的单元格,检查总和是否正好等于笼子的和    remaining_cells = sum(1 for r, c in cage_cells if board[r][c] == 0)    if remaining_cells == 1 and current_sum != cage_sum:        return False        return True def find_smallest_empty_cage(board, cage_map):    """找到具有最小可能值的空单元格(用于优化)"""    for i in range(N):        for j in range(N):            if board[i][j] == 0:                return (i, j)    return None def solve_killer_sudoku(board, cage_map):    """使用回溯法解决killer数独"""    # 找到一个空位置    empty_pos = find_smallest_empty_cage(board, cage_map)        if not empty_pos:        return True  # 没有空位置,问题已解决        row, col = empty_pos        # 尝试填入1-9之间的数字    for num in range(1, N+1):        if is_valid(board, row, col, num):            # 如果当前位置有效,则尝试填入            board[row][col] = num                        # 递归尝试解决剩余部分            if solve_killer_sudoku(board, cage_map):                return True                        # 如果当前数字导致后面无解,回溯            board[row][col] = 0        # 尝试了1-9都不行,返回False    return False # 解决 Killer Sudokusolution = [row[:] for row in sudoku]if solve_killer_sudoku(solution, cage_map):    print_sudoku(solution)else:    print("无解")

运行即可得到输出

text
 2 4 1 | 5 7 3 | 9 8 6 3 9 7 | 1 8 6 | 2 4 5 6 8 5 | 2 4 9 | 3 1 7---------------------- 8 5 9 | 4 6 1 | 7 3 2 7 1 3 | 9 2 8 | 6 5 4 4 6 2 | 7 3 5 | 1 9 8---------------------- 5 3 8 | 6 1 2 | 4 7 9 9 7 6 | 3 5 4 | 8 2 1 1 2 4 | 8 9 7 | 5 6 3

提取出主对角线上的数字295425423,根据试练二给出的提示用“25$23`

解压得到的葵花宝典.txt内容如下:

text
DJ?ELtbo`0+o8F0Eb2G9dPN

Rot47->Rot13解码得到flag:

sdpcctf2025-2

flag
flag{R3@1_M@th_g3niu5!}

small_challenge

Challenge

看了半天,没有收获?其实亦有收获。

Solution

解压得到

sdpcctf2025-3

binwalk提取得到一个压缩包,里面包含压缩包flag.zip和下面这张图片

sdpcctf2025-4

用StegSolver的Image Combiner将两张图XOR处理,得到下面这个DataMatrix条码

sdpcctf2025-5

在线阅读Data Matrix条码扫码得到:

text
<E:8E?W^Z<=tEZ)=lP6n>;.Tg>q@+!/6=B)/6_%hLg*.rH<gLN

base85解码得到:

text
UV!W_X_YZ,U,Y∈[0,9], V,W,X,Z∈[A,z]

这就是压缩包密码的范围

先用John the Ripper提出哈希

text
zip2john flag.zip > hash.txt
text
flag.zip/flag.txt:$pkzip2$1*1*2*0*26*1c*405453ef*0*26*8*26*4054*5c53*c8ca4c0435c8b2f6eeb7fe58830b8956e16b669b8c970b8086fea94f45902d111e440e655857*$/pkzip2$:flag.txt:flag.zip::flag.zip

前后删一下把它修改成hashcat能识别的格式

text
$pkzip2$1*1*2*0*26*1c*405453ef*0*26*8*26*4054*5c53*c8ca4c0435c8b2f6eeb7fe58830b8956e16b669b8c970b8086fea94f45902d111e440e655857

然后用hashcat进行掩码攻击

text
hashcat -a 3 -m 17200 --custom-charset1=?d --custom-charset2=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ "hash.txt" ?1?2!?2_?2_?1?2

不到1分钟就解出来了

text
$pkzip2$1*1*2*0*26*1c*405453ef*0*26*8*26*4054*5c53*c8ca4c0435c8b2f6eeb7fe58830b8956e16b669b8c970b8086fea94f45902d111e440e655857*$/pkzip2$:9h!Y_a_8D

因此解压密码就是9h!Y_a_8D,解压得到flag

flag
flag{It3_s0_3@syIlIlIIlIllI}