---
# System prepended metadata

title: HKCERT - EasyRev
tags: [MBA, Patch, Write-up, SIMD, Antidebug, XTEA]

---

# HKCERT - EasyRev


![image](https://hackmd.io/_uploads/Syr8QFPm-e.png)

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ố `}`.
![image](https://hackmd.io/_uploads/Bk5qtq_mZg.png)

```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)
```

![image](https://hackmd.io/_uploads/ByZwP5O7bl.png)

![image](https://hackmd.io/_uploads/BJP3D5OmZg.png)

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
![image](https://hackmd.io/_uploads/SyebMoumbx.png)
Make function cho nó rồi decompile thì mình đã thấy được đoạn check debug
![image](https://hackmd.io/_uploads/rkOZ7odXWg.png)


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);
```