前言 :目前的许多 CTF 二进制竞赛中出现了许多单字节加密验证题,例如 NCTF-ezVM、TPCTF-Poly 等。这些单字节验证程序中,很多都是虚拟机(VM)类型的。VM 程序通常有一个指令分发器,在分发指令时需要一个类似于 EIP(指令指针寄存器)的累加器来确保指令正确执行。而在单字节验证的过程中,如果出现一个字节不匹配的情况,程序会立即退出。这里存在一个相关关系:当当前字节验证正确时,EIP 会向下移动,累加器也会相应增加。因此,我们使用 Frida 在指令分发器处插入代码,在程序退出时检查累加器的变化,以此判断当前位是否验证成功。同理,若程序不是 VM 类型,则我们只需要在判断位数的累加器处插入代码,即可。
通过单字节验证,验证时间随验证字节长度呈线性增长,这远远优于传统爆破方法的指数增长。结合之前的描述,这种优化源于对虚拟机程序的特定操作方式,利用 EIP 的变化关系,在单字节验证过程中进行精准的判断和优化。
IDA(Interactive Disassembler)是一款强大的反汇编软件,用于逆向工程和漏洞分析。它允许用户将机器码转换成可读的汇编代码,以便更好地理解程序的运行方式和结构。IDA 提供了丰富的功能,包括自动分析、图形化表示程序的控制流、数据流和函数调用关系,以及交互式地修改和调试程序。它广泛应用于软件逆向工程、漏洞分析、恶意代码分析等领域,是安全研究人员和逆向工程师的首选工具之一。IDA 的界面和功能使得用户可以深入分析程序,了解其内部结构和运行机制,有助于发现漏洞、理解程序逻辑以及编写补丁。
Frida 是一个强大的动态分析工具,可用于在运行时修改和监视应用程序。它提供了跨平台的框架,可以对多种操作系统、架构和应用程序类型进行操作。Frida 允许你通过 JavaScript 或 Python 等脚本语言来编写脚本,然后将这些脚本注入到目标应用程序中,从而实现对目标应用程序的监视、跟踪和修改。
这段代码实现了一个简单的单字节比较程序,与之前介绍的虚拟机指令分发不同,这里只是进行了简单的单字节比较。但与之前相似的地方在于存在一个类似累加器的概念,我们可以通过观察这个累加器的变化来判断当前字节是否正确。
将程序使用 MinGW GCC 9.2.0 32-bit Debug 并且关闭基地址随机化编译,我们得到 test1.exe。并使用 IDA 分析。
图(1)
图(2)
从图(1)中可以确定 i++
指令的地址是 0x4014AB,而根据图(2)判断错误时进入 puts
函数的第一条地址是 0x401489。因此,我们需要 hook 的地址是这两个记录的地址。在 i++
处,我们要植入的代码是使我们的插桩数加一,在 puts
处,我们要植入的代码是回显我们的插桩数。
该代码检测了内存中是否存在 test1.exe 程序,并且获取了 test1.exe 的基地址,通过偏移量确定了之前测定的 0x4014AB 与 0x401489。
运行 test1.exe 程序,并且执行如下命令
图(3)
图(4)
如果程序执行成功,你将会得到类似图(3)的界面。当我们输入'a',你会看到类似图(4)的回显。我们已知程序正确验证为 'flag{12321213}',所以再输入'f'来查看回显。
输入 'f' 后,你会看到类似以下信息:
message: {'type': 'send', 'payload': 1} data: None
然后输入 'fl' 后,你会看到类似以下信息:
message: {'type': 'send', 'payload': 2} data: None
显然,正确字节越多,得到的 number 数字也随之增加。因此,这个 number 可作为我们判断当前字节是否正确的侧信道。
程序名称 easyChallenge.exe,使用 IDA 查看该程序可以得到如下所示的伪代码
easyChllenge.exe Main 函数伪代码:
根据分析,发现 v2 存放指令集,v4 存放 EIP(指令指针寄存器)的值。程序利用 v2 中的指令集对输入进行处理,并逐字节验证。验证失败时,程序立即退出,不再继续执行。这显示了程序在验证中的严谨性,一旦发现验证失败就停止后续步骤。
因此,我们选择在 switch 语句处进行 hook 代码的插入,以便在运行到该点时对插装数进行 +1 操作。随后,我们继续在 puts 函数的地址处进行插桩数验证。这些插桩的位置如图(5)和(6)所示。
图(5)
图(6)
Hook 代码:
同样我们运行 easyChallenge.exe 后执行如下命令。
输入简单的 'a' 后,得到回显:
[Local::easyChallenge.exe ]-> message: {'type': 'send', 'payload': 0} data: None
我们观察到程序并没有经过我们插桩的点。这是因为我们的输入不足 32 位,导致程序没有进入虚拟机的分发器。
输入 '12345678911234567891123456789112' 继续查看回显:
[Local::easyChallenge.exe ]-> Process terminated
[Local::easyChallenge.exe ]->
输入 '12345678911234567891123456789112' 后,程序终止并没有返回 number 数字的回显。这可能是因为程序在返回 number 数字之前就被终止了,导致我们无法看到完整的回显信息。这种情况表明程序运行时间不足以完成整个流程,需要使用其他方法来延长程序的运行时间。观察程序发现程序中出现了 puts 函数,那么我们可以劫持 puts 函数循环输出,来增加程序 IO 时间从而等待 number 数回传。
操作如下:
这段代码则是调用了程序中原本存在的 puts 函数,当我们放在发送 number 操作之后,程序则会等待我们回传 number。
执行操作后再重复输入 '12345678911234567891123456789112' ,就可以得到如下回显了:
[Local::easyChallenge.exe ]-> message: {'type': 'send', 'payload': 197} data: None
重复皂搓输入'f2345678911234567891123456789112',得到回显:
[Local::easyChallenge.exe ]-> message: {'type': 'send', 'payload': 203} data: None
发现当第一位输入正确时,插桩数则增大。
程序调用以及 hook 函数:
这段代码实现了一个名为 brute
的函数,函数接受一个参数 F
。函数解读如下:
这段代码的目的是通过 Frida 脚本监控进程的执行,在进程执行过程中,当收到特定类型的消息时(例如 'send'
),将其中的 'payload'
提取出来作为结果返回。
调用该函数传入我们的输入,我们则可以根据函数返回的 result,来分析输入是否正确了。
爆破主体代码:
这段代码是一个循环,尝试逐字节破解一个 flag。让我们逐步解读:
count = 0
: 初始化一个计数器,用于追踪已经尝试的字节位置。
new_number = brute(flag)
: 调用 brute()
函数并将结果保存在 new_number
中。
number = new_number
: 将 new_number
赋值给 number
。
while count < flaglen:
: 开始一个循环,条件是 count
小于 flaglen
,即 flag 的长度。
number = brute(flag)
: 再次调用 brute()
函数,更新 number
的值。
如果 number
大于 new_number
:
如果 number
不大于 new_number
:
最后输出解码后的 flag
字符串。
这段代码在不断尝试对一个密文进行破解,通过比较不同位置的字符对应的数字(是一个侧信道攻击中的某种特定指标)来判断解密进展,逐字节地逼近正确的结果。
最终我们获得完整 Exploit:
程序运行结果如图(7)所示:
图(7)
平均每位耗时 2.7s,32 位程序总耗时 78s
程序 Main 函数伪代码:
本程序也属于 VM 类型,相较于上一程序,本程序分析起来更加复杂,验证逻辑更为繁琐,因此我们也可以考虑道使用之前提出的侧信道解法来爆破本程序的正确输入。我们 hook 的点位仍然是指令分发器的位置以及 putchar 位置,分别为图(8)和(9):
图(8)
图(9)
HOOK 脚本如下:
由于本题在 hook 程序之后导致程序退出异常缓慢,因此在程序中可以找到 exit 函数的地址,通过调用 exit 函数来让程序退出。并且,发现最后一位如果争取的 eip 运行次数会减少。那么我们更改 exp 为检测到 number 变化即为正确字符。
运行效果如图(10):
图(10)
Main 程序伪代码:
本程序加密逻辑十分繁琐以及复杂,但是依旧满足单字节加密验证
运行结果如图(11)
图(11)
#include<iostream>
#include<stdlib.h>
using
namespace
std;
typedef
int
status;
typedef
int
selemtype;
#include<windows.h>
char
flag[] =
"flag{12321213}"
;
char
w[] =
"Wrong!"
;
char
r[] =
"Right!"
;
int
main ()
{
char
input[256] = {0};
gets
(input);
for
(
int
i = 0 ; flag[i] ; i ++ ){
if
(flag[i]!=input[i]){
puts
(
"Wrong!"
);
Sleep(0x10);
return
0;
}
}
puts
(
"Right!"
);
}
#include<iostream>
#include<stdlib.h>
using
namespace
std;
typedef
int
status;
typedef
int
selemtype;
#include<windows.h>
char
flag[] =
"flag{12321213}"
;
char
w[] =
"Wrong!"
;
char
r[] =
"Right!"
;
int
main ()
{
char
input[256] = {0};
gets
(input);
for
(
int
i = 0 ; flag[i] ; i ++ ){
if
(flag[i]!=input[i]){
puts
(
"Wrong!"
);
Sleep(0x10);
return
0;
}
}
puts
(
"Right!"
);
}
var
number = 0
function
main()
{
var
base = Module.findBaseAddress(
"test1.exe"
)
if
(base){
Interceptor.attach(base.add(0x1489), {
onEnter:
function
(args) {
send(number);
}
});
Interceptor.attach(base.add(0x14AB), {
onEnter:
function
(args) {
number+=1;
}
});
}
}
setImmediate(main);
var
number = 0
function
main()
{
var
base = Module.findBaseAddress(
"test1.exe"
)
if
(base){
Interceptor.attach(base.add(0x1489), {
onEnter:
function
(args) {
send(number);
}
});
Interceptor.attach(base.add(0x14AB), {
onEnter:
function
(args) {
number+=1;
}
});
}
}
setImmediate(main);
frida
-l
.\h00k.js
-n
test1.exe
frida
-l
.\h00k.js
-n
test1.exe
int
main()
{
char
Str[100];
_DWORD v2[513];
_DWORD v3[100];
int
v4;
size_t
i;
__main();
memset
(v3, 0,
sizeof
(v3));
qmemcpy(v2, &unk_404020,
sizeof
(v2));
memset
(Str, 0,
sizeof
(Str));
puts
(
"input the flag:"
);
scanf
(
"%s"
, Str);
if
(
strlen
(Str) == 32 )
{
for
( i = 0;
strlen
(Str) > i; ++i )
v3[i + 1] = Str[i];
v4 = 0;
while
( v4 <= 512 )
{
switch
( v2[v4] )
{
case
1:
s += v2[++v4];
goto
LABEL_20;
case
2:
s -= v2[++v4];
goto
LABEL_20;
case
3:
s *= v2[++v4];
goto
LABEL_20;
case
4:
s /= (
int
)v2[++v4];
goto
LABEL_20;
case
5:
s ^= v2[++v4];
goto
LABEL_20;
case
6:
s = v3[v3[0]];
goto
LABEL_20;
case
7:
v3[v3[0]] = s;
goto
LABEL_20;
case
8:
if
( v2[v4 + 1] != s )
goto
LABEL_22;
++v4;
goto
LABEL_20;
case
9:
puts
(
"right!"
);
return
1;
case
0xA:
s = v3[0];
goto
LABEL_20;
case
0xB:
v3[0] = s;
goto
LABEL_20;
default
:
LABEL_20:
++v4;
break
;
}
}
}
LABEL_22:
puts
(
"wrong!"
);
return
0;
}
int
main()
{
char
Str[100];
_DWORD v2[513];
_DWORD v3[100];
int
v4;
size_t
i;
__main();
memset
(v3, 0,
sizeof
(v3));
qmemcpy(v2, &unk_404020,
sizeof
(v2));
memset
(Str, 0,
sizeof
(Str));
puts
(
"input the flag:"
);
scanf
(
"%s"
, Str);
if
(
strlen
(Str) == 32 )
{
for
( i = 0;
strlen
(Str) > i; ++i )
v3[i + 1] = Str[i];
v4 = 0;
while
( v4 <= 512 )
{
switch
( v2[v4] )
{
case
1:
s += v2[++v4];
goto
LABEL_20;
case
2:
s -= v2[++v4];
goto
LABEL_20;
case
3:
s *= v2[++v4];
goto
LABEL_20;
case
4:
s /= (
int
)v2[++v4];
goto
LABEL_20;
case
5:
s ^= v2[++v4];
goto
LABEL_20;
case
6:
s = v3[v3[0]];
goto
LABEL_20;
case
7:
v3[v3[0]] = s;
goto
LABEL_20;
case
8:
if
( v2[v4 + 1] != s )
goto
LABEL_22;
++v4;
goto
LABEL_20;
case
9:
puts
(
"right!"
);
return
1;
case
0xA:
s = v3[0];
goto
LABEL_20;
case
0xB:
v3[0] = s;
goto
LABEL_20;
default
:
LABEL_20:
++v4;
break
;
}
}
}
LABEL_22:
puts
(
"wrong!"
);
return
0;
}
var number = 0
function main()
{
var base = Module.findBaseAddress(
"easyChallenge.exe"
)
if
(base){
Interceptor.attach(base.add(0x3D08), {
onEnter: function(args) {
send(number);
}
});
Interceptor.attach(base.add(0x155A), {
onEnter: function(args) {
number+=1;
}
});
}
}
setImmediate(main);
var number = 0
function main()
{
var base = Module.findBaseAddress(
"easyChallenge.exe"
)
if
(base){
Interceptor.attach(base.add(0x3D08), {
onEnter: function(args) {
send(number);
}
});
Interceptor.attach(base.add(0x155A), {
onEnter: function(args) {
number+=1;
}
});
}
}
setImmediate(main);
frida
-l
.\h00k.js
-n
easyChallenge.exe
frida
-l
.\h00k.js
-n
easyChallenge.exe
var st = Memory.allocUtf8String(
"Suprise!"
);
var f = new NativeFunction(base.add(0x3D08),
'void'
,[
'pointer'
]);
for
(var i = 0 ; i < 999 ; i ++ ){
f(st);
}
var st = Memory.allocUtf8String(
"Suprise!"
);
var f = new NativeFunction(base.add(0x3D08),
'void'
,[
'pointer'
]);
for
(var i = 0 ; i < 999 ; i ++ ){
f(st);
}
def
brute(F):
def
on_message(message, data):
global
result
if
message[
'type'
]
=
=
'send'
:
result
=
message[
'payload'
]
else
:
print
(message)
process
=
subprocess.Popen(filename, stdin
=
subprocess.PIPE,
stdout
=
subprocess.PIPE,
stderr
=
subprocess.PIPE,
universal_newlines
=
True
)
session
=
frida.attach(filename)
script
=
session.create_script(jscode)
script.on(
'message'
, on_message)
script.load()
process.stdin.write(F.decode())
output, error
=
process.communicate()
process.terminate()
return
result
def
brute(F):
def
on_message(message, data):
global
result
if
message[
'type'
]
=
=
'send'
:
result
=
message[
'payload'
]
else
:
print
(message)
process
=
subprocess.Popen(filename, stdin
=
subprocess.PIPE,
stdout
=
subprocess.PIPE,
stderr
=
subprocess.PIPE,
universal_newlines
=
True
)
session
=
frida.attach(filename)
script
=
session.create_script(jscode)
script.on(
'message'
, on_message)
script.load()
process.stdin.write(F.decode())
output, error
=
process.communicate()
process.terminate()
return
result
count
=
0
new_number
=
brute(flag)
number
=
new_number
while
count < flaglen:
number
=
brute(flag)
if
number > new_number:
print
(flag.decode())
new_number
=
number
count
+
=
1
else
:
flag[count]
+
=
1
while
(flag[count] >
127
):
flag[count]
=
33
count
-
=
1
flag[count]
+
=
1
print
(flag.decode())
count
=
0
new_number
=
brute(flag)
number
=
new_number
while
count < flaglen:
number
=
brute(flag)
if
number > new_number:
print
(flag.decode())
new_number
=
number
count
+
=
1
else
:
flag[count]
+
=
1
while
(flag[count] >
127
):
flag[count]
=
33
count
-
=
1
flag[count]
+
=
1
print
(flag.decode())
import
subprocess
import
frida
import
sys
import
win32api
import
win32con
number
=
0
flaglen
=
32
filename
=
"easyChallenge.exe"
flag
=
bytearray(b
'!'
*
flaglen)
jscode
=
open
(
"h00k.js"
,
"rb"
).read().decode()
new_number
=
0
result
=
0
def
brute(F):
def
on_message(message, data):
global
result
if
message[
'type'
]
=
=
'send'
:
result
=
message[
'payload'
]
else
:
print
(message)
process
=
subprocess.Popen(filename, stdin
=
subprocess.PIPE,
stdout
=
subprocess.PIPE,
stderr
=
subprocess.PIPE,
universal_newlines
=
True
)
session
=
frida.attach(filename)
script
=
session.create_script(jscode)
script.on(
'message'
, on_message)
script.load()
process.stdin.write(F.decode())
output, error
=
process.communicate()
process.terminate()
return
result
import
time
count
=
0
new_number
=
brute(flag)
number
=
new_number
t
=
time.time()
st
=
t
while
count < flaglen:
number
=
brute(flag)
if
number > new_number:
print
(f
"本位耗时:{time.time()-t}s,正确字符为:{chr(flag[count])}"
)
t
=
time.time()
print
(flag.decode())
new_number
=
number
count
+
=
1
else
:
flag[count]
+
=
1
while
(flag[count] >
127
):
flag[count]
=
33
count
-
=
1
flag[count]
+
=
1
print
(flag.decode())
print
(f
"总耗时{time.time()-st}"
)
import
subprocess
import
frida
import
sys
import
win32api
import
win32con
number
=
0
flaglen
=
32
filename
=
"easyChallenge.exe"
flag
=
bytearray(b
'!'
*
flaglen)
jscode
=
open
(
"h00k.js"
,
"rb"
).read().decode()
new_number
=
0
result
=
0
def
brute(F):
def
on_message(message, data):
global
result
if
message[
'type'
]
=
=
'send'
:
result
=
message[
'payload'
]
else
:
print
(message)
process
=
subprocess.Popen(filename, stdin
=
subprocess.PIPE,
stdout
=
subprocess.PIPE,
stderr
=
subprocess.PIPE,
universal_newlines
=
True
)
session
=
frida.attach(filename)
script
=
session.create_script(jscode)
script.on(
'message'
, on_message)
script.load()
process.stdin.write(F.decode())
output, error
=
process.communicate()
process.terminate()
return
result
import
time
count
=
0
new_number
=
brute(flag)
number
=
new_number
t
=
time.time()
st
=
t
while
count < flaglen:
number
=
brute(flag)
if
number > new_number:
print
(f
"本位耗时:{time.time()-t}s,正确字符为:{chr(flag[count])}"
)
t
=
time.time()
print
(flag.decode())
new_number
=
number
count
+
=
1
else
:
flag[count]
+
=
1
while
(flag[count] >
127
):
flag[count]
=
33
count
-
=
1
flag[count]
+
=
1
print
(flag.decode())
print
(f
"总耗时{time.time()-st}"
)
int
__cdecl main(
int
argc, const char
*
*
argv, const char
*
*
envp)
{
unsigned __int8 v3;
/
/
r15
__int64 v4;
/
/
rdi
__int64 v5;
/
/
rax
__int64 v6;
/
/
rcx
unsigned __int8 v7;
/
/
cl
__int16 v8;
/
/
cx
int
v9;
/
/
ecx
__int64 v10;
/
/
rcx
int
v11;
/
/
ebp
unsigned __int64 v12;
/
/
rbx
unsigned __int8 v13;
/
/
r14
rsize_t v14;
/
/
rdx
__int64 v15;
/
/
rax
__int64 v16;
/
/
rdx
__int64 v17;
/
/
rcx
v3
=
0
;
LODWORD(v4)
=
0
;
LABEL_2:
v5
=
(unsigned
int
)dword_14001FF94;
while
(
2
)
{
v6
=
(unsigned
int
)v4;
v4
=
(unsigned
int
)(v4
+
1
);
switch ( byte_140004040[v6] )
{
case
0xBu
:
v5
=
(unsigned
int
)(v5
+
8
);
dword_14001FF94
=
v5;
continue
;
case
0xCu
:
v8
=
*
(_WORD
*
)&byte_140004040[v4];
v5
=
(unsigned
int
)(v5
-
2
);
dword_14001FF94
=
v5;
LODWORD(v4)
=
v4
+
2
;
*
(_WORD
*
)&byte_14002058F[v5
+
1
]
=
v8;
continue
;
case
0xEu
:
v5
=
(unsigned
int
)(v5
-
1
);
dword_14001FF94
=
v5;
byte_14002058F[(unsigned
int
)v5
+
1
]
=
byte_14002058F[(unsigned
int
)(v5
+
1
)
+
1
];
continue
;
case
0x19u
:
return
*
(_DWORD
*
)&byte_140004040[v4];
case
0x32u
:
v7
=
byte_140004040[v4];
v5
=
(unsigned
int
)(v5
-
1
);
dword_14001FF94
=
v5;
LODWORD(v4)
=
v4
+
1
;
byte_14002058F[v5
+
1
]
=
v7;
continue
;
case
0x49u
:
byte_14002058F[(unsigned
int
)(v5
+
1
)
+
1
]
=
~byte_14002058F[(unsigned
int
)(v5
+
1
)
+
1
];
continue
;
case
0x71u
:
v16
=
(unsigned
int
)(v5
+
1
);
byte_14002058F[v16
+
1
] &
=
byte_14002058F[v5
+
1
];
v5
=
(unsigned
int
)v16;
dword_14001FF94
=
v16;
continue
;
case
0x72u
:
byte_14002058F[v5
+
1
]
=
~byte_14002058F[v5
+
1
];
continue
;
case
0x7Bu
:
v14
=
(char)byte_14002058F[v5
+
1
];
v15
=
(unsigned
int
)(v5
-
7
);
dword_14001FF94
=
v15;
*
(_QWORD
*
)&byte_14002058F[v15
+
1
]
=
Buffer
;
gets_s(
Buffer
, v14);
goto LABEL_2;
case
0x7Cu
:
v5
=
(unsigned
int
)(v5
-
2
);
dword_14001FF94
=
v5;
byte_14002058F[v5
+
1
]
=
byte_14002058F[(unsigned
int
)(v5
+
2
)
+
1
];
byte_14002058F[(unsigned
int
)(v5
+
1
)
+
1
]
=
byte_14002058F[(unsigned
int
)(v5
+
3
)
+
1
];
continue
;
case
0x8Du
:
if
( !byte_14002058F[v5
+
1
] )
LODWORD(v4)
=
*
(_DWORD
*
)&byte_14002058F[v5
+
2
];
v5
=
(unsigned
int
)(v5
+
5
);
dword_14001FF94
=
v5;
continue
;
case
0x8Eu
:
v5
=
(unsigned
int
)(v5
+
2
);
dword_14001FF94
=
v5;
continue
;
case
0x91u
:
v9
=
*
(_DWORD
*
)&byte_140004040[v4];
v5
=
(unsigned
int
)(v5
-
4
);
dword_14001FF94
=
v5;
LODWORD(v4)
=
v4
+
4
;
*
(_DWORD
*
)&byte_14002058F[v5
+
1
]
=
v9;
continue
;
case
0x99u
:
v5
=
(unsigned
int
)(v5
+
4
);
dword_14001FF94
=
v5;
continue
;
case
0xADu
:
v5
=
(unsigned
int
)(v5
-
1
);
dword_14001FF94
=
v5;
byte_14002058F[(unsigned
int
)v5
+
1
]
=
v3;
continue
;
case
0xB5u
:
if
( byte_14002058F[v5
+
1
] )
byte_14002058F[v5
+
1
]
=
1
;
continue
;
case
0xB7u
:
v3
=
byte_14002058F[v5
+
1
];
goto LABEL_9;
case
0xB8u
:
byte_14002058F[v5
+
1
]
=
*
(_BYTE
*
)(byte_14002058F[v5
+
1
]
+
*
(_QWORD
*
)&byte_14002058F[v5
+
2
]);
continue
;
case
0xD3u
:
v10
=
*
(_QWORD
*
)&byte_140004040[v4];
v5
=
(unsigned
int
)(v5
-
8
);
dword_14001FF94
=
v5;
LODWORD(v4)
=
v4
+
8
;
*
(_QWORD
*
)&byte_14002058F[v5
+
1
]
=
v10;
continue
;
case
0xEAu
:
LABEL_9:
v5
=
(unsigned
int
)(v5
+
1
);
dword_14001FF94
=
v5;
continue
;
case
0xFBu
:
v11
=
byte_140004040[v4];
v12
=
0i64
;
v4
=
(unsigned
int
)(v4
+
1
);
v13
=
byte_140004040[v4] ^ v11;
LODWORD(v4)
=
v4
+
1
;
if
( v13 )
{
do
{
putchar(v11 ^ byte_14002058F[v13
+
(unsigned
int
)v5
-
v12]);
LODWORD(v5)
=
dword_14001FF94;
+
+
v12;
}
while
( v12 < v13 );
}
dword_14001FF94
=
v13
+
(_DWORD)v5;
putchar(
10
);
goto LABEL_2;
case
0xFFu
:
v17
=
byte_14002058F[v5
+
1
];
if
( (_BYTE)v17 )
{
if
( (_BYTE)v17
=
=
1
)
{
if
( (unsigned
int
)v5 >
=
0x100ui64
)
{
_report_rangecheckfailure(v17, (unsigned
int
)v5, envp);
__debugbreak();
}
byte_14002058F[v5
+
1
]
=
0
;
}
}
else
{
byte_14002058F[v5
+
1
]
=
1
;
}
continue
;
default:
continue
;
}
}
}
int
__cdecl main(
int
argc, const char
*
*
argv, const char
*
*
envp)
{
unsigned __int8 v3;
/
/
r15
__int64 v4;
/
/
rdi
__int64 v5;
/
/
rax
__int64 v6;
/
/
rcx
unsigned __int8 v7;
/
/
cl
__int16 v8;
/
/
cx
int
v9;
/
/
ecx
__int64 v10;
/
/
rcx
int
v11;
/
/
ebp
unsigned __int64 v12;
/
/
rbx
unsigned __int8 v13;
/
/
r14
rsize_t v14;
/
/
rdx
__int64 v15;
/
/
rax
__int64 v16;
/
/
rdx
__int64 v17;
/
/
rcx
v3
=
0
;
LODWORD(v4)
=
0
;
LABEL_2:
v5
=
(unsigned
int
)dword_14001FF94;
while
(
2
)
{
v6
=
(unsigned
int
)v4;
v4
=
(unsigned
int
)(v4
+
1
);
switch ( byte_140004040[v6] )
{
case
0xBu
:
v5
=
(unsigned
int
)(v5
+
8
);
dword_14001FF94
=
v5;
continue
;
case
0xCu
:
v8
=
*
(_WORD
*
)&byte_140004040[v4];
v5
=
(unsigned
int
)(v5
-
2
);
dword_14001FF94
=
v5;
LODWORD(v4)
=
v4
+
2
;
*
(_WORD
*
)&byte_14002058F[v5
+
1
]
=
v8;
continue
;
case
0xEu
:
v5
=
(unsigned
int
)(v5
-
1
);
dword_14001FF94
=
v5;
byte_14002058F[(unsigned
int
)v5
+
1
]
=
byte_14002058F[(unsigned
int
)(v5
+
1
)
+
1
];
continue
;
case
0x19u
:
return
*
(_DWORD
*
)&byte_140004040[v4];
case
0x32u
:
v7
=
byte_140004040[v4];
v5
=
(unsigned
int
)(v5
-
1
);
dword_14001FF94
=
v5;
LODWORD(v4)
=
v4
+
1
;
byte_14002058F[v5
+
1
]
=
v7;
continue
;
case
0x49u
:
byte_14002058F[(unsigned
int
)(v5
+
1
)
+
1
]
=
~byte_14002058F[(unsigned
int
)(v5
+
1
)
+
1
];
continue
;
case
0x71u
:
v16
=
(unsigned
int
)(v5
+
1
);
byte_14002058F[v16
+
1
] &
=
byte_14002058F[v5
+
1
];
v5
=
(unsigned
int
)v16;
dword_14001FF94
=
v16;
continue
;
case
0x72u
:
byte_14002058F[v5
+
1
]
=
~byte_14002058F[v5
+
1
];
continue
;
case
0x7Bu
:
v14
=
(char)byte_14002058F[v5
+
1
];
v15
=
(unsigned
int
)(v5
-
7
);
dword_14001FF94
=
v15;
*
(_QWORD
*
)&byte_14002058F[v15
+
1
]
=
Buffer
;
gets_s(
Buffer
, v14);
goto LABEL_2;
case
0x7Cu
:
v5
=
(unsigned
int
)(v5
-
2
);
dword_14001FF94
=
v5;
byte_14002058F[v5
+
1
]
=
byte_14002058F[(unsigned
int
)(v5
+
2
)
+
1
];
byte_14002058F[(unsigned
int
)(v5
+
1
)
+
1
]
=
byte_14002058F[(unsigned
int
)(v5
+
3
)
+
1
];
continue
;
case
0x8Du
:
if
( !byte_14002058F[v5
+
1
] )
LODWORD(v4)
=
*
(_DWORD
*
)&byte_14002058F[v5
+
2
];
v5
=
(unsigned
int
)(v5
+
5
);
dword_14001FF94
=
v5;
continue
;
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
上传的附件: