# -*- coding:utf-8 -*-
import re
import os
import shutil
import sys
import zipfile
import time
import requests
import ssl
import http.cookies
import datetime
import random
import flask, json
import frida
from pathlib import Path
from flask import Flask, redirect, url_for, request, render_template
from z3 import *
import struct



class byte_util:
    @staticmethod
    def bytes_to_c_array(bytes, sign):
        if sign == 'I':
            sign_len = 4
        lens = len(bytes)
        if lens % sign_len != 0:
            print('lens%num!=0')
            return None
        num = lens // sign_len
        format_str = '<{}{}'.format(num, sign)
        # print(format_str)
        return list(struct.unpack(format_str, bytes))

    @staticmethod
    def c_array_to_bytes(arr, sign):
        if sign == 'I':
            sign_len = 4
        num = len(arr)
        format_str = '<{}{}'.format(num, sign)
        return struct.pack(format_str, *arr)


class cryphy_util:
    @staticmethod
    def check1(lelf, right):
        str2 = ''
        str3 = ''
        for i, ch in enumerate(lelf):
            res = ord(ch) & 0xf | ord(right[i]) & 0xf0
            str2 += chr(res)
            res = ord(ch) & 0xf0 | ord(right[i]) & 0xf
            str3 += chr(res)
        return str2 + str3

    @staticmethod
    def tea_encrypt_two_32num(v0,v1, k):
        # 加密两个32位的数字
        delta = 0x9e3779b9
        mask = 0xffffffff
        rounds = 32
        # rounds = 2
        # print(hex(v0),hex(v1))
        sum_ = 0

        for i in range(rounds):
            sum_ = (sum_ + delta) & mask
            
            v0 = (v0 + (((v1 << 4) + k[0]) ^ (v1 + sum_) ^ ((v1 >> 5) + k[1]))) & mask
            v1 = (v1 + (((v0 << 4) + k[2]) ^ (v0 + sum_) ^ ((v0 >> 5) + k[3]))) & mask
        
            # print(hex(v0),hex(v1),hex(sum_),i)
        return v0, v1
    
    @staticmethod
    def tea_decrypt_two_32num(v0,v1, k):
        # 解密两个32位数字
        delta = 0x9e3779b9
        sum_ = 0xC6EF3720
        mask = 0xffffffff
        rounds = 32
      
        for i in range(rounds):
            
            v1 = (v1 - (((v0 << 4) + k[2]) ^ (v0 + sum_) ^ ((v0 >> 5) + k[3]))) & mask
            v0 = (v0 - (((v1 << 4) + k[0]) ^ (v1 + sum_) ^ ((v1 >> 5) + k[1]))) & mask
            sum_ = (sum_ - delta) & mask
        
            # print(hex(v0),hex(v1),hex(sum_),i)
        return v0, v1

    @staticmethod
    def tea_encrypt_array(arr):
        res=[]
        k=[0x42, 0x37, 0x2c, 0x21]
        i=0
        while i<len(arr): 
            encry_arr1,encry_arr2=cryphy_util.tea_encrypt_two_32num(arr[i],arr[i+1],k)
            # print(encry_arr1,encry_arr2)
            res.extend([encry_arr1,encry_arr2])
            i+=2
        # encry_arr1,encry_arr2=cryphy_util.tea_encrypt(arr[i],arr[i+1],k)
        # print(byte_util.c_array_to_bytes(res,'I').hex(' '))
        return res
    
    @staticmethod
    def tea_decrypt_array(arr):
  
        res=[]
        k=[0x42, 0x37, 0x2c, 0x21]
        i=0
        while i<len(arr): 
            decry1,decry2=cryphy_util.tea_decrypt_two_32num(arr[i],arr[i+1],k)
            # print(encry_arr1,encry_arr2)
            res.extend([decry1,decry2])
            i+=2
        # encry_arr1,encry_arr2=cryphy_util.tea_encrypt(arr[i],arr[i+1],k)
        # print(byte_util.c_array_to_bytes(res,'I').hex(' '))
        return res
  
  
    @staticmethod
    def base64_encode(binary_data: bytes):
        # chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
        chars='abcdefghijklmnopqrstuvwxyz!@#$%^&*()ABCDEFGHIJKLMNOPQRSTUVWXYZ+/'
        # 二进制数据字节数不是 3 的倍数时，使用 \x00 填充
        padding_count = 3 - len(binary_data) % 3
        if padding_count == 3:
            padding_count = 0
        encode_data = binary_data + b'\x00' * padding_count

        result = ''
        # 每次取出 3 个字节进行编码
        for index in range(0, len(encode_data), 3):
            piece = encode_data[index:index+3]
            # 将字节数据转换为二进制 bit 数据
            binary_string = bin(int.from_bytes(piece, 'big'))[2:].zfill(24)
            # 每次取出 6 个 bit
            for i in range(0, 24, 6):
                result += chars[int(binary_string[i:i+6], base=2)]

        # 若使用了 \x00 填充过编码前数据，使用等数量的 = 填充编码后数据
        if padding_count:
            result = result[:-padding_count] + '=' * padding_count

        # 输出的格式为 ascii 编码的 bytes
        return result
    
    @staticmethod
    def base64_decode(encoded_data: str):
        # chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
        chars='abcdefghijklmnopqrstuvwxyz!@#$%^&*()ABCDEFGHIJKLMNOPQRSTUVWXYZ+/'
        binary_string = ''
        # 去除末尾的填充字符
        padding_count = encoded_data.count('=')
        if padding_count > 0:
            encoded_data = encoded_data.replace('=','')
        # 将Base64编码的字符转换为6位二进制
        for char in encoded_data:
            if char in chars:
                binary_string += bin(chars.index(char))[2:].zfill(6)

        if padding_count>0:
            binary_string=binary_string[:-2*padding_count]
        
        # 将二进制数据转换为字节串
        binary_data = bytearray()
        for i in range(0, len(binary_string), 8):
            binary_data.append(int(binary_string[i:i+8], 2))

        return bytes(binary_data)
    @staticmethod
    def resume_base64_order(data):
        # 还原改变了顺序的base64_encode输出，还原成标准型，即b0 b1 b2 b3
        # 魔改成的顺序是，b1 b2 b0 b3
        res=''
        for i in range(0,len(data),4):
            # print(data[i])
            res=res+data[i+2]+data[i]+data[i+1]+data[i+3]
        # print('res',res)
        return res
        
       
