安洵杯SYCTF2023misc方向wp

转载请备注来源

sudoku_easy

简单的数独交互,几个小注意点,每次发送level之后sleep5秒才会返回题目

image-20230610185716309

  • 将形如

    ---------------------

    800103720

    023840650

    410006008

    300001062

    000052407

    072060090

    160000375

    205019846

    000030000

    ---------------------

​ 转换成二维数组进行解数独,并将返回结果重新转换成多行字符串形式

def parse_input(input_list):
    board = []

    for row in input_list:
        nums = list(map(int, row))
        board.append(nums)

    return board

def format_output(board):
    formatted = ""
    for row in board:
        formatted += "".join(map(str, row)) + "\n"
    return formatted.strip()
  • 一开始以为每次获得5分,要拿到120分,range了24次,一直出问题,后来发现获得分数是递增的,同时调试了一下发现拿到120分会返回一个getshell,因此修改一下range7次

    最终脚本:

def find_empty(board):
    for row in range(9):
        for col in range(9):
            if board[row][col] == 0:
                return row, col
    return None


def is_valid(board, num, pos):
    row, col = pos
    for i in range(9):
        if board[row][i] == num and col != i:
            return False
        if board[i][col] == num and row != i:
            return False

    box_row = row // 3
    box_col = col // 3

    for i in range(box_row * 3, box_row * 3 + 3):
        for j in range(box_col * 3, box_col * 3 + 3):
            if board[i][j] == num and (i, j) != pos:
                return False

    return True


def solve(board):
    find = find_empty(board)
    if not find:
        return True
    else:
        row, col = find

    for i in range(1, 10):
        if is_valid(board, i, (row, col)):
            board[row][col] = i

            if solve(board):
                return True

            board[row][col] = 0

    return False

def parse_input(input_list):
    board = []

    for row in input_list:
        nums = list(map(int, row))
        board.append(nums)

    return board

def format_output(board):
    formatted = ""
    for row in board:
        formatted += "".join(map(str, row)) + "\n"
    return formatted.strip()

# input_string = '''---------------------
# 800103720
# 023840650
# 410006008
# 300001062
# 000052407
# 072060090
# 160000375
# 205019846
# 000030000
# ---------------------
# now give me you solve:'''

# lists=input_string.split('\n')[1:10]
# board = parse_input(lists)
# print(board)
# solve(board)
# print(board)

from pwn import *

# 创建连接
conn = remote('47.108.165.60',27539)

# 接收欢迎信息
for i in range(7):
    msg = conn.recvuntil("Please input:").strip().decode("utf-8")
    print(msg)
    # 发送选择
    conn.sendline('1'.encode())

    # 接收下一步提示
    msg = conn.recvuntil("Please select the level:").strip().decode("utf-8")
    print(msg)

    conn.sendline('5'.encode())

    msg = conn.recvuntil("clock start").strip().decode("utf-8")
    print(msg)
    time.sleep(5)

    msg = conn.recvuntil("now give me you solve:").strip().decode("utf-8")
    print(msg)
    lists = msg.split('\n')[1:10]
    board = parse_input(lists)
    solve(board)
    solved = format_output(board)
    conn.sendline(solved.encode())

conn.interactive()

getflag

image-20230610190212900

烦人的压缩包

爆破

image-20230610190304845

jpg文件尾压缩包

image-20230610190322841

提取出来直接解压提示crc报错

image-20230610193516762

观察后发现store算法却有着极高的压缩率明显不合理

image-20230610193550071

改一下压缩方式和解压方式为default(单单改解压方式也够了)

image-20230610193624253

解开后ook解密

image-20230610193746752

sudoku_speedrun

小小升级版数独,telnet交互

kali :: ~ 127 » telnet 47.108.165.60 37569
Trying 47.108.165.60...
Connected to 47.108.165.60.
Escape character is '^]'.

Ubuntu 22.04.2 LTS
Welcome to Play Sudoku Game!
Play(1)
Exit(2)
Please input
> 1

Tips:
R to replay
Q to exit
WASD to move
You have 10000ms to solve it :)
Please select the level
easy(5)
normal(6)
hard(7)
>5

image-20230610193910056

这次需要解出之后通过移动光标将数独还原

