-
-
[原创] 看雪 2022 KCTF 秋季赛 第十题 两袖清风
-
发表于: 2022-12-11 05:16 15280
-
一道奇奇怪怪的题,直到最后也理解不了考察点是什么,希望出题人可以开源出来看看。
(自己从周五晚上开始认真看题,爆肝一整天直到周六晚上才找到答案。10个小时出一血是真的快,应该是完全没有被外围逻辑分散精力)
主要逻辑都在 sub_140007660 里。策略还是先标记出函数,然后动态调试验证。
重要函数:
关键逻辑:
0x1400080DA:
这里限制了输入的长度上限是205
0x1400081E8:
检查了输入长度最小为89。
特别的,由于这个printf输出的是no,所以这个if块后面的部分完全不需要看(从0x14000824B开始到0x140008C91,在F5伪代码中占了足足一半)(最开始没有先注意到这个printf,浪费了一些时间。这些代码似乎都是内联进来的析构函数)
0x140008C91:
截取输入的前85个字节,按照十六进制解析初始化为一个大数,作为bn_powmod的指数参与运算(底数和模是上面的两个常量),计算结果再转回十六进制、hexdecode,暂时存入come_from_input_first_85_bytes变量中。
这里同时初始化了v197,后面会用到。
截取输入索引85开始的4个字节。由于LABEL_275输出no,所以不能跳转过去,这4个字节要求是数字。
后面是一个看起来很复杂的三重循环(其实到最后也没理清楚),但是值得关注的只有中间一部分:
0x140009178:
0x140009288
由于 0x140009288 的判断存在,所以 stdstring_concat 必须要被调用到,所以要从上面的break跳出来,而不能goto LABEL_201。
从 v114 == v115 + v111 && v114 == (char)v215 + v111 && v114 == v115 + SLOBYTE(v214[0])
推出 v115 == v215
且 v111 == SLOBYTE(v214[0])
;同时反向可验证只要满足这两个等式,if的条件一定会通过。
动态调试发现这4个数分别就是输入索引85开始的4个字节,约束是第1等于第3,第2等于第4。随手试,"0000" 不行,但 "0101" 可以(不知道具体原因)。
0x1400092D1:
这段主要是 aes_cbc_decrypt 解密一段固定常量。算法是 AES 256,密钥 key 是 come_from_input_first_85_bytes(v126),iv 是 v197(v125)。
(v125和v126在IDA中被标记为VALUE MAY BE UNDEFINED,需要看汇编+动态调试确认)
iv: v197在很早以前就计算出来了,值是固定的"ABCDEF0123456789"。
key:come_from_input_first_85_bytes 原本是模幂的计算结果的hexdecode,但是经过上面的三重循环后,其前面被附加了输入索引85开始的4个字节。无论如何,key是由输入的前89个字节完全确定的。跟进aes内部的key expansion,由 0x140001167 处的循环可以判断出 key 的长度为 32,即 AES256。
0x1400094F6:
这里取了输入索引89以后的所有字节
0x140009545:
如果索引89以后的的字节不为空(即输入长度大于89),则会进入这个if判断,核心部分是检查输入的全部字节为[0-9A-Z],同时在索引89之后不能有两个连续的'0'。
0x14000979E:
这里是把v134写入最开始分配出来的内存中。动态调试可以发现开头4个字符固定是"kctf",后面输入索引89以后的字节的hexdecode。同时也向偏移220和240的两个地方写入了 "Try again!\n" 和 "good!\n" 两个字符串。
0x1400098D0:
0x14000758C:(在 sub_140007410 内部)
sub_14000AF4E里面是很多syscall,没看懂是什么原理,但是从对它的调用 sub_14000AF4E((__int64)hObject, RtlFillMemory, (__int64)&a2[v12], 1i64, *a3, v19)
来看,应该等价于调用第二个参数指示的函数。
根据上下文,这两块逻辑应该是创建一个线程,动态调试发现前面aes解密出来的shellcode被写入一块内存中。
0x14000992C:
sub_14000AF4E再次出现了,所以之前解密出的shellcode会被当做函数(注意,函数是需要ret的,后面会利用这一点),在ResumeThread时执行。
(由于shellcode是根据输入的前89个字节解密的,所以如果随便输入,动态调试到这里时程序会因为非法指令而异常退出。)
暂时修改rip跳过这里,先调试下一段代码。
0x1400099CF:
最后一块逻辑是经典的利用uuid隐藏shellcode:再次分配了一段内存,然后UuidFromStringA从很多uuid常量中解出shellcode,作为第一个参数调用EnumSystemLocalesA(第一个参数会被当做函数在EnumSystemLocalesA中回调)
回顾前面对偏移220和240位置的写入,似乎只要 v154[4] * v154[4] + 5 * v154[8] * v154[8] * v154[8] - 2 * v154[4] * v154[6] * v154[6] + 3 == 0
就会成功,但是,稍微爆破一下 v154[4], v154[6], v154[8]
这三个字节,就会发现是无解的。
所以,EnumSystemLocalesA调用的shellcode内部肯定做了一些事情。
开头是自修改,运行完自修改(到偏移0x23的位置)再dump。
结合动态调试,整体逻辑还是相对清晰的。查找"kctf"找内存段,BaseAddress即为主要函数sub_140007660开始分配的内存区域,前4个字节是"kctf",后面跟着的是输入索引89以后的字节hexdecode的内容,然后是一块空白区域、一串01,以及220偏移处的"Try again!\n"和240偏移处的"good!\n"。
如果通过了shellcode末尾的检查,则会把220偏移处的"Try again!\n"修改为"good!\n",所以真正的检查逻辑就是这段shellcode。
这段shellcode整体逻辑如下(不太好描述,直接看代码吧。不过上面ida输出的伪代码可以复制出来编译,也能本地测试):
整块内存前4个字节是"kctf",然后是输入索引89以后的字节hexdecode的内容(这块内容的第一个字节是长度;后面的字节会hexencode,奇偶相间分别构成两个序列,每个序列的相邻两个值相差要求为1,且第二个序列要以0开头,同时两个序列至少有一个是以0或9结尾)。后面是两个10*10的区域,对每个区域,前面的两个序列分别是横纵坐标,检查要求所有坐标的位置都是0;以及,第一个区域的全部100个字节都要是0(第二个区域无此要求)。
反调试:
代码中有大量反调试,并且会修改 antidebug(0x140079CD0)这个全局变量指向的内存,而且位置会向后递增。
0x1400076C2
这是 sub_140007660 开头的一段代码,lpBaseAddress_ 是最后shellcode检查的内存段,动态调试看到的01序列在这里初始化;另外,antidebug也落在了两个10*10的区域的范围内。
反调试很多,大部分都能在调试器中忽略并继续,但这一处有些特殊:
0x140007375 (在 check_if_is_digit 中)
在x64dbg调试时如果忽略这里的异常,程序并不会调用TopLevelExceptionFilter,而是两次异常后直接退出,但是自己写代码测试发现如果不附加调试器就完全正常。
猜测原因是这里的异常由RaiseException api主动引发,异常的派生可能是内核处理?而UnhandledException在有调试器附加的时候会被调试器接收到,即使调试器选择忽略,但已经影响了系统的处理逻辑?(不太确定,熟悉Windows的朋友可以留言解释一下)
大部分反调试如果触发,会在 antidebug++ 相应的位置赋值为非0值,这会直接影响最后shellcode的检查。
但是有一处例外,在前面检查输入字符是否为[0-9A-Z]的位置(0x140009545的if块内部的0x1400096B3位置),对于每个符合要求的字符都会在 antidebug++ 指向的位置多赋值一个 0,这意味着如果输入较长,会被赋值更多的0,有利于最后的shellcode检查。
分析的差不多了,现在是时候寻找程序的正确输入了
首先是最后shellcode检查,受限于输入最长不能超过205个字符,所以 0x1400096B3 antidebug++ 赋值0的位置不会超过 0xDC (220) 的位置,而这里的位置保存在 "Try again!\n" 非 0 字符,也即中间的空白区域小于两个 10*10 区域(大概只有一百几十个字节),所以需要让索引尽可能小。
两个10*10 区域共用一套索引,第一个区域100个字节都要是0,则第二个区域只有开头的几十个字节才能是0。区域索引是二维坐标,所以横坐标要尽可能小。
横纵坐标各自的序列相邻位置差值必须是1,且第一个纵坐标必须是0,最后一个横坐标和纵坐标至少有1个是0或9;另外由于坐标值直接来源于原始输入,也受到原始输入不能存在相邻的0的限制。
基于以上限制,考虑先把最后一个纵坐标限定为9,那么一个最短的可行坐标序列如下:
对应到原始输入索引89之后的字节即为 "10011203140516071809"
实测发现,空白区域还是少了几个字节。根据之前的分析,增大2字节输入长度会使得 antidebug++ 赋值2个0,但是在此处只增加1个字节,合计增加了1个0的空白区域,所以适当增加长度,例如:
对应到原始输入索引89之后的字节即为 "1021120312031203140516071809",可以通过shellcode的检查。显然这里的构造方法不唯一。
还剩下最后一个问题没有解决:前面0x14000992C代码块会在ResumeThread(hThread)
时异常退出。这里实际上是由于根据输入前89字节解密出的shellcode函数存在非法指令,所以需要控制解密出来的字节。
既然shellcode是需要ret的函数,最简单的方式是控制ret指令(C3)在第一个字节,就可以不触发异常的通过这里。
无法反推到原始输入(因为要逆推aes key,再解离散对数,都是不可能的任务),但是由于只需要控制解密后的第一个字节,所以可以直接爆破
得到一个输入 "123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF01243"
把三部分拼起来
得到一个可行的答案:
通过验证:
(按照上面的分析,显然题目存在无数的解,所以非常好奇题目的源码逻辑是怎样的)
sub_140006DE0:scanf_s
sub_1400007F0:printf
sub140006FD0:str_xor,主要是异或解密一些常量
sub_140007180:hexdecode
sub_1400072B0:check_if_is_digit,检查一个std::string的字符是否全部是数字
sub_1400093C0:aes_cbc_decrypt,AES256 CBC 模式解密
std::string相关:
sub_140006060:stdstring_substr,取子串
sub_1400015F0:stdstring_init_from_cstr,构造函数(从char
*
构造)
sub_140006230,stdstring_copy,拷贝构造函数
sub_1400015C0:str_destructor,析构函数
sub_140006130:stdstring_cstr,返回内部缓冲区指针
sub_140006660:stdstring_concat,连接两个字符串
sub_140006140:stdstring_get,取索引位置的字符
大数运算:
sub_140001EE0:bn_init_from_str,从
16
进制大端序列的std::string初始化(bn内部是小端序)
sub_140004D70:bn_to_str,转换为
16
进制大端序的std::string
sub_1400042D0:bn_powmod,模幂运算
sub_140006DE0:scanf_s
sub_1400007F0:printf
sub140006FD0:str_xor,主要是异或解密一些常量
sub_140007180:hexdecode
sub_1400072B0:check_if_is_digit,检查一个std::string的字符是否全部是数字
sub_1400093C0:aes_cbc_decrypt,AES256 CBC 模式解密
std::string相关:
sub_140006060:stdstring_substr,取子串
sub_1400015F0:stdstring_init_from_cstr,构造函数(从char
*
构造)
sub_140006230,stdstring_copy,拷贝构造函数
sub_1400015C0:str_destructor,析构函数
sub_140006130:stdstring_cstr,返回内部缓冲区指针
sub_140006660:stdstring_concat,连接两个字符串
sub_140006140:stdstring_get,取索引位置的字符
大数运算:
sub_140001EE0:bn_init_from_str,从
16
进制大端序列的std::string初始化(bn内部是小端序)
sub_140004D70:bn_to_str,转换为
16
进制大端序的std::string
sub_1400042D0:bn_powmod,模幂运算
scanf_s(
"%s"
, v32, a1.s.size);
/
/
sub_140006DE0
scanf_s(
"%s"
, v32, a1.s.size);
/
/
sub_140006DE0
if
( inputlen <
0x59
)
/
/
0x59
,
89
{
v46
=
(char
*
)&v179.s;
if
( v179.s.capacity >
=
0x10ui64
)
v46
=
(char
*
)v179.s.s;
str_xor(v46, v179.s.size,
"Y?j0?"
);
v47
=
(const char
*
)&v179.s;
if
( v179.s.capacity >
=
0x10ui64
)
v47
=
(const char
*
)v179.s.s;
printf(v47);
/
/
"no!\n"
0x140008238
...
if
( inputlen <
0x59
)
/
/
0x59
,
89
{
v46
=
(char
*
)&v179.s;
if
( v179.s.capacity >
=
0x10ui64
)
v46
=
(char
*
)v179.s.s;
str_xor(v46, v179.s.size,
"Y?j0?"
);
v47
=
(const char
*
)&v179.s;
if
( v179.s.capacity >
=
0x10ui64
)
v47
=
(const char
*
)v179.s.s;
printf(v47);
/
/
"no!\n"
0x140008238
...
stdstring_substr(&a1, &input_first_85_bytes,
0i64
,
85ui64
);
stdstring_init_from_cstr(
&v208,
"B20446102D1C343D0575674CA28EBC0419BCFE4D75682C2AC81C9502454650BDDAEF6968AF269B54C182"
);
stdstring_init_from_cstr(
&v189,
"4F62187B5F6590C6CFF0FBDBBEBDAF60AA861BD2F66F8F7FFD57A66AE50DB7D2FFFFFFFFFFFFFFFFFFFFF"
);
bn_init_from_str(&v207, &v189);
str_destructor(&v189);
stdstring_init_from_cstr(&v189,
"11"
);
bn_init_from_str(&v211, &v189);
str_destructor(&v189);
v95
=
stdstring_cstr(&input_first_85_bytes);
stdstring_init_from_cstr(&v210, v95);
bn_init_from_str(&v206, &v210);
str_destructor(&v210);
bn_init_from_str(&v205, &v208);
bn_powmod(&v205, &v204, &v206, &v207);
bn_to_str(&v204, &v195);
v96
=
stdstring_cstr(&v195);
hexdecode(v96, v97);
v98
=
stdstring_cstr(&v195);
v100
=
str_xor(v98, v99,
"Y?j0?"
);
stdstring_init_from_cstr(&come_from_input_first_85_bytes, v100);
origin_size_of_come_from_input_first_85_bytes
=
come_from_input_first_85_bytes.s.size;
stdstring_init_from_cstr(&v197, byte_1400710A0);
stdstring_substr(&a1, &from_input_4_bytes_at_85,
85ui64
,
4ui64
);
sub_140009ED0(&v180, from_input_4_bytes_at_85.s.size);
*
(_QWORD
*
)v214
=
&v189;
v215
=
&v210;
v101
=
sub_14000A140(&from_input_4_bytes_at_85, &v189);
v102
=
sub_14000A1E0(&from_input_4_bytes_at_85, &v210);
sub_14000A270(&v180, v102, v101);
v103
=
stdstring_cstr(&v197);
str_xor(v103, v197.s.size,
"Y?j0?"
);
/
/
"ABCDEF0123456789"
v187
=
(unsigned __int64)&v189;
v104
=
stdstring_copy(&v189, &from_input_4_bytes_at_85);
if
( !check_if_is_digit(v104) || from_input_4_bytes_at_85.s.size !
=
4
)
goto LABEL_275;
ii
=
0i64
;
start
=
v180.v.start;
...
stdstring_substr(&a1, &input_first_85_bytes,
0i64
,
85ui64
);
stdstring_init_from_cstr(
&v208,
"B20446102D1C343D0575674CA28EBC0419BCFE4D75682C2AC81C9502454650BDDAEF6968AF269B54C182"
);
stdstring_init_from_cstr(
&v189,
"4F62187B5F6590C6CFF0FBDBBEBDAF60AA861BD2F66F8F7FFD57A66AE50DB7D2FFFFFFFFFFFFFFFFFFFFF"
);
bn_init_from_str(&v207, &v189);
str_destructor(&v189);
stdstring_init_from_cstr(&v189,
"11"
);
bn_init_from_str(&v211, &v189);
str_destructor(&v189);
v95
=
stdstring_cstr(&input_first_85_bytes);
stdstring_init_from_cstr(&v210, v95);
bn_init_from_str(&v206, &v210);
str_destructor(&v210);
bn_init_from_str(&v205, &v208);
bn_powmod(&v205, &v204, &v206, &v207);
bn_to_str(&v204, &v195);
v96
=
stdstring_cstr(&v195);
hexdecode(v96, v97);
v98
=
stdstring_cstr(&v195);
v100
=
str_xor(v98, v99,
"Y?j0?"
);
stdstring_init_from_cstr(&come_from_input_first_85_bytes, v100);
origin_size_of_come_from_input_first_85_bytes
=
come_from_input_first_85_bytes.s.size;
stdstring_init_from_cstr(&v197, byte_1400710A0);
stdstring_substr(&a1, &from_input_4_bytes_at_85,
85ui64
,
4ui64
);
sub_140009ED0(&v180, from_input_4_bytes_at_85.s.size);
*
(_QWORD
*
)v214
=
&v189;
v215
=
&v210;
v101
=
sub_14000A140(&from_input_4_bytes_at_85, &v189);
v102
=
sub_14000A1E0(&from_input_4_bytes_at_85, &v210);
sub_14000A270(&v180, v102, v101);
v103
=
stdstring_cstr(&v197);
str_xor(v103, v197.s.size,
"Y?j0?"
);
/
/
"ABCDEF0123456789"
v187
=
(unsigned __int64)&v189;
v104
=
stdstring_copy(&v189, &from_input_4_bytes_at_85);
if
( !check_if_is_digit(v104) || from_input_4_bytes_at_85.s.size !
=
4
)
goto LABEL_275;
ii
=
0i64
;
start
=
v180.v.start;
...
if
( v112 !
=
kk && v112 !
=
jj && v113 !
=
ii )
{
v114
=
(char)v215
+
SLOBYTE(v214[
0
]);
v115
=
start[v113];
if
( v114
=
=
v115
+
v111 && v114
=
=
(char)v215
+
v111 && v114
=
=
v115
+
SLOBYTE(v214[
0
]) )
break
;
}
+
+
v112;
+
+
v113;
if
( v112 >
=
4
)
goto LABEL_201;
}
kk
=
5
;
ii_i
=
5i64
;
v110
=
5i64
;
jj
=
5
;
v187
=
5i64
;
ii
=
5i64
;
v116
=
stdstring_concat(&v189, &from_input_4_bytes_at_85, &come_from_input_first_85_bytes);
strnode_assign(&come_from_input_first_85_bytes, v116);
str_destructor(&v189);
start
=
v180.v.start;
if
( v112 !
=
kk && v112 !
=
jj && v113 !
=
ii )
{
v114
=
(char)v215
+
SLOBYTE(v214[
0
]);
v115
=
start[v113];
if
( v114
=
=
v115
+
v111 && v114
=
=
(char)v215
+
v111 && v114
=
=
v115
+
SLOBYTE(v214[
0
]) )
break
;
}
+
+
v112;
+
+
v113;
if
( v112 >
=
4
)
goto LABEL_201;
}
kk
=
5
;
ii_i
=
5i64
;
v110
=
5i64
;
jj
=
5
;
v187
=
5i64
;
ii
=
5i64
;
v116
=
stdstring_concat(&v189, &from_input_4_bytes_at_85, &come_from_input_first_85_bytes);
strnode_assign(&come_from_input_first_85_bytes, v116);
str_destructor(&v189);
start
=
v180.v.start;
if
( come_from_input_first_85_bytes.s.size > (unsigned __int64)origin_size_of_come_from_input_first_85_bytes )
...
if
( come_from_input_first_85_bytes.s.size > (unsigned __int64)origin_size_of_come_from_input_first_85_bytes )
...
v214[
0
]
=
8
;
v214[
1
]
=
14
;
stdstring_resize(&stru_140079DB0,
0xDC0ui64
);
v118
=
stdstring_cstr(&stru_140079DB0);
memcpy(v118, Src,
0xDC0ui64
);
v119
=
stdstring_cstr(&stru_140079DB0);
str_xor(v119, stru_140079DB0.s.size,
"?x}da"
);
src_size
=
(unsigned __int64)stru_140079DB0.s.size >>
1
;
v121
=
stdstring_cstr(&stru_140079DB0);
hexdecode(v121, src_size);
v122
=
stdstring_cstr(&come_from_input_first_85_bytes);
str_xor(v122
+
4
, v123,
"Y?j0?"
);
stdstring_cstr(&v197);
/
/
iv
stdstring_cstr(&come_from_input_first_85_bytes);
/
/
key
from_src
=
stdstring_cstr(&stru_140079DB0);
v127
=
aes_cbc_decrypt(v214, from_src, src_size, v126, v125);
stdstring_init_from_cstr(&v196, v127);
v128
=
stdstring_cstr(&v185);
str_xor(v128, v185.s.size,
"!?>d*"
);
v129
=
stdstring_cstr(&v181);
str_xor(v129, v181.s.size,
"?x)da"
);
v130
=
stdstring_cstr(&v181);
v131
=
stdstring_cstr(&v185);
ModuleHandleA
=
GetModuleHandleA(v131);
/
/
kernel32.dll
RtlFillMemory
=
(__int64)GetProcAddress(ModuleHandleA, v130);
/
/
RtlFillMemory
if
( !RtlFillMemory )
goto LABEL_274;
virtualalloc_region_1
=
(char
*
)VirtualAllocEx(hProcess,
0i64
, v196.s.size,
0x3000u
,
0x40u
);
v134
=
(char
*
)malloc2(a1.s.size);
v135
=
stdstring_cstr(&v186);
str_xor(v135, v186.s.size,
"*s>0?"
);
v136
=
stdstring_cstr(&v186);
/
/
"kctf"
v137
=
v134
-
v136;
v214[
0
]
=
8
;
v214[
1
]
=
14
;
stdstring_resize(&stru_140079DB0,
0xDC0ui64
);
v118
=
stdstring_cstr(&stru_140079DB0);
memcpy(v118, Src,
0xDC0ui64
);
v119
=
stdstring_cstr(&stru_140079DB0);
str_xor(v119, stru_140079DB0.s.size,
"?x}da"
);
src_size
=
(unsigned __int64)stru_140079DB0.s.size >>
1
;
v121
=
stdstring_cstr(&stru_140079DB0);
hexdecode(v121, src_size);
v122
=
stdstring_cstr(&come_from_input_first_85_bytes);
str_xor(v122
+
4
, v123,
"Y?j0?"
);
stdstring_cstr(&v197);
/
/
iv
stdstring_cstr(&come_from_input_first_85_bytes);
/
/
key
from_src
=
stdstring_cstr(&stru_140079DB0);
v127
=
aes_cbc_decrypt(v214, from_src, src_size, v126, v125);
stdstring_init_from_cstr(&v196, v127);
v128
=
stdstring_cstr(&v185);
str_xor(v128, v185.s.size,
"!?>d*"
);
v129
=
stdstring_cstr(&v181);
str_xor(v129, v181.s.size,
"?x)da"
);
v130
=
stdstring_cstr(&v181);
v131
=
stdstring_cstr(&v185);
ModuleHandleA
=
GetModuleHandleA(v131);
/
/
kernel32.dll
RtlFillMemory
=
(__int64)GetProcAddress(ModuleHandleA, v130);
/
/
RtlFillMemory
if
( !RtlFillMemory )
goto LABEL_274;
virtualalloc_region_1
=
(char
*
)VirtualAllocEx(hProcess,
0i64
, v196.s.size,
0x3000u
,
0x40u
);
v134
=
(char
*
)malloc2(a1.s.size);
v135
=
stdstring_cstr(&v186);
str_xor(v135, v186.s.size,
"*s>0?"
);
v136
=
stdstring_cstr(&v186);
/
/
"kctf"
v137
=
v134
-
v136;
v139
=
stdstring_substr(&a1, &v189,
89ui64
, a1.s.size);
v140
=
stdstring_cstr(v139);
v141
=
v134
-
1
;
do
+
+
v141;
while
(
*
v141 );
strcpy(v141, v140);
v139
=
stdstring_substr(&a1, &v189,
89ui64
, a1.s.size);
v140
=
stdstring_cstr(v139);
v141
=
v134
-
1
;
do
+
+
v141;
while
(
*
v141 );
strcpy(v141, v140);
if
( a1.s.size )
{
...
if
( v145[i_2] >
=
'a'
)
{
if
(
*
stdstring_get(&a1, j_2) <
=
'z'
)
{
v146
=
antidebug;
*
(_BYTE
*
)antidebug
=
1
;
goto LABEL_237;
}
size_2
=
a1.s.size;
...
if
( (
*
(char
*
)(i_2
+
v147) <
'0'
||
*
stdstring_get(&a1, j_2) >
'9'
)
&& (
*
stdstring_get(&a1, j_2) <
'A'
||
*
stdstring_get(&a1, j_2) >
'Z'
) )
{
v146
=
antidebug;
*
(_BYTE
*
)antidebug
=
2
;
}
else
{
v146
=
antidebug;
*
(_BYTE
*
)antidebug
=
0
;
/
/
!
}
LABEL_237:
antidebug
=
v146
+
1
;
if
( j_2 >
89
&&
*
stdstring_get(&a1, j_2)
=
=
'0'
&&
*
stdstring_get(&a1, j_2
-
1i64
)
=
=
'0'
)
{
v148
=
stdstring_cstr(&v179);
str_xor(v148, v179.s.size,
"Y?j0?"
);
v149
=
stdstring_cstr(&v179);
printf(v149);
/
/
"no!\n"
str_destructor(&v196);
goto LABEL_276;
if
( a1.s.size )
{
...
if
( v145[i_2] >
=
'a'
)
{
if
(
*
stdstring_get(&a1, j_2) <
=
'z'
)
{
v146
=
antidebug;
*
(_BYTE
*
)antidebug
=
1
;
goto LABEL_237;
}
size_2
=
a1.s.size;
...
if
( (
*
(char
*
)(i_2
+
v147) <
'0'
||
*
stdstring_get(&a1, j_2) >
'9'
)
&& (
*
stdstring_get(&a1, j_2) <
'A'
||
*
stdstring_get(&a1, j_2) >
'Z'
) )
{
v146
=
antidebug;
*
(_BYTE
*
)antidebug
=
2
;
}
else
{
v146
=
antidebug;
*
(_BYTE
*
)antidebug
=
0
;
/
/
!
}
LABEL_237:
antidebug
=
v146
+
1
;
if
( j_2 >
89
&&
*
stdstring_get(&a1, j_2)
=
=
'0'
&&
*
stdstring_get(&a1, j_2
-
1i64
)
=
=
'0'
)
{
v148
=
stdstring_cstr(&v179);
str_xor(v148, v179.s.size,
"Y?j0?"
);
v149
=
stdstring_cstr(&v179);
printf(v149);
/
/
"no!\n"
str_destructor(&v196);
goto LABEL_276;
TickCount64
=
GetTickCount64();
v153
=
(
int
)v150
+
5
;
v154
=
(char
*
)lpBaseAddress;
v155
=
(
int
)hProcess;
WriteProcessMemory(hProcess, lpBaseAddress, v134, v153, (SIZE_T
*
)NumberOfBytesWritten);
v156
=
(char
*
)&try_again.s;
if
( try_again.s.capacity >
=
0x10ui64
)
v156
=
(char
*
)try_again.s.s;
str_xor(v156, try_again.s.size,
"Y?j0?"
);
v157
=
&try_again.s;
if
( try_again.s.capacity >
=
0x10ui64
)
v157
=
(const void
*
)try_again.s.s;
*
(_QWORD
*
)v214
=
v154
+
220
;
memcpy(v154
+
220
, v157, try_again.s.size);
/
/
"Try again!\n"
v158
=
(char
*
)&good.s;
if
( good.s.capacity >
=
0x10ui64
)
v158
=
(char
*
)good.s.s;
str_xor(v158, good.s.size,
"Y?j0?"
);
v159
=
&good.s;
if
( good.s.capacity >
=
0x10ui64
)
v159
=
(const void
*
)good.s.s;
v215
=
(struct strnode
*
)(v154
+
240
);
memcpy(v154
+
240
, v159, good.s.size);
/
/
"good!\n"
shellcode_1
=
(unsigned __int8
*
)&v196.s;
if
( v196.s.capacity >
=
0x10ui64
)
shellcode_1
=
(unsigned __int8
*
)v196.s.s;
TickCount64
=
GetTickCount64();
v153
=
(
int
)v150
+
5
;
v154
=
(char
*
)lpBaseAddress;
v155
=
(
int
)hProcess;
WriteProcessMemory(hProcess, lpBaseAddress, v134, v153, (SIZE_T
*
)NumberOfBytesWritten);
v156
=
(char
*
)&try_again.s;
if
( try_again.s.capacity >
=
0x10ui64
)
v156
=
(char
*
)try_again.s.s;
str_xor(v156, try_again.s.size,
"Y?j0?"
);
v157
=
&try_again.s;
if
( try_again.s.capacity >
=
0x10ui64
)
v157
=
(const void
*
)try_again.s.s;
*
(_QWORD
*
)v214
=
v154
+
220
;
memcpy(v154
+
220
, v157, try_again.s.size);
/
/
"Try again!\n"
v158
=
(char
*
)&good.s;
if
( good.s.capacity >
=
0x10ui64
)
v158
=
(char
*
)good.s.s;
str_xor(v158, good.s.size,
"Y?j0?"
);
v159
=
&good.s;
if
( good.s.capacity >
=
0x10ui64
)
v159
=
(const void
*
)good.s.s;
v215
=
(struct strnode
*
)(v154
+
240
);
memcpy(v154
+
240
, v159, good.s.size);
/
/
"good!\n"
shellcode_1
=
(unsigned __int8
*
)&v196.s;
if
( v196.s.capacity >
=
0x10ui64
)
shellcode_1
=
(unsigned __int8
*
)v196.s.s;
if
( (unsigned
int
)sub_140007410(v155, virtualalloc_region_1, shellcode_1, LODWORD(v196.s.size)
+
1
)
|| (v176
=
0i64
,
v175
=
0i64
,
v174
=
0i64
,
v173
=
0i64
,
v172
=
1
,
(unsigned
int
)sub_14000B629((
int
)&hThread,
0x1FFFFF
,
0
, v155, (
int
)ExitThread,
0
)) )
if
( (unsigned
int
)sub_140007410(v155, virtualalloc_region_1, shellcode_1, LODWORD(v196.s.size)
+
1
)
|| (v176
=
0i64
,
v175
=
0i64
,
v174
=
0i64
,
v173
=
0i64
,
v172
=
1
,
(unsigned
int
)sub_14000B629((
int
)&hThread,
0x1FFFFF
,
0
, v155, (
int
)ExitThread,
0
)) )
if
( !(unsigned
int
)sub_14000B629((
int
)&hObject,
0x1FFFFF
,
0
, a4, (
int
)ExitThread,
0
) )
{
if
( !r9d0 )
{
LABEL_15:
ResumeThread(hObject);
WaitForSingleObject(hObject,
0xFFFFFFFF
);
CloseHandle(hObject);
return
0i64
;
}
while
( !(unsigned
int
)sub_14000AF4E((__int64)hObject, RtlFillMemory, (__int64)&a2[v12],
1i64
,
*
a3, v19) )
{
+
+
v12;
+
+
a3;
if
( v12 >
=
r9d0 )
goto LABEL_15;
if
( !(unsigned
int
)sub_14000B629((
int
)&hObject,
0x1FFFFF
,
0
, a4, (
int
)ExitThread,
0
) )
{
if
( !r9d0 )
{
LABEL_15:
ResumeThread(hObject);
WaitForSingleObject(hObject,
0xFFFFFFFF
);
CloseHandle(hObject);
return
0i64
;
}
while
( !(unsigned
int
)sub_14000AF4E((__int64)hObject, RtlFillMemory, (__int64)&a2[v12],
1i64
,
*
a3, v19) )
{
+
+
v12;
+
+
a3;
if
( v12 >
=
r9d0 )
goto LABEL_15;
sub_14000AF4E((__int64)hThread, (__int64)virtualalloc_region_1,
0i64
,
0i64
,
0
, v171[
0
]);
v161
=
(
int
)(GetTickCount64()
-
TickCount64) <
6000
;
v162
=
(_BYTE
*
)antidebug;
if
( !v161 )
{
*
(_BYTE
*
)antidebug
=
9
;
antidebug
=
(__int64)
+
+
v162;
}
if
( debugger_present )
{
*
v162
=
6
;
antidebug
=
(__int64)(v162
+
1
);
}
ResumeThread(hThread);
WaitForSingleObject(hThread,
0xFFFFFFFF
);
CloseHandle(hThread);
if
( (unsigned
int
)sub_140006E40() !
=
0x478E
)
sub_14000AF4E((__int64)hThread, (__int64)virtualalloc_region_1,
0i64
,
0i64
,
0
, v171[
0
]);
v161
=
(
int
)(GetTickCount64()
-
TickCount64) <
6000
;
v162
=
(_BYTE
*
)antidebug;
if
( !v161 )
{
*
(_BYTE
*
)antidebug
=
9
;
antidebug
=
(__int64)
+
+
v162;
}
if
( debugger_present )
{
*
v162
=
6
;
antidebug
=
(__int64)(v162
+
1
);
}
ResumeThread(hThread);
WaitForSingleObject(hThread,
0xFFFFFFFF
);
CloseHandle(hThread);
if
( (unsigned
int
)sub_140006E40() !
=
0x478E
)
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)