# HKCERT - EasyRev

Xử lí SIMD noise injection (patch nop)
```py
from capstone import *
from capstone.x86 import *
import mmap
with open("main.exe", "rb") as f:
data = bytearray(f.read())
BASE = 0x140001000 - 0x400
START = 0x140001000
END = 0x140002C02
md = Cs(CS_ARCH_X86, CS_MODE_64)
md.detail = True
for insn in md.disasm(data[START-BASE:END-BASE], START):
mnem = insn.mnemonic
if mnem.startswith(("cmpss", "va", "ve", "vr", "vu", "vf", "vt", "vb", "vs", "vh", "vm", "vp", "vx", "vo", "vc", "vd", "sm", "ae", "rd", "fm", "fu", "fc", "fs", "tz", "rc", "pabs", "phsub", "psign")):
print(f"patch {hex(insn.address)} {mnem} size={insn.size}")
off = insn.address - BASE
data[off:off+insn.size] = b"\x90" * insn.size
with open("patched.exe", "wb") as f:
f.write(data)
```
Nhưng capstone lỗi ở lệnh 'nop r8' (multi-byte nop) nên bị dừng disasm. Để bypass qua chỗ đó thì mình có thể skip qua 4 byte và tiếp tục disasm. Nhưng mình muốn viết script tự nhảy pc để đọc lệnh để phần sau không bị lỗi nữa nếu có thêm byte rác.
```py
from capstone import *
from capstone.x86 import *
with open("main.exe", "rb") as f:
data = bytearray(f.read())
BASE_ADDRESS = 0x140001000
START = 0x400
END = 0x23400
md = Cs(CS_ARCH_X86, CS_MODE_64)
md.detail = True
code = data[START:END]
pc = 0
def is_rex_nop(buf):
return (
len(buf) >= 4 and
buf[0] in range(0x40, 0x50) and
buf[1] == 0x0F and
buf[2] == 0x1F
)
def checkSIMD(s):
# if 'mm' in s.op_str or 'st' in s.op_str:
# return 1
if s.mnemonic.startswith(("str", "cmpss", "cmpsd", "vi", "va", "ve", "vr", "vu", "vf", "vt", "vb", "vs", "vh", "vm", "vp", "vx", "vo", "vc", "vd", "sm", "ae", "fa", "ff", "fm", "fu", "fc", "fs", "tz", "rc", "rd", "pa", "pm", "ph", "ps", "sldt")):
return 1
return 0
while pc < len(code):
buf = code[pc:pc+15]
insns = list(md.disasm(buf, pc))
if insns:
insn = insns[0]
file_off = START + pc
if checkSIMD(insn):
data[file_off:file_off+insn.size] = b'\x90' * insn.size
pc += insn.size
else:
if is_rex_nop(buf):
pc += 4
else:
pc += 1
with open("patched.exe", "wb") as f:
f.write(data)
```
Patch vẫn chưa sạch lắm nhưng mà thôi kệ vẫn đọc được.
Code hàm main sau khi patch:
```c
int __fastcall main(int argc, const char **argv, const char **envp)
{
__m64 v3; // mm1
__m64 v4; // mm7
__m128 v5; // xmm1
__m128 v6; // xmm2
float v7; // xmm3_4
double v8; // xmm4_8
__int16 v9; // dx
char v10; // cl
__int64 v11; // rdx
__int64 v12; // rax
__int64 v13; // rdx
__int64 v14; // r11
__m128i v15; // xmm4
__int64 v16; // rdx
__int64 v17; // rcx
__int64 v18; // r8
char *v20; // rax
__int64 v21; // rdx
__int64 v22; // rdx
__int64 v23; // r9
__int64 v24; // r8
__int64 v25; // rdx
int v26; // edx
__int64 v27; // rcx
__int64 v28; // rdx
int v29; // eax
__int64 v30; // rax
__int64 v31; // rax
_BYTE v33[12]; // [rsp+24h] [rbp-74h] BYREF
_BYTE v34[12]; // [rsp+30h] [rbp-68h] BYREF
int v35; // [rsp+3Ch] [rbp-5Ch]
unsigned __int64 v36; // [rsp+40h] [rbp-58h]
unsigned __int64 k; // [rsp+48h] [rbp-50h]
_QWORD v38[3]; // [rsp+50h] [rbp-48h] BYREF
unsigned __int64 j; // [rsp+68h] [rbp-30h]
unsigned __int64 i; // [rsp+70h] [rbp-28h]
_BYTE v41[12]; // [rsp+7Ch] [rbp-1Ch] BYREF
unsigned __int64 len; // [rsp+88h] [rbp-10h]
int v43; // [rsp+94h] [rbp-4h]
v43 = 0;
((void (__fastcall *)(int, const char **, const char **))((char *)off_7FF768480260 + 0x2FAB1BB7013BFA7LL))(
argc,
argv,
envp);
((void (__fastcall *)(void *, char *))((char *)off_7FF768480268 + 0x3533C92875EBF31ELL))(
&unk_7FF768480FBC,
(char *)&unk_7FF7684743A0 + 468);
*(double *)v5.m128_u64 = sqrt(v8);
((void (__fastcall *)(void *, void *))((char *)off_7FF768480270 - 0x592B6E96FCCDB559LL))(
&unk_7FF768480FBC,
&byte_7FF768480E30);
LOWORD(v11) = v9 >> v10;
len = ((__int64 (__fastcall *)(void *, __int64))((char *)off_7FF768480278 - 0x100E985395D3C573LL))(
&byte_7FF768480E30,
v11); // len
if ( len == 42 ) // len = 42
{
((void (*)(void))((char *)off_7FF7684802A0 - 0xFF6F2DEE741D53CLL))();// func1
for ( i = 0LL; ; ++i )
{
v3 = _m_punpckhbw(v3, v4);
v6 = (__m128)_mm_unpacklo_epi32((__m128i)v6, (__m128i)v6);
if ( i >= len )
break;
v13 = (unsigned int)(*((char *)off_7FF768480098 + i + 0x12ADADE3AD60017CLL)
+ *((char *)encrypting_input + i + 0x6A36A897964DBCB7LL));
*((_BYTE *)encrypting_input + i + 0x6A36A897964DBCB7LL) += *((_BYTE *)off_7FF768480098 + i + 0x12ADADE3AD60017CLL);
v14 >>= 36;
}
LOWORD(v13) = v13 | 0xFF9C;
((void (__fastcall *)(_QWORD, __int64))((char *)off_7FF7684802A0 - 0xFF6F2DEE741D53CLL))(// func1
(unsigned int)_mm_extract_epi32(v15, 32),
v13);
for ( j = 0LL; j < len; ++j )
{
v20 = (char *)encrypting_input + 0x6A36A897964DBCB7LL;
v7 = *(double *)v5.m128_u64;
__asm { rdsspq r9 }
v18 = ~(~(~(~(*((char *)encrypting_input + j + 0x6A36A897964DBCB7LL) & 0xD80AF07D) & ~(~*((char *)encrypting_input
+ j
+ 0x6A36A897964DBCB7LL) & 0x27F50F82)) & 0x6AC02584) & ~(~(*((char *)encrypting_input + j + 0x6A36A897964DBCB7LL) & 0xD80AF07D) & ~(~*((char *)encrypting_input + j + 0x6A36A897964DBCB7LL) & 0x27F50F82) & 0x953FDA7B) & 0xB2CAD586);
v20[j] = ~(~(~(~(~(*((_BYTE *)encrypting_input + j + 0x6A36A897964DBCB7LL) & 0x7D) & ~(~*((_BYTE *)encrypting_input
+ j
+ 0x6A36A897964DBCB7LL) & 0x82)) & 0x84) & ~(~(*((_BYTE *)encrypting_input + j + 0x6A36A897964DBCB7LL) & 0x7D) & ~(~*((_BYTE *)encrypting_input + j + 0x6A36A897964DBCB7LL) & 0x82) & 0x7B) & 0x86) & ~(~(~(~(~(*((_BYTE *)encrypting_input + j + 0x6A36A897964DBCB7LL) & 0x7D) & ~(~*((_BYTE *)encrypting_input + j + 0x6A36A897964DBCB7LL) & 0x82)) & 0x84) & ~(~(*((_BYTE *)encrypting_input + j + 0x6A36A897964DBCB7LL) & 0x7D) & ~(~*((_BYTE *)encrypting_input + j + 0x6A36A897964DBCB7LL) & 0x82) & 0x7B)) & 0x79));
v16 = (unsigned int)(char)v20;
v5 = _mm_movelh_ps(v5, v6);
v17 = 0x1DAAD26BEAAFCF79LL;
}
((void (__fastcall *)(__int64, __int64, __int64, __int64))((char *)off_7FF7684802A0 - 0xFF6F2DEE741D53CLL))(// func1
v17,
v16,
v18,
_R9);
v38[0] = 0x6589602598654235LL;
v22 = __ROR8__(v21, 152);
v23 = (unsigned __int16)v22;
v38[1] = 0x5556575865841236LL;
LOBYTE(v22) = (unsigned __int8)v22 >> 1;
((void (__fastcall *)(_QWORD *, __int64, __int64, __int64))((char *)off_7FF7684802A8 - 0x7DA4E0BDECC7FFFCLL))(// func2
v38,
v22,
v24,
v23);
for ( k = 0LL; k < len >> 3; ++k )
{
((void (__fastcall *)(__int64, char *, _QWORD *))((char *)off_7FF7684802B0 + 0x6295BE8F36376BC7LL))(// func3
102LL,
(char *)encrypting_input + 8 * k + 0x6A36A897964DBCB7LL,
v38);
v25 = v26 - ((unsigned int)__CFADD__(k + 0x30CBCAE69232D1CDLL, 1LL) + 364126667);
}
((void (__fastcall *)(unsigned __int64, __int64))((char *)off_7FF7684802A0 - 0xFF6F2DEE741D53CLL))(len >> 3, v25);// func1
LOBYTE(v28) = v28 ^ 0xF6;
*(double *)v6.m128_u64 = v7;
v36 = 0LL;
while ( 1 )
{
v6 = (__m128)_mm_cmpistrm((__m128i)v6, (__m128i)v5, 46);
if ( v36 >= len )
break;
LOWORD(v27) = __ROR2__(v27, v27);
((void (__fastcall *)(__int64, __int64))((char *)off_7FF7684802A0 - 0xFF6F2DEE741D53CLL))(v27, v28);// func1
v35 = v29;
if ( *((char *)encrypting_input + v36 + 0x6A36A897964DBCB7LL) != v29
+ *((char *)ciphertext + v36 - 0x2B7A95E9A80E6A6FLL) )// checker
{
((void (__fastcall *)(void *, char *))((char *)off_7FF768480280 + 0x1B55CF27643E8BF0LL))(// Wrong
&unk_7FF768480FC8,
(char *)&unk_7FF7684743A0 + 528);
((void (__fastcall *)(_BYTE *, void *))((char *)off_7FF768480288 + 0x421BDD46CCB7BD16LL))(
v34,
&unk_7FF768480FC8); // print
v30 = ((__int64 (__fastcall *)(_BYTE *))((char *)off_7FF768480290 - 0x2871973C69EB090LL))(v34);
((void (__fastcall *)(__int64))((char *)off_7FF768480298 - 0x5A4CC83C3524CFF2LL))(v30);
return 0;
}
v27 = 0x73291284FC5F8C6BLL;
++v36;
v28 = (unsigned int)__ROL4__(v29, 1);
}
((void (__fastcall *)(void *, char *))((char *)off_7FF7684802B8 + 0x46C556EBE30FBC8LL))(// Correct
&unk_7FF768480FD8,
(char *)&unk_7FF7684743A0 + 585);
((void (__fastcall *)(_BYTE *, void *))((char *)off_7FF768480288 + 0x421BDD46CCB7BD16LL))(v33, &unk_7FF768480FD8);// print
v31 = ((__int64 (__fastcall *)(_BYTE *))((char *)off_7FF768480290 - 0x2871973C69EB090LL))(v33);
((void (__fastcall *)(__int64))((char *)off_7FF768480298 - 0x5A4CC83C3524CFF2LL))(v31);
}
else
{
((void (__fastcall *)(void *, char *))((char *)off_7FF768480280 + 0x1B55CF27643E8BF0LL))(// Wrong
&unk_7FF768480FC8,
(char *)&unk_7FF7684743A0 + 528);
((void (__fastcall *)(_BYTE *, void *))((char *)off_7FF768480288 + 0x421BDD46CCB7BD16LL))(v41, &unk_7FF768480FC8);// print
v12 = ((__int64 (__fastcall *)(_BYTE *))((char *)off_7FF768480290 - 0x2871973C69EB090LL))(v41);
((void (__usercall *)(__int64@<rcx>))((char *)off_7FF768480298 - 0x5A4CC83C3524CFF2LL))(v12);
return 0;
}
return v43;
}
```
func2: keygen XTEA
```c
__int64 __fastcall func2(__int64 a1, int a2, double a3, signed __int64 a4)
{
__int64 v4; // r10
__m64 v5; // mm7
__m64 v6; // mm5
unsigned int v7; // et0
__int64 result; // rax
int j; // [rsp+Ch] [rbp-14h]
int i; // [rsp+10h] [rbp-10h]
__int64 v11; // [rsp+18h] [rbp-8h]
v6 = _mm_cvttpd_pi32(*(__m128d *)&a3);
v11 = a1;
for ( i = 0; i < 32; ++i )
{
for ( j = 0; j < 4; ++j )
{
LOWORD(a1) = j;
a4 = (a4 >> 9) ^ 0xFFFFFFFFEA5EF272uLL;
a2 = *(_DWORD *)(v11 + 4LL * ((j + 1) % 4)) + 305419896 + *(_DWORD *)(v11 + 4LL * j);
*(_DWORD *)(v11 + 4LL * j) = a2;
v4 = __ROL8__(v4, 61);
v6 = _m_pcmpgtw(v6, v5);
}
HIWORD(v7) = a1;
LOWORD(v7) = a2;
LOWORD(a1) = v7 >> 3;
result = (unsigned int)(i + 1);
}
return result;
}
```
func3: XTEA round
```c
unsigned int *__fastcall func3(unsigned int a1, unsigned int *a2, __int64 a3)
{
__m64 v3; // mm0
__m64 v4; // mm3
__m64 v5; // mm4
__m64 v6; // mm5
__m64 v7; // mm6
__m64 v8; // mm7
__m64 v9; // mm0
__m64 v10; // mm6
unsigned int v11; // ecx
unsigned int v12; // eax
unsigned int v13; // ecx
unsigned int v14; // eax
unsigned int v15; // r8d
unsigned int *result; // rax
unsigned int v17; // [rsp+4h] [rbp-24h]
unsigned int v18; // [rsp+8h] [rbp-20h]
unsigned int v19; // [rsp+Ch] [rbp-1Ch]
unsigned int i; // [rsp+10h] [rbp-18h]
v19 = *a2;
v18 = a2[1];
v17 = 0;
v9 = _m_pcmpeqw(_m_por(v3, v5), v6);
v10 = _m_pcmpeqw(v7, v8);
for ( i = 0; i < a1; ++i )
{
v11 = ~((v18
+ 1272462553
- (~(~(~((v18 >> 5) & 0x5FAAD220) & ~(~(v18 >> 5) & 0xA0552DDF) & ~(~((16 * v18) & 0x61E7097E) & ~(~(16 * v18) & 0x9E18F681))) & ~(~((16 * v18) & 0x61E7097E) & ~(~(16 * v18) & 0x9E18F681) & ~(~((v18 >> 5) & 0x5FAAD220) & ~(~(v18 >> 5) & 0xA0552DDF))) & 0x3E4DDB5E) & ~(~(~(~((v18 >> 5) & 0x5FAAD220) & ~(~(v18 >> 5) & 0xA0552DDF) & ~(~((16 * v18) & 0x61E7097E) & ~(~(16 * v18) & 0x9E18F681))) & ~(~((16 * v18) & 0x61E7097E) & ~(~(16 * v18) & 0x9E18F681) & ~(~((v18 >> 5) & 0x5FAAD220) & ~(~(v18 >> 5) & 0xA0552DDF)))) & 0xC1B224A1))
- 1272462554) & 0x2D67FDBA);
v12 = ~(v11 & ~(~(v18
+ 1272462553
- (~(~(~((v18 >> 5) & 0x5FAAD220) & ~(~(v18 >> 5) & 0xA0552DDF) & ~(~((16 * v18) & 0x61E7097E) & ~(~(16 * v18) & 0x9E18F681))) & ~(~((16 * v18) & 0x61E7097E) & ~(~(16 * v18) & 0x9E18F681) & ~(~((v18 >> 5) & 0x5FAAD220) & ~(~(v18 >> 5) & 0xA0552DDF))) & 0x3E4DDB5E) & ~(~(~(~((v18 >> 5) & 0x5FAAD220) & ~(~(v18 >> 5) & 0xA0552DDF) & ~(~((16 * v18) & 0x61E7097E) & ~(~(16 * v18) & 0x9E18F681))) & ~(~((16 * v18) & 0x61E7097E) & ~(~(16 * v18) & 0x9E18F681) & ~(~((v18 >> 5) & 0x5FAAD220) & ~(~(v18 >> 5) & 0xA0552DDF)))) & 0xC1B224A1))
- 1272462554) & 0xD2980245));
v19 += ~(~(~(~((*(_DWORD *)(a3 + 4LL * ~((unsigned __int8)~(_BYTE)v17 | 0xFFFFFFFC)) + v17) & 0x212F72F5) & ~(~(*(_DWORD *)(a3 + 4LL * ~((unsigned __int8)~(_BYTE)v17 | 0xFFFFFFFC)) + v17) & 0xDED08D0A) & v12) & ~(~v12 & ~(~((*(_DWORD *)(a3 + 4LL * ~((unsigned __int8)~(_BYTE)v17 | 0xFFFFFFFC)) + v17) & 0x212F72F5) & ~(~(*(_DWORD *)(a3 + 4LL * ~((unsigned __int8)~(_BYTE)v17 | 0xFFFFFFFC)) + v17) & 0xDED08D0A))) & 0xC488F4F) & ~(~(~(~((*(_DWORD *)(a3 + 4LL * ~((unsigned __int8)~(_BYTE)v17 | 0xFFFFFFFC)) + v17) & 0x212F72F5) & ~(~(*(_DWORD *)(a3 + 4LL * ~((unsigned __int8)~(_BYTE)v17 | 0xFFFFFFFC)) + v17) & 0xDED08D0A) & v12) & ~(~v12 & ~(~((*(_DWORD *)(a3 + 4LL * ~((unsigned __int8)~(_BYTE)v17 | 0xFFFFFFFC)) + v17) & 0x212F72F5) & ~(~(*(_DWORD *)(a3 + 4LL * ~((unsigned __int8)~(_BYTE)v17 | 0xFFFFFFFC)) + v17) & 0xDED08D0A)))) & 0xF3B770B0));
v17 += ~(~(~(~(~(*(_DWORD *)((_BYTE *)off_7FF768480078 + 0x3D5A6525234A0D3LL) & 0xFD88B062) & ~(~*(_DWORD *)((char *)off_7FF768480078 + 0x3D5A6525234A0D3LL) & 0x2774F9D)) & 0xAFC63A1) & ~(~(*(_DWORD *)((_BYTE *)off_7FF768480078 + 0x3D5A6525234A0D3LL) & 0xFD88B062) & ~(~*(_DWORD *)((char *)off_7FF768480078 + 0x3D5A6525234A0D3LL) & 0x2774F9D) & 0xF5039C5E) & 0x7B77FC02) & ~(~(~(~(~(*(_DWORD *)((_BYTE *)off_7FF768480078 + 0x3D5A6525234A0D3LL) & 0xFD88B062) & ~(~*(_DWORD *)((char *)off_7FF768480078 + 0x3D5A6525234A0D3LL) & 0x2774F9D)) & 0xAFC63A1) & ~(~(*(_DWORD *)((_BYTE *)off_7FF768480078 + 0x3D5A6525234A0D3LL) & 0xFD88B062) & ~(~*(_DWORD *)((char *)off_7FF768480078 + 0x3D5A6525234A0D3LL) & 0x2774F9D) & 0xF5039C5E)) & 0x848803FD));
v13 = ~((v19
+ -(~(~(~((v19 >> 5) & 0x928A6F5C) & ~(~(v19 >> 5) & 0x6D7590A3) & ~(~((16 * v19) & 0x9EE30EA5) & ~(~(16 * v19) & 0x611CF15A))) & ~(~((16 * v19) & 0x9EE30EA5) & ~(~(16 * v19) & 0x611CF15A) & ~(~((v19 >> 5) & 0x928A6F5C) & ~(~(v19 >> 5) & 0x6D7590A3))) & 0xC6961F9) & ~(~(~(~((v19 >> 5) & 0x928A6F5C) & ~(~(v19 >> 5) & 0x6D7590A3) & ~(~((16 * v19) & 0x9EE30EA5) & ~(~(16 * v19) & 0x611CF15A))) & ~(~((16 * v19) & 0x9EE30EA5) & ~(~(16 * v19) & 0x611CF15A) & ~(~((v19 >> 5) & 0x928A6F5C) & ~(~(v19 >> 5) & 0x6D7590A3)))) & 0xF3969E06))
- 1177430714
+ 1177430713) & 0xC4A157E1);
v14 = ~(v13 & ~(~(v19
+ -(~(~(~((v19 >> 5) & 0x928A6F5C) & ~(~(v19 >> 5) & 0x6D7590A3) & ~(~((16 * v19) & 0x9EE30EA5) & ~(~(16 * v19) & 0x611CF15A))) & ~(~((16 * v19) & 0x9EE30EA5) & ~(~(16 * v19) & 0x611CF15A) & ~(~((v19 >> 5) & 0x928A6F5C) & ~(~(v19 >> 5) & 0x6D7590A3))) & 0xC6961F9) & ~(~(~(~((v19 >> 5) & 0x928A6F5C) & ~(~(v19 >> 5) & 0x6D7590A3) & ~(~((16 * v19) & 0x9EE30EA5) & ~(~(16 * v19) & 0x611CF15A))) & ~(~((16 * v19) & 0x9EE30EA5) & ~(~(16 * v19) & 0x611CF15A) & ~(~((v19 >> 5) & 0x928A6F5C) & ~(~(v19 >> 5) & 0x6D7590A3)))) & 0xF3969E06))
- 1177430714
+ 1177430713) & 0x3B5EA81E));
v9 = _m_por(v9, v9);
v10 = _m_punpcklwd(v10, v4);
v15 = ~((*(_DWORD *)(a3 + 4LL * ~((unsigned __int8)~(v17 >> 11) | 0xFFFFFFFC)) + v17) & 0x9B947D9A) & ~(~(*(_DWORD *)(a3 + 4LL * ~((unsigned __int8)~(v17 >> 11) | 0xFFFFFFFC)) + v17) & 0x646B8265);
v18 += ~(~(~(v15 & v14) & ~(~v14 & ~v15) & 0x5F352A7B) & ~(~(~(v15 & v14) & ~(~v14 & ~v15)) & 0xA0CAD584));
}
*a2 = v19;
result = a2;
a2[1] = v18;
return result;
}
```
Debug step-in vào từng hàm con được gọi trong main ta có được Flow:
* input (42 bytes)
* xor 0x7f (IV)
* func2 -> key
* func3: for 102 lần XTEA (chia 5 block 8 bytes)
* so khớp cipher
Debug Lấy key: breakpoint sau func2, lấy giá trị ở mảng v38.
`CD 85 74 C7 F1 31 C4 09 70 6A D7 A3 37 49 0C 56`
Debug Lấy cipher: breakpoint trước cmp, lấy giá trị tại rcx sau khi add cs:ciphertext.
`F8 AC F7 66 C8 BB 9A C7 DC 1A 82 FF 27 04 0E 91 15 BD 1C 2F 98 F7 96 D2 C2 DF 12 0C 56 50 E6 20 58 AE 5C 67 7A FF 8A 95 43 1A`
Debug lại logic của func3 để lấy chính xác code XTEA đã custom:
Trong func3:
* off_7FF768480078 + 0x3D5A6525234A0D3LL = 0x12345678 --> v17 += 0x9E3779B9 (delta)
* ...
Script python:
```py
```
SAI.
Mình đã mặc định bỏ qua hàm func1 nhưng có vẻ như chỗ lưu cipher bị ghi đè rất nhiều lần qua mỗi lần func1 được gọi?? Antidebug chăng?. Thử cipher ban đầu xem. Với 2 byte cuối cố định, ta có thể tính được giá trị xor là 0xbf để có hậu tố `}`.

