代码没有加混淆,非常好评
IDA打开,逻辑非常清楚。有一些明面的反调试,如果需要动态调试,patch掉即可。
从main函数开始看:
输入是一个十进制整数,范围在 [4096, 4294967296] 之间。这个整数需要通过sub_4015A0的验证并且减1后不能通过验证。
根据cpu数量开不同数量的线程,并行执行StartAddress(sub_4010D0)函数。
StartAddress的参数lpThreadParameter包含一个long long整数(来自用户输入)和一个循环次数参数(此参数来自sub_4015A0,为10000/dwNumberOfProcessors)。每一次循环检查,都会随机生成一组新的a、b、c、d数据,然后结合用户输入的整数x做运算,并根据运算情况为global_fail赋值。
结合sub_4015A0,实际上是把10000次的检查按照cpu数量平分到多个进程中。如果要通过main函数中第一次global_fail==0的检查,需要10000次循环中生成的随机数据都通过检查。程序要求10000组随机数据都通过测试,实际上是要求在随机数据产生范围内的所有可能值都能通过验证(只是这个空间太大无法逐一检验),所以,从破解角度需要找到的是一个通用的值,这里的多线程可以当做障眼法。
StartAddress函数有很多__PAIR64__,能看出来实际上是64位整数的运算,但程序本身是32位的,伪代码看起来非常难受。
基于以上分析,先对整体校验逻辑做一个重写:(基于Linux x64环境)
(其实这一步并不容易,因为要保证逻辑完全一致,而且不容易动态调试验证,实际花费的时间和精力非常大,而且过程中确实推翻逻辑了很多次)
基于重写后的代码继续分析:
每轮检查有四个全局数组a、b、c、d,其中a和c的值只能取2, 4, 5, 6, 7, 8, 13这七个数之一,b的值则不能超过对应位a的值。
之后的第一个循环,可以先想象成一个人在网格图上游走形成路径的过程:
(i,j)是坐标,t是实时负重,x是负重限额
每次行走一步,每一步只能选择向右(j+=1)或向下(i+=1)
如果向右走,则会拾起物品(b[j])增加负重(t = b[j] + a[j] * t);如果向下走,则会丢弃物品(d[i]减少负重(t = t / c[i])
具体向哪边走,则由两个方向下一步的负重乘积与x的大小关系决定,如果太小则向右走增加负重,如果太大则向左走减少负重,使得当前负重t始终在x附近震荡
最后,当向右行走10000步后,如果剩余负重大于0,继续不断向下走并丢弃物品(d[i])直到负重为0停止
第一个循环结束后会形成一个轨迹。而第二个循环是从终点开始反向,每一步根据情况决定向上走还是向左走(丢弃b[j])。如果决定向上走,则重新拾取丢弃的物品(d[i])增加负重(t = d[i] + c[i] * t);如果决定向左走,则丢弃物品减少负重(t = t / a[j]),但要保证与正向路径向右走时拾取的物品(b[j])重量相等。
由于物品的重量都是随机的,所以要保证每次反向向左走时的判断成立,反向路径必须与正向路径完全重叠。此外可得到一个推论,即正反路径在相同坐标点的负重也一定是相同的。
但是,对于正反路径相同的坐标点(i,j),用于决定下一步判断的a、b、c、d值的索引不同,正向路径是i或j,反向路径是i-1或j-1(虽然循环中没有减一,但是注意到进入第二轮循环之前已经预先对i和j减了一),这就使得反向的每一步并不是平凡的一定沿着正向的相反方向,而是要根据实际情况而定;而我们的目标是找到一个合适的x使得这个条件无论如何都能成立。
(题外话:不知道这个抽象是不是出题人预设的数学模型,但单从这个抽象来看感觉应该有纯数学的解法,而且应该非常优雅无需爆破,可惜想了很久也没想出来)
(题外话2:题目的背景故事给的是数据在七颗不同链路卫星之间通信的问题,所以以上抽象应该不是出题人的预设;另,按照卫星链路的故事找到了一篇专利通信系统中前向和反向链路切换边界的平衡方法和设备,摘要是“一种使前向链路切换边界的位置与反向链路切换边界匹配的方法和设备。选择一个定义每个基台接收功率和发射导频功率乘积的系统常数。在基台测量反向链路功率电平,并用前向链路功率电平补偿反向链路负载以保持乘积常数。从而使前向链路切换边界对准反向链路切换边界并同处一个位置”,其中“乘积常数”、前向链路对准反向链路“并同处一个位置”的描述感觉非常契合代码逻辑,可惜从文中也没看出解法)
想不到优雅的求解那就只好爆破了。(p.s.本届KCTF的逆向题这么都这么偏爱爆破……)。原始输入的范围有42亿个取值,再加上每个取值都要做两层嵌套的万级循环,显然太多,要考虑下如何缩小范围。
观察一:
注意正向行进时的方向判定条件 (b[j] + a[j] * t) * (t / c[i]) < x
,其中a、b、c、x都有范围限定,因此可以反推出t的范围限定(大致在0到sqrt(13/2*x)的区间);而已知a、b、c、t的取值范围后,由于它们都是整数,所以该不等式的左侧取值也是有限的。
用一个粗糙的Python脚本把它们全部找出并存下来:(如果用C写,要自己处理去重和排序;即使用C++标准库stl有实现,但也远没有Python方便)
可以看到这里左侧只有9823158种不同的取值,从十亿量级直接下降了一百倍到了千万量级。
观察二:
原始程序的检查是正向路径全部走完再从终点开始检查反向路径;但基于之前的分析,路径重合实际要求每一步都重叠,所以可以正向每走一步就即时检查该步能否反向,如果不通则立刻判定失败提前返回。这一步预期能大量剪枝,不合适的x值很可能在几步之内就会产生无法反向的行进,而不必先花费万步把正向路径走完再检查。
观察三:
原程序会执行10000次检验,每次都会生成一组新的a、b、c、d数据,然后再跑两个路径循环。首先,只有正确的x值能通过全部随机数据空间的检验,那么错误的x值大概只需要几组随机结果的检查就会暴露出问题,此时也可以直接宣告失败,不必继续生成新的随机数据检验;其次,如果某个x未通过某组随机数据的检查,我们仍然可以用这组随机数据继续检查下一个x而不必每次都重新初始化。
原本对每个可能的取值的检查都要做二重循环,且两层都是万级别,则计算量是十亿*万*万;
观察一使得取值空间从十亿降到了千万;观察二使得对大多数的值,检查的外层循环从万降到了个位数;观察三使得对大多数的值,检查的内层循环从万降到了个位数。所以总的计算量降到了千万,变得勉强可以接受。
(p.s. 这里降到了千万级的计算量一度不敢继续下手爆破,而是还在继续找优化点,因为以往做常规逆向题,哪怕不确定的答案只有几个复杂度都很搞了,千万级的计算量根本不敢想象有爆破的可能,还要担心爆破代码写错的风险;但这届KCTF的几道暴力题,int32以内(亿级别)的遍历似乎都平淡无奇……)
爆破脚本:
(注意两处注释的细节)
Linux x64环境下 gcc -O3
优化编译,再配合一个脚本分十个进程一起跑:
只用了5分多钟(即使单线程也只需30分钟),找到了唯一的正确答案:
(不过,我还是觉得题目应该有完全0爆破的解法,期待作者出题文档的公开)
int
__cdecl main(
int
argc,
const
char
**argv,
const
char
**envp)
{
unsigned
int
ii;
int
v4;
int
v5;
int
length;
int
v7;
int
i;
HWND
WindowW;
int
n_0;
int
n_1;
bool
success;
HANDLE
CurrentProcess;
int
n[2];
int
seed;
BOOL
pbDebuggerPresent;
char
buf[8];
__int16
v19;
char
v20;
char
Buffer[8];
__int16
v22;
char
v23;
v19 = 0;
*(_QWORD *)n = 0i64;
*(_QWORD *)buf = 0i64;
v20 = 0;
*(_QWORD *)Buffer = 0i64;
v22 = 0;
v23 = 0;
printf
(
"Please input: "
);
ii = 0;
while
( 1 )
{
v4 =
getchar
();
if
( v4 == 10 )
break
;
v5 = ii + 1;
buf[ii] = v4;
if
( ii + 1 >= 0xB )
goto
LABEL_41;
buf[v5] = 0;
if
( ii == 9 &&
getchar
() != 10 )
goto
LABEL_39;
++ii;
if
( v5 >= 10 )
goto
LABEL_10;
}
if
( ii >= 0xB )
{
LABEL_41:
__report_rangecheckfailure();
__debugbreak();
}
buf[ii] = 0;
LABEL_10:
length = 0;
if
( buf[0] )
{
while
( ++length <= 10 )
{
if
( !buf[length] )
goto
LABEL_15;
}
length = -1;
}
LABEL_15:
if
(
sscanf
(buf,
"%lld"
, n) == 1 )
{
v7 =
sprintf
(Buffer, 11u,
"%lld"
, *(_QWORD *)n);
if
( length > 0 && v7 > 0 && length == v7 )
{
i = 0;
while
( buf[i] == Buffer[i] )
{
if
( ++i >= length )
{
if
( *(
__int64
*)n > 0 )
{
WindowW = FindWindowW(L
"OLLYDBG"
, 0);
n_0 = n[0];
n_1 = n[1];
if
( WindowW )
{
n_0 = n[0] | 0xFFFF;
n[0] |= 0xFFFFu;
}
if
( __PAIR64__(n[1], n_0) - 4096 <= 4294963200 )
{
if
( CryptAcquireContextW(&hProv, 0, 0, 1u, 0xF0000000) )
{
hMutex = CreateMutexW(0, 0, 0);
if
( hMutex )
{
seed = 0;
CryptGenRandom(hProv, 4u, (
BYTE
*)&seed);
srand
(seed);
global_fail = 0;
success = 0;
if
( sub_4015A0(n_0, n_1) )
{
if
( !global_fail )
{
global_fail = 0;
if
( sub_4015A0(n_0 - 1, (__PAIR64__(n_1, n_0) - 1) >> 32) )
{
if
( global_fail )
success = 1;
}
}
}
CryptReleaseContext(hProv, 0);
CloseHandle(hMutex);
pbDebuggerPresent = 0;
CurrentProcess = GetCurrentProcess();
if
( CheckRemoteDebuggerPresent(CurrentProcess, &pbDebuggerPresent) && pbDebuggerPresent )
success = 0;
if
( success )
{
MessageBoxW(0, L
"Accepted!"
, L
"Result"
, 0x40u);
return
0;
}
}
}
}
}
break
;
}
}
}
}
LABEL_39:
MessageBoxW(0, L
"Wrong answer!"
, L
"Result"
, 0x10u);
return
0;
}
int
__cdecl main(
int
argc,
const
char
**argv,
const
char
**envp)
{
unsigned
int
ii;
int
v4;
int
v5;
int
length;
int
v7;
int
i;
HWND
WindowW;
int
n_0;
int
n_1;
bool
success;
HANDLE
CurrentProcess;
int
n[2];
int
seed;
BOOL
pbDebuggerPresent;
char
buf[8];
__int16
v19;
char
v20;
char
Buffer[8];
__int16
v22;
char
v23;
v19 = 0;
*(_QWORD *)n = 0i64;
*(_QWORD *)buf = 0i64;
v20 = 0;
*(_QWORD *)Buffer = 0i64;
v22 = 0;
v23 = 0;
printf
(
"Please input: "
);
ii = 0;
while
( 1 )
{
v4 =
getchar
();
if
( v4 == 10 )
break
;
v5 = ii + 1;
buf[ii] = v4;
if
( ii + 1 >= 0xB )
goto
LABEL_41;
buf[v5] = 0;
if
( ii == 9 &&
getchar
() != 10 )
goto
LABEL_39;
++ii;
if
( v5 >= 10 )
goto
LABEL_10;
}
if
( ii >= 0xB )
{
LABEL_41:
__report_rangecheckfailure();
__debugbreak();
}
buf[ii] = 0;
LABEL_10:
length = 0;
if
( buf[0] )
{
while
( ++length <= 10 )
{
if
( !buf[length] )
goto
LABEL_15;
}
length = -1;
}
LABEL_15:
if
(
sscanf
(buf,
"%lld"
, n) == 1 )
{
v7 =
sprintf
(Buffer, 11u,
"%lld"
, *(_QWORD *)n);
if
( length > 0 && v7 > 0 && length == v7 )
{
i = 0;
while
( buf[i] == Buffer[i] )
{
if
( ++i >= length )
{
if
( *(
__int64
*)n > 0 )
{
WindowW = FindWindowW(L
"OLLYDBG"
, 0);
n_0 = n[0];
n_1 = n[1];
if
( WindowW )
{
n_0 = n[0] | 0xFFFF;
n[0] |= 0xFFFFu;
}
if
( __PAIR64__(n[1], n_0) - 4096 <= 4294963200 )
{
if
( CryptAcquireContextW(&hProv, 0, 0, 1u, 0xF0000000) )
{
hMutex = CreateMutexW(0, 0, 0);
if
( hMutex )
{
seed = 0;
CryptGenRandom(hProv, 4u, (
BYTE
*)&seed);
srand
(seed);
global_fail = 0;
success = 0;
if
( sub_4015A0(n_0, n_1) )
{
if
( !global_fail )
{
global_fail = 0;
if
( sub_4015A0(n_0 - 1, (__PAIR64__(n_1, n_0) - 1) >> 32) )
{
if
( global_fail )
success = 1;
}
}
}
CryptReleaseContext(hProv, 0);
CloseHandle(hMutex);
pbDebuggerPresent = 0;
CurrentProcess = GetCurrentProcess();
if
( CheckRemoteDebuggerPresent(CurrentProcess, &pbDebuggerPresent) && pbDebuggerPresent )
success = 0;
if
( success )
{
MessageBoxW(0, L
"Accepted!"
, L
"Result"
, 0x40u);
return
0;
}
}
}
}
}
break
;
}
}
}
}
LABEL_39:
MessageBoxW(0, L
"Wrong answer!"
, L
"Result"
, 0x10u);
return
0;
}
char
__cdecl sub_4015A0(
int
a1,
int
a2)
{
int
dwNumberOfProcessors;
int
v3;
int
v4;
_DWORD *v5;
int
i;
int
v8;
struct
_SYSTEM_INFO SystemInfo;
char
Parameter[1024];
void
*Handles[64];
memset
(Handles, 0,
sizeof
(Handles));
memset
(Parameter, 0,
sizeof
(Parameter));
memset
(&SystemInfo, 0,
sizeof
(SystemInfo));
GetSystemInfo(&SystemInfo);
dwNumberOfProcessors = SystemInfo.dwNumberOfProcessors;
if
( (
int
)SystemInfo.dwNumberOfProcessors <= 0 )
return
0;
if
( (
int
)SystemInfo.dwNumberOfProcessors > 64 )
dwNumberOfProcessors = 64;
v8 = 10000 / dwNumberOfProcessors;
if
( IsDebuggerPresent() )
{
v3 = v8 >> 4;
v4 = 0;
v8 >>= 4;
}
else
{
v4 = 0;
if
( dwNumberOfProcessors <= 0 )
goto
LABEL_10;
v3 = 10000 / dwNumberOfProcessors;
}
v5 = Parameter;
do
{
*v5 = a1;
v5[1] = a2;
v5[2] = v3;
Handles[v4] = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)StartAddress, v5, 0, 0);
v5 += 4;
v3 = v8;
++v4;
}
while
( v4 < dwNumberOfProcessors );
LABEL_10:
if
( WaitForMultipleObjects(dwNumberOfProcessors, Handles, 1, 0xFFFFFFFF) >= dwNumberOfProcessors )
return
0;
for
( i = 0; i < dwNumberOfProcessors; ++i )
CloseHandle(Handles[i]);
return
1;
}
char
__cdecl sub_4015A0(
int
a1,
int
a2)
{
int
dwNumberOfProcessors;
int
v3;
int
v4;
_DWORD *v5;
int
i;
int
v8;
struct
_SYSTEM_INFO SystemInfo;
char
Parameter[1024];
void
*Handles[64];
memset
(Handles, 0,
sizeof
(Handles));
memset
(Parameter, 0,
sizeof
(Parameter));
memset
(&SystemInfo, 0,
sizeof
(SystemInfo));
GetSystemInfo(&SystemInfo);
dwNumberOfProcessors = SystemInfo.dwNumberOfProcessors;
if
( (
int
)SystemInfo.dwNumberOfProcessors <= 0 )
return
0;
if
( (
int
)SystemInfo.dwNumberOfProcessors > 64 )
dwNumberOfProcessors = 64;
v8 = 10000 / dwNumberOfProcessors;
if
( IsDebuggerPresent() )
{
v3 = v8 >> 4;
v4 = 0;
v8 >>= 4;
}
else
{
v4 = 0;
if
( dwNumberOfProcessors <= 0 )
goto
LABEL_10;
v3 = 10000 / dwNumberOfProcessors;
}
v5 = Parameter;
do
{
*v5 = a1;
v5[1] = a2;
v5[2] = v3;
Handles[v4] = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)StartAddress, v5, 0, 0);
v5 += 4;
v3 = v8;
++v4;
}
while
( v4 < dwNumberOfProcessors );
LABEL_10:
if
( WaitForMultipleObjects(dwNumberOfProcessors, Handles, 1, 0xFFFFFFFF) >= dwNumberOfProcessors )
return
0;
for
( i = 0; i < dwNumberOfProcessors; ++i )
CloseHandle(Handles[i]);
return
1;
}
DWORD
__stdcall StartAddress(unsigned
int
*lpThreadParameter)
{
int
*b;
int
*c;
int
*d;
void
*a_;
char
v5;
int
v6;
int
*b_i;
int
v8;
BOOL
v9;
int
v10;
int
i;
int
v12;
int
*c__;
int
new_t1_;
int
new_t0_;
int
*b_j_;
int
j_;
int
i_;
unsigned
__int64
v19;
__int64
v20;
int
i__;
int
c_minus_d;
int
t1;
int
j;
int
*v3_i;
unsigned
int
t0;
int
new_t0;
__int64
v28;
bool
v29;
__int64
v30;
void
(__cdecl *v31)(
void
*);
__int64
v33;
__int64
v34;
__int64
v35;
__int64
v36;
int
*v37;
int
*b_j;
int
*v3_i_;
int
*b_i_;
int
t1_;
int
v1_____;
int
*c_;
int
j___;
int
i___;
int
*a;
int
*b_;
int
*d_;
int
t0_;
int
t1___;
int
a_minus_b;
unsigned
int
t0___;
unsigned
int
x_1;
int
v54;
unsigned
int
x_0;
unsigned
int
seed;
a = (
int
*)
calloc
(10000u, 4u);
b = (
int
*)
calloc
(10000u, 4u);
b_ = b;
c = (
int
*)
calloc
(20000u, 4u);
c_ = c;
d = (
int
*)
calloc
(20000u, 4u);
a_ = a;
d_ = d;
if
( !a )
goto
LABEL_41;
if
( !b )
goto
LABEL_40;
if
( !c )
goto
LABEL_40;
if
( !d )
goto
LABEL_40;
v54 = 0;
if
( (
int
)lpThreadParameter[2] <= 0 )
goto
LABEL_40;
while
( 2 )
{
WaitForSingleObject(hMutex, 0xFFFFFFFF);
v5 = global_fail;
ReleaseMutex(hMutex);
if
( v5 )
break
;
seed = 0;
CryptGenRandom(hProv, 4u, (
BYTE
*)&seed);
srand
(seed);
v6 = 0;
b_i = b;
b_i_ = b;
a_minus_b = (
char
*)a - (
char
*)b;
do
{
v8 = dword_4031CC[
rand
() % 7];
*(
int
*)((
char
*)b_i + a_minus_b) = v8;
v9 = v6 == 0;
v10 =
rand
() % (
int
)((__PAIR64__(v8, v6++) - 1) >> 32);
*b_i_ = v9 + v10;
b_i = ++b_i_;
}
while
( v6 < 10000 );
for
( i = 0; i < 20000; ++i )
{
v12 =
rand
();
c__ = c_;
c_[i] = dword_4031CC[v12 % 7];
}
new_t1_ = 0;
new_t0_ = 0;
x_0 = *lpThreadParameter;
b_j_ = b_;
x_1 = lpThreadParameter[1];
j_ = 0;
i_ = 0;
LABEL_12:
b_j = b_j_;
j___ = j_;
while
( 1 )
{
t0_ = new_t0_;
t1_ = new_t1_;
if
( j_ >= 10000 && (new_t1_ < 0 || new_t1_ <= 0 && !new_t0_) )
break
;
if
( i_ >= 20000 )
{
LABEL_38:
WaitForSingleObject(hMutex, 0xFFFFFFFF);
global_fail = 1;
ReleaseMutex(hMutex);
b = b_;
goto
LABEL_39;
}
if
( j_ >= 10000 )
{
v34 = c__[i_];
v20 = __SPAIR64__(new_t1_, new_t0_) / v34;
new_t1_ = (unsigned
__int64
)(__SPAIR64__(new_t1_, new_t0_) / v34) >> 32;
new_t0_ = v20;
c__ = c_;
d_[i_++] = __SPAIR64__(t1_, t0_) % v34;
j_ = j___;
b_j_ = b_j;
}
else
{
new_t1_ = (*b_j + *(
int
*)((
char
*)b_j_ + a_minus_b) * __PAIR64__(new_t1_, new_t0_)) >> 32;
v33 = c_[i_];
new_t0_ = *b_j + *(
int
*)((
char
*)b_j_ + a_minus_b) * new_t0_;
if
( (
__int64
)(__SPAIR64__(t1_, t0_) / v33 * __PAIR64__(new_t1_, new_t0_)) < __SPAIR64__(x_1, x_0) )
{
j_ = j___ + 1;
c__ = c_;
b_j_ = b_j + 1;
goto
LABEL_12;
}
v19 = __SPAIR64__(t1_, t0_) / v33;
new_t1_ = HIDWORD(v19);
new_t0_ = v19;
c__ = c_;
d_[i_++] = __SPAIR64__(t1_, t0_) % v33;
j_ = j___;
b_j_ = b_j;
}
}
i__ = i_ - 1;
i___ = i__;
c_minus_d = (
char
*)c__ - (
char
*)d_;
t1 = 0;
j = 9999;
v3_i = &d_[i__];
v1_____ = c_minus_d;
t0 = 0;
v3_i_ = v3_i;
while
( 1 )
{
t0___ = t0;
t1___ = t1;
if
( i__ < 0 && (t1 < 0 || t1 <= 0 && !t0) )
break
;
if
( j < 0 )
goto
LABEL_38;
if
( i__ < 0 )
{
v36 = a[j];
v30 = __SPAIR64__(t1, t0) / v36;
t1 = (unsigned
__int64
)(__SPAIR64__(t1, t0) / v36) >> 32;
t0 = v30;
v29 = (unsigned
int
)(__SPAIR64__(t1___, t0___) % v36) == b_[j];
LABEL_34:
if
( !v29 )
goto
LABEL_38;
i__ = i___;
--j;
v3_i = v3_i_;
c_minus_d = v1_____;
}
else
{
new_t0 = *v3_i_ + *(
int
*)((
char
*)v3_i + c_minus_d) * t0;
t1 = (*v3_i_ + *(
int
*)((
char
*)v3_i + c_minus_d) * __PAIR64__(t1, t0)) >> 32;
v35 = a[j];
v28 = __SPAIR64__(t1___, t0) / v35;
t0 = new_t0;
if
( (
signed
__int64
)(v28 * __PAIR64__(t1, new_t0)) >= *(_QWORD *)lpThreadParameter )
{
t1 = HIDWORD(v28);
t0 = v28;
v29 = (unsigned
int
)(__SPAIR64__(t1___, t0___) % v35) == b_[j];
goto
LABEL_34;
}
i__ = i___ - 1;
c_minus_d = v1_____;
v3_i = v3_i_ - 1;
--i___;
--v3_i_;
}
}
b = b_;
if
( ++v54 < (
int
)lpThreadParameter[2] )
continue
;
break
;
}
LABEL_39:
a_ = a;
d = d_;
c = c_;
LABEL_40:
free
(a_);
LABEL_41:
if
( b )
{
v37 = b;
v31 =
free
;
free
(v37);
}
else
{
v31 =
free
;
}
if
( c )
v31(c);
if
( d )
v31(d);
if
( NtCurrentPeb()->BeingDebugged )
{
WaitForSingleObject(hMutex, 0xFFFFFFFF);
global_fail = 1;
ReleaseMutex(hMutex);
}
return
0;
}
DWORD
__stdcall StartAddress(unsigned
int
*lpThreadParameter)
{
int
*b;
int
*c;
int
*d;
void
*a_;
char
v5;
int
v6;
int
*b_i;
int
v8;
BOOL
v9;
int
v10;
int
i;
int
v12;
int
*c__;
int
new_t1_;
int
new_t0_;
int
*b_j_;
int
j_;
int
i_;
unsigned
__int64
v19;
__int64
v20;
int
i__;
int
c_minus_d;
int
t1;
int
j;
int
*v3_i;
unsigned
int
t0;
int
new_t0;
__int64
v28;
bool
v29;
__int64
v30;
void
(__cdecl *v31)(
void
*);
__int64
v33;
__int64
v34;
__int64
v35;
__int64
v36;
int
*v37;
int
*b_j;
int
*v3_i_;
int
*b_i_;
int
t1_;
int
v1_____;
int
*c_;
int
j___;
int
i___;
int
*a;
int
*b_;
int
*d_;
int
t0_;
int
t1___;
int
a_minus_b;
unsigned
int
t0___;
unsigned
int
x_1;
int
v54;
unsigned
int
x_0;
unsigned
int
seed;
a = (
int
*)
calloc
(10000u, 4u);
b = (
int
*)
calloc
(10000u, 4u);
b_ = b;
c = (
int
*)
calloc
(20000u, 4u);
c_ = c;
d = (
int
*)
calloc
(20000u, 4u);
a_ = a;
d_ = d;
if
( !a )
goto
LABEL_41;
if
( !b )
goto
LABEL_40;
if
( !c )
goto
LABEL_40;
if
( !d )
goto
LABEL_40;
v54 = 0;
if
( (
int
)lpThreadParameter[2] <= 0 )
goto
LABEL_40;
while
( 2 )
{
WaitForSingleObject(hMutex, 0xFFFFFFFF);
v5 = global_fail;
ReleaseMutex(hMutex);
if
( v5 )
break
;
seed = 0;
CryptGenRandom(hProv, 4u, (
BYTE
*)&seed);
srand
(seed);
v6 = 0;
b_i = b;
b_i_ = b;
a_minus_b = (
char
*)a - (
char
*)b;
do
{
v8 = dword_4031CC[
rand
() % 7];
*(
int
*)((
char
*)b_i + a_minus_b) = v8;
v9 = v6 == 0;
v10 =
rand
() % (
int
)((__PAIR64__(v8, v6++) - 1) >> 32);
*b_i_ = v9 + v10;
b_i = ++b_i_;
}
while
( v6 < 10000 );
for
( i = 0; i < 20000; ++i )
{
v12 =
rand
();
c__ = c_;
c_[i] = dword_4031CC[v12 % 7];
}
new_t1_ = 0;
new_t0_ = 0;
x_0 = *lpThreadParameter;
b_j_ = b_;
x_1 = lpThreadParameter[1];
j_ = 0;
i_ = 0;
LABEL_12:
b_j = b_j_;
j___ = j_;
while
( 1 )
{
t0_ = new_t0_;
t1_ = new_t1_;
if
( j_ >= 10000 && (new_t1_ < 0 || new_t1_ <= 0 && !new_t0_) )
break
;
if
( i_ >= 20000 )
{
LABEL_38:
WaitForSingleObject(hMutex, 0xFFFFFFFF);
global_fail = 1;
ReleaseMutex(hMutex);
b = b_;
goto
LABEL_39;
}
if
( j_ >= 10000 )
{
v34 = c__[i_];
v20 = __SPAIR64__(new_t1_, new_t0_) / v34;
new_t1_ = (unsigned
__int64
)(__SPAIR64__(new_t1_, new_t0_) / v34) >> 32;
new_t0_ = v20;
c__ = c_;
d_[i_++] = __SPAIR64__(t1_, t0_) % v34;
j_ = j___;
b_j_ = b_j;
}
else
{
new_t1_ = (*b_j + *(
int
*)((
char
*)b_j_ + a_minus_b) * __PAIR64__(new_t1_, new_t0_)) >> 32;
v33 = c_[i_];
new_t0_ = *b_j + *(
int
*)((
char
*)b_j_ + a_minus_b) * new_t0_;
if
( (
__int64
)(__SPAIR64__(t1_, t0_) / v33 * __PAIR64__(new_t1_, new_t0_)) < __SPAIR64__(x_1, x_0) )
{
j_ = j___ + 1;
c__ = c_;
b_j_ = b_j + 1;
goto
LABEL_12;
}
v19 = __SPAIR64__(t1_, t0_) / v33;
new_t1_ = HIDWORD(v19);
new_t0_ = v19;
c__ = c_;
d_[i_++] = __SPAIR64__(t1_, t0_) % v33;
j_ = j___;
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2023-9-29 05:11
被mb_mgodlfyn编辑
,原因: