把今年 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
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 函数
得知对 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) |
为了加快运行速度,直接由 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 在调试状态不退出
此处使用 mprotect, 将一段内存区域标记为可读可写可执行,然后经过异或解密,所以可以直接去看这段解密后的代码
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 算法
通过动态调试得知 chacha20 的 key
为 hgame{th
, counter
为 0x12345678
, nonce
为 ['h','g','a']
但是把数据放到 chacha20 算法里面却不能输出 flag
所以我直接找到对矩阵进行操作的函数,
并且得到了最终的矩阵
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} |