TPCTF2023 re

比赛没打,赛后补题

maze

首先得知道这是个python打包的elf,先用pyinstxtractor解一下
TPCTF2023 re_第1张图片

解完以后平平无奇,反编译chal.pyc也只有导入maze运行run函数
那就只有一个maze.so可以分析
maze.so肯定是python打包成so了
通过手动python导入maze调用help可以看到maze库的很多东西,还可以把密文等参数打印出来
不过导入要满足一些条件

  • linux
  • python3.8
  • 满足文件依赖
    TPCTF2023 re_第2张图片
import maze
help(maze)
print('EqdU3uQNCi=',maze.EqdU3uQNCi)
print('UJ9mxXxeoS=',maze.UJ9mxXxeoS)
print('c2VjcmV0=',maze.c2VjcmV0)
print('regexes=',maze.regexes)

help整理的结果如下

NAME
    maze

CLASSES
    builtins.object
        Q2Fy
        Q2VsbA
        TWF6ZUxhbmc
    
    class Q2Fy(builtins.object)    # Car
     |  Q2Fy(value, x, y)
     |  
     |  Methods defined here:
     |  
     |  __init__(self, value, x, y)
     |  
     |  __repr__(self)
     |  
     |  ----------------------------------------------------------------------
     |  Data descriptors defined here:
     |  
     |  __dict__
     |      dictionary for instance variables (if defined)
     |  
     |  __weakref__
     |      list of weak references to the object (if defined)
    
    class Q2VsbA(builtins.object)    # Cell
     |  Q2VsbA(name, value)
     |  
     |  Methods defined here:
     |  
     |  __init__(self, name, value)
     |  
     |  __repr__(self)
     |  
     |  ----------------------------------------------------------------------
     |  Data descriptors defined here:
     |  
     |  __dict__
     |      dictionary for instance variables (if defined)
     |  
     |  __weakref__
     |      list of weak references to the object (if defined)
    
    class TWF6ZUxhbmc(builtins.object)    # MazeLang
     |  TWF6ZUxhbmc(code)
     |  
     |  Methods defined here:
     |  
     |  YWRkX2NlbGw(self, code)    # add_cell
     |  
     |  YWRkX2Z1bmN0aW9u(self, code)    # add_function
     |  
     |  Z2V0X2NlbGw(self, code)    # get_cell
     |  
     |  Z2V0X3Bvcw(self, pos, direction)    # get_pos
     |  
     |  __init__(self, code)
     |  
     |  aW5pdA(self)    # init
     |  
     |  b3Bw(self, direction)    # opp
     |  
     |  c3RlcA(self)    # step
     |  
     |  cnVuX3RpbGxfb3V0cHV0(self)    # run_till_output
     |  
     |  ----------------------------------------------------------------------
     |  Data descriptors defined here:
     |  
     |  __dict__
     |      dictionary for instance variables (if defined)
     |  
     |  __weakref__
     |      list of weak references to the object (if defined)

FUNCTIONS
    aW5pdF9zZWNyZXQ()    # init_secret
    
    c29sdmU(SvL6VEBRwx) -> 'int'    # solve
    
    exit(status=None, /)
        Exit the interpreter by raising SystemExit(status).
        
        If the status is omitted or None, it defaults to zero (i.e., success).
        If the status is an integer, it will be used as the system exit status.
        If it is another kind of object, it will be printed and the system
        exit status will be one (i.e., failure).
    
    run()

DATA
    EqdU3uQNCi= [18, 17, 15, 0, 27, 31, 10, 19, 14, 21, 25, 22, 6, 3, 30, 8, 24, 5, 7, 4, 13, 29, 9, 26, 1, 2, 28, 16, 20, 32, 12, 23, 11]
    UJ9mxXxeoS= 'IyMgIyMgIyMgIyMgIyMgIyMgIyMKIyMgIyMgIyMgXl4gIyMgXl4gIyMKIyMgIyMgIyMgLi4gIyMgSVogIyMgIyMgIyMgIyMKIyMgJVIgLi4gJUQgIyMgJUQgLi4gLi4gJUwgIyMKIyMgPj4gIyMgLi4gIyMgRUEgKiogUFAgJVUgIyMKIyMgJVUgSUEgVEEgIyMgRUIgKiogUFAgJVUgIyMKIyMgJVUgSUIgVEIgIyMgRUMgKiogUFAgJVUgIyMKIyMgJVUgSUMgVEMgIyMgRUQgKiogUFAgJVUgIyMKIyMgJVUgSUQgVEQgIyMgRUUgKiogUFAgJVUgIyMKIyMgJVUgSUUgVEUgIyMgRUYgKiogUFAgJVUgIyMKIyMgJVUgSUYgVEYgIyMgJVIgKiogSVogJVUgIyMKIyMgJVUgSUcgJUwgIyMgIyMgIyMgIyMgIyMgIyMKIyMgIyMgIyMgIyMgIyMgIyMKClBQIC0+ICs9MQpNTSAtPiAtPTEKSVogLT4gPTAKRUEgLT4gSUYgPT0wIFRIRU4gJVIgRUxTRSAlRApFQiAtPiBJRiA9PTEgVEhFTiAlUiBFTFNFICVECkVDIC0+IElGID09MiBUSEVOICVSIEVMU0UgJUQKRUQgLT4gSUYgPT0zIFRIRU4gJVIgRUxTRSAlRApFRSAtPiBJRiA9PTQgVEhFTiAlUiBFTFNFICVECkVGIC0+IElGID09NSBUSEVOICVSIEVMU0UgJUQKVEEgLT4gSUYgKiogVEhFTiAlTCBFTFNFICVECklBIC0+ID03MgpUQiAtPiBJRiAqKiBUSEVOICVMIEVMU0UgJUQKSUIgLT4gPTczClRDIC0+IElGICoqIFRIRU4gJUwgRUxTRSAlRApJQyAtPiA9ODQKVEQgLT4gSUYgKiogVEhFTiAlTCBFTFNFICVECklEIC0+ID04MApURSAtPiBJRiAqKiBUSEVOICVMIEVMU0UgJUQKSUUgLT4gPTY3ClRGIC0+IElGICoqIFRIRU4gJUwgRUxTRSAlRApJRiAtPiA9ODQKSUcgLT4gPTcwCkxUIC0+IElGID09NiBUSEVOICVEIEVMU0UgJUwK'
