首页
社区
课程
招聘
[原创] RCTF2019 DontEatMe 分析
发表于: 2022-3-11 10:18 9754

[原创] RCTF2019 DontEatMe 分析

2022-3-11 10:18
9754

EXE文件,IDA反编译:

image-20220118163315821

通过srand固定时间戳生成伪随机数,然后在调用rand之前,有一段反调试:

拿到Ntdll的模块句柄,从句柄中查找ZwSetInformationThread的地址,然后调用这个函数去检查当前线程是否处于Debug模式下:

关于ZwSetInformationThread的类型:

线程信息类型为枚举类型:

该程序中载入的参数就是ThreadHideFromDebugger,此时如果检测到处理Debugger模式就会将该线程强制分离出调试器,该函数与IsDebuggerPresent类似都是用于反调试的

image-20220121154513211

载入调试模式后在该call之后程序会因为Debug退出,为了不影响程序后续的正常运行,这里过反调试尽量不要有大的修改,该函数的功能根据的ThreadInformaitonClass这个参数,将该参数的值设为ThreadHideFromDebugger时便是处于反调试状态,那么过反调试只需要将ThreadHideFromDebugger 改成 ThreadBasicInformation即可,体现在汇编指令上就是将push 0x11改成push 0x00:

image-20220125112522906

image-20220125112613621

ps: 这里发现如果有其他的修改,可能会导致堆栈存在问题,影响后面strlen的结果,所以在Patch时以最小字节修改为最佳方式,针对该反调试的修改只修改了一个字节,即压入的参数值,对整体的程序无影响,也不影响堆栈的平衡

在前面的动态分析中可以发现call esi指向的是NtSetInformationThread的地址而不是ZwSetInformationThread的地址,这里再深入了解一下Zw和Nt函数的区别,首先关于这两个前缀的函数在Ring3Ring0都是有的,在Ring3中由ntdll.dll导出,可以发现两个函数指向同一个函数地址,从这里可以得到在Ring3情况下两个函数没有区别:

image-20220121162828516

在用户态下,Zw和Nt函数的EntryPoint相同,可以理解为是同一个函数,而我们通过x32dbg或者OllyDBG实际上都是用户态的调试,所以在调试中显示的调用的这两个函数实际上就是同一个函数,两种函数在内核态的系统调用下才会存在区别,具体参考文章https://www.cnblogs.com/seamanj/p/3181151.html,本文不再展开

回到该题,main函数拢共200+行代码,中间一部份都是些数据处理,猜测可能存在算法,FindCrypt查看,发现存在BlowFish算法:

image-20220118163531387

blowfish加密算法是一种对称的分组加密算法,对Plaintext进行分组,每组长度为64bit,而该加密的密钥为变长密钥,32bit-448bit都可以当作密钥进行加解密处理

密钥可以定义为Key数组,该数组的长度为[1, 14]

存在两个数组pBox和sBox,pBox为18个32位子密钥组成,sBox为4*256个32位子密钥组成,一般情况下,是用Π的小数点的16进制:

BlowFish加密过程

主加密函数,总共为8轮加密,每轮都会从pBox中拿取64bit的数据分成2*32bit异或给leftpart和rightpart,然后再分别异或从sBox中查表得到的值:

image-20220124155352654

image-20220124163343733

BlowFish 解密

根据Paul Kocher的源码,可以发现在循环处理中是逆序进行处理,逆序异或pBox,从pBox[17] - pBox[2],对leftpart进行异或,出循环后对rightpart异或pBox[1]leftpart异或pBox[0],整体流程跟加密一样,只是pBox的顺序不同:

关于BLOWFISH的定位,发现在sub_401090中进行调用,但是该函数调用时并未传入flag相关的内容,所以猜测该函数应该不是对flag进行加密,通过前面了解到的BLOWFISH的特性,该函数应该是对pboxsbox进行预处理

image-20220118165317501

在预处理之前,发现存在srand和rand函数,但是该srand指定了时间戳,所以此时应该是伪随机数,将rand生成的数低8位存放到byte_4057A8中,通过测试可以发现,每次生成的数是相同的,顺序也是相同的:

image-20220119104531098

只取低8位,所以最终得到:a1 18 2c 3a 23 5f 33 cd

image-20220119104643179

pBox的地址-this指针的地址:

image-20220124174546490

在循环前发现对刚刚srand生成的值进行了覆盖,得到00 0F 1A 01 35 3A 3B 20

