首页
社区
课程
招聘
[原创] 看雪 2024 KCTF 大赛 第六题 异星文明
发表于: 2024-8-28 07:12 3740

[原创] 看雪 2024 KCTF 大赛 第六题 异星文明

2024-8-28 07:12
3740

又是这种加混淆的题目……做起来体验感真的几乎为零
 
现在看到用“规则二”出的题有点PTSD了,期望第七题缓一缓
(本题是晚上回家看到一血只用了5个多小时才敢尝试的;另外, 此时做题速度已经不重要了,因为按照现行的计分,除非贴着一血的时间交题,否则非一血无论如何都只能拿到一半多一点的分数)
(建议把题目使用了规则一还是二与题目分类写在一起尽早公开,这样开赛前好提早有心理准备)
 
目前的“规则二”要求出题人公开混淆脚本确实不错,但是作为攻击方,相对于加混淆的方法,更希望看到的是出题人自己的去混淆脚本(简单的说,防守方不能只管出不管做)
 
顺便,继续等待第三题出题人发布自己的去混淆脚本的那一天

先对题目做一些初始探索
 
静态分析,从start函数开始,进入 sub_140108580 ,然后是 sub_140108000 (位于zxvmp1区段),里面有一个大循环,未被混淆的代码差不多只有这些,另外多出来的有zxvmp开头的几个区段。导入表只有少量函数,而且无法直接找到交叉引用。

 
动态分析,修改exe头关闭dynamic base,然后上x64dbg调试,在调试器环境下输入公开的name-serial能正常通过,是个好消息,至少题目没有埋暗坑。
 
观察导入表的函数,猜测程序会通过GetWindowTextW函数获取输入框的值。下个断点观察调用栈和返回地址,向上找几层找到调用来源是0x140108207(位于sub_140108000的一个分支中)
 
0x140108207是 ((void (*)(void))v12->field_A8)(); 间接调用,在这里下断点然后单步进入,发现总是会调用一个导入表的函数。
 
回到GetWindowTextW,这个函数被调用了两次,分别对应两个输入框的值。在第二次调用到的时候,对第一个参数的内存下硬件数据读取断点,继续执行,程序停在了0x140114994(movzx eax, word ptr [rax+rcx*2]),这里是访问输入的serial的地方。
继续执行会返回到0x14010825D(sub_140108000中调用sub_1401085FB的下一行),但调用栈里却没有发现。
调试sub_1401085FB,发现它的ret并不是返回到调用处,而是会每次进入zxvmp3区段的一个不同的位置(例如刚才提到的0x140114993),直到再一次ret才会回到真正的调用点。

至此可以确定,sub_140108000是虚拟机的主循环,下方的两个分支,v12->field_A8)()的间接调用用于导入表函数,sub_1401085FB用于执行虚拟机指令。sub_14010848F总是返回常量0x140006000(zxvmp0区段的起始地址),保存着虚拟机的各种状态,巨大的for循环用于寻找下一条虚拟机指令。
 
虚拟机循环和状态储存看起来很有规律,但是先不花费精力去分析。根据上面的分析,只要在0x1401086C2(即sub_1401085FB函数最后ret指令)处下断点,单步一次即可进入zxvmp3区段的虚拟机指令块处。
人工观察这些虚拟机指令块,发现具有明显的规律:总是以popfq开头,然后跟着一句看起来很正常的指令,然后是pushfq(也有一些地方没有中间的指令)
继续跟踪几轮,把中间这句看着很正常的指令连起来,得到的代码非常顺眼,具有明显的编译器生成的特征。由此可以得出结论,程序的混淆并没有改变原始指令,只是把指令拆散分布到各处,然后由sub_140108000的循环不断寻找并执行。

 

不由想起了KCTF2021春季赛的第七题,也是类似这样把真实指令混在垃圾指令之间,不过那题用了SMC自解密而且真实指令周围没有太明显的特征,相比之下本题做追踪简单多了

将以上过程自动化,首先是一小段x64dbg脚本,作用是找到sub_1401085FB函数最后ret指令(0x1401086C2)每次跳转到的位置并记录下来:

