Real World CTF 5th Re_Ferris_proxy_wp

 

 

 视频讲解:

https://www.bilibili.com/video/BV1gY411R7gs/?spm_id_from=333.337.search-card.all.click&vd_source=87f7ad8544d4c3ad070c5c2ff28b7698

第一次认真逆向rust程序,逆了好久,rust逆向经验+1
发现ida在动态调试方面真是个弟弟,gdb调试才是唯一真神,hhh
ghrida的反汇编能力也是极强,结合IAD一块分析简直爽歪歪

一、rust逆向技巧

1、关键函数位置

我这里所说的关键代码指的是作者自己写的代码,他们一般和main函数属于同一命名空间,在IDA的函数表里直接搜索main函数的命名空间即可
 
0

2、block_on函数 + async语法创建的异步代码块和函数

我在逆向多线程rust的时候发现,rust 对async处理是比较复杂的
0
(之前我一直以为他是回调函数 (逃...))
我手动写了一个案例
0
用IDA反编译进入main函数查看,发现main函数内部没有明显的调用异步函数或代码块的操作,而是直接调用block_on函数堵塞当前线程
0
 
经过漫长的搜索和交叉引用发现,异步函数或代码块被block_on内部的内部的内部...的内部的某个函数调用,它被藏得太深了,很只通过读伪代码很难寻其踪迹
但这样的异步代码块其命名空间和main函数命名空间是相同的(也就是和生成的文件名相同)
0
在ida中我们可以通过直接搜索函数的方式找到这些异步代码块
tokio::spawn的函数也可以用这种方法分析

3、字符串

rust的字符串存储不以 \x00 为结尾,所以在ida中,我们经常看到一大堆毫不相关的字符串被连接到了一块
rust 用结构体存储字符串,存储方式大致是这样的:
struct string{
    __int64 len;
    __int64 char* str;
}

4、浮点数

用c语言编写,gcc编译的程序,浮点数会被ida直接识别出来,伪代码以小数的方式呈现出来
而rust编写的程序不这样
案例:
0
IDA并不会自动把他识别为浮点数,仍然16进制的形式显示
0
 

5、除法

rust的加法,减法,乘法都是正常的,但其除法比较有讲究
 
0
 
0
他检查了是否除以0的情况

6、Delay关键字

rust的关键字 延迟执行
 
0
他的伪代码和函数名在ida中是这样的:
 
0
函数名上带有 Delay
所以说,遇到延迟执行的异步函数或代码块,我们直接在ida中搜索delay即能找到函数

7、命名格式

使用IDA在逆向的时候经常见到这种长长的函数名
_$LT$$RF$mut$u20$F$u20$as$u20$core..future..future..Future$GT$::poll::h0c253c03b9c05ada
(1)、$LT$ 代表的是生成的类型的泛型名称
0
(2)、$u20$ 是 Unicode 编码中空格字符的编码,它被用来替代 ASCII 码中的空格。 这种命名格式可能用于在类型名称中使用点号和空格的问题。
(3)、.. 代表 :: 作用域
用ghrida 进行反编译可以发现完整的正确的函数名
我们也可以使用ghrida进行逆向,其可以很好的识别函数名字(有符号的前提)

8、有的linux标准库函数通过syscall实现

比如getrandom函数
0
我们在导入表里找不到他,但strace 却能检测到
注意辨识

9、函数参数之字符串传递

x64参数传递是 rdi rsi rdx rcx r8 r9
rust的字符串参数传递
源代码:
 
0
反汇编:
 
0
可以发现 rdi 寄存器记录了字符串, rsi记录字符串的长度,rdx记录字符串,rcx记录该字符串的长度,r8,r9记录其他参数
0
但IDA和ghrida认为最后传递过去的参数只有四个:
0
分别是rdi rdx r8 r9
 
而当 字符串和长度只能有一个值通过寄存就传参的话,r9寄存器传递长度,堆栈传递字符串
0
 
0
 

10、rust函数返回值经常保存在rsa寄存器中

 
 
 

11、以tokio为命名空间的大部分函数

rust代码中调用了bind函数
 
0
 
会发现代码中会出现好多 bind函数
0
一般先调用bind的函数函数名较短的,后调用的函数名很长,而且后调用的函数其函数名包括了先调用的函数名,而且先调用的bind函数内部基本上代码很少
就像这样
 
0
后调用的函数代码则很多
0
后调用的函数就像前面函数的具体实现
 
之后我们在逆向tokio 命名空间的函数时,可以把其放入IDA的函数搜索框里直接搜索,然后找长的函数进行逆向分析
0
 
0

12、擅用函数导入表

程序使用了什么函数一定会在ida中有所对应,在面对一些加密库的时候,比如openssl ,我们很难逆向它,但我们可以通过导入表中的函数来猜测使用了哪些解密算法

13、结合ghrida进行逆向分析

ghrida对代码的反汇编以及符号的利用要比ida强,我们可以以ida为主,ghrida为辅进行逆向分析

14、利用strace工具对程序的执行进行初步了解

注意,对多线程程序,一定要开启 -f 命令,进行全面的函数跟踪

二、逆向程序

两个没有去除符号的rust通信程序
逆向环境: win10主机 + ubuntu20
逆向工具: IDA7.7(静态分析) + Ghrida(静态分析) + gdb(动态调试) + strace(跟踪系统调用函数) + chatgpt(询问函数功能)

1、查看导入表

发现大致使用了rc4、RSA、aes加密、sha256哈希摘要

2、strace 程序

 strace  -s 4096 -i -f ./server > text1.txt
 strace  -s 4096 -i -f ./client > text2.txt
程序大致行为:
server程序运行建立tcp监听 8888端口
client程序运行与server 8888端口连接后(此过程没有发生tcp数据的接送),监听12345号端口
之后程序线程被堵塞死
尝试使用脚本和client的12345端口建立通信
import socket
import time

tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

server_addr = ("192.168.190.128", 12345)
tcp_socket.connect(server_addr)


dataaa = b"0123456789abcdef0123456789abcdef"
tcp_socket.send(dataaa)
recv_data = tcp_socket.recv(1024)  # 接收1024个字节
print('接收到的数据为:', recv_data.decode('gbk'))
tcp_socket.close()
client在与python脚本建立联系后,开始向server接送数据
0
并且调用了getrandom函数,在对程序行为有了大概认识后,我们开始逆向程序

3、开始逆向client

由于client和server所作的工作相似,挑选一个认真逆向即可
首先是client::client::main 函数
0
其调用了 block_on函数堵塞了当前进程

4、分析 client::main::_$u7b$$u7b$closure$u7d$$u7d$::h36985f3a7fbd50d6 函数

0

5、rc4绑定流

000055555548131B 函数的位置
该函数进行了rc4加密与Tcp流、Duplex流的绑定
lib::protocol::rc4::Rc4<tokio::net::tcp::stream::tcpstream,_tokio::io::util::mem::duplexstream>
::new<tokio::net::tcp::stream::tcpstream,_tokio::io::util::mem::duplexstream>
0

6、之后的所有操作

之后的逆向分析有点无聊,简化成地址 => 功能的形式了(基址为0x555555400000):
# 000055555548131B stream流绑定RC4

# 00005555554577E2 getrandom 生成随机密钥 

# 00005555554578EF 使用RSA公钥加密随机密钥

# 00005555554579A3 向流中写入RSA加密随机密钥的长度 (2字节)

# 0000555555457B98 向流中写入RSA加密随机密钥后的数据

# 0000555555457CE2 从流中读取 2字节

# 0000555555457F6A 从流中读取 数据,数据大小和上次读出两字节的值有关

# 00005555554581C7 使用RSA私钥解密从流中读取的数据

# 0000555555458274 真正的 ex_keychange 函数, 把随机密钥和rsa解密的值进行异或

# 0000555555458388 sha256 摘要 ex_keychange 异或后的值

# 00005555554583AC 把sha256加密后的结果写入流中

# 000055555545850F 从流中读取32个字节

# 0000555555458686 从流中读取的字节和sha256加密后的结果做比较,即进行校验

# 00005555554807D1 => 000055555545951E => 0000555555458DFD => 000055555545B394  调用getrandom 函数获取16字节

# 00005555554807D1 => 000055555545951E => 0000555555458DFD => 000055555545B4D9 => 00005555555B9582  AES 128 cbc 加密 
# 其中刚刚生成的随机密钥是 iv, ex_keychange 得到的16字节数据是 key , 第三方客户端输入的数据是 密文 cip


# 00005555554807D1 => 000055555545951E => 0000555555458DFD => 000055555545B606 (000055555545B0C6) 把AES加密后的密文和其他36字节送入流中
# 初步猜测,含有iv 密文

三、分析流量包

1、rc4解密流

分别收集server发送的tcp数据包和client发送的tcp数据包,进行rc4解密
from scapy.all import *
from Crypto.Cipher import ARC4 as rc4cipher
from struct import pack,unpack


u32 = lambda x: unpack('>I', x)[0]
u16 = lambda x: unpack('>H', x)[0]
def deRc4(cip):
    key = b"explorer"
    enc = rc4cipher.new(key)
    s = enc.decrypt(cip)
    return s