```py
import struct
import ctypes
cipher_str = "BA 7A AA 6A 2F 7E F8 03 2D B4 AB 92 6B 91 31 DA 95 37 51 13 1F CE 1C 62 51 BC 3F B2 B1 B3 54 17 EF 28 93 AE 52 CA CE A7 DE C2"
# debug sai
# cipher_str = "F8 AC F7 66 C8 BB 9A C7 DC 1A 82 FF 27 04 0E 91 15 BD 1C 2F 98 F7 96 D2 C2 DF 12 0C 56 50 E6 20 58 AE 5C 67 7A FF 8A 95 43 1A"
ciphertext = bytes.fromhex(cipher_str.replace(" ", ""))
key_str = "CD 85 74 C7 F1 31 C4 09 70 6A D7 A3 37 49 0C 56"
key_bytes = bytes.fromhex(key_str.replace(" ", ""))
key = struct.unpack('<4I', key_bytes)
def c_uint32(val):
return ctypes.c_uint32(val).value
def xtea_decrypt_custom(v0, v1, key):
DELTA = 0x9E3779B9
ROUNDS = 102
s = c_uint32(DELTA * ROUNDS)
for _ in range(ROUNDS):
entry1 = c_uint32((v0 << 4) ^ (v0 >> 5)) + v0
entry2 = s + key[(s >> 11) & 3]
v1 = c_uint32(v1 - (entry1 ^ entry2))
s = c_uint32(s - DELTA)
entry3 = c_uint32((v1 << 4) ^ (v1 >> 5)) + v1
entry4 = s + key[s & 3]
v0 = c_uint32(v0 - (entry3 ^ entry4))
return v0, v1
decrypted_buffer = bytearray()
num_blocks = len(ciphertext) // 8
for i in range(num_blocks):
block = ciphertext[i*8 : (i+1)*8]
v0, v1 = struct.unpack('<2I', block)
d0, d1 = xtea_decrypt_custom(v0, v1, key)
decrypted_buffer += struct.pack('<2I', d0, d1)
decrypted_buffer += ciphertext[num_blocks*8:]
flag_chars = []
for b in decrypted_buffer:
flag_chars.append(chr(((b ^ 0xbf) & 0x7F)))
flag = "".join(flag_chars)
print(flag)
```


