babyre
第一个是一个 AES
key 是
0x35, 0x77, 0x40, 0x2E, 0xCC, 0xA4, 0x4A, 0x3F, 0x9A, 0xB7,
0x21, 0x82, 0xF9, 0xB0, 0x1F, 0x35
从后往前看
__int64 __fastcall sub_4020F7(__int64 result)
{
int v1; // r8d
int v2; // ecx
int v3; // ecx
int var38[16]; // [rsp+8h] [rbp-38h]
int i; // [rsp+38h] [rbp-8h]
unsigned int v7; // [rsp+3Ch] [rbp-4h]
v7 = 1;
for ( i = 0; i <= 15; ++i )
{
var38[11] = *(_DWORD *)(48i64 * i + result);
var38[10] = *(_DWORD *)(48i64 * i + result + 4);
var38[9] = *(_DWORD *)(48i64 * i + result + 8);
var38[8] = *(_DWORD *)(48i64 * i + result + 12);
var38[7] = *(_DWORD *)(48i64 * i + result + 16);
var38[6] = *(_DWORD *)(48i64 * i + result + 20);
var38[5] = *(_DWORD *)(48i64 * i + result + 24);
var38[4] = *(_DWORD *)(48i64 * i + result + 28);
var38[3] = *(_DWORD *)(48i64 * i + result + 32);
var38[2] = *(_DWORD *)(48i64 * i + result + 36);
var38[1] = *(_DWORD *)(48i64 * i + result + 40);
var38[0] = *(_DWORD *)(48i64 * i + result + 44);
v1 = var38[2] & var38[3] & var38[4] & (var38[6] == 0) & (var38[7] == 0) & var38[8] & ((var38[9] | var38[10] | var38[11]) == 0) & (var38[5] == 0) & (var38[1] == 0) | var38[2] & var38[4] & var38[6] & (var38[8] == 0) & (var38[9] == 0) & var38[11] & (var38[10] == 0) & (var38[7] == 0) & (var38[5] == 0) & (var38[3] == 0) & (var38[1] == 0) | var38[1] & (var38[3] == 0) & (var38[4] == 0) & (var38[5] == 0) & var38[6] & var38[7] & (unsigned __int8)(var38[9] & var38[10] & LOBYTE(var38[11])) & (var38[8] == 0) & (var38[2] == 0);
v2 = var38[0] & var38[1] & var38[3] & var38[4] & var38[5] & var38[6] & var38[7] & (var38[9] == 0) & (unsigned __int8)(var38[10] & LOBYTE(var38[11])) & (var38[8] == 0) & (var38[2] == 0) | (var38[1] == 0) & (var38[2] == 0) & var38[3] & var38[4] & var38[5] & var38[7] & var38[8] & var38[10] & (var38[11] == 0) & (var38[9] == 0) & (var38[6] == 0) & (var38[0] == 0) | var38[0] & (var38[2] == 0) & var38[3] & var38[5] & var38[7] & var38[8] & var38[9] & var38[11] & (var38[10] == 0) & (var38[6] == 0) & (var38[4] == 0) & (var38[1] == 0) | var38[0] & var38[2] & var38[3] & var38[5] & var38[6] & var38[8] & var38[9] & (*(_QWORD *)&var38[10] == 0i64) & (var38[7] == 0) & (var38[4] == 0) & (var38[1] == 0) | (v1 | var38[1] & var38[2] & (var38[4] == 0) & var38[5] & (var38[7] == 0) & var38[8] & var38[9] & var38[11] & (var38[10] == 0) & (var38[6] == 0) & (var38[3] == 0)) & (var38[0] == 0);
v3 = var38[0] & var38[1] & (var38[3] == 0) & (var38[4] == 0) & var38[5] & (var38[7] == 0) & (var38[8] == 0) & (var38[9] == 0) & (unsigned __int8)(var38[10] & LOBYTE(var38[11])) & (var38[6] == 0) & (var38[2] == 0) | (var38[1] == 0) & (var38[2] == 0) & (var38[3] == 0) & (var38[4] == 0) & var38[5] & (var38[7] == 0) & var38[8] & ((var38[9] | var38[10] | var38[11]) == 0) & (var38[6] == 0) & (var38[0] == 0) | var38[0] & var38[1] & var38[2] & (var38[4] == 0) & (var38[5] == 0) & var38[6] & var38[7] & (var38[9] == 0) & var38[10] & (var38[11] == 0) & (var38[8] == 0) & (var38[3] == 0) | var38[0] & var38[2] & (var38[4] == 0) & (var38[5] == 0) & var38[6] & ((var38[7] | var38[8] | var38[9] | var38[10] | var38[11]) == 0) & (var38[3] == 0) & (var38[1] == 0) | var38[0] & (var38[2] == 0) & (var38[3] == 0) & var38[4] & var38[5] & var38[6] & var38[7] & (var38[9] == 0) & var38[11] & (var38[10] == 0) & (var38[8] == 0) & (var38[1] == 0) | v2;
if ( !(var38[1] & var38[3] & var38[5] & var38[7] & (var38[9] == 0) & var38[10] & (var38[11] == 0) & (var38[8] == 0) & (var38[6] == 0) & (var38[4] == 0) & (var38[2] == 0) & (var38[0] == 0) | var38[0] & var38[1] & var38[2] & var38[3] & (var38[5] == 0) & (var38[6] == 0) & var38[7] & (var38[9] == 0) & var38[10] & (var38[11] == 0) & (var38[8] == 0) & (var38[4] == 0) | v3 | var38[1] & var38[2] & var38[3] & var38[5] & var38[7] & ((var38[8] | var38[9] | var38[10] | var38[11]) == 0) & (var38[6] == 0) & (var38[4] == 0) & (var38[0] == 0)) )
v7 = 0;
}
return v7;
}
char __fastcall sub_402001(int *result, unsigned __int8 *buf)
{
__int64 k_1; // rax
int k; // [rsp+0h] [rbp-10h]
int j; // [rsp+4h] [rbp-Ch]
int i; // [rsp+8h] [rbp-8h]
int now_i; // [rsp+Ch] [rbp-4h]
for ( i = 0; i <= 15; ++i )
{
LOBYTE(k_1) = i;
now_i = i;
for ( j = 0; j <= 3; ++j )
{
k_1 = 11 - j;
result[12 * i + k_1] = now_i & 1; // 8-11 index
now_i >>= 1;
}
for ( k = 0; k <= 7; ++k )
{
result[12 * i + 7 - k] = buf[i] & 1; // 0-7 buf
LOBYTE(k_1) = buf[i] >> 1;
buf[i] = k_1;
}
}
return k_1;
}
把输入按位拆开,前 8 bits 放在 0-7(大的在前面),后面 8-11 放 index 的 bits
那就反转过来 3-11 是我们想要的数据,写个 z3 求解出来:
from z3 import *
res = []
for i in range(16):
sol = Solver()
v5 = [BitVec(f"v{i}", 1) for i in range(12)]
v1 = v5[2] & v5[3] & v5[4] & (~v5[6]) & (~v5[7]) & v5[8] & (~(v5[9] | v5[10] | v5[11])) & (~v5[5]) & (~v5[1]) | v5[2] & v5[4] & v5[6] & (~v5[8]) & (~v5[9]) & v5[11] & (~v5[10]) & (~v5[7]) & (~v5[5]) & (~v5[3]) & (~v5[1]) | v5[1] & (~v5[3]) & (~v5[4]) & (~v5[5]) & v5[6] & v5[7] & (v5[9] & v5[10] & v5[11]) & (~v5[8]) & (~v5[2])
v2 = v5[0] & v5[1] & v5[3] & v5[4] & v5[5] & v5[6] & v5[7] & (~v5[9]) & v5[10] & v5[11] & (~v5[8]) & (~v5[2]) | (~v5[1]) & (~v5[2]) & v5[3] & v5[4] & v5[5] & v5[7] & v5[8] & v5[10] & (~v5[11]) & (~v5[9]) & (~v5[6]) & (~v5[0]) | v5[0] & (~v5[2]) & v5[3] & v5[5] & v5[7] & v5[8] & v5[9] & v5[11] & (~v5[10]) & (~v5[6]) & (~v5[4]) & (~v5[1]) | v5[0] & v5[2] & v5[3] & v5[5] & v5[6] & v5[8] & v5[9] & (~v5[10]) & (~v5[11]) & (~v5[7]) & (~v5[4]) & (~v5[1]) | (v1 | v5[1] & v5[2] & (~v5[4]) & v5[5] & (~v5[7]) & v5[8] & v5[9] & v5[11] & (~v5[10]) & (~v5[6]) & (~v5[3])) & (~v5[0])
v3 = v5[0] & v5[1] & (~v5[3]) & (~v5[4]) & v5[5] & (~v5[7]) & (~v5[8]) & (~v5[9]) & v5[10] & v5[11] & (~v5[6]) & (~v5[2]) | (~v5[1]) & (~v5[2]) & (~v5[3]) & (~v5[4]) & v5[5] & (~v5[7]) & v5[8] & (~(v5[9] | v5[10] | v5[11])) & (~v5[6]) & (~v5[0]) | v5[0] & v5[1] & v5[2] & (~v5[4]) & (~v5[5]) & v5[6] & v5[7] & (~v5[9]) & v5[10] & (~v5[11]) & (~v5[8]) & (~v5[3]) | v5[0] & v5[2] & (~v5[4]) & (~v5[5]) & v5[6] & (~(v5[7] | v5[8] | v5[9] | v5[10] | v5[11])) & (~v5[3]) & (~v5[1]) | v5[0] & (~v5[2]) & (~v5[3]) & v5[4] & v5[5] & v5[6] & v5[7] & (~v5[9]) & v5[11] & (~v5[10]) & (~v5[8]) & (~v5[1]) | v2
v4 = v5[1] & v5[3] & v5[5] & v5[7] & (~v5[9]) & v5[10] & (~v5[11]) & (~v5[8]) & (~v5[6]) & (~v5[4]) & (~v5[2]) & (~v5[0]) | v5[0] & v5[1] & v5[2] & v5[3] & (~v5[5]) & (~v5[6]) & v5[7] & (~v5[9]) & v5[10] & (~v5[11]) & (~v5[8]) & (~v5[4]) | v3 | v5[1] & v5[2] & v5[3] & v5[5] & v5[7] & (~(v5[8] | v5[9] | v5[10] | v5[11])) & (~v5[6]) & (~v5[4]) & (~v5[0])
sol.add(v4 == 1)
sol.add(v5[0] == i&1)
sol.add(v5[1] == (i>>1)&1)
sol.add(v5[2] == (i>>2)&1)
sol.add(v5[3] == (i>>3)&1)
sol.check()
mod = sol.model()
# print(mod)
x = 0
for j in range(11, 3, -1):
x = (x << 1) | (mod[v5[j]].as_long())
res.append(x)
print(res)
for _ in res:
print(hex(_)[2:], end=" ")
18, 143, 236, 194, 133, 4, 178, 76, 91, 186, 74, 207, 17, 54, 10, 72
12 8f ec c2 85 4 b2 4c 5b ba 4a cf 11 36 a 48
35 77 40 2E CC A4 4A 3F 9A B7 21 82 F9 B0 1F 35
好像 no-padding 才是对的
4d87ef03-77bb-491a-80f5-4620245807c4
easyre
https://bbs.kanxue.com/thread-284044.htm?style=1
https://blog.xmcve.com/2024/10/20/%E5%BC%BA%E7%BD%91%E6%8B%9F%E6%80%812024-Writeup/#title-11
反调试绕过: https://github.com/x64dbg/ScyllaHide/
什么超级动调大师训练题(
j__fgetc_nolock
和 strlen
可以确定输入位置 在 sub_7FF7CC614A9C(__int64 a1, int a2)
对输入位置下硬件断点,ponce 调试
len = strlen(flag) cmp rdx, 38h ;
好麻烦,用输入验证到底干嘛了,有两次操作,一次加法,一次取反和与运算乱七八糟合在一起,
应该是一一对应,输入进去一样的输出一样,那么遍历输入就能直接得到字典
有 shr 11
有 TEA 加密特征数
这里就是 key[(sum>>11) & 3]
的取数的地方
key = [0x0EF6FD9DB,0x0D2C273D3,0x6F97E412,0x72BFD624]
在返回的时候查看栈帧,可以看到参数的传递(硬件断点)
所以加密次数是 0x66
(原始的函数栈还是很干净的
00007FF7CC60B1A0
什么鬼,IDA 爆炸了,trace 出来看罢
在这里比较最后一位,往前溯源,得到密文(其实就是 data 段的开头,猜的话应该也是猜放在这)
0xA1, 0xE3, 0x51, 0x98, 0x86, 0x56, 0x76, 0x49, 0x6F, 0x6B,
0x2B, 0x81, 0xCF, 0xCE, 0x12, 0x96, 0xA2, 0x70, 0x35, 0x3C,
0x31, 0x62, 0x5C, 0xF1, 0xFA, 0x77, 0x6B, 0xAA, 0x9E, 0x6D,
0x05, 0xBE, 0xE8, 0x24, 0xA4, 0xF8, 0xDB, 0x23, 0x3A, 0x0B,
0x16, 0x20, 0xCC, 0x03, 0xAD, 0xB5, 0x2B, 0xA9, 0x34, 0x9F,
0x78, 0x1D, 0x2E, 0xB9, 0xF9, 0x9E
根据前面的密码本就能复原
#include <stdint.h>
#include <stdio.h>
/* take 64 bits of data in v[0] and v[1] and 128 bits of key[0] - key[3] */
void encipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
unsigned int i;
uint32_t v0 = v[0], v1 = v[1], sum = 0, delta = 0x9E3779B9;
for (i = 0; i < num_rounds; i++) {
v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
sum += delta;
v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum >> 11) & 3]);
}
v[0] = v0;
v[1] = v1;
}
void decipher(unsigned int num_rounds, uint32_t v[2], uint32_t const key[4]) {
unsigned int i;
uint32_t v0 = v[0], v1 = v[1], delta = 0x9E3779B9, sum = delta * num_rounds;
for (i = 0; i < num_rounds; i++) {
v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum >> 11) & 3]);
sum -= delta;
v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);
}
v[0] = v0;
v[1] = v1;
}
int main() {
uint8_t cipher[] = {
0xA1, 0xE3, 0x51, 0x98, 0x86, 0x56, 0x76, 0x49, 0x6F, 0x6B, 0x2B, 0x81,
0xCF, 0xCE, 0x12, 0x96, 0xA2, 0x70, 0x35, 0x3C, 0x31, 0x62, 0x5C, 0xF1,
0xFA, 0x77, 0x6B, 0xAA, 0x9E, 0x6D, 0x05, 0xBE, 0xE8, 0x24, 0xA4, 0xF8,
0xDB, 0x23, 0x3A, 0x0B, 0x16, 0x20, 0xCC, 0x03, 0xAD, 0xB5, 0x2B, 0xA9,
0x34, 0x9F, 0x78, 0x1D, 0x2E, 0xB9, 0xF9, 0x9E};
uint32_t key[4] = {0x0EF6FD9DB, 0x0D2C273D3, 0x6F97E412, 0x72BFD624};
for (int i = 0; i * 8 < sizeof(cipher); i++) {
decipher(0x66, (uint32_t *)(cipher + i * 8), key);
}
uint8_t ebokk[] = {0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, 0x18, 0x17, 0x16,
0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0F, 0x0E, 0x0D,
0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04,
0x03, 0x02, 0x01, 0x00, 0xFF, 0xFE, 0xFD, 0xFC, 0xFB,
0xFA, 0xF9, 0xF8, 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2,
0xF1, 0xF0, 0xEF, 0xEE, 0xED, 0xEC, 0xEB, 0xEA, 0xE9,
0xE8, 0xE7, 0xE6, 0xE5, 0xE4, 0xE3, 0xE2, 0xE1, 0xE0,
0xDF, 0xDE, 0xDD, 0xDC, 0xDB, 0xDA, 0xD9, 0xD8, 0xD7,
0xD6, 0xD5, 0xD4, 0xD3, 0xD2, 0xD1, 0xD0, 0xCF, 0xCE,
0xCD, 0xCC, 0xCB, 0xCA, 0xC9, 0xC8, 0xC7, 0xC6, 0xC5,
0xC4, 0xC3, 0xC2, 0xC1};
for (int i = 0; i < sizeof(cipher); i++) {
int ch = 0;
for (int j = 0; j < sizeof(ebokk); j++) {
if (cipher[i] == ebokk[j]) {
ch = j;
break;
}
}
printf("%c", ch + 0x21);
}
return 0;
}
flag{u_ar3_re@11y_g00d_@t_011vm_de0bf_and_anti_debugger}