cli_wire_data = b""
src_wire_data = b""
wire = rdpcap('flag2.pcapng')
for pkt in wire:
    cip = bytes(pkt[TCP].payload)
    if pkt[IP].dport == 8888:
        cli_wire_data += cip

    if pkt[IP].sport == 8888:
        src_wire_data += cip


cli_wire_data = deRc4(cli_wire_data)
src_wire_data = deRc4(src_wire_data)
print(cli_wire_data)
print(src_wire_data)
得到的数据大概长这样:
0
不难发现这些数据存在规律,每隔一部分数据总会有12字节的相似的部分,经过实验和有依据的猜测
这12字节的数据包含了后面紧跟着的数据的信息,就像某结构的头信息似的

2、分析数据

我们打印出头结构数据:
脚本如下:
from scapy.all import *
from Crypto.Cipher import ARC4 as rc4cipher
from struct import pack,unpack


u32 = lambda x: unpack('>I', x)[0]
u16 = lambda x: unpack('>H', x)[0]
def deRc4(cip):
    key = b"explorer"
    enc = rc4cipher.new(key)
    s = enc.decrypt(cip)
    return s



cli_wire_data = b""
src_wire_data = b""
wire = rdpcap('flag2.pcapng')
for pkt in wire:
    cip = bytes(pkt[TCP].payload)
    if pkt[IP].dport == 8888:
        cli_wire_data += cip

    if pkt[IP].sport == 8888:
        src_wire_data += cip


cli_wire_data = deRc4(cli_wire_data)
src_wire_data = deRc4(src_wire_data)


def  extrat_real_data(wire_data):
    tcp_data = {}
    idx = 0
    while idx < len(wire_data):
        head_structure = wire_data[idx:idx+12]
        data_size = head_structure[3] -  8
        idx += 12
        print(head_structure)
        if data_size == 0:
            continue

        elif data_size  > 0:    # 存在数据
            tcp_data_type = head_structure[8:12]
            if tcp_data_type not in tcp_data.keys():
                tcp_data[tcp_data_type] = b""
            
            realdata = wire_data[idx:idx+data_size]
            # print(head_structure)
            # print(realdata)
            tcp_data[tcp_data_type] += realdata
            idx += data_size
        else:
            print(head_structure)
            assert 0
    return tcp_data

# cli_tcpdata =  extrat_real_data(cli_wire_data)
srv_tcpdata =  extrat_real_data(src_wire_data)

数据如下:

client:

b'\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00'
b'\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x01'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x00'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x00'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x00'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x00'
b'\x00\x00\x00\n\x00\x00\x00\x01\x00\x00\x00\x00'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x01'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x01'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x01'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x01'
b'\x00\x00\x00\n\x00\x00\x00\x01\x00\x00\x00\x01'
b'\x00\x00\x00(\x00\x00\x00\x01\x00\x00\x00\x01'
b'\x00\x00\x00(\x00\x00\x00\x01\x00\x00\x00\x00'
b'\x00\x00\x00,\x00\x00\x00\x01\x00\x00\x00\x00'
b'\x00\x00\x00,\x00\x00\x00\x01\x00\x00\x00\x01'
b'\x00\x00\x00<\x00\x00\x00\x01\x00\x00\x00\x00'
b'\x00\x00\x00<\x00\x00\x00\x01\x00\x00\x00\x01'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x00'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x00'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x00'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x00'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x00'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x00'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x00'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x00'
b'\x00\x00\x00\x1c\x00\x00\x00\x01\x00\x00\x00\x00'
b'\x00\x00\x00\x08\x00\x00\x00\x02\x00\x00\x00\x00'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x01'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x01'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x01'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x01'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x01'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x01'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x01'
b'\x00\x00\x00,\x00\x00\x00\x01\x00\x00\x00\x01'
b'\x00\x00\x00\x08\x00\x00\x00\x02\x00\x00\x00\x01'
b'\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x02'
b'\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x03'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x03'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x03'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x03'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x03'
b'\x00\x00\x00\n\x00\x00\x00\x01\x00\x00\x00\x03'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x02'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x02'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x02'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x02'
b'\x00\x00\x00\n\x00\x00\x00\x01\x00\x00\x00\x02'
b'\x00\x00\x00(\x00\x00\x00\x01\x00\x00\x00\x03'
b'\x00\x00\x00,\x00\x00\x00\x01\x00\x00\x00\x03'
b'\x00\x00\x00<\x00\x00\x00\x01\x00\x00\x00\x03'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x03'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x03'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x03'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x03'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x03'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x03'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x03'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x03'
b'\x00\x00\x00\x1c\x00\x00\x00\x01\x00\x00\x00\x03'
b'\x00\x00\x00(\x00\x00\x00\x01\x00\x00\x00\x02'
b'\x00\x00\x00,\x00\x00\x00\x01\x00\x00\x00\x02'
b'\x00\x00\x00<\x00\x00\x00\x01\x00\x00\x00\x02'
b'\x00\x00\x00\x08\x00\x00\x00\x02\x00\x00\x00\x03'

server:

b'\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00'
b'\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x01'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x01'   
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x01'   
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x01'   
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x01'   
b'\x00\x00\x00\n\x00\x00\x00\x01\x00\x00\x00\x01'  
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x00'   
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x00'   
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x00'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x00'
b'\x00\x00\x00\n\x00\x00\x00\x01\x00\x00\x00\x00'
b'\x00\x00\x00(\x00\x00\x00\x01\x00\x00\x00\x00'
b'\x00\x00\x00(\x00\x00\x00\x01\x00\x00\x00\x01'
b'\x00\x00\x00,\x00\x00\x00\x01\x00\x00\x00\x00'
b'\x00\x00\x00,\x00\x00\x00\x01\x00\x00\x00\x01'
b'\x00\x00\x00,\x00\x00\x00\x01\x00\x00\x00\x00'
b'\x00\x00\x00,\x00\x00\x00\x01\x00\x00\x00\x01'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x00'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x00'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x00'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x00'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x00'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x00'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x00'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x00'
b'\x00\x00\x00\x0c\x00\x00\x00\x01\x00\x00\x00\x00'
b'\x00\x00\x00\x08\x00\x00\x00\x02\x00\x00\x00\x00'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x01'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x01'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x01'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x01'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x01'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x01'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x01'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x01'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x01'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x01'
b'\x00\x00\x00,\x00\x00\x00\x01\x00\x00\x00\x01'
b'\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x02'
b'\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x03'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x03'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x03'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x03'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x03'
b'\x00\x00\x00\n\x00\x00\x00\x01\x00\x00\x00\x03'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x02'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x02'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x02'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x02'
b'\x00\x00\x00\n\x00\x00\x00\x01\x00\x00\x00\x02'
b'\x00\x00\x00(\x00\x00\x00\x01\x00\x00\x00\x03'
b'\x00\x00\x00,\x00\x00\x00\x01\x00\x00\x00\x03'
b'\x00\x00\x00,\x00\x00\x00\x01\x00\x00\x00\x03'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x03'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x03'
b'\x00\x00\x00H\x00\x00\x00\x01\x00\x00\x00\x03'
b'\x00\x00\x00<\x00\x00\x00\x01\x00\x00\x00\x03'
b'\x00\x00\x00(\x00\x00\x00\x01\x00\x00\x00\x02'
b'\x00\x00\x00,\x00\x00\x00\x01\x00\x00\x00\x02'
b'\x00\x00\x00,\x00\x00\x00\x01\x00\x00\x00\x02'

 