其实大差不差,这里主要几个点

  • 题目用了ANSI转义码,读取数据时会有大量的乱码,需要replace掉

    response=response.replace(b'\x1b[7;32m',b'').replace(b'\x1b[0m',b'').replace(b'\x1b[1;32m',b'').replace(b'\x1b[H\x1b[2J',b'')
    
  • 这里我为方便采用了在每一行右移填补到最后之后,往下再重新左移到最左边,再开始下一行的右移填补,而不是用左移填补导致需要倒着索引,略微增加了时间复杂度

    def solve(input_string):
        original_board = parse_input(input_string)# 创建原始数组的副本
        board_copy = [row[:] for row in original_board]
    
    
        solution = solve_sudoku(original_board)
        # print(board_copy)
        # print(solution)
        lists=[]
        for i in range(9):
            for j in range(9):
                if board_copy[i][j] == 0:
                    lists.append(str(solution[i][j]))
                if j != 8:
                    lists.append('d')
            lists.extend('saaaaaaaa')
                # print(f"索引为 ({i}, {j}) 的位置,填入数字 {solution[i][j]}")
        return lists
    
  • 读取到形如

    ‘’’

    -------------------------

    | 4 3 0 | 0 0 6 | 2 0 0 |

    | 8 0 0 | 0 7 0 | 0 0 3 |

    | 2 0 7 | 0 5 0 | 1 4 6 |

    -------------------------

    | 0 0 0 | 0 0 0 | 0 7 5 |

    | 7 5 0 | 8 0 0 | 6 2 0 |

    | 0 2 9 | 7 3 5 | 0 1 0 |

    -------------------------

    | 5 6 0 | 4 0 3 | 0 9 0 |

    | 0 0 2 | 5 0 0 | 8 0 0 |

    | 3 0 1 | 0 8 2 | 0 6 4 |

    -------------------------’’’

    转二维数组

    def parse_input(input_string):
        rows = input_string.strip().split('\n')
        board = []
    
        for row in rows:
            row = row.replace('-', '').replace('|', '').split()
            nums = [int(num) if num != '0' else 0 for num in row]
            if nums!=[]:
                board.append(nums)
    
        return board
    
  • 经过尝试后发现只要发送数组服务器便会执行移动与填充操作,例如发送[‘d’,‘d’,‘1’]光标会右移两个单位并填入1

    最终脚本:

import telnetlib
def solve_sudoku(board):
    if is_complete(board):
        return board

    row, col = find_empty_cell(board)
    for num in range(1, 10):
        if is_valid(board, row, col, num):
            board[row][col] = num
            if solve_sudoku(board):
                return board
            board[row][col] = 0

    return None

def is_complete(board):
    for row in board:
        if 0 in row:
            return False
    return True

def find_empty_cell(board):
    for i in range(9):
        for j in range(9):
            if board[i][j] == 0:
                return i, j
    return None, None

def is_valid(board, row, col, num):
    # Check row
    if num in board[row]:
        return False

    # Check column
    for i in range(9):
        if board[i][col] == num:
            return False

    # Check 3x3 box
    box_row = (row // 3) * 3
    box_col = (col // 3) * 3
    for i in range(box_row, box_row + 3):
        for j in range(box_col, box_col + 3):
            if board[i][j] == num:
                return False

    return True

def parse_input(input_string):
    rows = input_string.strip().split('\n')
    board = []

    for row in rows:
        row = row.replace('-', '').replace('|', '').split()
        nums = [int(num) if num != '0' else 0 for num in row]
        if nums!=[]:
            board.append(nums)

    return board

def solve(input_string):
    original_board = parse_input(input_string)# 创建原始数组的副本
    board_copy = [row[:] for row in original_board]


    solution = solve_sudoku(original_board)
    # print(board_copy)
    # print(solution)
    lists = []
    for i in range(9):
        for j in range(9):
            if board_copy[i][j] == 0:
                lists.append(str(solution[i][j]))
            if j != 8:
                lists.append('d')
        lists.extend('saaaaaaaa')
            # print(f"索引为 ({i}, {j}) 的位置,填入数字 {solution[i][j]}")
    return lists

tn = telnetlib.Telnet('47.108.165.60',36697)

welcome_msg = tn.read_until(b"Please input")
print(welcome_msg.decode("utf-8"))

# 发送返回值到服务器
tn.write("1".encode("utf-8") + b"\n")

msg = tn.read_until(b"hard(7)")
print(msg.decode("utf-8"))

tn.write("5".encode("utf-8") + b"\n")

msg = ''
for i in range(15):
    response = tn.read_until(b"\n")
    # print((response))
    response = response.replace(b'\x1b[7;32m',b'').replace(b'\x1b[0m',b'').replace(b'\x1b[1;32m',b'').replace(b'\x1b[H\x1b[2J',b'')
    msg += response.decode().strip('> 5')
tn.write(str(solve(msg)).encode("utf-8") + b"\n")
tn.interact()

image-20230610195935427

cancellation

浅恰了个三血还行

题目得到noise.mp4,意外的发现用windows media player播放可以读到一串sstv

image-20230610200317154

结合file用Matroska打包猜测应该是mkv文件

image-20230610200410070

用mkvtool发现确实有多个音频轨道

image-20230610200535476

mkvextract.exe提取出来两个音频(轨道是从0开始的,mkvtool里的轨道编号从1开始的)

image-20230610201638810

轨道3可以读到一张图

image-20230610200931537

轨道2可以读到一个模糊无法识别的二维码,仔细观察可以发现背景图似乎就是轨道3读到的图

image-20230610201035296

在测试过程中发现在一定位置挂上notch之后,可以读到很清晰的后半边的二维码,左半边变得更加模糊了,但却更加清晰的显示出背景图,明显就是轨道3的图

image-20230610201214671

再结合题目名,大胆猜测轨道2的sstv做了一个叠加处理,尝试几次后2*轨道2-轨道3可以扫描出正确的图像(这里放完整二维码图片会被csdnban掉)

import librosa
import soundfile as sf
import numpy as np

audio1, sr1 = librosa.load('2.wav', sr=None)
audio2, sr2 = librosa.load('3.wav', sr=None)

result =  2*audio1-audio2
sf.write('result.wav', result, sr1)

image-20230610215510870

扫描的结果解base64得到图片

image-20230610202014820

拿到flag

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值