def z3_check1(expected_output):
        # 输入字节流
    input_stream1 = [BitVec(f"input_stream1_{i}", 8) for i in range(16)]
    input_stream2 = [BitVec(f"input_stream2_{i}", 8) for i in range(16)]

    # 期望的输出字节流
    # expected_output = [0xee, 0x8b, 0xb2, 0x9f, 0x57, 0x48, 0xab, 0xd6, 0xe7, 0x15, 0x42, 0x04, 0x63, 0x1f, 0x13, 0xf1,
                #    0x5f, 0xaf, 0xc7, 0x5c, 0x04, 0x97, 0x5c, 0xfc, 0x08, 0x32, 0x6d, 0x6b, 0x50, 0x25, 0xe9, 0x44]
    
    # expected_output ='qbcqbctcadqcvcqd314314cqfdcqguga'.encode()

    # 定义Z3求解器
    solver = Solver()

    # 添加约束条件
    for i in range(16):
        res2 = (input_stream1[i] & 0x0f) | (input_stream2[i] & 0xf0)
        res3 = (input_stream1[i] & 0xf0) | (input_stream2[i] & 0x0f)
        solver.add(res2 == expected_output[i])
        solver.add(res3 == expected_output[i + 16])

    # 求解
    if solver.check() == sat:
        model = solver.model()
        result_stream1 = [model[input_stream1[i]].as_long() for i in range(16)]
        result_stream2 = [model[input_stream2[i]].as_long() for i in range(16)]

        # 转换为字节流
        input_bytes1 = bytes(result_stream1)
        input_bytes2 = bytes(result_stream2)
        res=input_bytes1+input_bytes2
        return res
        print('z3',res.decode('utf-8'))
    
    else:
        print("No solution found.")

if __name__ == '__main__':
    
    base=0x711e38a000
    print(hex(base+0xF620))
    print("flag{123123dsadasfsadsadsadsafdsawewa}")
  
    # print(check1('123123dsadasfsad','sadsadsafdsawewa'))
    str1='qbcqbctcadqcvcqd314314cqfdcqguga'
    str_stream1=str1.encode()
    # print(str_stream1.hex(' '))
    k=[0x42, 0x37, 0x2c, 0x21]
    

    resu_str=cryphy_util.resume_base64_order('e)n*pNe%PQy!^oS(@HtkUu+Cd$#hmmK&ieytiWwYkIA=')
    decoded=cryphy_util.base64_decode(resu_str)
    arr=byte_util.bytes_to_c_array(decoded,'I')
    tea_decoded_arr=cryphy_util.tea_decrypt_array(arr)
    tea_decoded_bytes=byte_util.c_array_to_bytes(tea_decoded_arr,'I')
    res_bytes=z3_check1(tea_decoded_bytes)
    print(res_bytes.decode())
    
    # bstr=cryphy_util.base64_encode(tea_batyes)
    # print(bstr)

    
    # z3_check1()
    




   
    
    