我们把除头结构外的数据分别打印并整理出来:
client:
 0  =>   64  =>   b'\x01\x00\x1d\xb2\xeeTx7\xc2\xb09O\x93\x16\xa3\xc6r\x10\x9c\x85Gi\xd9b|\xe7\x15\xaa\x82\xaev\xafO\xc7\xd4h\x90?\xfaO|\x9dJ\xfc\xf19R\x8c\xeb$\xcb_d\xa1\x92(r\x82\xee\x7f\xd0v\x99/'
 1  =>   64  =>   b'\xe7?\ns\x0b\x98\xe02\xe9\n\xfa\xf7;\x8d\xda\xb1\xe8!C,>\x1c,Q9i\x14\xf5?\xb3\x04\xf2l\xbc\x8f\x85\xechF/\xf8]\xfb\tyd\x8dC\x002\x91\xcc\xb9A\x8e{@\x16\xf5\xd32]@\x83'
 2  =>   64  =>   b'\xd4LZ\xffA\x0f(\xc8A\xfbQ\xc2\xe9\x82$M\x7fsp\xfbks\xd6\xe5\xca\xbaV\xc1\xb4\xb8\xf9k\xea\x19\n\xa8\xd6n~7\xd7o\xe2\xe5\xfe\xf7\xf7\x8b\r\xe9\x0e\x12\xee\xfd\xa3\xa3awX4\x12\xca\x07N'
 3  =>   64  =>   b'\x96\xa1yj\xf8g\xe4@\xa7.\xe8\x1e6\xe0_;s\xc34\x1faf\xb8\x04\xbf\x83\xc3\xd0\xb4}\xf7L\xc7t\x05Y\\\xe4M<\xcf\xb79Ik\x8a\xcbx\xfd\xb0+\xcdQ\x08Q\xb3\xe3\xde\x01_\xc0n\xad\xb4'
 4  =>    2  =>   b'\x0f\x8e'
 5  =>   64  =>   b'\x01\x002\x0b\x11\x98\t\xb7\x93\xab\xf3W\xa7\xf7\x8b\x07B\xee\x93\xa9W\xe5c\xa5\xa9O\xdb\t\x80N\x89Yo%\x97\xa2\xcb\x9a\xe9\xf5\x16\x1d_\xda\x88\xff\x05\x0eG\xb1\xd2\x8b\xeb\xc6V4e\xd2\xe7\x95\x9e\x8abJ'
 6  =>   64  =>   b"\xcd9\xb2\x05<\x17\x02\x1f\x93\x03\x0e;\x9b\xc7\x14\x9f\xf5B?\xafdi92\xf7j\x8d\xbf\xfaRo\xff|\x07hE\xb1\xd3\x19g\xef\xca\x0bV\xb0f\xe8\xba\xce\xdc\x19'\xe6)\xc6\xd0\xe8\x7fa\xbf\x14\xee09"
 7  =>   64  =>   b'\x05=f\x8e\xf1\x85T&%|\xe6\x8c\xdb\xc2\xf6i\x19\xa2\xf9\xef\xbc\xb62\xda\xa6\x17\x0c\xb8$j\xb7\xa24\x802\xf4\x8c\xef\xdb\xc3\xaa\xdc\xeek\x9a\xb8g7\x13F\xbb\xe9\x0f\xd6\x9d!7\x05\xed\x1d\xe3\x89"\xb3'
 8  =>   64  =>   b'E\xbb\xbf\x8e\x0b\x10\xc5CnYt\xf4d&\xd3\xef\xdb\xea\xba\x81\x9e\xa5\xd0I\xbbB\x02\x19\xa4&3n\x14\xbc6\xe5u<\xb7\x1f\xb2\x1a+x\xf6\x99\x91\x8a\x00E\xa8\xba\xdd\xddidn\xd6ZY\xe1\x7f\xee\xc8'
 9  =>    2  =>   b'\xb3\x0c'