循环为18次,pBox进行异或,说明该位置就是对pBox的预处理,那么key就是覆盖后的值:

image-20220124180159831

异或得到:

image-20220124180648802

进入401000,pBox异或之后的值与eax继续异或:

image-20220125101914916

根据动态调试可以发现v3最开始指向的就是pBox的首地址,往下对pBox查表之后进行异或:

C实现的blowfish算法在searchTable查表是通过sBox查表的,根据内存分布,可以发现pBoxsBox是连续的,该题中反编译的结果是从pBox开始查,但其偏移已经添加了0x12,所以跟从sBox查表的结果相同:

通过对比源码可以发现sub_401000就是BlowFish下的轮函数,回到sub_401090,可以判断该函数就是blowFishInit

往下取flag,先&7,根据规律可以发现&7就是判断字符串的长度是否被8整除,如果不被整除则在后面格式化输入时进行填充,往下格式化字符串输入,转成16进制,根据这个可以知道输入的flag范围0-9A-Fa-f

在进入第一个do-while之前会将指针指向第三个字节,然后可以看到第一个do-while循环中,取了8个字节分为上下两组进行或运算和移位运算,得到pre_dwordsuf_dwordv13[1] | ((*v13 | ((*(v13 - 1) | (*(v13 - 2) << 8)) << 8)) << 8)可以发现其实就是以dword形式输出:例如0x12,0x34, 0x56,0x78 -> 0x12345678,回到BLOWFISH,注意他的plain是以64位为一组,每组中又将64位拆分成上32位和下32位,第二个do-while循环中可以看到pre_dword异或v14之后给到suf_dword,而suf_dword进行几步异或之后给到pre_dword ,可以猜测该部分应该是BLOWFISH的加密或者解密:

变量较多,直接动态调试:

image-20220125150635662

第一次循环异或的是pBox[17],循环16次并且倒序异或pBox,最后再异或pBox[0]pBox[1],确定该部分应该是blowfish的解密:

image-20220125152210088

首先是对v27-v30进行了字节序的调转:

image-20220119161746320

通过do-whilebyte_405018 - byte_40503A进行了异或处理

image-20220119165755627

image-20220125163720261

对异或之后的结果进行移位运算和或运算,得到一个只有01的大矩阵:

根据switch-case以及前面得到的矩阵得到这部分就是解迷宫了,起点line=10, row=5,终点line=4, row=9

动态调试根据eax*4+AC53A8可以发现这里取值时是先将rowline相加,初始化时line160,而row5d往右走,所以得到160+5+1 = 0xA6,然后再乘4,找值,所以可以发现如果是左右走的话应该是每步加减4,而上下走每步应该是加减64

image-20220125170138429

根据生成的矩阵可以发现只在低byte有值,高3个byte都是0,所以可以把多余的0去掉方便找到路线:

得到:

image-20220125174128662

根据起点和终点,并且步数不能超过16步,得到:ddddwwwaaawwwddd

image-20220125174700134

image-20220125180243499

代入加密算法:

得到:db824ef8605c5235b4bbacfa2ff8e087

校验:

image-20220125174920093

image-20220125181328783

题目难度不高,整体流程也很简单:输入的flag的作为密文,通过blowfish算法解密得到的一串明文为迷宫的路线,涉及到的内容:

blowfish各版本源码:https://www.schneier.com/academic/blowfish/download/

参考文章:

[1] Blowfish Cipher 浅析: https://bbs.pediy.com/thread-256209.htm

[2] BlowFish加解密原理与代码实现: https://www.cnblogs.com/iBinary/p/14883752.html#tid-AwA6xn

[3] windows常用的反调试技术-静态反调试技术:https://bbs.pediy.com/thread-249572.htm

[4] blowfish加密算法(c实现): https://blog.csdn.net/qq_40890756/article/details/89256847

