-
-
[原创] RCTF2019 DontEatMe 分析
-
发表于: 2022-3-11 10:18 9754
-
EXE文件,IDA反编译:
通过srand
固定时间戳生成伪随机数,然后在调用rand
之前,有一段反调试:
拿到Ntdll
的模块句柄,从句柄中查找ZwSetInformationThread
的地址,然后调用这个函数去检查当前线程是否处于Debug
模式下:
关于ZwSetInformationThread
的类型:
线程信息类型为枚举类型:
该程序中载入的参数就是ThreadHideFromDebugger
,此时如果检测到处理Debugger
模式就会将该线程强制分离出调试器,该函数与IsDebuggerPresent
类似都是用于反调试的
载入调试模式后在该call之后程序会因为Debug退出,为了不影响程序后续的正常运行,这里过反调试尽量不要有大的修改,该函数的功能根据的ThreadInformaitonClass
这个参数,将该参数的值设为ThreadHideFromDebugger
时便是处于反调试状态,那么过反调试只需要将ThreadHideFromDebugger
改成 ThreadBasicInformation
即可,体现在汇编指令上就是将push 0x11
改成push 0x00
:
ps: 这里发现如果有其他的修改,可能会导致堆栈存在问题,影响后面strlen的结果,所以在Patch时以最小字节修改为最佳方式,针对该反调试的修改只修改了一个字节,即压入的参数值,对整体的程序无影响,也不影响堆栈的平衡
在前面的动态分析中可以发现call esi
指向的是NtSetInformationThread
的地址而不是ZwSetInformationThread
的地址,这里再深入了解一下Zw和Nt函数的区别,首先关于这两个前缀的函数在Ring3
和Ring0
都是有的,在Ring3
中由ntdll.dll
导出,可以发现两个函数指向同一个函数地址,从这里可以得到在Ring3
情况下两个函数没有区别:
在用户态下,Zw和Nt函数的EntryPoint相同,可以理解为是同一个函数,而我们通过x32dbg或者OllyDBG实际上都是用户态的调试,所以在调试中显示的调用的这两个函数实际上就是同一个函数,两种函数在内核态的系统调用下才会存在区别,具体参考文章https://www.cnblogs.com/seamanj/p/3181151.html,本文不再展开
回到该题,main函数拢共200+行代码,中间一部份都是些数据处理,猜测可能存在算法,FindCrypt查看,发现存在BlowFish算法:
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中查表得到的值:
BlowFish 解密:
根据Paul Kocher
的源码,可以发现在循环处理中是逆序进行处理,逆序异或pBox,从pBox[17] - pBox[2]
,对leftpart进行异或,出循环后对rightpart
异或pBox[1]
,leftpart
异或pBox[0]
,整体流程跟加密一样,只是pBox
的顺序不同:
关于BLOWFISH的定位,发现在sub_401090
中进行调用,但是该函数调用时并未传入flag
相关的内容,所以猜测该函数应该不是对flag进行加密,通过前面了解到的BLOWFISH的特性,该函数应该是对pbox
和sbox
进行预处理
在预处理之前,发现存在srand和rand函数,但是该srand指定了时间戳,所以此时应该是伪随机数,将rand生成的数低8位存放到byte_4057A8中,通过测试可以发现,每次生成的数是相同的,顺序也是相同的:
只取低8位,所以最终得到:a1 18 2c 3a 23 5f 33 cd
pBox的地址-this指针的地址:
在循环前发现对刚刚srand生成的值进行了覆盖,得到00 0F 1A 01 35 3A 3B 20
:
循环为18次,pBox进行异或,说明该位置就是对pBox的预处理,那么key就是覆盖后的值:
异或得到:
进入401000,pBox异或之后的值与eax继续异或:
根据动态调试可以发现v3最开始指向的就是pBox的首地址,往下对pBox查表之后进行异或:
C实现的blowfish算法在searchTable
查表是通过sBox
查表的,根据内存分布,可以发现pBox
和sBox
是连续的,该题中反编译的结果是从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_dword
和suf_dword
,v13[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的加密或者解密:
变量较多,直接动态调试:
第一次循环异或的是pBox[17]
,循环16次并且倒序异或pBox
,最后再异或pBox[0]
和pBox[1]
,确定该部分应该是blowfish的解密:
首先是对v27-v30
进行了字节序的调转:
通过do-while
对byte_405018 - byte_40503A
进行了异或处理
对异或之后的结果进行移位运算和或运算,得到一个只有0
和1
的大矩阵:
根据switch-case
以及前面得到的矩阵得到这部分就是解迷宫了,起点line=10, row=5
,终点line=4, row=9
动态调试根据eax*4+AC53A8
可以发现这里取值时是先将row
和line
相加,初始化时line
为160
,而row
为5
,d
往右走,所以得到160+5+1
= 0xA6
,然后再乘4
,找值,所以可以发现如果是左右走的话应该是每步加减4
,而上下走每步应该是加减64
:
根据生成的矩阵可以发现只在低byte有值,高3个byte都是0,所以可以把多余的0去掉方便找到路线:
得到:
根据起点和终点,并且步数不能超过16步,得到:ddddwwwaaawwwddd
代入加密算法:
得到:db824ef8605c5235b4bbacfa2ff8e087
校验:
题目难度不高,整体流程也很简单:输入的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期)