Phân tích lại func1:
```c
__int64 __fastcall func1(__int64 a1, __int64 a2, float a3, double a4)
{
__m64 v4; // mm3
__m64 v5; // mm4
__m64 v6; // mm4
char v7; // al
char v8; // al
char v9; // r9
char v10; // r10
float v11; // xmm4_4
int i; // [rsp+20h] [rbp-8h]
unsigned int v14; // [rsp+24h] [rbp-4h]
v6 = _m_punpckldq(v5, v4);
LOWORD(a2) = (unsigned __int16)a2 >> a1;
v7 = ((__int64 (__fastcall *)(__int64, __int64))((char *)off_7FF768480248 + 0x2FAB1BB7013BFA7LL))(a1, a2);
v14 = v7 & 1;
if ( (v7 & 1) != 0 )
{
for ( i = 0; i < 42; ++i )
{
*(float *)&a4 = *(float *)&a4 * a3;
v8 = ((__int64 (*)(void))((char *)off_7FF768480250 + 0x3533C92875EBF31ELL))();
v9 = ~(*((_BYTE *)off_7FF768480070 + i + 0x3D5A6525234A0D3LL) & 0xA7) & ~(~*((_BYTE *)off_7FF768480070
+ i
+ 0x3D5A6525234A0D3LL) & 0x58);
v10 = ~(v8 & 0x6B) & ~(~v8 & 0x94);
*(__m128i *)&a4 = _mm_unpacklo_epi16(*(__m128i *)&a4, *(__m128i *)&a4);
v4 = _m_pcmpeqw(v4, v6);
*(float *)&a4 = v11;
*((_BYTE *)off_7FF768480070 + i + 0x3D5A6525234A0D3LL) = ~(~(~(v10 & ~v9) & ~(v9 & ~v10) & 0xCC) & ~(~(~(v10 & ~v9) & ~(v9 & ~v10)) & 0x33));
}
}
return v14;
}
```
Vậy nếu v7 lẻ thì vùng nhớ đó sẽ bị ghi đè. debug xem đoạn v7 này nó call đi đâu

Make function cho nó rồi decompile thì mình đã thấy được đoạn check debug

Update: Có thể làm sạch hơn đoạn gọi hàm bằng các thao tác trên IDA hoặc IDAPython script hoặc patch raw bằng cách tính ra offset rồi ghi đè vào. Sau bài này mình sẽ thử viết/tổng hợp thêm vài plugin deobfuscator cho IDA.
Cách obfuscate để ép thành char* + offset như jumptable kia:
```c
typedef long long (__fastcall *fp_t)(long long, long long);
void *table[] = {
(void *)((char *)func1 - 0x12345678),
};
fp_t f = (fp_t)((char *)table[0] + 0x12345678);
f(a, b);
```