[5] Zw函数与Nt函数的分别与联系:https://www.cnblogs.com/seamanj/p/3181151.html

 
 
 
v3 = GetModuleHandleA("Ntdll");
ZwSetInformationThread = GetProcAddress(v3, "ZwSetInformationThread");
v5 = GetCurrentThread();
((void (__stdcall *)(HANDLE, int, _DWORD, _DWORD))ZwSetInformationThread)(v5, 17, 0, 0);
v3 = GetModuleHandleA("Ntdll");
ZwSetInformationThread = GetProcAddress(v3, "ZwSetInformationThread");
v5 = GetCurrentThread();
((void (__stdcall *)(HANDLE, int, _DWORD, _DWORD))ZwSetInformationThread)(v5, 17, 0, 0);
typedef NTSTATUS(NTAPI* pZwSetInformationThread)(
    IN HANDLE ThreadHandle,                            // 线程对象句柄
    IN THREAD_INFO_CLASS ThreadInformaitonClass,    // 线程信息类型
    IN PVOID ThreadInformation,                        // 线程信息指针
    IN ULONG ThreadInformationLength                // 线程信息大小
);
typedef NTSTATUS(NTAPI* pZwSetInformationThread)(
    IN HANDLE ThreadHandle,                            // 线程对象句柄
    IN THREAD_INFO_CLASS ThreadInformaitonClass,    // 线程信息类型
    IN PVOID ThreadInformation,                        // 线程信息指针
    IN ULONG ThreadInformationLength                // 线程信息大小
);
typedef enum _THREADINFOCLASS {
    ThreadBasicInformation,
    ThreadTimes,
    ThreadPriority,
    ThreadBasePriority,
    ThreadAffinityMask,
    ThreadImpersonationToken,
    ThreadDescriptorTableEntry,
    ThreadEnableAlignmentFaultFixup,
    ThreadEventPair,
    ThreadQuerySetWin32StartAddress,
    ThreadZeroTlsCell,
    ThreadPerformanceCount,
    ThreadAmILastThread,
    ThreadIdealProcessor,
    ThreadPriorityBoost,
    ThreadSetTlsArrayAddress,
    ThreadIsIoPending,
    ThreadHideFromDebugger
}THREAD_INFO_CLASS;
typedef enum _THREADINFOCLASS {
    ThreadBasicInformation,
    ThreadTimes,
    ThreadPriority,
    ThreadBasePriority,
    ThreadAffinityMask,
    ThreadImpersonationToken,
    ThreadDescriptorTableEntry,
    ThreadEnableAlignmentFaultFixup,
    ThreadEventPair,
    ThreadQuerySetWin32StartAddress,
    ThreadZeroTlsCell,
    ThreadPerformanceCount,
    ThreadAmILastThread,
    ThreadIdealProcessor,
    ThreadPriorityBoost,
    ThreadSetTlsArrayAddress,
    ThreadIsIoPending,
    ThreadHideFromDebugger
}THREAD_INFO_CLASS;
 
 
 
 
 
 
 
 
 
 
 
 
 
void BF_Fn(ULONG& leftPart, ULONG& rightPart)
{
    for (int i = 0; i < 16; i += 2) {
        leftPart ^= p_box[i];
        rightPart ^= SearchTable(leftPart);
        rightPart ^= p_box[i + 1];
        leftPart ^= SearchTable(rightPart);
    }
 
    leftPart ^= p_box[16];
    rightPart ^= p_box[17];
 
    //swap
    ULONG temp = leftPart;
    leftPart = rightPart;
    rightPart = temp;
 
}
void BF_Fn(ULONG& leftPart, ULONG& rightPart)
{
    for (int i = 0; i < 16; i += 2) {
        leftPart ^= p_box[i];
        rightPart ^= SearchTable(leftPart);
        rightPart ^= p_box[i + 1];
        leftPart ^= SearchTable(rightPart);
    }
 
    leftPart ^= p_box[16];
    rightPart ^= p_box[17];
 
    //swap
    ULONG temp = leftPart;
    leftPart = rightPart;
    rightPart = temp;
 
}
unsigned DWORD pBox[18] = {
    0x243F6A88L, 0x85A308D3L, 0x13198A2EL, 0x03707344L,
    0xA4093822L, 0x299F31D0L, 0x082EFA98L, 0xEC4E6C89L,
    0x452821E6L, 0x38D01377L, 0xBE5466CFL, 0x34E90C6CL,
    0xC0AC29B7L, 0xC97C50DDL, 0x3F84D5B5L, 0xB5470917L,
    0x9216D5D9L, 0x8979FB1BL
};
unsigned DWORD sBox[4][256] = {
    {
        0xD1310BA6L, 0x98DFB5ACL, 0x2FFD72DBL, 0xD01ADFB7L,
        0xB8E1AFEDL, 0x6A267E96L, 0xBA7C9045L, 0xF12C7F99L,
        0x24A19947L, 0xB3916CF7L, 0x0801F2E2L, 0x858EFC16L,
        0x636920D8L, 0x71574E69L, 0xA458FEA3L, 0xF4933D7EL,
 
        ......
 
        0x85CBFE4EL, 0x8AE88DD8L, 0x7AAAF9B0L, 0x4CF9AA7EL,
        0x1948C25CL, 0x02FB8A8CL, 0x01C36AE4L, 0xD6EBE1F9L,
        0x90D4F869L, 0xA65CDEA0L, 0x3F09252DL, 0xC208E69FL,
        0xB74E6132L, 0xCE77E25BL, 0x578FDFE3L, 0x3AC372E6L
    }
}
unsigned DWORD pBox[18] = {
    0x243F6A88L, 0x85A308D3L, 0x13198A2EL, 0x03707344L,
    0xA4093822L, 0x299F31D0L, 0x082EFA98L, 0xEC4E6C89L,
    0x452821E6L, 0x38D01377L, 0xBE5466CFL, 0x34E90C6CL,
    0xC0AC29B7L, 0xC97C50DDL, 0x3F84D5B5L, 0xB5470917L,
    0x9216D5D9L, 0x8979FB1BL
};
unsigned DWORD sBox[4][256] = {
    {
        0xD1310BA6L, 0x98DFB5ACL, 0x2FFD72DBL, 0xD01ADFB7L,
        0xB8E1AFEDL, 0x6A267E96L, 0xBA7C9045L, 0xF12C7F99L,
        0x24A19947L, 0xB3916CF7L, 0x0801F2E2L, 0x858EFC16L,
        0x636920D8L, 0x71574E69L, 0xA458FEA3L, 0xF4933D7EL,
 
        ......
 
        0x85CBFE4EL, 0x8AE88DD8L, 0x7AAAF9B0L, 0x4CF9AA7EL,
        0x1948C25CL, 0x02FB8A8CL, 0x01C36AE4L, 0xD6EBE1F9L,
        0x90D4F869L, 0xA65CDEA0L, 0x3F09252DL, 0xC208E69FL,
        0xB74E6132L, 0xCE77E25BL, 0x578FDFE3L, 0x3AC372E6L
    }
}
 
 
 
