-
-
[原创]看雪.深信服 2021 KCTF 春季赛 第六题 寻回宝剑
-
发表于: 2021-5-19 00:15 7377
-
IDA打开,发现代码加了混淆,但规律性很强。
解混淆是一个迭代的过程:
首先注意到一个反复出现的代码片段:
这段代码的效果等同于push一个地址,其值等于pop rax
指令的地址异或上xor
指令里的常量,是一个能够静态计算出来的确定的值。(注意文件头的IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE
没有置位,程序没有开启动态基址,因此xor
运算后的地址才有效)
这样的代码片段可以统一替换为VIRTUAL push XXXXYYYY
(VIRTUAL前缀是人为加的,为了区分程序里真实的push指令)
替换之后,程序里出现大量的
等同于一条无条件跳转指令VIRTUAL jmp XXXXYYYY
对同一个寄存器连续的push和pop,可以直接去除
对VIRTUAL jmp
连接的代码块重新排序让它们顺序连在一起,从而省略掉无用的VIRTUAL jmp
指令。在完成这一步后,重做第3步。
出现了一个新的模式(这个模式只有在前4步都做完之后才能看出来,因为这些指令在源程序中并不是连续的)
与第1步类似,整个片段等价为push一个常量。可以将整个片段替换为VIRTUAL push XXXXYYYY
,然后重做第2步
反复迭代以上的步骤,重点是指令块的重新排序(第4步),每次重新排序后再次搜索第1、2、3、5步的代码模式做替换。直到代码不再能化简,打印输出即可。
由于混淆模式非常固定,所以先用objdump工具获得反汇编:objdump -d -M intel KCTF.exe > KCTF_objdump.txt
,然后对字符串做操作。
(更好的方法应该使用Capstone这样的反汇编引擎,可惜不太熟悉)
代码如下:(与上面的步骤描述有少许不同,但主要思路是一致的)
简单解释一下代码:
其实deobfuscation2之后得到的代码就已经完全没有了混淆,但是注意到里面出现了孤立的VIRTUAL push XXXXXXXX
指令,且若干条指令之后一定会在栈平衡的情况下出现一个ret
指令。
这种模式其实是函数调用,其中VIRTUAL push XXXXXXXX
的常量是压栈的返回地址,即在原始函数中的真实的下一条指令。
deobfuscation2的输出结果是深入调用函数内部后的指令序列;recognize_function函数对这种情况进行了处理,从而恢复出“完整”的原始函数。(缺陷是,由于Block不是真正意义上的基本块,所以原始程序里的条件分支只能看到一条路径,不过问题不大,对另一条路径的起始地址也调用一次该函数即可)
有了解混淆脚本,现在可以分析程序逻辑了
从start函数开始(recognize_function(0x14005FE4C)),找出真正的main函数位于0x140083814
(可以自己写一个小程序再反汇编与之对比)
(在deobfuscation2(0x14005FE4C)的输出中看到调用了很多反调试函数,应该是在main之前的initterm中调用的。从后面的算法看,本题无需动态调试。如果需要调试,只要程序启动后再附加调试器即可)
main函数很长,截取若干个片段如下:(recognize_function的输出)
片段1
可以看出,真正的输入长度为84,下一阶段的检查逻辑在0x1400356b1
片段2
合法的输入字符有42种:0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ+-*/%=
片段3
输入的2个字符被转换为1个字符,转换方式是先转为[0,41]的数字(对应前面的合法字符列表的索引),然后第一个数字*42再加第二个数字
片段4
把输入的84个字符转换为42个整数,要求严格单调递增
片段5
前面得到的42个整数,分别除以42,取整作为横坐标,取余作为纵坐标,要求横纵坐标分别都没有重复(从这里看出,输入的84个字符其实是42个坐标,横纵交替)
片段6
最复杂的检查,二重循环遍历点对,计算纵坐标之差和横坐标之差(如果纵坐标之差为负则两个值都取反),然后计算后者*42+前者,要求这个值不重复(实际上是要求,不存在位置相对值一样的点对)
片段7
最后一处检查,限定了输入的前28个字符(其实依次是42*42棋盘的前14行的点的坐标,每行一个)
检查逻辑有点像N皇后,只不过斜线规则改成了更复杂的点对相对位置检查
求解:回溯法爆破(参考了网上的一段代码),修改了验证规则
算法性能不高,cpython跑不出来,换用pypy3跑了17分钟才出答案
最终答案:
02152S3X4Z5Q6C7T819/ADB%C*DLEIFUG3HRIHJ6K7L0MBNKOJPPQ=RNS+TEUOVWWGXYYMZ9+4-8*F/-%V=A
push rax
push rax
pushf
call $
+
5
pop rax
xor rax,XXXXXXXX
mov QWORD PTR [rsp
+
0x10
],rax
popf
pop rax
push rax
push rax
pushf
call $
+
5
pop rax
xor rax,XXXXXXXX
mov QWORD PTR [rsp
+
0x10
],rax
popf
pop rax
VIRTUAL push XXXXYYYY
ret
VIRTUAL push XXXXYYYY
ret
push AAA
pop AAA
push AAA
pop AAA
push AAA
push BBB
pop BBB
pop AAA
push AAA
push BBB
pop BBB
pop AAA
push rax
push rax
pushf
VIRTUAL push XXXXXXXX
pop rax
add rax,YYYYYYYY
mov QWORD PTR [rsp
+
0x10
],rax
popf
pop rax
push rax
push rax
pushf
VIRTUAL push XXXXXXXX
pop rax
add rax,YYYYYYYY
mov QWORD PTR [rsp
+
0x10
],rax
popf
pop rax
class
Instruction:
__slots__
=
[
"va"
,
"s"
]
def
__init__(
self
, va, s):
self
.va
=
va
self
.s
=
s
def
__str__(
self
):
return
hex
(
self
.va)
+
"\t"
+
self
.s
class
Block:
__slots__
=
[
"startva"
,
"jmpva"
,
"insts"
]
def
__init__(
self
):
self
.startva
=
None
self
.jmpva
=
None
self
.insts
=
[]
def
__str__(
self
):
r
=
""
r
+
=
f
"; {hex(self.startva)}, {hex(self.jmpva) if self.jmpva else None}:\n"
for
inst
in
self
.insts:
r
+
=
str
(inst)
+
"\n"
return
r
def
simplify1(
self
):
i
=
0
while
(i <
len
(
self
.insts)):
tmp
=
self
.insts[i].s
i
+
=
1
if
tmp.split()[
0
]
=
=
"push"
and
i <
len
(
self
.insts):
tmp2
=
self
.insts[i].s
i
+
=
1
if
tmp2.split()[
0
]
=
=
"pop"
and
tmp2.split()[
1
]
=
=
tmp.split()[
1
]:
"push xxx ; pop xxx"
i
-
=
2
if
self
.startva
=
=
0x14007def2
:
print
(
"xxx"
,
self
.insts[i])
self
.insts.pop(i)
self
.insts.pop(i)
else
:
i
-
=
1
def
simplify2(
self
):
i
=
0
while
i
+
8
<
len
(
self
.insts):
if
self
.insts[i].s.startswith(
"push rax"
) \
and
self
.insts[i
+
1
].s.startswith(
"push rax"
) \
and
self
.insts[i
+
2
].s.startswith(
"pushf"
) \
and
self
.insts[i
+
3
].s.startswith(
"call"
) \
and
self
.insts[i
+
4
].s.startswith(
"pop rax"
) \
and
self
.insts[i
+
5
].s.startswith(
"xor rax,"
) \
and
self
.insts[i
+
6
].s.startswith(
"mov QWORD PTR [rsp+0x10],rax"
) \
and
self
.insts[i
+
7
].s.startswith(
"popf"
) \
and
self
.insts[i
+
8
].s.startswith(
"pop rax"
):
const1
=
self
.insts[i
+
4
].va
tmp1
=
self
.insts[i
+
3
].s
assert
(
int
(tmp1.split()[
1
],
16
)
=
=
const1)
tmp2
=
self
.insts[i
+
5
].s
const2
=
int
(tmp2[tmp2.index(
","
)
+
1
:],
16
)
newinst
=
Instruction(
self
.insts[i].va, f
"VIRTUAL push {hex(const1^const2)}"
)
for
_
in
range
(
9
):
self
.insts.pop(i)
self
.insts.insert(i, newinst)
i
+
=
1
def
simplify3(
self
):
i
=
0
while
i
+
8
<
len
(
self
.insts):
if
self
.insts[i].s.startswith(
"push rax"
) \
and
self
.insts[i
+
1
].s.startswith(
"push rax"
) \
and
self
.insts[i
+
2
].s.startswith(
"pushf"
) \
and
self
.insts[i
+
3
].s.startswith(
"VIRTUAL push"
) \
and
self
.insts[i
+
4
].s.startswith(
"pop rax"
) \
and
self
.insts[i
+
5
].s.startswith(
"add rax,"
) \
and
self
.insts[i
+
6
].s.startswith(
"mov QWORD PTR [rsp+0x10],rax"
) \
and
self
.insts[i
+
7
].s.startswith(
"popf"
) \
and
self
.insts[i
+
8
].s.startswith(
"pop rax"
):
tmp1
=
self
.insts[i
+
3
].s
const1
=
int
(tmp1.split()[
2
],
16
)
tmp2
=
self
.insts[i
+
5
].s
const2
=
int
(tmp2[tmp2.index(
","
)
+
1
:],
16
)
newinst
=
Instruction(
self
.insts[i].va, f
"VIRTUAL push {hex((const1+const2) & 0xffffffffffffffff)}"
)
for
_
in
range
(
9
):
self
.insts.pop(i)
self
.insts.insert(i, newinst)
i
+
=
1
def
simplify4(
self
):
if
len
(
self
.insts) >
=
2
:
if
self
.insts[
-
2
].s.startswith(
"VIRTUAL push"
) \
and
self
.insts[
-
1
].s.startswith(
"ret"
):
tmp1
=
self
.insts[
-
2
].s
self
.jmpva
=
int
(tmp1.split()[
2
],
16
)
self
.insts.pop(
-
1
)
self
.insts.pop(
-
1
)
def
simplify(
self
):
lastlen
=
0x7fffffff
while
len
(
self
.insts) < lastlen:
#print("aa", len(self.insts), lastlen)
lastlen
=
len
(
self
.insts)
self
.simplify1()
self
.simplify1()
self
.simplify2()
self
.simplify3()
self
.simplify4()
with
open
(
"KCTF_objdump.txt"
,
"r"
) as f:
lines
=
f.readlines()
allinsts
=
[]
instaddr2index
=
{}
def
initialize():
global
allinsts
global
instaddr2index
for
line
in
lines:
tokens
=
line.split(
"\t"
)
if
len
(tokens)
=
=
3
:
va
=
int
(tokens[
0
].rstrip(
":"
),
16
)
s
=
tokens[
2
].strip()
if
s !
=
"int3"
:
#print(hex(addr), s)
inst
=
Instruction(va, s)
allinsts.append(inst)
instaddr2index[va]
=
len
(allinsts)
-
1
def
searchblock(va):
global
allinsts
global
instaddr2index
bb
=
Block()
bb.startva
=
va
i
=
instaddr2index[va]
while
True
:
inst
=
allinsts[i]
tokens
=
inst.s.split()
bb.insts.append(inst)
if
(tokens[
0
]
=
=
"ret"
):
break
i
+
=
1
return
bb
def
mergeblocklist(blocklist):
bbb
=
Block()
bbb.startva
=
blocklist[
0
].startva
bbb.jmpva
=
blocklist[
-
1
].jmpva
bbb.insts
=
[]
for
i
in
range
(
len
(blocklist)):
bb
=
blocklist[i]
bbb.insts.extend(bb.insts)
return
bbb
def
deobfuscation1(nextva):
blocklist
=
[]
seenva
=
set
()
while
nextva
and
nextva
not
in
seenva:
seenva.add(nextva)
#print(hex(nextva))
bb
=
searchblock(nextva)
bb.simplify()
#print(bb)
blocklist.append(bb)
nextva
=
bb.jmpva
bbb
=
mergeblocklist(blocklist)
# print(bbb)
bbb.simplify()
# print(bbb)
return
bbb
# mostly single instruction
def
deobfuscation2(nextva):
blocklist
=
[]
seenva
=
set
()
while
nextva
and
nextva
not
in
seenva:
seenva.add(nextva)
bbb
=
deobfuscation1(nextva)
blocklist.append(bbb)
nextva
=
bbb.jmpva
bbbb
=
mergeblocklist(blocklist)
# print(bbbb)
return
bbbb
# mostly deep first block instructions
def
recognize_function(va):
# notice: must do block.simplify4 before do this
blocklist
=
[]
seenva
=
set
()
while
va
and
va
not
in
seenva:
#print(hex(va))
seenva.add(va)
block
=
deobfuscation2(va)
newblock
=
Block()
newblock.startva
=
block.startva
newblock.jmpva
=
block.jmpva
newblock.insts
=
[]
i
=
0
while
i <
len
(block.insts):
#print(i)
inst
=
block.insts[i]
if
inst.s.startswith(
"VIRTUAL push"
):
const1
=
int
(inst.s.split()[
2
],
16
)
newblock.insts.append(Instruction(inst.va,f
"VIRTUAL call {hex(block.insts[i+1].va)}"
))
newblock.jmpva
=
const1
break
else
:
newblock.insts.append(inst)
i
+
=
1
#print("newblock:", newblock)
blocklist.append(newblock)
va
=
newblock.jmpva
bbbbb
=
mergeblocklist(blocklist)
print
(bbbbb)
return
bbbbb
initialize()
#deobfuscation2(0x14005FE4C) # start
#recognize_function(0x14005FE4C) # start:part1
#recognize_function(0x1400bf93f) # start:part2
#recognize_function(0x140083814) # main
class
Instruction:
__slots__
=
[
"va"
,
"s"
]
def
__init__(
self
, va, s):
self
.va
=
va
self
.s
=
s
def
__str__(
self
):
return
hex
(
self
.va)
+
"\t"
+
self
.s
class
Block:
__slots__
=
[
"startva"
,
"jmpva"
,
"insts"
]
def
__init__(
self
):
self
.startva
=
None
self
.jmpva
=
None
self
.insts
=
[]
def
__str__(
self
):
r
=
""
r
+
=
f
"; {hex(self.startva)}, {hex(self.jmpva) if self.jmpva else None}:\n"
for
inst
in
self
.insts:
r
+
=
str
(inst)
+
"\n"
return
r
def
simplify1(
self
):
i
=
0
while
(i <
len
(
self
.insts)):
tmp
=
self
.insts[i].s
i
+
=
1
if
tmp.split()[
0
]
=
=
"push"
and
i <
len
(
self
.insts):
tmp2
=
self
.insts[i].s
i
+
=
1
if
tmp2.split()[
0
]
=
=
"pop"
and
tmp2.split()[
1
]
=
=
tmp.split()[
1
]:
"push xxx ; pop xxx"
i
-
=
2
if
self
.startva
=
=
0x14007def2
:
print
(
"xxx"
,
self
.insts[i])
self
.insts.pop(i)
self
.insts.pop(i)
else
:
i
-
=
1
def
simplify2(
self
):
i
=
0
while
i
+
8
<
len
(
self
.insts):
if
self
.insts[i].s.startswith(
"push rax"
) \
and
self
.insts[i
+
1
].s.startswith(
"push rax"
) \
and
self
.insts[i
+
2
].s.startswith(
"pushf"
) \
and
self
.insts[i
+
3
].s.startswith(
"call"
) \
and
self
.insts[i
+
4
].s.startswith(
"pop rax"
) \
and
self
.insts[i
+
5
].s.startswith(
"xor rax,"
) \
and
self
.insts[i
+
6
].s.startswith(
"mov QWORD PTR [rsp+0x10],rax"
) \
and
self
.insts[i
+
7
].s.startswith(
"popf"
) \
and
self
.insts[i
+
8
].s.startswith(
"pop rax"
):
const1
=
self
.insts[i
+
4
].va
tmp1
=
self
.insts[i
+
3
].s
assert
(
int
(tmp1.split()[
1
],
16
)
=
=
const1)
tmp2
=
self
.insts[i
+
5
].s
const2
=
int
(tmp2[tmp2.index(
","
)
+
1
:],
16
)
newinst
=
Instruction(
self
.insts[i].va, f
"VIRTUAL push {hex(const1^const2)}"
)
for
_
in
range
(
9
):
self
.insts.pop(i)
self
.insts.insert(i, newinst)
i
+
=
1
def
simplify3(
self
):
i
=
0
while
i
+
8
<
len
(
self
.insts):
if
self
.insts[i].s.startswith(
"push rax"
) \
and
self
.insts[i
+
1
].s.startswith(
"push rax"
) \
and
self
.insts[i
+
2
].s.startswith(
"pushf"
) \
and
self
.insts[i
+
3
].s.startswith(
"VIRTUAL push"
) \
and
self
.insts[i
+
4
].s.startswith(
"pop rax"
) \
and
self
.insts[i
+
5
].s.startswith(
"add rax,"
) \
and
self
.insts[i
+
6
].s.startswith(
"mov QWORD PTR [rsp+0x10],rax"
) \
and
self
.insts[i
+
7
].s.startswith(
"popf"
) \
and
self
.insts[i
+
8
].s.startswith(
"pop rax"
):
tmp1
=
self
.insts[i
+
3
].s
const1
=
int
(tmp1.split()[
2
],
16
)
tmp2
=
self
.insts[i
+
5
].s
const2
=
int
(tmp2[tmp2.index(
","
)
+
1
:],
16
)
newinst
=
Instruction(
self
.insts[i].va, f
"VIRTUAL push {hex((const1+const2) & 0xffffffffffffffff)}"
)
for
_
in
range
(
9
):
self
.insts.pop(i)
self
.insts.insert(i, newinst)
i
+
=
1
def
simplify4(
self
):
if
len
(
self
.insts) >
=
2
:
if
self
.insts[
-
2
].s.startswith(
"VIRTUAL push"
) \
and
self
.insts[
-
1
].s.startswith(
"ret"
):
tmp1
=
self
.insts[
-
2
].s
self
.jmpva
=
int
(tmp1.split()[
2
],
16
)
self
.insts.pop(
-
1
)
self
.insts.pop(
-
1
)
def
simplify(
self
):
lastlen
=
0x7fffffff
while
len
(
self
.insts) < lastlen:
#print("aa", len(self.insts), lastlen)
lastlen
=
len
(
self
.insts)
self
.simplify1()
self
.simplify1()
self
.simplify2()
self
.simplify3()
self
.simplify4()
with
open
(
"KCTF_objdump.txt"
,
"r"
) as f:
lines
=
f.readlines()
allinsts
=
[]
instaddr2index
=
{}
def
initialize():
global
allinsts
global
instaddr2index
for
line
in
lines:
tokens
=
line.split(
"\t"
)
if
len
(tokens)
=
=
3
:
va
=
int
(tokens[
0
].rstrip(
":"
),
16
)
s
=
tokens[
2
].strip()
if
s !
=
"int3"
:
#print(hex(addr), s)
inst
=
Instruction(va, s)
allinsts.append(inst)
instaddr2index[va]
=
len
(allinsts)
-
1
def
searchblock(va):
global
allinsts
global
instaddr2index
bb
=
Block()
bb.startva
=
va
i
=
instaddr2index[va]
while
True
:
inst
=
allinsts[i]
tokens
=
inst.s.split()
bb.insts.append(inst)
if
(tokens[
0
]
=
=
"ret"
):
break
i
+
=
1
return
bb
def
mergeblocklist(blocklist):
bbb
=
Block()
bbb.startva
=
blocklist[
0
].startva
bbb.jmpva
=
blocklist[
-
1
].jmpva
bbb.insts
=
[]
for
i
in
range
(
len
(blocklist)):
bb
=
blocklist[i]
bbb.insts.extend(bb.insts)
return
bbb
def
deobfuscation1(nextva):
blocklist
=
[]
seenva
=
set
()
while
nextva
and
nextva
not
in
seenva:
seenva.add(nextva)
#print(hex(nextva))
bb
=
searchblock(nextva)
bb.simplify()
#print(bb)
blocklist.append(bb)
nextva
=
bb.jmpva
bbb
=
mergeblocklist(blocklist)
# print(bbb)
bbb.simplify()
# print(bbb)
return
bbb
# mostly single instruction
def
deobfuscation2(nextva):
blocklist
=
[]
seenva
=
set
()
while
nextva
and
nextva
not
in
seenva:
seenva.add(nextva)
bbb
=
deobfuscation1(nextva)
blocklist.append(bbb)
nextva
=
bbb.jmpva
bbbb
=
mergeblocklist(blocklist)
# print(bbbb)
return
bbbb
# mostly deep first block instructions
def
recognize_function(va):
# notice: must do block.simplify4 before do this
blocklist
=
[]
seenva
=
set
()
while
va
and
va
not
in
seenva:
#print(hex(va))
seenva.add(va)
block
=
deobfuscation2(va)
newblock
=
Block()
newblock.startva
=
block.startva
newblock.jmpva
=
block.jmpva
newblock.insts
=
[]
i
=
0
while
i <
len
(block.insts):
#print(i)
inst
=
block.insts[i]
if
inst.s.startswith(
"VIRTUAL push"
):
const1
=
int
(inst.s.split()[
2
],
16
)
newblock.insts.append(Instruction(inst.va,f
"VIRTUAL call {hex(block.insts[i+1].va)}"
))
newblock.jmpva
=
const1
break
else
:
newblock.insts.append(inst)
i
+
=
1
#print("newblock:", newblock)
blocklist.append(newblock)
va
=
newblock.jmpva
bbbbb
=
mergeblocklist(blocklist)
print
(bbbbb)
return
bbbbb
initialize()
#deobfuscation2(0x14005FE4C) # start
#recognize_function(0x14005FE4C) # start:part1
#recognize_function(0x1400bf93f) # start:part2
#recognize_function(0x140083814) # main
0x14000f17c
VIRTUAL call
0x140026de8
# call std::cin
0x14001eb47
lea rcx,[rsp
+
0x1010
]
0x14003a798
lea rdx,[rip
+
0xfffffffffffc9ddf
]
# *** 0x14000457e, char[] "1743"
0x1400beaab
mov QWORD PTR [rsp
+
0x50
],rax
0x140002c25
VIRTUAL call
0x1400d4a33
# *** 140004C88, strcmp with "1743" # 0x1400d4a33
0x1400f1dda
movsxd rcx,eax
0x14009f9b9
cmp
rcx,
0x0
0x1400a988a
jne
0x1400a98a3
# 0x1400dab0e
0x14009954a
lea rcx,[rip
+
0xfffffffffff6af6d
]
# 0x1400044be # " >>> 阁下的数学功底十分扎实,只可惜与在下的绝世武学无缘,请回吧。"
0x14002587c
VIRTUAL call
0x1400cd482
0x1400dab0e
lea rcx,[rsp
+
0x1010
]
0x14008475a
VIRTUAL call
0x140050476
# get input string length
0x140083333
cmp
rax,
0x54
# 84
0x140035698
je
0x1400356b1
0x140048e00
lea rcx,[rip
+
0xfffffffffffbb695
]
# 0x14000449c # " >>> 阁下的数学成绩堪忧,请回吧。"
0x14000f17c
VIRTUAL call
0x140026de8
# call std::cin
0x14001eb47
lea rcx,[rsp
+
0x1010
]
0x14003a798
lea rdx,[rip
+
0xfffffffffffc9ddf
]
# *** 0x14000457e, char[] "1743"
0x1400beaab
mov QWORD PTR [rsp
+
0x50
],rax
0x140002c25
VIRTUAL call
0x1400d4a33
# *** 140004C88, strcmp with "1743" # 0x1400d4a33
0x1400f1dda
movsxd rcx,eax
0x14009f9b9
cmp
rcx,
0x0
0x1400a988a
jne
0x1400a98a3
# 0x1400dab0e
0x14009954a
lea rcx,[rip
+
0xfffffffffff6af6d
]
# 0x1400044be # " >>> 阁下的数学功底十分扎实,只可惜与在下的绝世武学无缘,请回吧。"
0x14002587c
VIRTUAL call
0x1400cd482
0x1400dab0e
lea rcx,[rsp
+
0x1010
]
0x14008475a
VIRTUAL call
0x140050476
# get input string length
0x140083333
cmp
rax,
0x54
# 84
0x140035698
je
0x1400356b1
0x140048e00
lea rcx,[rip
+
0xfffffffffffbb695
]
# 0x14000449c # " >>> 阁下的数学成绩堪忧,请回吧。"
;
0x1400877ad
,
None
:
0x1400877ad
push rax
0x1400da463
mov BYTE PTR [rsp
+
0x7
],cl
0x1400254a5
movsx eax,BYTE PTR [rsp
+
0x7
]
0x140027b39
cmp
eax,
0x30
0x140087ceb
jl
0x140087d04
# 0x140045036
0x1400d1b0f
movsx eax,BYTE PTR [rsp
+
0x7
]
0x1400cbfad
cmp
eax,
0x39
0x140032877
mov cl,
0x1
0x14004cbd4
mov BYTE PTR [rsp
+
0x6
],cl
0x14005134f
jle
0x140051368
0x140045036
movsx eax,BYTE PTR [rsp
+
0x7
]
0x1400a27a9
cmp
eax,
0x41
0x1400db7db
jl
0x1400db7f4
0x1400dabed
movsx eax,BYTE PTR [rsp
+
0x7
]
0x1400a07d9
cmp
eax,
0x5a
0x1400ed537
mov cl,
0x1
0x140025ead
mov BYTE PTR [rsp
+
0x6
],cl
0x140032ada
jle
0x140032af3
# 0x14005e3af
0x1400388fa
movsx eax,BYTE PTR [rsp
+
0x7
]
0x140045713
cmp
eax,
0x2b
0x1400779b8
mov cl,
0x1
0x1400ca53a
mov BYTE PTR [rsp
+
0x6
],cl
0x1400bdc5a
je
0x1400bdc73
# 0x14005e3af
0x1400b40d3
movsx eax,BYTE PTR [rsp
+
0x7
]
0x140071b51
cmp
eax,
0x2d
0x140031fa6
mov cl,
0x1
0x1400a85c9
mov BYTE PTR [rsp
+
0x6
],cl
0x140021689
je
0x1400216a2
0x140059269
movsx eax,BYTE PTR [rsp
+
0x7
]
0x1400f5da9
cmp
eax,
0x2a
0x140067a65
mov cl,
0x1
0x1400477a2
mov BYTE PTR [rsp
+
0x6
],cl
0x14005d81b
je
0x14005d834
0x140082dcc
movsx eax,BYTE PTR [rsp
+
0x7
]
0x140014c52
cmp
eax,
0x2f
0x1400afc6d
mov cl,
0x1
0x14006091f
mov BYTE PTR [rsp
+
0x6
],cl
0x1400020ec
je
0x140002105
0x1400dde99
movsx eax,BYTE PTR [rsp
+
0x7
]
0x140081c7a
cmp
eax,
0x25
0x1400f43b2
mov cl,
0x1
0x1400200b9
mov BYTE PTR [rsp
+
0x6
],cl
0x1400819ac
je
0x1400819c5
0x140085a98
movsx eax,BYTE PTR [rsp
+
0x7
]
0x140003a93
cmp
eax,
0x3d
0x1400f9bac
sete cl
0x140080797
mov BYTE PTR [rsp
+
0x6
],cl
0x14005e3af
mov al,BYTE PTR [rsp
+
0x6
]
0x14006e388
and
al,
0x1
0x1400bd7f2
movzx eax,al
0x1400d73bf
pop rcx
0x140095d39
ret
;
0x1400877ad
,
None
:
0x1400877ad
push rax
0x1400da463
mov BYTE PTR [rsp
+
0x7
],cl
0x1400254a5
movsx eax,BYTE PTR [rsp
+
0x7
]
0x140027b39
cmp
eax,
0x30
0x140087ceb
jl
0x140087d04
# 0x140045036
0x1400d1b0f
movsx eax,BYTE PTR [rsp
+
0x7
]
0x1400cbfad
cmp
eax,
0x39
0x140032877
mov cl,
0x1
0x14004cbd4
mov BYTE PTR [rsp
+
0x6
],cl
0x14005134f
jle
0x140051368
0x140045036
movsx eax,BYTE PTR [rsp
+
0x7
]
0x1400a27a9
cmp
eax,
0x41
0x1400db7db
jl
0x1400db7f4
0x1400dabed
movsx eax,BYTE PTR [rsp
+
0x7
]
0x1400a07d9
cmp
eax,
0x5a
0x1400ed537
mov cl,
0x1
0x140025ead
mov BYTE PTR [rsp
+
0x6
],cl
0x140032ada
jle
0x140032af3
# 0x14005e3af
0x1400388fa
movsx eax,BYTE PTR [rsp
+
0x7
]
0x140045713
cmp
eax,
0x2b
0x1400779b8
mov cl,
0x1
0x1400ca53a
mov BYTE PTR [rsp
+
0x6
],cl
0x1400bdc5a
je
0x1400bdc73
# 0x14005e3af
0x1400b40d3
movsx eax,BYTE PTR [rsp
+
0x7
]
0x140071b51
cmp
eax,
0x2d
0x140031fa6
mov cl,
0x1
0x1400a85c9
mov BYTE PTR [rsp
+
0x6
],cl
0x140021689
je
0x1400216a2
0x140059269
movsx eax,BYTE PTR [rsp
+
0x7
]
0x1400f5da9
cmp
eax,
0x2a
0x140067a65
mov cl,
0x1
0x1400477a2
mov BYTE PTR [rsp
+
0x6
],cl
0x14005d81b
je
0x14005d834
0x140082dcc
movsx eax,BYTE PTR [rsp
+
0x7
]
0x140014c52
cmp
eax,
0x2f
0x1400afc6d
mov cl,
0x1
0x14006091f
mov BYTE PTR [rsp
+
0x6
],cl
0x1400020ec
je
0x140002105
0x1400dde99
movsx eax,BYTE PTR [rsp
+
0x7
]
0x140081c7a
cmp
eax,
0x25
0x1400f43b2
mov cl,
0x1
0x1400200b9
mov BYTE PTR [rsp
+
0x6
],cl
0x1400819ac
je
0x1400819c5
0x140085a98
movsx eax,BYTE PTR [rsp
+
0x7
]
0x140003a93
cmp
eax,
0x3d
0x1400f9bac
sete cl
0x140080797
mov BYTE PTR [rsp
+
0x6
],cl
0x14005e3af
mov al,BYTE PTR [rsp
+
0x6
]
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!