10  =>   32  =>   b'P?\xdd&s\t\x86aB\xae\x96\xb3\x19u\x15\xb7,\xcdvm\xed\xbc\t\xd6\x1c%\xf0\xc3\xfay\xeb\xd4'
11  =>   32  =>   b'*\xcc\xc9f\xcc\xafH\xa1GG\x11q\xfb\x95\x89\xc9\\V\x11\x00\xd6T\x8a\xd9y\xf3(\xe4;\xcf\xe0u'
12  =>   35  =>   b'\x00\x00\x00\x10#\xa5E~\x1f\xa2\xe2\xf4\xa22B\xb1\xe6\x1aY}\x14X\xbe\xe4\x87\x1eoD\xe9)h\x01G(0'
13  =>   36  =>   b'\x00\x00\x00\x10\xbdh\x8b\xc8eyrs\x0f\x1d\x9a\\4\x0c\xd5U`)W\xfaD\xcfd4#\xbb#sK\xf8I\x0b'
14  =>   51  =>   b'\x00\x00\x00\xa6\xf9^\xc8\t\xba\xc6x\xaa\x1fJt\xa0\tN\x00\xd3>B\xda\x05s1\xc9Za\xc6\xb5\xc3\xcd$\xda\xef\xeb6~\x01\xd3v^\x91d>7\xe2\xac\x95\xe9'
15  =>   51  =>   b"\x00\x00\x00\x18O\xf5\x94\x0cG\xe4\xfcB\xa2\xbd\x1fa\xb3\x04\xf5\xfd\xfc^E1\x04\xa3\x94m\x06\xc4\x89z\x86\xf7\xd2\x87,\x94\x8f\xf0k'\x0bM\x02DF\xdf\x8b`\xfa"
16  =>   63  =>   b'\x00\x00\x02\x00D\xf4\xcfd\xa9\x05\xe4p\xa2\xd8\t\x1eS\xc0\xb8\xa3p\x19?\xe4G(4\x0cECa\xc8Ex\xf3\xb4i\x96=\x12\xfa`\x8a\xb9k\xf2\xe8\xc9\xc2\x11`\x10\xd5\x0e\x15\x1bd\x070\x8d<\xb6\xa2'
17  =>   64  =>   b'\xbc\x02\x02jv\xb5\xbe\x1df\xcf\x03\xd9\x0e\xa50:P\x91\xb4\x8d7\n\xc1\x86@!8`m\xa3\\\x90\xfe~\xfb\n!\xf0\xa1w\x89oIk\xa4\x0f\x02\xe0y\xb8"\x18\xbe\x01$\xab}\xe5\xd4\xf4\x8c\xfd\x92\x1e'
18  =>   64  =>   b'2=(G\xd08\x80\xfa\\\xb4\x853\x93\x91A\x11\\=\xc1_\xa3*\x82\xbeY\xd7\x88&\xe3\xd3\x7f\\\xac\x12\x01\x0c\xe1\x0c\x85\r\xf66&\xf9FW\xa5\xbe\xac\xf7\xd5\x02\xb5\x9f\xc1\x0fW\x19Y\xcea\x01\xb8\xd6'
19  =>   64  =>   b'pNT\x1c\x93\x0c\xa3\xa8\xd1V\xd7\xf6\x12/\xda{\xbd\xff\xed\x9b\x9b\xc6\x16\x0fN\xc8\xac\xe4\x89x\xbdE\x88i\xa66\xa7\xd8y\x8d}\xbdP>\x0cA\xaa\xd8$\x96W\x8d\xf4\xfb\xff\xbd<\\\x88]\xc0\xbd=\xee'
20  =>   63  =>   b'mj\xf1\xef\xc8#e\xf1a\x92\x86\xe7\xa6\x12\x15]\x87\x03\x8fL\xcb9\xe2^\x06`\xf9\xf2\xd3\xaeC!\x99ki\x18{\xa6\x8a\xbd\xf3\xe6\xabA\xab\xfa-\xd3Y\xc7\xea\xa5\xd3D\xfc\x1a\xcb\x97\xb5\x8d\xd4M\x86'
21  =>   64  =>   b'\xd4D\xd1|\x16^\xe7\x8e\x1dU\xf5\xc4+\x1f\x1b\xcf\x9c\x0f0%\x88\xb6\x8d&\xd2\xa3\x08%\x0cB\xd1\xdf\x13\xbe\x07i:\xa0\xf4,\xef\xcb\x9d\xc1h\x82\x16G\x8a\x1a\x04\x1c\x9a\x0cf0\x8b>JQ5\xfd/\x0f'
22  =>   64  =>   b',}\x9d\xf8\x1c|\x9c\xcbt"\x08\x9f\x94\xc0\xfaT\x06~lO\xc64\xc7%\xc9\xaa\x97\x10\xaa\xed\xd6q\xf7,\xf9(\x7f8\xdea\x11\xac\xe6\xc0\xc3.\xd5hV\x9bEt:\xbf\xc5\x19\xe2:\xab\xcc\xdf0\xa9\xaf'
23  =>   64  =>   b'\xd1\xbb\xca\xb1"M\xaf\x8c\xcf\xb5\xe6\xdb\xf4.\xe9$\x93[\x99\x0e\xeez\xbep\xacU7Bb6\xe0\xff\x1b*\xc4t\x8cf]:\xbaa\xc4hW\x98\xaeb\x12m\x89"\x0c\xd5\xae\x8cj|2\xe3<\xe1#m'
24  =>   20  =>   b'\xb8\x02\x08\x8e^0<\x83\x89\x88\x0c\t\xc3\x92PS\xcc!\x08%'
25  =>   64  =>   b"\x00\x00\x01\xd0o\xe6\xd3\xc4\xb7v\x1f\xfe\xa3\xde\xa5\xca\x1bu0_;\xd8(\x92^\x04\x1b\xaa\xbc\x00\xaaQ\xf9>]Y\xaal\\\x02N\x1d\xe9<\xca\xbb\xccw6'\x1d\xe06e\xa2\xb1p\xa4/\xac\xa2\xe8i\x98"
26  =>   64  =>   b"lkP\xfe\xcdN\x0e\x1a\x9c\xa0p\xfa\xfa\x04\xc0j\x12\xf2z\xf9MT0\xcc\xce\x12\x9a\xdag\xc3\x04\rDKw'X\x19Sf\x02Rg\xbf\xea\x9e5\xcb\xaa\xf8\x16\x02+4u]Z\xc2\xa4\xd7\xdf\x85w2"
27  =>   64  =>   b'\xed\xe0\xbf`\xb0\xca#\xf4\x065\xdc\xbd\xa7n\xaf;Y\xfa\xa1@\xde\xe0\xb2H\n\xac\xd8\xdfv[\xa5\xcf\xd14\x7f"\xc9AP\x06!\x0e\xb4\xf2$3+\\\xfc\xac{\xe9\x8e\r\xa9Oti=\x8a\xf2.\x1f\xad'
28  =>   63  =>   b'\x06\x14\xfe\xad\xa5\xc2\xaaINa\xa0\xb2\xa8H\xb8(3\x86\rl\x12\x13\xc4\xac\xee\xbc\xbeU\xf4\x19@>\xcd\x8485\xf1O,\xaa\x83\x10\xbek\xfa\xd7\xadT\xdfP\nT&\x8b\x17S\x01\x83\xefLI\xf1\xc5'
29  =>   63  =>   b'\x1e\xd3?">c#V\x01*BHL\x12A\xd4\x1e\xc5Bk\xa9L\x0cH\x87\xa8k\x86\xb4\x1a\xc7<\xa8\xb7\x9d\x90%m9\x11\x90\xbc\xb2%n\x88\x16B\xc5\xa0\xfb\xc1xi\x1c\xf9\xec\x98>\x1f\x1d\xb4\x00'
30  =>   64  =>   b',PCS\r(\xce\x81\xe8\x9c\nq\xba\xeb\x82\x1f\xf0$\r\x18\xfb\xac\x0e\x01\xb0\x95+\xb6+\x915E\x97\xb9\x06\x1d\xc4@1\x8c\xe3\xea\xbd\x95t&\x07TlAN\xbf=\xa3(y\xb2\xaf5\x00\xd0\x8c\xb4\xe9'
31  =>   64  =>   b'\xb4\x04\xa5);\x85\xaa\xda\xa3\xd5\x95\xd3\x89\x92\xc2\x19\xdd\xd7\xa4\xe5\xf0\x0c\t\xafG~\xea\x99G{=S\xackg\xc4\x9f\x0c\xbdZ\x7f\xf08\x90M\xfc\x1a;X\xca\xbe,%\xdc\xb8o\xa5ZS\xf3\xd3b\xf0Q'
32  =>   36  =>   b'(\xbfY\x16g\xdc\xd1\xd6\x00\xab\xe1\xdbH\xf4\x9b\x17\xa5\xad\x9dVP\xf7y:\xf7\xa2CA\xb7q\xa9$\x7f\x1e\xb4\x80'
33  =>   64  =>   b'\x01\x00\xab\xcf\x92Ev\xdec\x08|\x86\x95\xcc\xda7\x05\xe8g\x0cw\x0f+\xfd\xa1\xda\xfd\xed\xdc\xd0\x9b*\xa6\xd4\x85\xc6\xa8\x7f\xf3\x1c\x140\r\xdbf\x05v\xce\xedR\x04s\x18\xa3\r<\x05\xc9\x84\x8b\n\x1f\xb0S'
34  =>   64  =>   b'\x87\xd3x\xe9\xcb\xb8\x91NIjc5\x95\xc7\xf6\x8d\xa0\x97\xaf\xd4\xfb\xd08\x0bN\xaf\xe7\x90\xff\xe9\x99\xb8\x1c\xee\xff2\xee\xa4\xd8\xfaBy`l|I\x1e\xc4\xebJ~\xf5\xbfaC\x07\xc2\x1b\xd3\xa3\x14\xdb\x9d.'
35  =>   64  =>   b'\xe9\xf5\x05\xf0\x8cFN\x1f_\x12;\xcc\x18\x03\x05\xbbZ0\xf2\xc3\x82I:\x1c\xc6\xd6\xe5\xe1\x89\xe7YP\xf7\\\x8ay\n\xef,\x1f\xae\x18Cl\x9doH@\xa9\xea\xcb\xf0A9\xa2\xb2PB\xc2\x7f:?\xd7V'
36  =>   64  =>   b'\xfa\xea\xff\x92\xd71\xe3T\xd0=\xc4l\xbe\x8a\x00\x11\x88\xdd\xe3^u<%\x9d\xe3Y\x18\x16x\xd9NG\xd9\x07\t4_l\x99u(\x8d\xbe\xcf\xe1\xa6\xcf.\xb7\xa1Ix\x85K\xbcs\xd3\xac}\nr\xcc>\xf4'
37  =>    2  =>   b'\xc4\x1a'
38  =>   64  =>   b'\x01\x00\xd9/A\xb7[\xb8\xce\xd6\xbe/\xbb\xc0\xba\x1c\xfe\xee\xbd\xf1X&\xce\x92\xbax\xefL\xd0\xf6\xd4\x7f\xf0N\x9eY<\xfc_\xc7\xea\xc8\x10\x9e\xff\xce~u\xf5G\x87:\xb5Y\x18h\x85\xed\xf0\xe5\x19\xf7:\xed'
39  =>   64  =>   b'CB\x1e\x08\xde\xa7\x9f\xd1(\x89\xb2\x84\\\xa3e\x80;\xb4\xaa#\xc5\r\x0c)\x8efI\x12\x1bm\x91\x01\xf3-\x15\xa0C\xff\xdb\xc9>vea\x7f\xa7\xb4\xb3\xf0\x1d\xb7oTr\xc5\xaa:\x08]\xa5h>\xfc\xc4'
40  =>   63  =>   b"\xbf\x9a$\r\xf9\xaf\xc3YmK6\x13\xae\x9a!\x844\x05a\xc8\x96\xa6\x0c\xc5w\xe6\xcaP{^eH\xcc\xfc\xd8\xbc\xcf'\xdes\xde\xaa\xf0O\xabpz\xc6\xaa\x94\xfe\xbd\xf8\xa0\xa5S,\x0fLs\x95\x8e\x11"
41  =>   64  =>   b"\xfc\x147V|\xcd\x88kT\x96\xca\xbb\x11y\x93\xf3\x1a\xfe%\xf5=\x92r\x18w\x89.G+\xf8\xbb\xa1t;\x82~'\x7fP\rQ\xb7\xf7OF\x82\xe9C\xbe\r>\xbf\xdc0t.!\x1d\xc3\xeb\xa5\x1d\xac\x8b"
42  =>    2  =>   b'\x90t'
43  =>   32  =>   b'\xe86%`\x16\xa5\xf8\xca\x1e)s+s2\xd9wk\xdcf\x94\xa9\xdfl\x11r\x18?e\x91o\x83\xd5'
44  =>   36  =>   b'\x00\x00\x00\x10\xf4l\xbfh\x96\xbe\x85\x8f\\/\x86\xee<\x16#Y\xc5E\xb1\xf5\xbd\x1e\xec\x0c\xd0>+{\xf9\xc1\xb4\xb9'
45  =>   51  =>   b'\x00\x00\x00\xc5\x80\xaa\x8a\xad\x81\xa2\x80\x0f\xad\xf7GI\xe7\x9c2=\xa6Zm\x11\xe8\xfbQ}`\xba6\xa0\x11;4[\xe7\xc0\xfc\xe3\x90\xfb\xa6dwkgm\x82\xfd\xbe'
46  =>   64  =>   b'\x00\x00\x02\x00"\x92\xa5\x93\xb6\x8f\xdb\xf6\x15\xd4<\x127G\xcf\x1f\x15\x83a\x97\x086\x8bG\x1bJ7\xc8\xee\xd2\x1e\x07\xd1J{\xf3\t\xf4S5Y!4\xc5\xccz\x18\x15-\xe2\x0b\xb7\xd2\xfbu;\xee\x911\xd9'
47  =>   64  =>   b'0v\xa9\xd5~\xfa7\x9eO\x7fG\x00\x11mxlXkIR4T\xdd\x9b:\xe7\xcf\xde\x04\x16\xd9\xbf\xbbHn\xed1\xf8\x8f\xec\x81(\xcd\x1e\x0b\xf7\x83\xc8\x97\x8c\x04\xfd\xe5\xf1\xbb\xe6~\xcb\xe1\xc7n\x05\x96\xf5'
48  =>   64  =>   b'W\x9b\xbd\xb3\x11\t<*;\xb5\x8b\x84\x8b\xe8\x83\x02\xab+\xb6\xc2K\xf0v\xa6\x94\xde+/\xa1\xa8\xef\xf5?\xca\xa6\x80\x0e\x93\x8b\xde\xee\x83\x14\x98\xfc\xc7,\xc9\xb8"\xda\xd5\xb2\x07M[\xc2\x92\xc7f\xe4L\x13\xe0'
49  =>   64  =>   b"1\xff\xfa\x944Vv\xf2\x94\xec\xeb%\x9b\xaaQ\x10rg\x13j\xf1\xe8)\x86\x8e\x1a<^%\x14Q{\xfc\xfa\xecxx:\xfd\xe2\x87Lm/L\xb8Cn\xd4!\xe6\x7f\xe3'\xe8\xc6|\x85\x1d\xa9Dn\xf2&"
50  =>   63  =>   b'\xda\xff1\x94`\x9b\xf5\xa0\\\x1en\xc1\xe0\x85\x85Bu\xee\x81\xdb\xee\x01\xc9.,\xb3W\xfa\xeb\xa8\x11BK\x80\xbd\x9bMpgZ\xaf\x02o/#\xbb\x0e\x88"q\xba\xd3O\xf5)L\xc0\\\xd7\xfc\x07@\xac'
51  =>   64  =>   b'K[I\xca\x00\x9d\x186\xcf\xa1v\x11*\xafwu\xfa\x8c$\x1b\xd4_\x86\x1c\x1e\xec4\xdd+\x96T\xe8\x14Lt\xc1\xf8\x0c\x9e\x0f#\xca\xe4P:\xe8]\xe9u\xf7M%\x0b\xe6g\xa1\xf6(\\\x99Q\xa8\xf8\xc9'
52  =>   63  =>   b"/\xb4\xe2\xdd2\xd6\xfd\xd7\xe9?\xe2N#\xb9v\x99\xe1\xb1/]\x9c\xaem\xae}\xf3@\x1e3\x93\x1a\x8a\xf6X\x03\xc1S\x87\x16\xbd\xba\x05\x94\x8c\x88\x18\xf9'\x91\x01\x0e\xf8\xd6\xd3\x15\xfb\x97\xbc\xcd\xf2\xc2\xfb\xbf"
53  =>   64  =>   b'\xb9|\xd2\xe8\n#-\xcfA}\xa8\xac\x1b\x83[\xf9\xda\xb1X\x16\xbc\x1e.\x0c\x07!NS\x1a\xc9"\xca/]\xdb\xb2o\x8dY\x98\x05\xfe\xb5\xf6\xae\x1cn?\xe0\x8e\xf5\xcf}\xbd`\xeb@x\x92\xd6\xe7*g\xa3'
54  =>   20  =>   b'\xe7\xd7\x81\xf1\x8bg]\xad\x11\xf1\xf4\x96\x00\x05~\x80\x94b\x8a\xd0'
55  =>   32  =>   b'J\xc9\xc8{gM\xcd\x93-.\x9d:K|\x16\xa3\x98\x9eu\x0f\xa3\xa8\x89^\x8d\xd0\x97\x1cV\xfb\x96x'
56  =>   36  =>   b'\x00\x00\x00\x10\xcfl\xa6|\xfeY\xcd_\x11\x0c\x15\x86\xde\x9c!\x86\xcf\xb7!7\x84\x04?\xfb\x01\x7f\xdf\\\xfat\xac2'
57  =>   51  =>   b'\x00\x00\x00\xa0:\x82\xba\xe4b\x7f\xc7M\xe8\xc7T7\xe5\xb0w\xaa=c\xe5t_a\xf4sb\x95K\x80\xf5>\xdehg&v\x05\xb78?U\xe6\xa8\n\xef\xca\xe1S'  
server:
 0  =>   64  =>   b'\x01\x00\xbblKvw\xbe\xe4\xb0\xa91\x06\x96\xa0b\x9d\x007\r\x0c\xf4\xd4\x87\x02\xb3\xd8\xd4\xe4\x9b\xc8\x9b\x0e\xd4P\xdb\xa14\x9f!\xc3*\x98\x00\x0fu>9\xaf"\x99\xe8$\x04\xfd\xddH"\x90\xc3\xd8\xf7L|'
 1  =>   63  =>   b'\xa1\xcdv8\xba\x83\x9c\xcc\xc0\xe6\x05\xfe?\x8f\x1b\xe6f\xe8O\xab\xe5\x07\xd4Q\t~\xf3\xd1\x93\x99\xde\x8f\r[`p\x9c\x80kN\x0f\xb8\xf0\xc4\x1b\xa0!\xa0\x86\xd8\x1e\x16f\xaa\xd4\x11\xbbhX\xf0\xcf\xb2('
 2  =>   64  =>   b'\x08\xe8]\xae\x9c\xdf\x93pj\xcc\x01)n\xb5\x05\xcd7/\x8b{\xc7\xf9\x86\x19\xf7\n\x1c\xbc\xb1)\xaa>\xcc?\x1f7\x16\x07\n\xa0\xe3d\xff\xf5K\xf8B\xa2\xd6\x1cH\x18\x8cb1w\xfc\x03}4;\xf2[\x04'
 3  =>   64  =>   b'\x9c~&\xc5.\xa5\xf6\x968\xa1\x9atU\xa7c\x95\x83\xad.\xd2\xc98\x83\x12;\xccD.J\x0c\xaaa&\xc6z\xd9\xb8\xa9\xc45\x15\xcc"gAQ\x7f\xc1+U\xa9\xa7\x99^\xc1l!\x0f\xe8\xcd\xc8\xb9\xdfl'
 4  =>    2  =>   b'C\x0e'
 5  =>   64  =>   b"\x01\x00\xb22W\xfe\xc2\xb6?Y\x9e\xb52v:\xc8w\x81\xfd\xdc<\xc3\xb2\r\xa7A\xca\xe5\xf1\xdap^\x90t\xa9\xff\xb0\xe3\x91\x98\xcf\x12'\x1b5C2\xa2\x1e\xc5\xed\x89Z\xbd&r{^\x0c\xad\xd5\xb6\x14\x1e"
 6  =>   64  =>   b'\x0bw\x8b\xb9\xbe\xe6\x81\x07:\xfe\x9f\xea\xc5\xf8;A\x87\x9f?4\xd3\xc7\x18\x88z\x86\x8d#)\x9c\xe4\xaa\xc7u|\xa7\x17l\xf4\x14\xebb$\n\x8fX"\xe6\x03I\xdc\x94N\x17\x8b\x83\xa7\xb6b\xef\x93H\xe2\x04'
 7  =>   64  =>   b'^F\xfc\xd4\xec\xa9\x06\x00\xe4\x86\x0f\x05\x04\xf63\xc9*\xf9i\xe6\xdd\x8bX\xc4\x89\xa9\xa6\x06\x8c\x8ccy\xc9@\xb2?\xf1\x9fU\xde\xeci\xc8\x87\xe9\xe1\xc0k\xc8\xb0\x9f9\xfa\x97\x08\xd8\xd1UE\x977:\xf8\xad'
 8  =>   64  =>   b'M\xb4\xb9\x03j\xa8\x99\x89\xa6X\x14,\xa7y\xd8\xda\xe4\x9e\xe3\xea\xc1Nq\x89\x92h\xc9p\xb4\xa31\x00l\xdf\xb3\x11gV\x8d\x11\xb3\xc5\x95\xa0d\x9c\xb4\xf8x*\x9b\x8b9^\xaa\x8cf(\x7f\xe9K]"\xf2'
 9  =>    2  =>   b'\xac\xa5'