(p.s. 一开始让chatgpt GPT-4o帮忙写,结果x64dbg不停的报错。需要严谨的场景,个人还是更信任文档而不是生成式AI)
 
注意实施细节:
x64dbg的“脚本”窗口‘右键-载入脚本-粘贴’可以快速放入脚本,脚本的输出展示在x64dbg的“日志”窗口
“日志”窗口‘右键-重定向日志输出’可以指定一个文件
由于是GUI程序且各种界面的事件处理函数也被混淆了,因此如果一开始就启用脚本,UI会爆卡。我们只关心数据处理的部分,点击界面按钮后可以先断点在GetWindowTextW函数,然后再启用脚本,后续就不会被UI事件影响了。
 
这段trace脚本要跑若干分钟(不知道是“日志”窗口刷屏的原因还是调试器频繁中断的原因,应该怎样做才能加速呢……),得到的日志文件有4w多行。筛除无关信息,只保留log {[rsp]}记录的地址,只剩下18832行,而且可见的有大段循环重复。(见附件 trace_output_filtered.txt )
 
 
继续,写一个脚本将trace到的位置的指令提取出来(检查第一条指令是popfq,然后提取它后面的第二条指令,并检查第三条指令是pushfq
(p.s. capstone的用法来自chatgpt GPT-4o,不想查文档了)

忽略重复的地址,得到的输出(见附件disasm_output2.txt)只有386行。
 
将这些指令拼成一个二进制用IDA打开看看:

能比较直观的看到开头部分对serial的hexdecode;但是,由于上面的脚本没有处理好基本块之间的跳转关系,丢失了循环,所以对serial具体处理不能直接照抄(最开始没意识到,被坑了很久),但基本逻辑可以用来对照参考
(p.s. 处理循环应该不难(但可能比较复杂):每个地址可以当作只包含一条指令的基本块,那么根据trace结果,相邻的两行地址即为程序中记录过的执行转移,可以作为基本块的连接。做完所有基本块的连接后,修正条件跳转指令即可生成一个真正逻辑正确的二进制文件)

鉴于不重复的汇编指令只有386条,人工处理也许效率更高。
 
根据trace,汇编指令大致分为4个部分
 
第一部分:是一个循环,循环节如下(即:0x3d8后会jmp回0x336)

结合调试,栈上的几个变量如下:

虽然不长,但看汇编还是有点难受。IDA给出的结果一般:

这里chatgpt GPT-4o的表现反而很不错,经过几轮交互要求它简化代码后给出的结果(需要人工调试验证,但从最终的分析看,基本是正确的)(变量vx代表[rsp+x])

第二部分:(不是循环)

第三部分:(另一个循环,逻辑与之前差不多)

第四部分:(不是循环)

省略过程,直接给出整理后的最终代码和逆向逻辑:

 
最终的答案:
 
name: KCTF
serial: 901AB07A40D87A7B96ED4B0420EA2B552C9E12C71F9E967E5BEA37A83BC79E1F

在调试过程中遇到了一个奇怪的问题不知道是什么原因:
过滤后的汇编,有一行是0x31f 0x140110a0f: mov dword ptr [rsp], eax,只要在0x140110a0f下软件断点,此句执行后[rsp]保存的值就会不等于eax,而在其他地方下断点(例如前一句的0x140110a0e)则不会有问题。
具体操作:0. patch exe头禁用dynamic base 1. x64dbg (2024 Aug 5版本) 加载进程 2. cpu窗口定位到0x140110a0f,按F2下一个断点 3. 按F9运行,输入提供的name和serial,点击按钮 4. 程序停止在0x140110a0f,注意到此时rax是000000005A5F2142 5. 按F7单步执行,然后发现[rsp] 0000000140085E08处的内存变为了D1D2F49F5A5F2042,即eax的5A5F2142在执行mov dword ptr [rsp], eax后进入内存变为了5A5F2042,有一个bit改变了

__int64 __usercall sub_140108000@<rax>(
        __int32 a1@<edx>,
        unsigned __int64 a2@<rcx>,
        __int64 a3@<rbx>,
        __int64 a4@<rbp>,
        __int64 a5@<rdi>,
        __int64 a6@<rsi>,
        __int64 a7@<r12>,
        __int64 a8@<r13>,
        __int64 a9@<r14>,
        __int64 a10@<r15>)
{
  __int64 result; // rax
  char *v11; // rax
  struct machine *v12; // rax
  struct machine *v13; // [rsp+20h] [rbp-78h]
  __int32 v14; // [rsp+28h] [rbp-70h]
  unsigned __int64 i; // [rsp+30h] [rbp-68h]
  unsigned int v16; // [rsp+38h] [rbp-60h]
  struct instruction *current_inst; // [rsp+40h] [rbp-58h]
  __int64 v18; // [rsp+48h] [rbp-50h]
  char *v19; // [rsp+58h] [rbp-40h]
  unsigned __int64 v20; // [rsp+60h] [rbp-38h]
  __int64 v21; // [rsp+70h] [rbp-28h]
  __int64 v22; // [rsp+80h] [rbp-18h]
 
  v13 = sub_14010848F();   // it always return constant value 0x140006000
  current_inst = v13->current_inst;
  v13->field_D8 = a1;
  v19 = &sub_140108370()[current_inst->field_10];
  for ( i = a2; ; i += 4LL )
  {
    result = current_inst->field_18;
    if ( i == result )
      break;
    v16 = *(_DWORD *)&v19[i];
    if ( v13->field_D4 )
    {
      i = sub_1401083D0(current_inst, v13->field_D0, v13->field_DC);
      v16 = *(_DWORD *)&v19[i];
      v13->field_D4 = 0;
      v14 = v13->field_DC;
    }
    else if ( v13->field_D8 )
    {
      v14 = v13->field_D8;
      v13->field_D8 = 0;
    }
    else
    {
      v14 = *(_DWORD *)v13->maybe_rsp;
      v13->maybe_rsp += 8LL;
    }
    v20 = current_inst->field_28 / 12uLL;
    v11 = sub_140108370();
    v18 = sub_1401082A0(&v11[current_inst->field_20], v14 ^ v16, 0LL, (unsigned int)v20);
    if ( (v18 & 0x4000000000000000LL) != 0 )
    {
      v21 = sub_1401083A0() + (v18 & 0xBFFFFFFFFFFFFFFFuLL);
      sub_14010848F()->field_A8 = v21;
      v12 = sub_14010848F();
      ((void (*)(void))v12->field_A8)();
    }
    else
    {
      v22 = sub_1401083A0() + (v18 & 0x7FFFFFFFFFFFFFFFLL);
      sub_14010848F()->field_A8 = v22;
      sub_1401085FB(a3, a4, a5, a6, a7, a8, a9, a10);
      if ( v18 < 0 )
        return v13->field_B0;
    }
  }
  return result;
}
__int64 __usercall sub_140108000@<rax>(
        __int32 a1@<edx>,
        unsigned __int64 a2@<rcx>,
        __int64 a3@<rbx>,
        __int64 a4@<rbp>,
        __int64 a5@<rdi>,
        __int64 a6@<rsi>,
        __int64 a7@<r12>,
        __int64 a8@<r13>,
        __int64 a9@<r14>,
        __int64 a10@<r15>)
{
  __int64 result; // rax
  char *v11; // rax
  struct machine *v12; // rax
  struct machine *v13; // [rsp+20h] [rbp-78h]
  __int32 v14; // [rsp+28h] [rbp-70h]
  unsigned __int64 i; // [rsp+30h] [rbp-68h]
  unsigned int v16; // [rsp+38h] [rbp-60h]
  struct instruction *current_inst; // [rsp+40h] [rbp-58h]
  __int64 v18; // [rsp+48h] [rbp-50h]
  char *v19; // [rsp+58h] [rbp-40h]
  unsigned __int64 v20; // [rsp+60h] [rbp-38h]
  __int64 v21; // [rsp+70h] [rbp-28h]
  __int64 v22; // [rsp+80h] [rbp-18h]
 
  v13 = sub_14010848F();   // it always return constant value 0x140006000
  current_inst = v13->current_inst;
  v13->field_D8 = a1;
  v19 = &sub_140108370()[current_inst->field_10];
  for ( i = a2; ; i += 4LL )
  {
    result = current_inst->field_18;
    if ( i == result )
      break;
    v16 = *(_DWORD *)&v19[i];
    if ( v13->field_D4 )
    {
      i = sub_1401083D0(current_inst, v13->field_D0, v13->field_DC);
      v16 = *(_DWORD *)&v19[i];
      v13->field_D4 = 0;
      v14 = v13->field_DC;
    }
    else if ( v13->field_D8 )
    {
      v14 = v13->field_D8;
      v13->field_D8 = 0;
    }
    else
    {
      v14 = *(_DWORD *)v13->maybe_rsp;
      v13->maybe_rsp += 8LL;
    }
    v20 = current_inst->field_28 / 12uLL;
    v11 = sub_140108370();
    v18 = sub_1401082A0(&v11[current_inst->field_20], v14 ^ v16, 0LL, (unsigned int)v20);
    if ( (v18 & 0x4000000000000000LL) != 0 )
    {
      v21 = sub_1401083A0() + (v18 & 0xBFFFFFFFFFFFFFFFuLL);
      sub_14010848F()->field_A8 = v21;
      v12 = sub_14010848F();
      ((void (*)(void))v12->field_A8)();
    }
    else
    {
      v22 = sub_1401083A0() + (v18 & 0x7FFFFFFFFFFFFFFFLL);
      sub_14010848F()->field_A8 = v22;
      sub_1401085FB(a3, a4, a5, a6, a7, a8, a9, a10);
      if ( v18 < 0 )
        return v13->field_B0;
    }
  }
  return result;
}
bp 1401086c2
 
mainloop:
    log {[rsp]}
    run
    goto mainloop
bp 1401086c2
 
mainloop:
    log {[rsp]}
    run
    goto mainloop
from capstone import *
 
md = Cs(CS_ARCH_X86, CS_MODE_64)
 
def v2f(v):    # virtual address to file offset
    return v - (0x14010c000-0x7a00)
 
def f2v(f):
    return f + (0x14010c000-0x7a00)
 
with open("fzbz.exe", "rb") as f:
    content = f.read()
 
with open("trace_output_filtered.txt", "r") as f:
    lines = f.readlines()
addrs = [int(line, 16) for line in lines]
 
 
insts_bytes = b""
 
all_insts = []
insts_map = {}
next_block_map = {}
 
 
last_addr = -1
for addr in addrs:
    if addr in insts_map:
        next_block_map.setdefault(last_addr, set()).add(addr)
        continue
    code = content[v2f(addr):v2f(addr)+45]
    insns = list(md.disasm(code, addr))[:3]
    if not (insns[0].mnemonic == "popfq"):
        print(f"0x{insns[0].address:x}: what")
    else:
        insn = insns[1]
        if insn.mnemonic == "pushfq":
            continue
        text = f"0x{insn.address:x}:\t{insn.mnemonic}\t{insn.op_str}"
        all_insts.append((addr, len(insts_bytes), text))
        insts_map[addr] = text
        next_block_map.setdefault(last_addr, set()).add(addr)
        insts_bytes += code[insn.address-addr:insn.address-addr+insn.size]
        last_addr = addr
        print(text)
 
with open("disasm_output2.txt", "w") as f:
    for addr, offset, inst_text in all_insts:
        f.write(f"0x{offset:x}\t{inst_text}".ljust(64)+"\t"+str(list(map(hex, next_block_map.get(addr, set())))) + "\n")
 
with open("insts_bytes_1.bin", "wb") as f:
    f.write(insts_bytes)
from capstone import *
 
md = Cs(CS_ARCH_X86, CS_MODE_64)
 
def v2f(v):    # virtual address to file offset
    return v - (0x14010c000-0x7a00)
 
def f2v(f):
    return f + (0x14010c000-0x7a00)
 
with open("fzbz.exe", "rb") as f:
    content = f.read()
 
with open("trace_output_filtered.txt", "r") as f:
    lines = f.readlines()
addrs = [int(line, 16) for line in lines]
 
 
insts_bytes = b""
 
all_insts = []
insts_map = {}
next_block_map = {}
 
 
last_addr = -1
for addr in addrs:
    if addr in insts_map:
        next_block_map.setdefault(last_addr, set()).add(addr)
        continue
    code = content[v2f(addr):v2f(addr)+45]
    insns = list(md.disasm(code, addr))[:3]
    if not (insns[0].mnemonic == "popfq"):
        print(f"0x{insns[0].address:x}: what")
    else:
        insn = insns[1]
        if insn.mnemonic == "pushfq":
            continue
        text = f"0x{insn.address:x}:\t{insn.mnemonic}\t{insn.op_str}"
        all_insts.append((addr, len(insts_bytes), text))
        insts_map[addr] = text
        next_block_map.setdefault(last_addr, set()).add(addr)
        insts_bytes += code[insn.address-addr:insn.address-addr+insn.size]
        last_addr = addr
        print(text)
 
with open("disasm_output2.txt", "w") as f:
    for addr, offset, inst_text in all_insts:
        f.write(f"0x{offset:x}\t{inst_text}".ljust(64)+"\t"+str(list(map(hex, next_block_map.get(addr, set())))) + "\n")
 
with open("insts_bytes_1.bin", "wb") as f:
    f.write(insts_bytes)
void __fastcall sub_0(
        __int64 a1,
        __int64 a2,
        __int64 a3,
        __int64 a4,
        __int64 a5,
        __int64 a6,
        __int64 a7,
        __int64 a8,
        __int64 a9,
        __int64 a10,
        int a11,
        _WORD *a12,
        unsigned __int8 *a13)
{
  unsigned __int8 *v13; // rcx
  char v14; // al
  bool v15; // cc
  _BYTE *v16; // rdi
  unsigned int v17; // edx
  __int64 v18; // r8
  __int64 v19; // r9
  unsigned int v20; // [rsp+4h] [rbp-13Ch]
  unsigned int v21; // [rsp+4h] [rbp-13Ch]
  unsigned int v22; // [rsp+8h] [rbp-138h]
  char v23; // [rsp+6Ch] [rbp-D4h]
  _DWORD v24[6]; // [rsp+80h] [rbp-C0h] BYREF
  _BYTE v25[33]; // [rsp+98h] [rbp-A8h] BYREF
  _BYTE v26[7]; // [rsp+B9h] [rbp-87h] BYREF
  _QWORD v27[5]; // [rsp+C0h] [rbp-80h] BYREF
  unsigned __int8 v28; // [rsp+E8h] [rbp-58h] BYREF
  unsigned __int8 v29; // [rsp+E9h] [rbp-57h]
  unsigned __int8 v30; // [rsp+EAh] [rbp-56h]
  unsigned int v31; // [rsp+108h] [rbp-38h]
  _BYTE *v32; // [rsp+138h] [rbp-8h]
 
  if ( *a12 )
  {
    if ( !*(_WORD *)a13 )
    {
      memset(v27, 0, 0x21uLL);
      memset(v24, 0, 0x11uLL);
      LOBYTE(v24[0]) = *MEMORY[0xFFFFFFFFFFEEB4DD] ^ *a12;
      v28 = *a13;
      if ( v28 < 0x30u )
        goto LABEL_6;
      if ( v28 <= 0x39u )
        JUMPOUT(0x1C7LL);
      v13 = &v28;
      v14 = v29;
      v15 = v29 <= 0x39u;
      if ( v29 > 0x39u )
      {
LABEL_6:
        v23 = v29 - 55;
        v13 = &v28;
        v14 = v28;
        v15 = v28 <= 0x39u;
      }
      if ( !v15 )
      {
        v14 = (16 * (v28 - 48)) | v23;
        v13 = 0LL;
      }
      *((_BYTE *)v27 + (_QWORD)v13) = v14;
      if ( v30 >= 0x41u )
      {
        memset(v25, 0, sizeof(v25));
        v16 = v26;
        v20 = ((BYTE1(v24[0]) + (HIDWORD(v27[0]) >> 3)) ^ (v24[0] + HIDWORD(v27[0])) ^ (LOBYTE(v24[0])
                                                                                      + (HIDWORD(v27[0]) << 6)))
            + LODWORD(v27[0]);
        v22 = (v24[1] + v24[0]) ^ ((((unsigned __int8)((unsigned int)(v24[1] + v24[0]) >> 16) + (v20 >> 3)) ^ (v24[1] + v24[0] + v20) ^ (((unsigned int)(v24[1] + v24[0]) >> 24) + (v20 << 6)))
                                 + HIDWORD(v27[0]));
        v21 = ((LOBYTE(v24[2]) + (v22 >> 5)) ^ (v24[2] + v22) ^ (HIBYTE(v24[2]) + 16 * v22)) + ((v24[1] + v24[0]) ^ v20);
        *(_DWORD *)v25 = (v24[3] + v24[2]) ^ v21;
        *(_DWORD *)&v25[4] = (v24[3] + v24[2]) ^ ((((unsigned __int8)((unsigned __int16)(LOWORD(v24[3]) + LOWORD(v24[2])) >> 8)
                                                  + (v21 >> 5)) ^ (v24[3] + v24[2] + v21) ^ ((unsigned __int8)((unsigned int)(v24[3] + v24[2]) >> 16)
                                                                                           + 16 * v21))
                                                + v22);
        MEMORY[0xFFFFFFFFFFFF72CC](v26, a2, v25, 4LL, 128LL);
        if ( (char)*MEMORY[0xFFFFFFFFFFEE980A] != v25[0] )
        {
          v16 = v32;
          if ( !(unsigned int)MEMORY[0xFFFFFFFFFFFF551D](v32) )
            JUMPOUT(0x589LL);
          v19 = 0LL;
          v18 = -1148776LL;
          v17 = -1155031;
        }
        v32 = v16;
        v31 = v17;
        if ( v17 != 2 )
        {
          if ( v31 != 16 )
          {
            if ( v31 == 273 )
              JUMPOUT(0x5D4LL);
            if ( v31 == 312 )
              JUMPOUT(0x5DELL);
            MEMORY[0xFFFFFFFFFFFECD0F](v32, a2, v17, 0LL, v18, v19);
          }
          JUMPOUT(0x5CALL);
        }
        JUMPOUT(0x5C3LL);
      }
      JUMPOUT(0x271LL);
    }
    JUMPOUT(0xBDLL);
  }
  JUMPOUT(0x86LL);
}
void __fastcall sub_0(
        __int64 a1,
        __int64 a2,
        __int64 a3,
        __int64 a4,
        __int64 a5,
        __int64 a6,
        __int64 a7,
        __int64 a8,
        __int64 a9,
        __int64 a10,
        int a11,
        _WORD *a12,
        unsigned __int8 *a13)
{
  unsigned __int8 *v13; // rcx
  char v14; // al
  bool v15; // cc
  _BYTE *v16; // rdi
  unsigned int v17; // edx
  __int64 v18; // r8
  __int64 v19; // r9
  unsigned int v20; // [rsp+4h] [rbp-13Ch]
  unsigned int v21; // [rsp+4h] [rbp-13Ch]
  unsigned int v22; // [rsp+8h] [rbp-138h]
  char v23; // [rsp+6Ch] [rbp-D4h]
  _DWORD v24[6]; // [rsp+80h] [rbp-C0h] BYREF
  _BYTE v25[33]; // [rsp+98h] [rbp-A8h] BYREF
  _BYTE v26[7]; // [rsp+B9h] [rbp-87h] BYREF
  _QWORD v27[5]; // [rsp+C0h] [rbp-80h] BYREF
  unsigned __int8 v28; // [rsp+E8h] [rbp-58h] BYREF
  unsigned __int8 v29; // [rsp+E9h] [rbp-57h]
  unsigned __int8 v30; // [rsp+EAh] [rbp-56h]
  unsigned int v31; // [rsp+108h] [rbp-38h]
  _BYTE *v32; // [rsp+138h] [rbp-8h]
 
  if ( *a12 )
  {
    if ( !*(_WORD *)a13 )
    {
      memset(v27, 0, 0x21uLL);
      memset(v24, 0, 0x11uLL);
      LOBYTE(v24[0]) = *MEMORY[0xFFFFFFFFFFEEB4DD] ^ *a12;
      v28 = *a13;
      if ( v28 < 0x30u )
        goto LABEL_6;
      if ( v28 <= 0x39u )
        JUMPOUT(0x1C7LL);
      v13 = &v28;
      v14 = v29;
      v15 = v29 <= 0x39u;
      if ( v29 > 0x39u )
      {
LABEL_6:
        v23 = v29 - 55;
        v13 = &v28;
        v14 = v28;
        v15 = v28 <= 0x39u;
      }
      if ( !v15 )
      {
        v14 = (16 * (v28 - 48)) | v23;
        v13 = 0LL;
      }
      *((_BYTE *)v27 + (_QWORD)v13) = v14;
      if ( v30 >= 0x41u )
      {
        memset(v25, 0, sizeof(v25));
        v16 = v26;
        v20 = ((BYTE1(v24[0]) + (HIDWORD(v27[0]) >> 3)) ^ (v24[0] + HIDWORD(v27[0])) ^ (LOBYTE(v24[0])
                                                                                      + (HIDWORD(v27[0]) << 6)))
            + LODWORD(v27[0]);
        v22 = (v24[1] + v24[0]) ^ ((((unsigned __int8)((unsigned int)(v24[1] + v24[0]) >> 16) + (v20 >> 3)) ^ (v24[1] + v24[0] + v20) ^ (((unsigned int)(v24[1] + v24[0]) >> 24) + (v20 << 6)))
                                 + HIDWORD(v27[0]));
        v21 = ((LOBYTE(v24[2]) + (v22 >> 5)) ^ (v24[2] + v22) ^ (HIBYTE(v24[2]) + 16 * v22)) + ((v24[1] + v24[0]) ^ v20);
        *(_DWORD *)v25 = (v24[3] + v24[2]) ^ v21;
        *(_DWORD *)&v25[4] = (v24[3] + v24[2]) ^ ((((unsigned __int8)((unsigned __int16)(LOWORD(v24[3]) + LOWORD(v24[2])) >> 8)
                                                  + (v21 >> 5)) ^ (v24[3] + v24[2] + v21) ^ ((unsigned __int8)((unsigned int)(v24[3] + v24[2]) >> 16)
                                                                                           + 16 * v21))
                                                + v22);
        MEMORY[0xFFFFFFFFFFFF72CC](v26, a2, v25, 4LL, 128LL);
        if ( (char)*MEMORY[0xFFFFFFFFFFEE980A] != v25[0] )
        {
          v16 = v32;
          if ( !(unsigned int)MEMORY[0xFFFFFFFFFFFF551D](v32) )
            JUMPOUT(0x589LL);
          v19 = 0LL;
          v18 = -1148776LL;
          v17 = -1155031;
        }
        v32 = v16;
        v31 = v17;
        if ( v17 != 2 )
        {
          if ( v31 != 16 )
          {
            if ( v31 == 273 )
              JUMPOUT(0x5D4LL);
            if ( v31 == 312 )
              JUMPOUT(0x5DELL);
            MEMORY[0xFFFFFFFFFFFECD0F](v32, a2, v17, 0LL, v18, v19);
          }
          JUMPOUT(0x5CALL);
        }
        JUMPOUT(0x5C3LL);
      }
      JUMPOUT(0x271LL);
    }
    JUMPOUT(0xBDLL);
  }
  JUMPOUT(0x86LL);
}

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

最后于 2024-8-28 11:53 被mb_mgodlfyn编辑 ,原因:
上传的附件:
收藏
免费 1
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//