TPCTF2023 re

比赛没打,赛后补题

maze

首先得知道这是个python打包的elf,先用pyinstxtractor解一下
在这里插入图片描述

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

  • linux
  • python3.8
  • 满足文件依赖
    在这里插入图片描述
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,这才是真正的密文
    在这里插入图片描述
  • 但是并不影响解了以后还是不对,继续找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对我来说没啥用,剩余的慢慢复现

  • 13
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

UmVfX1BvaW50

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值