# secret
    c2VjcmV0= [7, 47, 60, 28, 39, 11, 23, 5, 49, 49, 26, 11, 63, 4, 9, 2, 25, 61, 36, 112, 25, 15, 62, 25, 3, 16, 102, 38, 14, 7, 37, 4, 40]
    regexes= {'wall': '##|``', 'path': '\\.\\.', 'splitter': '<>', 'pause': '[0-9]{2}', 'start': '\\^\\^', 'hole': '\\(\\)', 'out': '>>', 'in': '<<', 'one-use': '--', 'direction': '%[LRUDNlrudn]', 'signal': '(?<=\\*)[\\*A-Za-z0-9]', 'function': '[A-Za-z][A-Za-z0-9]'}
FILE
    /root/Desktop/maze.so

给定一个没有混淆的api和函数模块的debug功能,盲猜也不是不行【对于我来说无法手撕maze.so把函数逻辑还原,只能胡乱猜着构造】

下面这个是lchild的解题脚本

import maze
maze.aW5pdF9zZWNyZXQ()
flag = []
x0 = maze.TWF6ZUxhbmc(maze.base64.b64decode(maze.UJ9mxXxeoS).decode())
for i in range(33):
    flag.append(x0.cnVuX3RpbGxfb3V0cHV0() ^ maze.c2VjcmV0[i])
print(bytes(flag))
# TPCTF{yOu_@re_m@sT3r_OF_mAZElaN6}

nanoPyEnc

题目给了提示py,所以顺理成章的用pyinstxtractor解一下
然后pycdc反编译run.pyc

# Source Generated with Decompyle++
# File: run.pyc (Python 3.8)

Warning: block stack is not empty!
from secret import key, enc
from Crypto.Cipher import AES
from Crypto.Util.number import *
from Crypto.Util.Padding import pad
key = key.encode()
message = input('Enter your message: ').strip()
if not message.startswith('TPCTF{') or message.endswith('}'):
    raise AssertionError

def encrypt_message(key = None, message = None):
    cipher = AES.new(key, AES.MODE_ECB)
    ciphertext = cipher.encrypt(pad(message, AES.block_size))
    return ciphertext

encrypted = list(encrypt_message(key, message.encode()))
for x, y in zip(encrypted, enc):
    if x != y:
        print('Wrong!')
    
    print('Right!')
    return None

从表面上看起来也就是输入–>AES加密–>比对
首先from secret import key, enc,从secret把key和enc搞出来
反编译secret.pyc

#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
# Version: Python 3.8

key = '2033-05-18_03:33'
enc = [
    213,
    231,
    201,
    213,
    9,
    197,
    233,
    81,
    111,
    223,
    34,
    166,
    103,
    225,
    175,
    180]

拿去解密发现有问题

from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from numpy import byte

key = b'2033-05-18_03:33'
enc = [
    213,
    231,
    201,
    213,
    9,
    197,
    233,
    81,
    111,
    223,
    34,
    166,
    103,
    225,
    175,
    180]
def decrypt_message(key = None, message = None):
    cipher = AES.new(key, AES.MODE_ECB)
    ciphertext = cipher.decrypt(bytes(enc))
    return ciphertext
print(decrypt_message(key,enc))
# b'flag{test}\x06\x06\x06\x06\x06\x06'

那也只可能是对导入的库做了手脚了,结果就是在下面两个位置有问题

  • 首先第一个是Crypto.Util.number,反编译number.pyc,这才是真正的密文
    TPCTF2023 re_第3张图片
  • 但是并不影响解了以后还是不对,继续找Cipher,然后compat3有问题,如下的list函数

    最后把真正的密文异或1得到正确结果
from Crypto.Cipher import AES

key = b'2033-05-18_03:33'
enc = [153, 240, 237, 199, 63, 44, 237, 45, 25, 47, 97, 154, 158, 112, 46, 176, 219, 247, 44, 115, 169, 124, 64, 63, 121, 253, 250, 137, 34, 144, 33, 17, 182, 9, 16, 247, 249, 41, 165, 114, 87, 231, 222, 242, 126, 30, 124, 237]
enc = [i^1 for i in enc]
def decrypt_message(key = None, message = None):
    cipher = AES.new(key, AES.MODE_ECB)
    ciphertext = cipher.decrypt(bytes(enc))
    return ciphertext
print(decrypt_message(key,enc))
# b'TPCTF{83_C4u710U5_0F_PY7hON_k3YW0Rd_sHadOWIN9}\x02\x02'

这个确实是比较抽象,只能是猜到库做了手脚,然后对拍找问题…

其他题的话:apple目前不打算看了,研究gun apl对我来说没啥用,剩余的慢慢复现

你可能感兴趣的:(python,linux,开发语言)