10  =>   32  =>   b'*\xcc\xc9f\xcc\xafH\xa1GG\x11q\xfb\x95\x89\xc9\\V\x11\x00\xd6T\x8a\xd9y\xf3(\xe4;\xcf\xe0u'
11  =>   32  =>   b'P?\xdd&s\t\x86aB\xae\x96\xb3\x19u\x15\xb7,\xcdvm\xed\xbc\t\xd6\x1c%\xf0\xc3\xfay\xeb\xd4'
12  =>   36  =>   b'\x00\x00\x00\x10\xca\x9aX\xd5\xc9SfM\xa8\xd4\x9e8\x81\x8b\xb2\xe1$\x95\x83"\xeds#\x07\xbb\x0f\x1f-G\xeb\x05t'
13  =>   36  =>   b'\x00\x00\x00\x10\xf8\x1a\x9c~\xfa\\B\xa2\x1b\xdf\x8f\xba;.\xb5\xd4F\x10\xa3aHf\x9b\xb0\xb6s\xf5\x16x\xc8s0'
14  =>   36  =>   b'\x00\x00\x00\x10\xf2p6\x0b\xbe\xd1\x912\xa5\x8c\x8f\x10\x8ca\x87R\xa6\x81Yt\xc1\x15\xfc\x8e\xfb\xaa\xdc\xe5\xe3u\xcf\xfa'
15  =>   35  =>   b'\x00\x00\x00\x10\xeaP\xf4:\x94U\x9b\xb4~#\x85\x8a\xae\x9b\x0c\xdb\xa9J\x02tC\x8e"\t/\xd5yg\x8eD\xbe'
16  =>   64  =>   b'\x00\x00\x01\xf0\xa6\x97@/\xdb\xc1\xea\xdd\xe2-\x9f"k\xe5\xd8I\xf9\x93\xbbB\xc8\xa48\x02\xb4"\xdf\xa6\x9f/XNN\xcc\xa5\xc7q\xb9\xb6I\x87\xf6\x07%7\xbf-\x06.\xa11\x1fO\x94\t\xf2\xb7\xba\xcd\xb6'
17  =>   64  =>   b'\xc2\x11\xe7\xba\x91s\x96\xd7\xc2s\xb2\r\xac\xd00\x08\x94\x83\xfa\xf9\xd6Dv\xe2\xf7"\x9e\xbe7\xce\xaf\x81\xa7\xa9\x94/\xc2\xaaS\xc6lb\x99\xb5+\xa7KC\x80\x9a\n\xa1\x90\xfa\x9f\xbc\xc5\xf9I\xd3\x13\x14\x0b\xe5'
18  =>   64  =>   b"\xa9\xdf\\\xab\xcdl<\xc3E\x80\x9f\xe9\xe3\xc6'E\xde\x16\r_qJ$\x8cz\x9c1\x89l\x8cK\xea\x03.\\0\x1f/d\xdf\xc5\xcf\xc6\x01\xdc\x1f\xa2j\r\x80\xaa\x9aE\xb3>\xf2e\xa6\xcaF\\\xa2\xba\xd7"
19  =>   64  =>   b'Yf9\xa4[\x88a\x9f\xf8\xce\xf4\x02\xe4\x17*\xcc8\xe0F\\\xd5v\x0bh\xaa\xc8\x8b\xb8\x85\xfd\xb3\xbddO\x90~M\xd5g\xd7+\xc5\x95\xac\xd2\xa0!N\x17)\x03BQ\x85\xf1|\xc1!\xbbj\xe6\x87\x0b\x05'
20  =>   64  =>   b'\tFe\xa6sY\x878P\xbe\x9d\x82\xac\xd2EA\x17cU\x0b\x94U\x9fw\x99WNe8\xacL>\x1eL\x08Ai-\xb5\r\x14\x0b\x97\xa5\x1d\xbbi\xc5@\xb5\x9exb\xd1J7\xcc\x97Z\xf1%4\x9c\xcf'
21  =>   64  =>   b'\xb9\x87\xab\x1e\xb6\xcd\xad\xb4k\x99~\x8bJ\xa69\r\xbbj\x8b\x9b\xfdU3\xa5=\xbb\x00\x00\x89\xa2\xd3\x0e\xc1\x0c\xf6\xd2\x9c\x16\xbe\xef\xe96\x17Cl\xde]\xd4&G\xca\xf6\xd9\xb4\xb3u\x04\x90\x96\x9c\xc56\xf8\x95'
22  =>   64  =>   b'\xa0\xde+\xba\xf3\xd4\x8a\xf3@\xb3y\x08\xa1\x16\xd5\xe2\xd0{B)`\x13+y\xbb\xafq\xb5\x08\x8ee9\xd8\xcf\xb3\xe2\x1c\x8e\xb5\x12gs\x0b/\x94\ti^\xb7\x88%\tM\x89\x91Ul\xde\xcc_\xfe:\x10l'
23  =>   64  =>   b'\xa2\xed\xacT\xed\xa9?F\xe9(K8\xb8k%\x90\x01>\x92\x11\x89\xf99\x01`\xd7\x92\xdd\xd7\x0ec+\xa1n\xeb\tl\xf7\x0fC3\xaeCK\xffkSTY\xf2?\x8b\x98#&\xfa\x90\xba\xe9\t\xda\xc6\x7fz'
24  =>    4  =>   b'\xda-j\xc9'
25  =>   64  =>   b'\x00\x00\x02\x90\x8dF\x19X\xaaw\xe9\xbfr\xe9\x10\xccV\x8a\xc5B\xe0\n\xaa/:\x95\xec\xe3N\xa1EU\xb6#\\\x11\xfd\x00]\xf3\xb7\x0e\xaf\x83!\xe3\xa2Mf\xba\x83IM\xc4\x86\xa3\xa2C\xba\xe7\x7f\xbar\xa6'
26  =>   64  =>   b'\x18c\x08\xc7\x14[`\x95z\x85\xcfu\x86(&L\x15\xf0L\xe3\xe6\x13\r;\xed,\xf5[\x8f\xec\xd8\xc6\x983`\xebQC~/\x9c\xbb\xb6=\x13z\xe2>{\xa9\xdc\xd7GX\xff`E\x13\x1bC\x92o/d'
27  =>   64  =>   b'\xcc\xec\xf9\xa9\x06&\x0b\xd5\x90\xfc\x04\xac\xdcmt\x15yep\xf0\x1e\xd8\x84\xf7X\xb9V}9\x85\xe7\x17Vf\x8bsY)\x8e\x04\x01x)\xd7\x99\xadDN\xc2\xfe\x0b\xf9\xe0\xba\xdd_\xcd\xa8\xfb\xc0\x1d7\xf4\xd3'
28  =>   64  =>   b'\xc05\xc1UVBlN\xf7\xd5\xb2\xae\xfe\x15\x12GD\xb2N\x1fKNi\x83;3\xaa\xb1hw\\O\xde\xe8\x11\xec\x92_\x00\x80\xe7c\xe78\xe3\xf0\x11a\x02GQ\xbc\xbd\x04\x95[X\xda\x0c\x0f\x04He\xef'
29  =>   64  =>   b'f\xd9\xa9\x96\xec\xec\xb4Kz\x97\xe1~\x94\xd3\x04w\xf7\x0eK\xa71j\xad\xe3\xcc\xdc\xc8k\xdctJ&#\xb0\xdb5nl\x85\xc3k\xd58p\x8cy\xab\x9a#lG\xf8!\xb8\x14\xf4\x1a\xa7Br\xf7\x8d\xf1\x94'
30  =>   62  =>   b"\xe8-'\x04}RD\x0c\xbc\xb2\xbc\xb8\xd5\x91k\xb5\xe0\xd1F\x1b\xcc|\x0bR\x00\xf5]%\xd9\xc1\xbbU\x8fo&\xffp#]\xe8\xcd\xc7bE\x9f#n\xa2\xe1\xdck\n&\xad\xcb\xc6z\xed\xb8!\xfd\x11"
31  =>   64  =>   b'\x1eHoP6,i*\x91\x89\xc6\xeb\x08S\xfc(\x8c\x1a\xa57\x00=[W\xdc\x06G\xa6m\x9bt\xc9\x18\xfbM\x80k\x9dj\x9b\xf8\xbf@\xed-#\x03\xd78\xcaKcE\xcfl\xce\xae\xf9}w\xf4\xa4\r\xe8'
32  =>   64  =>   b'\xdb\xf8\r\x94\xa1\x7fCW3\x1b\xfe_\xc9\xc0\x93;\x9c\xd6\xacu\xdf\xc1\x08\xe3\x11\xaf\x15\xf5\x12=\xdfk\xca,\x92Z\xb7\xd8\xff\xd4\xfa\x80\xe7\x9eE{\xbd%2\xbcD\x97\x8a^@`F\xeec\x885\nq\xe1'
33  =>   63  =>   b"\xd3\x8b.\xea\x16\x14\xa9\xecI4\x17\xb8\xc6\xb4U\xb1\x14BK\x0c\xe6\x1e\xb5Z\xbb73\x9by\x0f\xde\xb50\xcf\xc0d\xbe\xcf\x83\xe7\xb2M\xf3\x06\x8e*z'\x8d\x8f\xe5\xa3W\x93\xda\x17JD\xa3\xcc\xec!\xfd"
34  =>   64  =>   b'g\xbe\x8f\xa7\x04\x04\xa1\xe0T5R\x9cZ\x8b{\xfb\x0b\xfd$*z*\xd4\xbd\x1f\xda\x06\x82i\xef\xe0-\xff\\\xcd\xc7\x11\x8d\xce&\xee\xfbv%6\x1c\xc5\x9c\x073\xa4G\x93C\xb2zQ\xf5\x02\xa9\xdbyz\xae'
35  =>   36  =>   b'\x81\x90\xf7\xf2\xb6w\x81\x8f\xba\x17[,\n\x88\x07\x91>\xe0\xea\xce\xcc\x87\xbf\x0f\x0fM\x86\xcf\x08\xf9\xaf\xcf\xbf\xde\x92\xc8'
36  =>   64  =>   b'\x01\x00\xa5)v\x86T\x0e>e\xa5\xb3h\xf2\xec\xc3\xd5\x14\xb4\x1b\x7f\xebV\x84\x82\x8di\xe6,\xf0\x9f9\xa3\x17\xb6u\xd6v\xfe\x8bw(7\x89\xb2\xaagS\x8b\xf1gF\xb6\xa5X7\xed\xfbkr\x1a\xb4X\x8e'
37  =>   63  =>   b'\xc5\x0b\xd2F\xb1\xd0D\xdb5{\x15>;X\xcd\x0c\xf6j\xa5OHs>\x96\xcc\xc0\x86\x01T\x01\x9e\xb0w\xf1\xff#\xaa\xe5\x83\xba\x1a\xd7\xa7\x9e\xbc\x8a\x96\x8cK\xde\xd98\xbe\xbc\x8d5_l\x98\x1e4\xbd\x88'
38  =>   64  =>   b"Y'\xac1J\xa3@\x00\x9e3\xee8s\xbe\xc8\x16\xf5\xcd\xc3n\x02p\x16WH\xd0}\x99\xf4\x04U5\\\xa3\xcbjGy\xcd\xd55\x83M\\k\x88L4`\xd2&\xa8\xa9d7\xc0\x80\xdac6\xc9\x95@\xd5"
39  =>   64  =>   b'\x0bOk\xb004\xe0;\xb3o\xa9b\x88\x0e\x1c\x1b\xe7\xe5\xf8\x93f\x02\x1c\xa3\x85\xa2"\xf3\xdfT7\xc1\x92ct\xa1&\xac\x10\x81\xd5\tb\xa5\xcc=R\xe3\x8b\xbf_\x10=\xeb~\x94\xb1\x85\x1e\x80\xf7\x92\xed*'
40  =>    2  =>   b'\xecr'
41  =>   64  =>   b'\x01\x00\x9fp\xa8g\x10q\xcc\xec#\xf3\xba\x1c\xf9\xccZ\x02\xe8\xdb\x04\xd8?T-iO\t\x90\xe1\xde\xf4\x80z\xdf\x06\x96\xe0\xb63\x8b\xed0\x9d\xa4\xf7\xf7nc\xa1\xdb^\xb9\n\x0f\x14\t\xe37!\xa6\x0b\x16r'
42  =>   64  =>   b'\xd6\xfb\xab\x08\xeb\xef\xa6\xbb{)z\x90\xcc\x85\r\xde\x9dRt\xc1\xb4\xefE\x86\x1d\x13j\xefS\x7f\x16Eq\xd6\xce\xd8\x1c_[\x94\xa3\xa8\x02\xe5\x9a\xf3\xa9\x04\x9e\x85\xa7\xd2+\x83Y\x8b\xc1;\xa1\x8e\x82\x8e\xa0\xe1'
43  =>   64  =>   b'\xab\xf9\x15\xa0\xed\xd0\x18\xf3\xcaD<\xe3\xacm?3$M\xc8\xa9,Z\xeb9\x84\x196eO\x99\xde\xb4\xa8\x7f*\xd1\x10?k\xd3\xe5u\xb54\xc7\x9f\xf1\x13\x14\x8e\x86\x08\x1e\x01\x95\xc6\x93\x8f\x07\xfaX\x7f\x06C'
44  =>   64  =>   b"\xeb}\x07\xa2p\x8dz\xa4\xa4\xa4.\xb6\xc1\xeb\x9c<!\x1a7\xb2\x0fI\xf3\xc4\xb5\t\x1d\x98|\xc7[af1'^!\x93\\\xa3\xc7\x1f\x07,\x01\x12!P\xbf\x03p\x8eI\xc5\x11\x81\x96\xa4\x19\x1c\xdfV\xf8\x83"
45  =>    2  =>   b'\xc5\x88'
46  =>   32  =>   b'\xe86%`\x16\xa5\xf8\xca\x1e)s+s2\xd9wk\xdcf\x94\xa9\xdfl\x11r\x18?e\x91o\x83\xd5'
47  =>   36  =>   b'\x00\x00\x00\x10\xa7\x1c\xa9\xca\x15K\xe8|\x04\xe7\x16\xa1Ng*\rw\x0f\xc6\x83\x1f?\x17\xa8\xff\xd4\xd8vO\xc6\xcf\xb8'
48  =>   36  =>   b'\x00\x00\x00\x10\xd4m\xa2\xb2\xf5K\xd3j\xf6\x8f\xc9\xc9\x9f\x1bZ\xaf\x01\xf1\n\x18^\xe9\xc9\xed\xbe/\x87\xb6\x0c\x05qU'
49  =>   64  =>   b'\x00\x00\x00\xe0\x9a\x12\x96\x8a5\xc8.\xc6Z\x9b\xb4~\x83\xe9)\xb9\xb2\xbdv2\x9c\xbd\xb2\x85!\x10\xbdNE\x9d\xfbR\xe4yil\xd6\x1f\x1f\x1a\x9d\x1d\xd4c\xbda[_\x8e\x92\x8fm\x8ff=8\xa5\x9f\x0c6'
50  =>   64  =>   b'E\xb1\xfc\xad\xae\xa4\x11op\xc6\x11\xea\xa5\xbd\x13\x84\x17)\x95{\xa4E>,\x84.Y\xf6\xc1\x18%\xa4G#\x13G2\xec"\xf9B9\x00\xbf"\nk\t\x90P\xf0\xb8Rv\xb9\x00\xc9<X\xbb\x0bj\xfb?'
51  =>   64  =>   b'\x93L\xc9\xf9\xef\x0fgF\xc7\xff\xb0\x04O\x19\xc9P\x87\xfd%6\\\x19\'=DA\x8e\xa9\xf8\xfd\xb5\x14m\x95\x0bY}\xad3\xc1\xe2&\xc8\x00j"\x0b_\xd4\xaa\x85l\x14\xef\xdd\xc2@>\x0b\xe8-\xae*\x9e'
52  =>   52  =>   b'\xf7\x88=\x14\x9f\xde!++l.\x05\x01\x95\x90\xfc\xa9\xd9\xe1\x92\xd2\xa7\x92{Y\xd4\xe7\x8aw7\xa4\x024%Ux\x9b0\x10\xcf\x08\xdc\\\xd2\xe1X\\\x80\xda\x122n'
53  =>   32  =>   b'J\xc9\xc8{gM\xcd\x93-.\x9d:K|\x16\xa3\x98\x9eu\x0f\xa3\xa8\x89^\x8d\xd0\x97\x1cV\xfb\x96x'
54  =>   36  =>   b"\x00\x00\x00\x10\x98\x9c\xb0*umt\x8eF\x918\x00_\x8a\xe8\x953\xdb\xd0\x16%\xa3\x1c\x88\xfb#\xc2\x07\t\x00n'"
55  =>   36  =>   b'\x00\x00\x00\x10\xf2\xc7\x08#\xa5\xc6\x94\x0by\x1e\x0f\x1d\xdd\x8a\x18\x10s\xa1h=\xbe\x0e>IP\xfd@\x04I\x1a`\xef'

 