#define N               16
typedef struct {
  unsigned long P[16 + 2];
  unsigned long S[4][256];
} BLOWFISH_CTX;
 
void Blowfish_Decrypt(BLOWFISH_CTX *ctx, unsigned long *xl, unsigned long *xr){
  unsigned long  Xl;
  unsigned long  Xr;
  unsigned long  temp;
  short       i;
 
  Xl = *xl;
  Xr = *xr;
 
  for (i = N + 1; i > 1; --i) {
    Xl = Xl ^ ctx->P[i];
    Xr = F(ctx, Xl) ^ Xr;
 
    /* Exchange Xl and Xr */
    temp = Xl;
    Xl = Xr;
    Xr = temp;
  }
 
  /* Exchange Xl and Xr */
  temp = Xl;
  Xl = Xr;
  Xr = temp;
 
  Xr = Xr ^ ctx->P[1];
  Xl = Xl ^ ctx->P[0];
 
  *xl = Xl;
  *xr = Xr;
}
#define N               16
typedef struct {
  unsigned long P[16 + 2];
  unsigned long S[4][256];
} BLOWFISH_CTX;
 
void Blowfish_Decrypt(BLOWFISH_CTX *ctx, unsigned long *xl, unsigned long *xr){
  unsigned long  Xl;
  unsigned long  Xr;
  unsigned long  temp;
  short       i;
 
  Xl = *xl;
  Xr = *xr;
 
  for (i = N + 1; i > 1; --i) {
    Xl = Xl ^ ctx->P[i];
    Xr = F(ctx, Xl) ^ Xr;
 
    /* Exchange Xl and Xr */
    temp = Xl;
    Xl = Xr;
    Xr = temp;
  }
 
  /* Exchange Xl and Xr */
  temp = Xl;
  Xl = Xr;
  Xr = temp;
 
  Xr = Xr ^ ctx->P[1];
  Xl = Xl ^ ctx->P[0];
 
  *xl = Xl;
  *xr = Xr;
}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
int *__usercall sub_401000@<eax>(int *a1@<edx>, _DWORD *pBox@<ecx>, int *a3)
{
  _DWORD *v3; // edi
  int v4; // eax
  unsigned int v5; // eax
  int v6; // edx
  bool v7; // zf
  int v8; // ecx
  int *result; // eax
  int v11; // [esp+14h] [ebp-8h]
  int v12; // [esp+18h] [ebp-4h]
 
  v11 = 16;
  v3 = pBox;
  v4 = *a1;
  v12 = *a3;
  do
  {
    v5 = *v3++ ^ v4;
    v6 = v5;
    v4 = v12 ^ (pBox[(unsigned __int8)v5 + 0x312]
              + (pBox[BYTE1(v5) + 0x212] ^ (pBox[BYTE2(v5) + 0x112] + pBox[HIBYTE(v5) + 0x12])));
    v7 = v11-- == 1;
    v12 = v6;
  }
  while ( !v7 );
  *a1 = v6 ^ pBox[17];
  v8 = v4 ^ pBox[16];
  result = a3;
  *a3 = v8;
  return result;
}
int *__usercall sub_401000@<eax>(int *a1@<edx>, _DWORD *pBox@<ecx>, int *a3)
{
  _DWORD *v3; // edi
  int v4; // eax
  unsigned int v5; // eax
  int v6; // edx
  bool v7; // zf
  int v8; // ecx
  int *result; // eax
  int v11; // [esp+14h] [ebp-8h]
  int v12; // [esp+18h] [ebp-4h]
 
  v11 = 16;
  v3 = pBox;
  v4 = *a1;
  v12 = *a3;
  do
  {
    v5 = *v3++ ^ v4;
    v6 = v5;
    v4 = v12 ^ (pBox[(unsigned __int8)v5 + 0x312]
              + (pBox[BYTE1(v5) + 0x212] ^ (pBox[BYTE2(v5) + 0x112] + pBox[HIBYTE(v5) + 0x12])));
    v7 = v11-- == 1;
    v12 = v6;
  }
  while ( !v7 );
  *a1 = v6 ^ pBox[17];
  v8 = v4 ^ pBox[16];
  result = a3;
  *a3 = v8;
  return result;
}
// 从sBox开始查表的反编译结果
int __cdecl searchTable(unsigned int a1)
{
  __CheckForDebuggerJustMyCode(&unk_41D0A3);
  return sBox[(unsigned __int8)a1 + 0x300] + (sBox[BYTE1(a1) + 0x200] ^ (sBox[BYTE2(a1) + 0x100] + sBox[HIBYTE(a1)]));
}
// 从sBox开始查表的反编译结果
int __cdecl searchTable(unsigned int a1)
{
  __CheckForDebuggerJustMyCode(&unk_41D0A3);
  return sBox[(unsigned __int8)a1 + 0x300] + (sBox[BYTE1(a1) + 0x200] ^ (sBox[BYTE2(a1) + 0x100] + sBox[HIBYTE(a1)]));
}
do                                            // 变换pBox
{
    BF_FN(&round, (_DWORD *)this, (int *)&v17);
    *(_DWORD *)(this + 4 * v10) = round;
    *(_DWORD *)(this + 4 * v10 + 4) = v17;
    v10 += 2;
}
while ( v10 < 18 );
v11 = (int **)(this + 76);
v16 = 4;
do                                            // 变换sBox
{
    v12 = 128;
    do
    {
        BF_FN(&round, (_DWORD *)this, (int *)&v17);
        *(v11 - 1) = (int *)round;
        result = v17;
        *v11 = v17;
        v11 += 2;
        --v12;
    }
    while ( v12 );
    --v16;
}
while ( v16 );
do                                            // 变换pBox
{
    BF_FN(&round, (_DWORD *)this, (int *)&v17);
    *(_DWORD *)(this + 4 * v10) = round;
    *(_DWORD *)(this + 4 * v10 + 4) = v17;
    v10 += 2;
}
while ( v10 < 18 );
v11 = (int **)(this + 76);
v16 = 4;
do                                            // 变换sBox
{
    v12 = 128;
    do
    {
        BF_FN(&round, (_DWORD *)this, (int *)&v17);
        *(v11 - 1) = (int *)round;
        result = v17;
        *v11 = v17;
        v11 += 2;
        --v12;
    }
    while ( v12 );
    --v16;
}
while ( v16 );
flag_len = strlen(flag);
v9 = flag_len;
v49 = flag_len;
if ( (flag_len & 7) != 0 )
{
    v9 = 8 * (flag_len >> 3) + 8;
    v49 = v9;
}
v54 = (char *)calloc(v9, 1u);
res_0 = (unsigned __int8 *)calloc(v9 / 2, 1u);
idx_0 = 0;
v51 = res_0;
if ( v9 / 2 > 0 )
{
    v12 = flag;
    do
    {
        sscanf(v12, "%02x", idx_0 + (_BYTE)res_0);
        res_0 = v51;
        ++idx_0;
        v12 += 2;
    }
    while ( idx_0 < v9 / 2 );
    v9 = v49;
}
flag_len = strlen(flag);
v9 = flag_len;
v49 = flag_len;
if ( (flag_len & 7) != 0 )
{
    v9 = 8 * (flag_len >> 3) + 8;
    v49 = v9;
}
v54 = (char *)calloc(v9, 1u);
res_0 = (unsigned __int8 *)calloc(v9 / 2, 1u);
idx_0 = 0;
v51 = res_0;
if ( v9 / 2 > 0 )
{
    v12 = flag;
    do
    {
        sscanf(v12, "%02x", idx_0 + (_BYTE)res_0);
        res_0 = v51;
        ++idx_0;
        v12 += 2;
    }
    while ( idx_0 < v9 / 2 );
    v9 = v49;
}
v50 = 0;
v55 = v9 / 16;
if ( v9 / 16 <= 0 )
{
    v26 = v54;
}
else
{
    v13 = res_0 + 2;
    v53 = v13;
    do
    {
        v14 = v57;
        v52 = 16;
        pre_dword = v13[1] | ((*v13 | ((*(v13 - 1) | (*(v13 - 2) << 8)) << 8)) << 8);
        suf_dword = v13[5] | ((v13[4] | ((v13[3] | (v13[2] << 8)) << 8)) << 8);
        do
        {
            v17 = *(_DWORD *)v14 ^ pre_dword;
            v14 -= 4;
            v18 = v17;
            pre_dword = suf_dword ^ (*(_DWORD *)&v57[4 * (unsigned __int8)v17 + 3076]
                                     + (*(_DWORD *)&v57[4 * BYTE1(v17) + 2052] ^ (*(_DWORD *)&v57[4 * BYTE2(v17) + 1028]
                                                                                  + *(_DWORD *)&v57[4 * HIBYTE(v17) + 4])));
            v19 = v52-- == 1;
            suf_dword = v18;
        }
        while ( !v19 );
        v20 = v18 ^ v56[0];
        v21 = calloc(4u, 1u);
        *v21 = HIBYTE(v20);
        v21[1] = BYTE2(v20);
        v21[2] = BYTE1(v20);
        v21[3] = v20;
        v22 = v56[1];
        *(_DWORD *)&v54[8 * v50] = *(_DWORD *)v21;
        v23 = pre_dword ^ v22;
        v24 = calloc(4u, 1u);
        *v24 = HIBYTE(v23);
        v24[1] = BYTE2(v23);
        v25 = v23 >> 8;
        v24[3] = v23;
        v26 = v54;
        v24[2] = v25;
        *(_DWORD *)&v54[8 * v50 + 4] = *(_DWORD *)v24;
        v13 = v53 + 8;
        v53 += 8;
        ++v50;
    }
    while ( v50 < v55 );
}
v50 = 0;
v55 = v9 / 16;
if ( v9 / 16 <= 0 )
{
    v26 = v54;
}
else
{
    v13 = res_0 + 2;
    v53 = v13;
    do
    {
        v14 = v57;
        v52 = 16;
        pre_dword = v13[1] | ((*v13 | ((*(v13 - 1) | (*(v13 - 2) << 8)) << 8)) << 8);
        suf_dword = v13[5] | ((v13[4] | ((v13[3] | (v13[2] << 8)) << 8)) << 8);
        do
        {
            v17 = *(_DWORD *)v14 ^ pre_dword;
            v14 -= 4;
            v18 = v17;
            pre_dword = suf_dword ^ (*(_DWORD *)&v57[4 * (unsigned __int8)v17 + 3076]
                                     + (*(_DWORD *)&v57[4 * BYTE1(v17) + 2052] ^ (*(_DWORD *)&v57[4 * BYTE2(v17) + 1028]
                                                                                  + *(_DWORD *)&v57[4 * HIBYTE(v17) + 4])));
            v19 = v52-- == 1;
            suf_dword = v18;
        }
        while ( !v19 );

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

最后于 2022-4-19 18:07 被Gushang编辑 ,原因: 忘记加title
上传的附件:
收藏
免费 5
支持
分享
最新回复 (1)
雪    币: 27071
活跃值: (63057)
能力值: (RANK:135 )
在线值:
发帖
回帖
粉丝
2
感谢分享,文中实例上传一下?
2022-4-2 16:57
0
游客
登录 | 注册 方可回帖
返回
//