通过分析、调试和一些合理的猜测,不难猜测出mux 的大致结构:

3、mux结构

typedef _mux{
    __int32 datalen;
    __int32 connect_type;
    __int32 data_type;
    unsigned char* data[];
} mux;
当connect_type为0时,该mux结构体不传送数据
不同的data_type代表了该数据流使用了不同的iv和key进行了数据加密
 
同时,我们不难发现,除头结构的data数据中仍然还存在 \x00\x00\x00\x10 这样的头信息,通过调试和分析,不难发现其结构如下
typedef _AES_Data{
    __int32 datalen;
    unsigned char iv[16];
    unsigned char data*;     //len(data) = datalen - 8
}

4、提取真正的数据

我们把所有的数据去除12字节的头部提取出来
def  extrat_real_data(wire_data):
    tcp_data = {}
    idx = 0
    while idx < len(wire_data):
        head_structure = wire_data[idx:idx+12]
        data_size = head_structure[3] -  8
        idx += 12
        
        if data_size == 0:
            continue

        elif data_size  > 0:    # 存在数据
            tcp_data_type = head_structure[8:12]
            if tcp_data_type not in tcp_data.keys():
                tcp_data[tcp_data_type] = b""
            
            realdata = wire_data[idx:idx+data_size]
            # print(head_structure)
            # print(realdata)
            tcp_data[tcp_data_type] += realdata
            idx += data_size
        else:
            print(head_structure)
            assert 0
    return tcp_data

cli_tcpdata =  extrat_real_data(cli_wire_data)
srv_tcpdata =  extrat_real_data(src_wire_data)
之后我们进行数据的解密即可

四、exp

from scapy.all import *
from Crypto.Cipher import ARC4 as rc4cipher
from struct import pack,unpack


u32 = lambda x: unpack('>I', x)[0]
u16 = lambda x: unpack('>H', x)[0]
def deRc4(cip):
    key = b"explorer"
    enc = rc4cipher.new(key)
    s = enc.decrypt(cip)
    return s



cli_wire_data = b""
src_wire_data = b""
wire = rdpcap('flag2.pcapng')
for pkt in wire:
    cip = bytes(pkt[TCP].payload)
    if pkt[IP].dport == 8888:
        cli_wire_data += cip

    if pkt[IP].sport == 8888:
        src_wire_data += cip


cli_wire_data = deRc4(cli_wire_data)
src_wire_data = deRc4(src_wire_data)


def  extrat_real_data(wire_data):
    tcp_data = {}
    idx = 0
    while idx < len(wire_data):
        head_structure = wire_data[idx:idx+12]
        data_size = head_structure[3] -  8
        idx += 12
        
        if data_size == 0:
            continue

        elif data_size  > 0:    # 存在数据
            tcp_data_type = head_structure[8:12]
            if tcp_data_type not in tcp_data.keys():
                tcp_data[tcp_data_type] = b""
            
            realdata = wire_data[idx:idx+data_size]
            # print(head_structure)
            # print(realdata)
            tcp_data[tcp_data_type] += realdata
            idx += data_size
        else:
            print(head_structure)
            assert 0
    return tcp_data

cli_tcpdata =  extrat_real_data(cli_wire_data)
srv_tcpdata =  extrat_real_data(src_wire_data)

from pwn import xor
from Crypto.Cipher import PKCS1_v1_5
from Crypto.PublicKey import RSA
srv_rsa = PKCS1_v1_5.new(RSA.importKey('''
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDbfWw2tfpbGVCl
+zLy7pVH2vDgfiVj3d+ykCZd5+MOFCFgI8z5LKkG8iBv/D1/wAaQTBSUNDF9kIKX
PvYYC5L2OuWyqD0ulIxn48kA7QENaKywkIm3LIQ1b/1VU+kksDRJJ5i5NgnzhYMB
yOxvRP75X3tNeVKKr2y9e3XosPEJAmNFe/07VRMGQOkYZmadHjEuJBP4/Hoo6oCy
slwAXQQlqOLloF8dVB2tdDCCarw8Sx+e+naJAItnaIM8uUZtFqF0V6KBddPgvpS+
OlsWv/0g28Nvb69CRGXvOUdW1QAxHhfmyZbacccfljJOLVw68wWw36g8bGAEalKp
gLGY/Ag3AgMBAAECggEADbfJC6JUA12RrM4GYSiIK/WDGITJ0XQMhxx7SWM0zax0
aY3TQb+I0OZRIK6jKVjXEC2xG5InhbGCd/F3cAlJJhqIQKJDMKYYIGYcKfKmHjBs
mpxt/wTJPo3BR5P2/lQE8I2I/gpilNXDWlk0bb/iL7PIAQ+UGRbdtPoCZIiqh+WA
qElaJ4LHXgKBXUpozfEtUa383IcwsQdB1BSwMOnJ5YFrplhx6fTgJ6noFB4eLp7h
SCSR2018r11UAANqWbc7a40TtLpWUmh3AExCeQACI1RloTSCRWYsXrxFMH6ZGDvE
K+Q9LS+jtkPCtOrbr+j8FU0Dgxh/5P0I2xR4hcgAAQKBgQDkcnwcaWRZv0uFxAtj
q3pVelWuu3uapwroO9asmeWsmL3LQeW22X5CNy1gYOlhyG6FqfMLOmzhCicFYX45
6EiDJpyX/LVcSDmzmTDwI25uEunhyhVATJWqwaITdLrJf8KDqqO8bvUHc/wB//2T
OTWpUB542DZJ2A8aServjR6ErwKBgQD19l+5xCHLOldtV56hbAQnhhl8lUAL/mBq
wXNrDNeqmDYFJ3kkHWk5raXUQR41qAubhKnLUJ4qj6FIBcRmsrTMITMWZ9/GzJhK
mNU+nync2IlSS7g3Vyee3wz1Fd2dRA3NwZ9JVK+xTSKgw1a/VXKcfC+iYnXmVIxa
3cCIZ9Um+QKBgQDE34Dj/1OzIG+WbPgfwiTgS1hSCFKiWfjFYORFxS8wykUuSLEO
Hmt35xNc7sfSNChDWs4QzB4O5m/wbC+a+fqbxAfJ18f4KmpHw+pv2SkPBY+3vS8J
Rbbp/IuP1tYuVsMsMz9+YeUasjLpClLesLv1GQ3ZuQM4KlIBptgn7+bwEwKBgQC1
ZDk8etShWClZziCC03JM46ywIDHXpoXctUY1UIdMnGxaaL4CUF5l1xZQ7qUk1QWa
b7/43T+IC9zZjMdHJcwILwPKJlj197TobsX1JNRutpKvSoBU78WceMrJhJKnhKTZ
dU3PetEHZOeAwA6dlJqtpThL/WkNsJTB/oAbGNgtoQKBgG4ytUXXwp61VHm/3Pon
9d6z5o02AQVCppJRcJwehbAm14813G/jPfjwM+KZ2ikhs+eW1peWhBrCo+M5/u5T
bxeDm9cbLMewkYNIdvUxtaBb+fJtIBAngAL2HEhqBdUFoQI+lr+F802UO2aM8Sg+
n82S/+EJZomQ7hhO7qnLtxkI
-----END PRIVATE KEY-----
'''.strip()))

cli_rsa = PKCS1_v1_5.new(RSA.importKey('''
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC93GDINPM6HX2+
NN3bCznyri2rDHDVcamzA/rPDXi9Mb2hu1Ypqek4km/kf4MKDsrOU/3T5mcdx5kA
80s7mBWlGaItg/sy6dsh2XOoKVEHcZYyrbSAbkYrT9CoLLM/JlipbsalKenkW9Jl
HB0h+vwv/rAwXJ9IMSc4RQkvjn/QKuBPhcXfrfaAIKNO0L+iqUL3asFM2CF8DXZX
y8pLAxMy2PDJLtb0I/rXDWRImWlBcIWBrhg7lDA0UxWXDD1i5MmMlvxmyho1F8Br
h7ietK3XW7LWshD2ARIDgPoTZ7lZm7P9JbKSN+Uk7fay6LdkJXYszfT89Owmi7tm
fUQ41fcBAgMBAAECggEAWyGJru+Dg/Sd44t6peY4lVy3fO/GxRz+qHeTjojX2HAk
ppnGHM96q3XWkWYHHu/Ets6n+msQOcIRldwx01QHp6yrJI/CJkkLrq6yjhfu1dTW
lFK+XhsQQT/ZVq/GBdzBF+qdHLAGnV7ZmUCqVyIipGLqbPw4VC2Ltr2kUBhlDySA
A+gCnUrPyVi6O9OFcyDepKMy481gZLLijakINejYrsbdCInz2omHq12w/50tuFt1
s4XMWJN+AW0g1Hx+tTk2jDX1Wqg/htmJhjGqTj02GLJ/CJQjRodEdA7mx3HGwhis
igeZgHTdPgP1B5Z9NXwUg9Qxln72D4mGhLCGYcw8VQKBgQD6+oltv1i44BO/ROUJ
kZPTLWeoBrxP2OOli4aOSilLifeGrUQOSUtvcFHOxzy5RrhvX89f3GnklXcGyHXD
03wg0/hqL0HM1EzNLmWkJW0Ng5WRFFgfcQIKbWBK9SHhAmKzkHtZPq6NwN8MbZUF
vndxDtcSOdH0/TbMtCMYYs0MswKBgQDBqM7QxWT6qebCU4YOV+5uwnP+hAunsWkv
VW7pHgiPnZ8ARRZ9iFIqqiVRvKeeyZBEK22eOJNguz6Cqfz2451D/AHA7sXht+1D
9GCE/ebvUw+lPNQIRKkAgwQ8Dx+R6ikaUGzUKYhmWYJ5xgS9ZALZ+k4+rSjFg9jV
jFjT7xQvewKBgHo9bJI3kE77VKLkO2ndrdI9Wy9LmIyLZtVKj87d8B8Ko7TEz1Dm
AgfU/QNppvnWqB4W3DokcK8U3VRAbptidiLHG0ccnT/WZ1HIN1kroWHjpQV0kzc9
I3FQtIXNvyKItuoehPWCwiHovrqe5OZXTnWSdM47uzdH3Vj2o+FMvfJhAoGAQvus
bTGZd8oEcvqIx7VKVy0TCdmKXnpSs3iNYDxvIZ2XPXSoDst0ACXRuq/SGm4FZE7R
H4TaFP8u4+sAADVCVB16Tc1IzIXdnz+LkvRvSCAmrTSY8jMtcWvfrxZcCRBBH0Tq
H4guEZisNIp1YTySb+rP3YXvMEImYdalcsii5rkCgYEAimnWJ5aFN3TDt3h76CL3
nRQegnzekJBjXZfcrHdExkgNChWjiz+WU/FW/Z87xMxtfIEwwzzIQHxbKZhgzO/U
p2eXdqH59DvauggbiS3h4p9k2kxWTocztarvdftMW0ncmA4yCKiUQEmWD784JCyx
OupNNfr2rgViWggVBEtJUIg=
-----END PRIVATE KEY-----
'''.strip()))

def dersa_key(client_data,server_data):
    clikey = srv_rsa.decrypt(client_data,None)
    serkey = cli_rsa.decrypt(server_data,None)
    return xor(clikey,serkey)



from hashlib import sha256
def sha256_verify(tcpdata,xor_key):
    assert tcpdata == sha256(xor_key).digest()


from Crypto.Cipher import AES
def deaes128cbc(stream,key):
    while 1:
        cip_len = stream.read(4)
        if not cip_len:
            break
        cip_len = u32(cip_len)
        iv = stream.read(16)
        cip = stream.read(cip_len)
        Cipher = AES.new(key,AES.MODE_CBC,iv)
        ming = Cipher.decrypt(cip)
        if b"rwctf" in ming:
            print("````````````````````````````````````````````````````````")
            print("````````````````````````````````````````````````````````")
            print(ming)
            print("````````````````````````````````````````````````````````")
            print("````````````````````````````````````````````````````````")
            print("congratulation you have found the flag")
            assert 0
            
        print(ming)


from io import BytesIO
if __name__ == '__main__':
    for type_data , clidata in cli_tcpdata.items():
        srvdata = srv_tcpdata[type_data]
        srv_io = BytesIO(srvdata)
        cli_io = BytesIO(clidata)

        aeskey = dersa_key(cli_io.read( u16(cli_io.read(2))),srv_io.read( u16(srv_io.read(2))))
        assert sha256(aeskey).digest() == srv_io.read(32)
        assert sha256(aeskey).digest() == cli_io.read(32)

        # aes解密
        deaes128cbc(srv_io,aeskey)
        deaes128cbc(cli_io,aeskey)

        
 
0

FLAG

得到flag:
rwctf{l1fe_1s_sh0rt_DO0_not_us3_rust}
 
posted @ 2023-01-19 12:56  TLSN  阅读(1198)  评论(0)    收藏  举报