-
-
[原创] KCTF 2023 第七题 wp - 98k
-
发表于: 2023-9-17 10:27 11196
-
main 函数挺大,不过没加混淆,其他函数都是加了混淆的。看看混淆模式后写个脚本提取指令去混淆:
得到指令后编译为二进制:
最后在 ida 里新加一个段,起始地址 0x800000 ,将指令放进去
得到的这些函数再手动处理一下多余的指令,逻辑就基本上出来了。
main 前面大部分逻辑都是与用户名相关的,直接跳到最后的判断逻辑:
输入 password 后 16 转成字节数组,传入魔改的 aes 加密,之后又用魔改的 des 加密 22 轮,再用个简单的虚拟机加密,再和最终的目标值比较。密钥和比较的值都应该是固定的或者只与用户名有关,所以调试拿值就行。
aes 实现方式:
多线程但是用一个全局锁控制流程,只有一种执行方式。部分 AES 的实现做了魔改,改一下 aes 板子即可
des 加密(实际上是解密):
与标准的 DES 中的常量相比, S 改了两个值, PC2 改了一个值。抄写出来得到:
最后还有个简单的虚拟机的形式的加密,抄写出来写逆:
将最终结果以及各个密钥动调拿出来,写逆得到密码:
#!/usr/bin/env python3
# import ida_bytes
import
keystone
import
capstone
def
set_x86():
global
ks, cs
ks
=
keystone.Ks(keystone.KS_ARCH_X86, keystone.KS_MODE_32)
cs
=
capstone.Cs(capstone.CS_ARCH_X86, capstone.CS_MODE_32)
set_x86()
def
asm(code, addr
=
0
):
return
bytes(ks.asm(code, addr)[
0
])
def
disasm(code, addr
=
0
):
for
i
in
cs.disasm(code, addr):
return
(
'%s %s'
%
(i.mnemonic, i.op_str))
def
ins_len(code):
return
len
(
next
(cs.disasm(code,
0
)).bytes)
def
to_char(x):
assert
0
<
=
x <
0x100
if
x >
=
0x80
: x
-
=
0x100
return
x
def
to_int(b):
assert
len
(b)
=
=
4
x
=
int
.from_bytes(b,
'little'
)
if
x >
=
1
<<
31
: x
-
=
1
<<
32
return
x
def
make_label(i):
return
'_%x'
%
(i
+
ob_start)
ob_start
=
0x403AC0
ob_end
=
0x617DE0
def
extract_block(ins, i):
# print('extract block: 0x%x' % (ob_start + i))
is_zero
=
False
ebx_ebp
=
False
push_eax
=
False
push_ebx
=
False
push_eax_i
=
None
push_ebx_i
=
None
eax_value
=
None
eax_value_i
=
None
eax_value_2
=
None
eax_value_2_i
=
None
ebx_value
=
None
ebx_value_i
=
None
test_eax
=
False
push_value
=
None
last_i
=
None
while
True
:
if
i
in
ins:
if
last_i:
ins[last_i]
+
=
'\njmp %s'
%
make_label(i)
return
[]
# print(hex(i + ob_start))
if
data[i]
=
=
0x0f
and
0x80
<
=
data[i
+
1
] <
0x90
:
# j?? dword
offset
=
to_int(data[i
+
2
: i
+
6
])
if
data[i
+
6
]
=
=
0x0f
and
data[i
+
7
]
=
=
data[i
+
1
] ^
1
and
\
offset
=
=
6
+
to_int(data[i
+
8
: i
+
12
]):
ins[i]
=
'jmp %s'
%
make_label(i
+
6
+
offset)
last_i
=
None
i
+
=
6
+
offset
elif
data[i
+
1
]
=
=
0x84
and
is_zero:
# jz
ins[i]
=
'jmp %s'
%
make_label(i
+
6
+
offset)
last_i
=
None
i
+
=
6
+
offset
elif
data[i
+
1
]
=
=
0x85
and
test_eax:
# jnz
ins[i]
=
'jmp %s'
%
make_label(i
+
6
+
offset)
last_i
=
None
i
+
=
6
+
offset
else
:
mnem
=
disasm(data[i: i
+
6
]).split(
' '
)[
0
]
ins[i]
=
'%s %s\njmp %s'
%
(mnem, make_label(i
+
6
+
offset), make_label(i
+
6
))
return
[i
+
6
, i
+
6
+
offset]
elif
data[i]
=
=
0x3b
and
data[i
+
1
]
=
=
0xc0
:
# cmp eax, eax
is_zero
=
True
test_eax
=
False
ins[i]
=
'cmp eax, eax'
last_i
=
i
i
+
=
2
elif
data[i]
=
=
0x3b
and
data[i
+
1
]
=
=
0xdb
:
# cmp ebx, ebx
is_zero
=
True
test_eax
=
False
ins[i]
=
'cmp ebx, ebx'
last_i
=
i
i
+
=
2
elif
data[i]
=
=
0x50
and
eax_value:
# push eax
push_eax_i
=
i
push_eax
=
True
ins[i]
=
'push eax'
last_i
=
i
i
+
=
1
elif
data[i]
=
=
0x53
:
# push ebx
push_ebx_i
=
i
push_ebx
=
True
ins[i]
=
'push ebx'
last_i
=
i
i
+
=
1
elif
data[i]
=
=
0x68
:
# push dword
value
=
to_int(data[i
+
1
: i
+
5
])
if
data[i
+
5
]
=
=
0xc3
:
# ret
ins[i]
=
'jmp %s'
%
make_label(value
-
ob_start)
last_i
=
None
i
=
value
-
ob_start
else
:
push_value
=
value
push_value_i
=
i
ins[i]
=
'push 0x%x'
%
push_value
last_i
=
i
i
+
=
5
elif
0x70
<
=
data[i] <
0x80
:
# j?? short
offset
=
to_char(data[i
+
1
])
if
data[i
+
2
]
=
=
data[i] ^
1
and
offset
=
=
2
+
to_char(data[i
+
3
]):
ins[i]
=
'jmp %s'
%
make_label(i
+
2
+
offset)
last_i
=
None
i
+
=
2
+
offset
elif
data[i]
=
=
0x74
and
is_zero:
# jz short
ins[i]
=
'jmp %s'
%
make_label(i
+
2
+
offset)
last_i
=
None
i
+
=
2
+
offset
elif
data[i]
=
=
0x75
and
test_eax:
# jnz short
ins[i]
=
'jmp %s'
%
make_label(i
+
2
+
offset)
last_i
=
None
i
+
=
2
+
offset
else
:
mnem
=
disasm(data[i: i
+
2
]).split(
' '
)[
0
]
ins[i]
=
'%s %s\njmp %s'
%
(mnem, make_label(i
+
2
+
offset), make_label(i
+
2
))
return
[i
+
2
, i
+
2
+
offset]
elif
data[i]
=
=
0x85
and
data[i
+
1
]
=
=
0xc0
and
eax_value:
# test eax, eax
if
eax_value_2 !
=
None
:
assert
eax_value_2 !
=
0
# call_dst
else
:
pass
test_eax
=
True
is_zero
=
False
ins[i]
=
'test eax, eax'
last_i
=
i
i
+
=
2
elif
data[i]
=
=
0x87
and
data[i
+
1
]
=
=
0x1c
and
data[i
+
2
]
=
=
0x24
and
push_ebx:
# xchg ebx, [esp]
if
ebx_value:
assert
not
ebx_ebp
ins[push_ebx_i]
=
'nop'
ins[ebx_value_i]
=
'push 0x%x'
%
ebx_value
ins[i]
=
'nop'
push_ebx
=
False
push_value
=
ebx_value
ebx_value
=
None
push_value_i
=
ebx_value_i
elif
ebx_ebp:
ins[push_ebx_i]
=
'push ebp'
ins[ebx_ebp_i]
=
'nop'
ins[i]
=
'nop'
push_ebx
=
False
ebx_ebp
=
False
else
:
ins[i]
=
'xchg ebx, [esp]'
push_ebx
=
False
last_i
=
i
i
+
=
3
elif
data[i]
=
=
0x8b
and
data[i
+
1
]
=
=
0xdd
and
push_ebx:
# mov ebx, ebp
ins[i]
=
'mov ebx, ebp'
last_i
=
i
ebx_ebp_i
=
i
ebx_ebp
=
True
i
+
=
2
elif
data[i]
=
=
0x90
:
# nop
ins[i]
=
'nop'
last_i
=
i
i
+
=
1
elif
data[i]
=
=
0xb8
:
# mov eax, dword
value
=
to_int(data[i
+
1
: i
+
5
])
ins[i]
=
'mov eax, 0x%x'
%
value
last_i
=
i
if
not
eax_value:
eax_value_i
=
i
eax_value
=
value
else
:
assert
push_eax
eax_value_2_i
=
i
eax_value_2
=
value
i
+
=
5
elif
data[i]
=
=
0xbb
and
push_ebx:
# mov ebx, dword
value
=
to_int(data[i
+
1
: i
+
5
])
ins[i]
=
'mov ebx, 0x%x'
%
value
last_i
=
i
ebx_value_i
=
i
ebx_value
=
value
i
+
=
5
elif
data[i]
=
=
0xe9
:
# jmp
ins[i]
=
'jmp %s'
%
make_label(i
+
5
+
to_int(data[i
+
1
: i
+
5
]))
last_i
=
None
i
+
=
5
+
to_int(data[i
+
1
: i
+
5
])
elif
data[i]
=
=
0xeb
:
# jmp short
ins[i]
=
'jmp %s'
%
make_label(i
+
2
+
to_char(data[i
+
1
]))
last_i
=
None
i
+
=
2
+
to_char(data[i
+
1
])
elif
data[i]
=
=
0xc3
:
# ret
if
push_value:
ins[i]
=
'ud2'
i
=
push_value_i
j
=
i
+
ob_start
dst
=
push_value
offset
=
dst
-
j
-
5
&
0xffffffff
ins[i]
=
'jmp %s'
%
make_label(dst
-
ob_start)
last_i
=
None
push_value
=
None
i
=
dst
-
ob_start
else
:
ins[i]
=
'ret'
return
[]
elif
data[i]
=
=
0xff
and
data[i
+
1
]
=
=
0xe0
:
# jmp eax
assert
push_eax
and
eax_value
and
eax_value_2
ins[i]
=
'ud2'
i
=
eax_value_2_i
j
=
i
+
ob_start
dst
=
eax_value_2
offset
=
dst
-
j
-
5
&
0xffffffff
ins[eax_value_i]
=
'nop'
ins[push_eax_i]
=
'nop'
ins[i]
=
'call f%s'
%
make_label(dst
-
ob_start)
funcs_to_handle.append(dst)
i
+
=
5
j
=
i
+
ob_start
dst
=
eax_value
offset
=
dst
-
j
-
5
&
0xffffffff
ins[i]
=
'jmp %s'
%
make_label(dst
-
ob_start)
last_i
=
None
i
=
dst
-
ob_start
push_eax
=
False
eax_value
=
None
eax_value_2
=
None
else
:
is_zero
=
False
test_eax
=
False
push_ebx
=
False
ebx_ebp
=
False
ebx_value
=
None
push_value
=
None
push_eax
=
False
eax_value
=
None
eax_value_2
=
None
l
=
ins_len(data[i: i
+
20
])
ins[i]
=
disasm(data[i: i
+
l], i
+
ob_start)
last_i
=
i
i
+
=
l
def
extract_function(function):
print
(
'// function: 0x%x'
%
function)
branches_to_handle
=
[function
-
ob_start]
ins
=
dict
()
while
branches_to_handle:
addr
=
branches_to_handle.pop(
0
)
if
addr
in
ins:
continue
branches_to_handle
+
=
extract_block(ins, addr)
code
=
'f%s:\n'
%
make_label(function
-
ob_start)
in_pushal
=
False
in_pushfd
=
False
for
i
in
ins:
if
in_pushal:
assert
ins[i] !
=
'pushal '
code
+
=
'%s:\n'
%
make_label(i)
if
ins[i].startswith(
'popal '
):
in_pushal
=
False
for
j
in
ins[i].splitlines()[
1
: ]:
code
+
=
j
+
'\n'
elif
in_pushfd:
assert
ins[i] !
=
'pushfd '
code
+
=
'%s:\n'
%
make_label(i)
if
ins[i].startswith(
'popfd '
):
in_pushfd
=
False
for
j
in
ins[i].splitlines()[
1
: ]:
code
+
=
j
+
'\n'
elif
ins[i]
=
=
'pushal '
:
code
+
=
'%s:\n'
%
make_label(i)
in_pushal
=
True
elif
ins[i]
=
=
'pushfd '
:
code
+
=
'%s:\n'
%
make_label(i)
in_pushfd
=
True
else
:
code
+
=
'%s:\n%s\n'
%
(make_label(i), ins[i])
return
code
offset
=
0x400c00
data
=
open
(
'./KCTF_CrackMe.exe'
,
'rb'
).read()[ob_start
-
offset: ob_end
-
offset]
funcs_to_handle
=
[
0x611e44
,
0x611513
,
0x610baf
,
0x60f9f2
,
0x60f17a
,
0x60e8b9
,
0x60df9a
,
0x60d635
,
0x60cce7
,
0x60c3ba
,
0x60bac0
,
0x60b190
,
0x60a819
,
0x609f67
,
0x609604
,
0x608ca6
,
0x608375
,
0x607aaa
,
0x60714f
,
0x6067da
,
0x605eba
,
0x60557e
,
0x604c95
,
0x604305
,
0x603a11
,
0x603091
,
0x60277c
,
0x601e0d
,
0x601434
,
0x600b97
,
0x60027e
,
0x5ff957
,
0x5fef61
,
0x5fe61e
,
0x5fdd3d
,
0x5fd517
,
0x5fcbc4
,
0x5fc2cb
,
0x5fb9af
,
0x5fb07f
,
0x5fa795
,
0x5f9e5c
,
0x5f94be
,
0x5f8bb2
,
0x5f822a
,
0x5f792b
,
0x5f700b
,
0x5f673f
,
0x40f9af
,
0x5f52e3
,
0x409de1
,
0x40e62d
,
0x403aca
,
0x5f50e0
]
funcs_to_handle
+
=
[
0x4055C4
,
0x404F6B
]
funcs_handled
=
set
()
code
=
''
while
funcs_to_handle:
f
=
funcs_to_handle.pop(
0
)
if
f
in
funcs_handled:
continue
funcs_handled.add(f)
if
ob_start <
=
f < ob_end:
code
+
=
extract_function(f)
else
:
print
(
"// unknown func (maybe library function): f%s"
%
make_label(f
-
ob_start))
code
+
=
'f%s:\njmp 0x%x\n'
%
(make_label(f
-
ob_start), f)
code
+
=
'\n\n.string "================"\n\n'
# print('\n' + code)
with
open
(
'out.s'
,
'w'
) as f:
f.write(code)
print
(
'OK'
)
#!/usr/bin/env python3
# import ida_bytes
import
keystone
import
capstone
def
set_x86():
global
ks, cs
ks
=
keystone.Ks(keystone.KS_ARCH_X86, keystone.KS_MODE_32)
cs
=
capstone.Cs(capstone.CS_ARCH_X86, capstone.CS_MODE_32)
set_x86()
def
asm(code, addr
=
0
):
return
bytes(ks.asm(code, addr)[
0
])
def
disasm(code, addr
=
0
):
for
i
in
cs.disasm(code, addr):
return
(
'%s %s'
%
(i.mnemonic, i.op_str))
def
ins_len(code):
return
len
(
next
(cs.disasm(code,
0
)).bytes)
def
to_char(x):
assert
0
<
=
x <
0x100
if
x >
=
0x80
: x
-
=
0x100
return
x
def
to_int(b):
assert
len
(b)
=
=
4
x
=
int
.from_bytes(b,
'little'
)
if
x >
=
1
<<
31
: x
-
=
1
<<
32
return
x
def
make_label(i):
return
'_%x'
%
(i
+
ob_start)
ob_start
=
0x403AC0
ob_end
=
0x617DE0
def
extract_block(ins, i):
# print('extract block: 0x%x' % (ob_start + i))
is_zero
=
False
ebx_ebp
=
False
push_eax
=
False
push_ebx
=
False
push_eax_i
=
None
push_ebx_i
=
None
eax_value
=
None
eax_value_i
=
None
eax_value_2
=
None
eax_value_2_i
=
None
ebx_value
=
None
ebx_value_i
=
None
test_eax
=
False
push_value
=
None
last_i
=
None
while
True
:
if
i
in
ins:
if
last_i:
ins[last_i]
+
=
'\njmp %s'
%
make_label(i)
return
[]
# print(hex(i + ob_start))
if
data[i]
=
=
0x0f
and
0x80
<
=
data[i
+
1
] <
0x90
:
# j?? dword
offset
=
to_int(data[i
+
2
: i
+
6
])
if
data[i
+
6
]
=
=
0x0f
and
data[i
+
7
]
=
=
data[i
+
1
] ^
1
and
\
offset
=
=
6
+
to_int(data[i
+
8
: i
+
12
]):
ins[i]
=
'jmp %s'
%
make_label(i
+
6
+
offset)
last_i
=
None
i
+
=
6
+
offset
elif
data[i
+
1
]
=
=
0x84
and
is_zero:
# jz
ins[i]
=
'jmp %s'
%
make_label(i
+
6
+
offset)
last_i
=
None
i
+
=
6
+
offset
elif
data[i
+
1
]
=
=
0x85
and
test_eax:
# jnz
ins[i]
=
'jmp %s'
%
make_label(i
+
6
+
offset)
last_i
=
None
i
+
=
6
+
offset
else
:
mnem
=
disasm(data[i: i
+
6
]).split(
' '
)[
0
]
ins[i]
=
'%s %s\njmp %s'
%
(mnem, make_label(i
+
6
+
offset), make_label(i
+
6
))
return
[i
+
6
, i
+
6
+
offset]
elif
data[i]
=
=
0x3b
and
data[i
+
1
]
=
=
0xc0
:
# cmp eax, eax
is_zero
=
True
test_eax
=
False
ins[i]
=
'cmp eax, eax'
last_i
=
i
i
+
=
2
elif
data[i]
=
=
0x3b
and
data[i
+
1
]
=
=
0xdb
:
# cmp ebx, ebx
is_zero
=
True
test_eax
=
False
ins[i]
=
'cmp ebx, ebx'
last_i
=
i
i
+
=
2
elif
data[i]
=
=
0x50
and
eax_value:
# push eax
push_eax_i
=
i
push_eax
=
True
ins[i]
=
'push eax'
last_i
=
i
i
+
=
1
elif
data[i]
=
=
0x53
:
# push ebx
push_ebx_i
=
i
push_ebx
=
True
ins[i]
=
'push ebx'
last_i
=
i
i
+
=
1
elif
data[i]
=
=
0x68
:
# push dword
value
=
to_int(data[i
+
1
: i
+
5
])
if
data[i
+
5
]
=
=
0xc3
:
# ret
ins[i]
=
'jmp %s'
%
make_label(value
-
ob_start)
last_i
=
None
i
=
value
-
ob_start
else
:
push_value
=
value
push_value_i
=
i
ins[i]
=
'push 0x%x'
%
push_value
last_i
=
i
i
+
=
5
elif
0x70
<
=
data[i] <
0x80
:
# j?? short
offset
=
to_char(data[i
+
1
])
if
data[i
+
2
]
=
=
data[i] ^
1
and
offset
=
=
2
+
to_char(data[i
+
3
]):
ins[i]
=
'jmp %s'
%
make_label(i
+
2
+
offset)
last_i
=
None
i
+
=
2
+
offset
elif
data[i]
=
=
0x74
and
is_zero:
# jz short
ins[i]
=
'jmp %s'
%
make_label(i
+
2
+
offset)
last_i
=
None
i
+
=
2
+
offset
elif
data[i]
=
=
0x75
and
test_eax:
# jnz short
ins[i]
=
'jmp %s'
%
make_label(i
+
2
+
offset)
last_i
=
None
i
+
=
2
+
offset
else
:
mnem
=
disasm(data[i: i
+
2
]).split(
' '
)[
0
]
ins[i]
=
'%s %s\njmp %s'
%
(mnem, make_label(i
+
2
+
offset), make_label(i
+
2
))
return
[i
+
2
, i
+
2
+
offset]
elif
data[i]
=
=
0x85
and
data[i
+
1
]
=
=
0xc0
and
eax_value:
# test eax, eax
if
eax_value_2 !
=
None
:
assert
eax_value_2 !
=
0
# call_dst
else
:
pass
test_eax
=
True
is_zero
=
False
ins[i]
=
'test eax, eax'
last_i
=
i
i
+
=
2
elif
data[i]
=
=
0x87
and
data[i
+
1
]
=
=
0x1c
and
data[i
+
2
]
=
=
0x24
and
push_ebx:
# xchg ebx, [esp]
if
ebx_value:
assert
not
ebx_ebp
ins[push_ebx_i]
=
'nop'
ins[ebx_value_i]
=
'push 0x%x'
%
ebx_value
ins[i]
=
'nop'
push_ebx
=
False
push_value
=
ebx_value
ebx_value
=
None
push_value_i
=
ebx_value_i
elif
ebx_ebp:
ins[push_ebx_i]
=
'push ebp'
ins[ebx_ebp_i]
=
'nop'
ins[i]
=
'nop'
push_ebx
=
False
ebx_ebp
=
False
else
:
ins[i]
=
'xchg ebx, [esp]'
push_ebx
=
False
last_i
=
i
i
+
=
3
elif
data[i]
=
=
0x8b
and
data[i
+
1
]
=
=
0xdd
and
push_ebx:
# mov ebx, ebp
ins[i]
=
'mov ebx, ebp'
last_i
=
i
ebx_ebp_i
=
i
ebx_ebp
=
True
i
+
=
2
elif
data[i]
=
=
0x90
:
# nop
ins[i]
=
'nop'
last_i
=
i
i
+
=
1
elif
data[i]
=
=
0xb8
:
# mov eax, dword
value
=
to_int(data[i
+
1
: i
+
5
])
ins[i]
=
'mov eax, 0x%x'
%
value
last_i
=
i
if
not
eax_value:
eax_value_i
=
i
eax_value
=
value
else
:
assert
push_eax
eax_value_2_i
=
i
eax_value_2
=
value
i
+
=
5
elif
data[i]
=
=
0xbb
and
push_ebx:
# mov ebx, dword
value
=
to_int(data[i
+
1
: i
+
5
])
ins[i]
=
'mov ebx, 0x%x'
%
value
last_i
=
i
ebx_value_i
=
i
ebx_value
=
value
i
+
=
5
elif
data[i]
=
=
0xe9
:
# jmp
ins[i]
=
'jmp %s'
%
make_label(i
+
5
+
to_int(data[i
+
1
: i
+
5
]))
last_i
=
None
i
+
=
5
+
to_int(data[i
+
1
: i
+
5
])
elif
data[i]
=
=
0xeb
:
# jmp short
ins[i]
=
'jmp %s'
%
make_label(i
+
2
+
to_char(data[i
+
1
]))
last_i
=
None
i
+
=
2
+
to_char(data[i
+
1
])
elif
data[i]
=
=
0xc3
:
# ret
if
push_value:
ins[i]
=
'ud2'
i
=
push_value_i
j
=
i
+
ob_start
dst
=
push_value
offset
=
dst
-
j
-
5
&
0xffffffff
ins[i]
=
'jmp %s'
%
make_label(dst
-
ob_start)
last_i
=
None
push_value
=
None
i
=
dst
-
ob_start
else
:
ins[i]
=
'ret'
return
[]
elif
data[i]
=
=
0xff
and
data[i
+
1
]
=
=
0xe0
:
# jmp eax
assert
push_eax
and
eax_value
and
eax_value_2
ins[i]
=
'ud2'
i
=
eax_value_2_i
j
=
i
+
ob_start
dst
=
eax_value_2
offset
=
dst
-
j
-
5
&
0xffffffff
ins[eax_value_i]
=
'nop'
ins[push_eax_i]
=
'nop'
ins[i]
=
'call f%s'
%
make_label(dst
-
ob_start)
funcs_to_handle.append(dst)
i
+
=
5
j
=
i
+
ob_start
dst
=
eax_value
offset
=
dst
-
j
-
5
&
0xffffffff
ins[i]
=
'jmp %s'
%
make_label(dst
-
ob_start)
last_i
=
None
i
=
dst
-
ob_start
push_eax
=
False
eax_value
=
None
eax_value_2
=
None
else
:
is_zero
=
False
test_eax
=
False
push_ebx
=
False
ebx_ebp
=
False
ebx_value
=
None
push_value
=
None
push_eax
=
False
eax_value
=
None
eax_value_2
=
None
l
=
ins_len(data[i: i
+
20
])
ins[i]
=
disasm(data[i: i
+
l], i
+
ob_start)
last_i
=
i
i
+
=
l
def
extract_function(function):
print
(
'// function: 0x%x'
%
function)
branches_to_handle
=
[function
-
ob_start]
ins
=
dict
()
while
branches_to_handle:
addr
=
branches_to_handle.pop(
0
)
if
addr
in
ins:
continue
branches_to_handle
+
=
extract_block(ins, addr)
code
=
'f%s:\n'
%
make_label(function
-
ob_start)
in_pushal
=
False
in_pushfd
=
False
for
i
in
ins:
if
in_pushal:
assert
ins[i] !
=
'pushal '
code
+
=
'%s:\n'
%
make_label(i)
if
ins[i].startswith(
'popal '
):
in_pushal
=
False
for
j
in
ins[i].splitlines()[
1
: ]:
code
+
=
j
+
'\n'
elif
in_pushfd:
assert
ins[i] !
=
'pushfd '
code
+
=
'%s:\n'
%
make_label(i)
if
ins[i].startswith(
'popfd '
):
in_pushfd
=
False
for
j
in
ins[i].splitlines()[
1
: ]:
code
+
=
j
+
'\n'
elif
ins[i]
=
=
'pushal '
:
code
+
=
'%s:\n'
%
make_label(i)
in_pushal
=
True
elif
ins[i]
=
=
'pushfd '
:
code
+
=
'%s:\n'
%
make_label(i)
in_pushfd
=
True
else
:
code
+
=
'%s:\n%s\n'
%
(make_label(i), ins[i])
return
code
offset
=
0x400c00
data
=
open
(
'./KCTF_CrackMe.exe'
,
'rb'
).read()[ob_start
-
offset: ob_end
-
offset]
funcs_to_handle
=
[
0x611e44
,
0x611513
,
0x610baf
,
0x60f9f2
,
0x60f17a
,
0x60e8b9
,
0x60df9a
,
0x60d635
,
0x60cce7
,
0x60c3ba
,
0x60bac0
,
0x60b190
,
0x60a819
,
0x609f67
,
0x609604
,
0x608ca6
,
0x608375
,
0x607aaa
,
0x60714f
,
0x6067da
,
0x605eba
,
0x60557e
,
0x604c95
,
0x604305
,
0x603a11
,
0x603091
,
0x60277c
,
0x601e0d
,
0x601434
,
0x600b97
,
0x60027e
,
0x5ff957
,
0x5fef61
,
0x5fe61e
,
0x5fdd3d
,
0x5fd517
,
0x5fcbc4
,
0x5fc2cb
,
0x5fb9af
,
0x5fb07f
,
0x5fa795
,
0x5f9e5c
,
0x5f94be
,
0x5f8bb2
,
0x5f822a
,
0x5f792b
,
0x5f700b
,
0x5f673f
,
0x40f9af
,
0x5f52e3
,
0x409de1
,
0x40e62d
,
0x403aca
,
0x5f50e0
]
funcs_to_handle
+
=
[
0x4055C4
,
0x404F6B
]
funcs_handled
=
set
()
code
=
''
while
funcs_to_handle:
f
=
funcs_to_handle.pop(
0
)
if
f
in
funcs_handled:
continue
funcs_handled.add(f)
if
ob_start <
=
f < ob_end:
code
+
=
extract_function(f)
else
:
print
(
"// unknown func (maybe library function): f%s"
%
make_label(f
-
ob_start))
code
+
=
'f%s:\njmp 0x%x\n'
%
(make_label(f
-
ob_start), f)
code
+
=
'\n\n.string "================"\n\n'
# print('\n' + code)
with
open
(
'out.s'
,
'w'
) as f:
f.write(code)
print
(
'OK'
)
import
pwn
# pwn.context.os = 'windows' # not needed
pwn.context.arch
=
'i386'
code
=
open
(
'out.s'
,
'r'
).read()
with
open
(
'out'
,
'wb'
) as f:
f.write(pwn.asm(code, vma
=
0x800000
))
print
(
'OK'
)
import
pwn
# pwn.context.os = 'windows' # not needed
pwn.context.arch
=
'i386'
code
=
open
(
'out.s'
,
'r'
).read()
with
open
(
'out'
,
'wb'
) as f:
f.write(pwn.asm(code, vma
=
0x800000
))
print
(
'OK'
)
import
ida_bytes
with
open
(
'out'
,
'rb'
) as f:
data
=
f.read()
ida_bytes.patch_bytes(
0x800000
, data)
import
ida_bytes
with
open
(
'out'
,
'rb'
) as f:
data
=
f.read()
ida_bytes.patch_bytes(
0x800000
, data)
printf
(v597);
// 输入序列号:
gets_s(password, 0x100u);
if
(
strlen
(password) >= 0x21 )
goto
LABEL_20;
for
( k = 0; ; ++k )
{
v5 =
strlen
(password);
if
( k >= v5 )
break
;
if
( password[k] >= 97 && password[k] <= 122 )
goto
LABEL_20;
}
v525 = (
char
*)((
int
(__cdecl *)(
char
*,
int
))loc_40E62D)(password, 32);
// hex to bytes
memset
(input, 0, 0x100u);
j_AES_encrypt(v525, v609, input);
// ...
j_decrypt1(&Source[189], output, input);
memcpy
(&output[8], v573, 8u);
j_decrypt1(&Source[180], v602, output);
memcpy
(&v602[8], v594, 8u);
j_decrypt1(&Source[171], output, v602);
memcpy
(&output[8], v593, 8u);
j_decrypt1(&Source[162], v602, output);
memcpy
(&v602[8], v592, 8u);
j_decrypt1(&Source[153], output, v602);
memcpy
(&output[8], v591, 8u);
j_decrypt1(&Source[144], v602, output);
memcpy
(&v602[8], v590, 8u);
j_decrypt1(&Source[135], output, v602);
memcpy
(&output[8], v589, 8u);
j_decrypt1(&Source[126], v602, output);
memcpy
(&v602[8], v588, 8u);
j_decrypt1(&Source[117], output, v602);
memcpy
(&output[8], v587, 8u);
j_decrypt1(&Source[108], v602, output);
memcpy
(&v602[8], v586, 8u);
j_decrypt1(&Source[99], output, v602);
memcpy
(&output[8], v585, 8u);
j_decrypt1(&Source[90], v602, output);
memcpy
(&v602[8], v584, 8u);
j_decrypt1(&Source[81], output, v602);
memcpy
(&output[8], v583, 8u);
j_decrypt1(&Source[72], v602, output);
memcpy
(&v602[8], v582, 8u);
j_decrypt1(&Source[63], output, v602);
memcpy
(&output[8], v581, 8u);
j_decrypt1(&Source[54], v602, output);
memcpy
(&v602[8], v580, 8u);
j_decrypt1(&Source[45], output, v602);
memcpy
(&output[8], v579, 8u);
j_decrypt1(&Source[36], v602, output);
memcpy
(&v602[8], v578, 8u);
j_decrypt1(&Source[27], output, v602);
memcpy
(&output[8], v577, 8u);
j_decrypt1(&Source[18], v602, output);
memcpy
(&v602[8], v575, 8u);
j_decrypt1(&Source[9], output, v602);
memcpy
(&output[8], v576, 8u);
j_decrypt1(Source, v602, output);
Str2[8] = 0;
memcpy
(Str2, v602, 8u);
memset
(Destination, 0, 0x1F4u);
for
( l = 0; l < 50; strcat_s(Destination, 0x400u, &Source[9 * l++]) )
;
memmove
(vm_key, Destination, 500u);
j_vm_encrypt(vm_key, Str2, 1);
if
( !
strcmp
(Str1, Str2) )
MessageBoxA(0,
"success"
,
"success"
, 0);
else
LABEL_20:
MessageBoxA(0,
"fail"
,
"fail"
, 0);
return
0;
}
printf
(v597);
// 输入序列号:
gets_s(password, 0x100u);
if
(
strlen
(password) >= 0x21 )
goto
LABEL_20;
for
( k = 0; ; ++k )
{
v5 =
strlen
(password);
if
( k >= v5 )
break
;
if
( password[k] >= 97 && password[k] <= 122 )
goto
LABEL_20;
}
v525 = (
char
*)((
int
(__cdecl *)(
char
*,
int
))loc_40E62D)(password, 32);
// hex to bytes
memset
(input, 0, 0x100u);
j_AES_encrypt(v525, v609, input);
// ...
j_decrypt1(&Source[189], output, input);
memcpy
(&output[8], v573, 8u);
j_decrypt1(&Source[180], v602, output);
memcpy
(&v602[8], v594, 8u);
j_decrypt1(&Source[171], output, v602);
memcpy
(&output[8], v593, 8u);
j_decrypt1(&Source[162], v602, output);
memcpy
(&v602[8], v592, 8u);
j_decrypt1(&Source[153], output, v602);
memcpy
(&output[8], v591, 8u);
j_decrypt1(&Source[144], v602, output);
memcpy
(&v602[8], v590, 8u);
j_decrypt1(&Source[135], output, v602);
memcpy
(&output[8], v589, 8u);
j_decrypt1(&Source[126], v602, output);
memcpy
(&v602[8], v588, 8u);
j_decrypt1(&Source[117], output, v602);
memcpy
(&output[8], v587, 8u);
j_decrypt1(&Source[108], v602, output);
memcpy
(&v602[8], v586, 8u);
j_decrypt1(&Source[99], output, v602);
memcpy
(&output[8], v585, 8u);
j_decrypt1(&Source[90], v602, output);
memcpy
(&v602[8], v584, 8u);
j_decrypt1(&Source[81], output, v602);
memcpy
(&output[8], v583, 8u);
j_decrypt1(&Source[72], v602, output);
memcpy
(&v602[8], v582, 8u);
j_decrypt1(&Source[63], output, v602);
memcpy
(&output[8], v581, 8u);
j_decrypt1(&Source[54], v602, output);
memcpy
(&v602[8], v580, 8u);
j_decrypt1(&Source[45], output, v602);
memcpy
(&output[8], v579, 8u);
j_decrypt1(&Source[36], v602, output);
memcpy
(&v602[8], v578, 8u);
j_decrypt1(&Source[27], output, v602);
memcpy
(&output[8], v577, 8u);
j_decrypt1(&Source[18], v602, output);
memcpy
(&v602[8], v575, 8u);
j_decrypt1(&Source[9], output, v602);
memcpy
(&output[8], v576, 8u);
j_decrypt1(Source, v602, output);
Str2[8] = 0;
memcpy
(Str2, v602, 8u);
memset
(Destination, 0, 0x1F4u);
for
( l = 0; l < 50; strcat_s(Destination, 0x400u, &Source[9 * l++]) )
;
memmove
(vm_key, Destination, 500u);
j_vm_encrypt(vm_key, Str2, 1);
if
( !
strcmp
(Str1, Str2) )
MessageBoxA(0,
"success"
,
"success"
, 0);
else
LABEL_20:
MessageBoxA(0,
"fail"
,
"fail"
, 0);
return
0;
}
void
__cdecl AES_encrypt(
char
*input,
char
*key,
char
*output)
{
char
v3[176];
// [esp+1Ch] [ebp-ECh] BYREF
char
v4[16];
// [esp+CCh] [ebp-3Ch] BYREF
int
v5;
// [esp+DCh] [ebp-2Ch]
char
state[16];
// [esp+E0h] [ebp-28h] BYREF
DWORD
v7;
// [esp+F0h] [ebp-18h] BYREF
Params *v8;
// [esp+F4h] [ebp-14h]
int
j;
// [esp+F8h] [ebp-10h]
Params *v10;
// [esp+FCh] [ebp-Ch]
int
i;
// [esp+100h] [ebp-8h]
v5 = 0;
j_memset_0(state, 0,
sizeof
(state));
j_memset_0(v4, 0,
sizeof
(v4));
j_memset_0(v3, 0,
sizeof
(v3));
j_AES_set_state(input, state);
j_AES_set_state(key, v4);
j_AES_KeyExpansion(v4, v3);
j_AES_AddRoundKey(state, v3, 4 * aes_lock_index);
aes_lock_index += 2;
j_AES_ShiftRows(state);
j_AES_SubBytes(state);
v7 = 1;
for
( i = 8; i <= 20; i += 4 )
{
v10 = (Params *)j_calloc_0(0xCu, 1u);
v10->index = i;
v10->state = state;
v10->exkey = v3;
CreateThread(0, 0, (LPTHREAD_START_ROUTINE)j_thread_1, v10, 0, &v7);
}
for
( j = 18; j > 0; j -= 4 )
{
v8 = (Params *)j_calloc_0(0xCu, 1u);
v8->index = j;
v8->state = state;
v8->exkey = v3;
CreateThread(0, 0, (LPTHREAD_START_ROUTINE)j_thread_2, v8, 0, &v7);
}
while
( aes_lock_index != -1 )
;
j_AES_AddRoundKey(state, v3, 0);
AES_get_state(state, output);
}
void
__cdecl thread_1(Params *p)
{
while
( aes_lock_index != p->index / 2 )
;
j_AES_AddRoundKey(p->state, p->exkey, 4 * (p->index / 2));
AES_MixColumns(p->state);
j_AES_ShiftRows(p->state);
j_AES_SubBytes(p->state);
if
( aes_lock_index == 10 )
--aes_lock_index;
else
aes_lock_index += 2;
j_free(p);
}
void
__cdecl thread_2(Params *p)
{
while
( aes_lock_index != p->index / 2 )
;
j_AES_AddRoundKey(p->state, p->exkey, 4 * (p->index / 2));
AES_MixColumns(p->state);
j_AES_ShiftRows(p->state);
j_AES_SubBytes(p->state);
aes_lock_index -= 2;
j_free(p);
}
void
__cdecl AES_encrypt(
char
*input,
char
*key,
char
*output)
{
char
v3[176];
// [esp+1Ch] [ebp-ECh] BYREF
char
v4[16];
// [esp+CCh] [ebp-3Ch] BYREF
int
v5;
// [esp+DCh] [ebp-2Ch]
char
state[16];
// [esp+E0h] [ebp-28h] BYREF
DWORD
v7;
// [esp+F0h] [ebp-18h] BYREF
Params *v8;
// [esp+F4h] [ebp-14h]
int
j;
// [esp+F8h] [ebp-10h]
Params *v10;
// [esp+FCh] [ebp-Ch]
int
i;
// [esp+100h] [ebp-8h]
v5 = 0;
j_memset_0(state, 0,
sizeof
(state));
j_memset_0(v4, 0,
sizeof
(v4));
j_memset_0(v3, 0,
sizeof
(v3));
j_AES_set_state(input, state);
j_AES_set_state(key, v4);
j_AES_KeyExpansion(v4, v3);
j_AES_AddRoundKey(state, v3, 4 * aes_lock_index);
aes_lock_index += 2;
j_AES_ShiftRows(state);
j_AES_SubBytes(state);
v7 = 1;
for
( i = 8; i <= 20; i += 4 )
{
v10 = (Params *)j_calloc_0(0xCu, 1u);
v10->index = i;
v10->state = state;
v10->exkey = v3;
CreateThread(0, 0, (LPTHREAD_START_ROUTINE)j_thread_1, v10, 0, &v7);
}
for
( j = 18; j > 0; j -= 4 )
{
v8 = (Params *)j_calloc_0(0xCu, 1u);
v8->index = j;
v8->state = state;
v8->exkey = v3;
CreateThread(0, 0, (LPTHREAD_START_ROUTINE)j_thread_2, v8, 0, &v7);
}
while
( aes_lock_index != -1 )
;
j_AES_AddRoundKey(state, v3, 0);
AES_get_state(state, output);
}
void
__cdecl thread_1(Params *p)
{
while
( aes_lock_index != p->index / 2 )
;
j_AES_AddRoundKey(p->state, p->exkey, 4 * (p->index / 2));
AES_MixColumns(p->state);
j_AES_ShiftRows(p->state);
j_AES_SubBytes(p->state);
if
( aes_lock_index == 10 )
--aes_lock_index;
else
aes_lock_index += 2;
j_free(p);
}
void
__cdecl thread_2(Params *p)
{
while
( aes_lock_index != p->index / 2 )
;
j_AES_AddRoundKey(p->state, p->exkey, 4 * (p->index / 2));
AES_MixColumns(p->state);
j_AES_ShiftRows(p->state);
j_AES_SubBytes(p->state);
aes_lock_index -= 2;
j_free(p);
}
#include <stdio.h>
#include <string.h>
#include <assert.h>
// AES
typedef
struct
{
unsigned
char
rk[4][11][4];
// round key
unsigned
char
iv[16];
} AES_CONTEXT;
const
unsigned
char
Sbox[256] = {
0x28, 0xC2, 0xE8, 0x57, 0x48, 0x24, 0x97, 0xC5, 0x18, 0x8C, 0x9B, 0x72, 0xF7, 0x99, 0xDE, 0xD3,
0x85, 0x58, 0x7A, 0x0B, 0x44, 0xD1, 0xB0, 0x47, 0xC7, 0xAE, 0xF0, 0x6D, 0x53, 0xE1, 0x60, 0xB4,
0x4B, 0x5C, 0x10, 0x52, 0x01, 0x39, 0xB9, 0x90, 0xAB, 0x00, 0xD4, 0x73, 0x64, 0x32, 0x9F, 0xA1,
0x6A, 0x1C, 0x6B, 0x21, 0xF1, 0xEF, 0x3F, 0x67, 0x95, 0xF2, 0x79, 0xE0, 0x0C, 0xD0, 0x66, 0x7F,
0x2C, 0xC3, 0x12, 0x5A, 0x34, 0xEB, 0x15, 0xA6, 0xBC, 0x7D, 0xA0, 0xB8, 0x55, 0x49, 0xC1, 0xFB,
0xE9, 0x08, 0x3C, 0xE2, 0x56, 0x2F, 0x30, 0x9E, 0x0E, 0xCB, 0x25, 0xE3, 0x46, 0x5D, 0xEC, 0x4C,
0x09, 0xBE, 0x87, 0x04, 0x89, 0xD8, 0x19, 0x3D, 0x71, 0x40, 0x7E, 0x5F, 0x16, 0x7B, 0x3A, 0x27,
0x43, 0x76, 0x45, 0x8A, 0x35, 0x96, 0xF9, 0x07, 0x8F, 0x0F, 0x54, 0xCF, 0xBA, 0x38, 0x83, 0xCE,
0x2A, 0xAC, 0x68, 0xF4, 0x80, 0x31, 0xA4, 0xFE, 0x93, 0xB3, 0x7C, 0xCA, 0xB6, 0x75, 0xDA, 0xA8,
0xD7, 0xB1, 0x37, 0xC4, 0x6C, 0x6F, 0xD5, 0x4F, 0x23, 0x14, 0x98, 0xAA, 0xDC, 0x65, 0x74, 0x42,
0xC8, 0x41, 0x8D, 0xA5, 0x22, 0xEA, 0x4D, 0xB5, 0x17, 0x02, 0x1E, 0x88, 0x91, 0x33, 0xC6, 0x78,
0x3B, 0x2D, 0xD9, 0xFC, 0x1B, 0x9A, 0xCD, 0xE6, 0x1F, 0xED, 0x92, 0x29, 0x4A, 0xFA, 0x1A, 0xEE,
0x0D, 0xE7, 0x63, 0x8E, 0xFF, 0x06, 0x3E, 0x1D, 0xF8, 0xAD, 0xE5, 0x36, 0x05, 0x70, 0xA2, 0x69,
0x84, 0xBF, 0xA9, 0x8B, 0x03, 0xD6, 0x26, 0x2E, 0x82, 0x62, 0x81, 0xE4, 0x94, 0xA7, 0xAF, 0x5E,
0x9D, 0xD2, 0xB2, 0x86, 0x2B, 0x51, 0xCC, 0xDD, 0x13, 0xF5, 0x77, 0x50, 0xC0, 0xB7, 0x0A, 0x59,
0x4E, 0xC9, 0xBB, 0x11, 0xA3, 0x6E, 0xDB, 0xF6, 0x61, 0x9C, 0x20, 0xDF, 0xFD, 0xBD, 0x5B, 0xF3
};
unsigned
char
InvSbox[256] = {
};
void
KeyExpansion(AES_CONTEXT *ctx,
const
unsigned
char
* key) {
int
i, j, r, c;
unsigned
char
rc[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36};
for
(r = 0; r < 4; r++) {
for
(c = 0; c < 4; c++) {
ctx->rk[r][0][c] = key[r + c * 4];
}
}
for
(i = 1; i <= 10; i++) {
for
(j = 0; j < 4; j++) {
unsigned
char
t[4];
for
(r = 0; r < 4; r++) {
t[r] = j ? ctx->rk[r][i][j - 1] : ctx->rk[r][i - 1][3];
}
if
(j == 0) {
unsigned
char
temp = t[0];
for
(r = 0; r < 3; r++) {
t[r] = Sbox[t[(r + 1) % 4]];
}
t[3] = Sbox[temp];
t[0] ^= rc[i - 1];
}
for
(r = 0; r < 4; r++) {
ctx->rk[r][i][j] = ctx->rk[r][i - 1][j] ^ t[r];
}
}
}
}
unsigned
char
FFmul(unsigned
char
a, unsigned
char
b) {
unsigned
char
bw[4];
unsigned
char
res = 0;
int
i;
bw[0] = b;
for
(i = 1; i < 4; i++) {
bw[i] = bw[i-1] << 1;
if
(bw[i - 1] & 0x80) {
bw[i] ^= 0x1b;
}
}
for
(i=0; i<4; i++) {
if
((a >> i) & 0x01) {
res ^= bw[i];
}
}
return
res;
}
void
SubBytes(AES_CONTEXT *ctx, unsigned
char
state[][4]) {
int
r, c;
for
(r = 0; r < 4; r++) {
for
(c = 0; c < 4; c++) {
state[r][c] = Sbox[state[r][c]];
}
}
}
unsigned
int
ror4(unsigned
int
x,
int
n) {
return
(x >> n) | (x << (32 - n));
}
unsigned
int
rol4(unsigned
int
x,
int
n) {
return
ror4(x, 32 - n);
}
void
ShiftRows(AES_CONTEXT *ctx, unsigned
char
state[][4]) {
unsigned
int
* _s = (unsigned
int
*) state;
_s[0] = ror4(_s[0], 0);
_s[1] = ror4(_s[1], 8);
_s[2] = ror4(_s[2], 24);
_s[3] = ror4(_s[3], 16);
}
void
MixColumns(AES_CONTEXT *ctx, unsigned
char
state[][4]) {
unsigned
char
t[4];
int
r, c;
for
(c = 0; c < 4; c++) {
for
(r = 0; r < 4; r++) {
t[r] = state[r][c];
}
for
(r=0; r<4; r++) {
state[r][c] = FFmul(0x0e, t[r]) ^ FFmul(0x0b, t[(r + 1) % 4]) ^ FFmul(0x0d, t[(r + 2) % 4]) ^ FFmul(0x09, t[(r + 3) % 4]);
}
}
}
void
AddRoundKey(AES_CONTEXT *ctx, unsigned
char
state[][4], unsigned
char
k[][11][4],
int
index) {
int
r, c;
for
(c = 0; c < 4; c++) {
for
(r = 0; r < 4; r++) {
state[c][r] ^= k[c][index][r];
}
}
}
void
InvSubBytes(AES_CONTEXT *ctx, unsigned
char
state[][4]) {
int
r, c;
for
(r = 0; r < 4; r++) {
for
(c = 0; c < 4; c++) {
state[r][c] = InvSbox[state[r][c]];
}
}
}
void
InvShiftRows(AES_CONTEXT *ctx, unsigned
char
state[][4]) {
unsigned
int
* _s = (unsigned
int
*) state;
_s[0] = rol4(_s[0], 0);
_s[1] = rol4(_s[1], 8);
_s[2] = rol4(_s[2], 24);
_s[3] = rol4(_s[3], 16);
}
void
InvMixColumns(AES_CONTEXT *ctx, unsigned
char
state[][4]) {
unsigned
char
t[4];
int
r, c;
for
(c = 0; c < 4; c++) {
for
(r = 0; r < 4; r++) {
t[r] = state[r][c];
}
for
(r = 0; r < 4; r++) {
state[r][c] = FFmul(0x02, t[r]) ^ FFmul(0x03, t[(r + 1) % 4]) ^ FFmul(0x01, t[(r + 2) % 4]) ^ FFmul(0x01, t[(r + 3) % 4]);
}
}
}
void
aes_init(AES_CONTEXT *ctx,
const
unsigned
char
* key,
const
void
* iv) {
for
(
int
i = 0; i < 16; i++) {
for
(
int
j = 0; j < 16; j++) {
InvSbox[Sbox[16 * i + j]] = 16 * i + j;
}
}
KeyExpansion(ctx, key);
if
(iv)
memcpy
(ctx->iv, iv, 16);
}
unsigned
char
* aes_encrypt_block(AES_CONTEXT* ctx, unsigned
char
* input) {
unsigned
char
state[4][4];
int
i, r, c;
for
(r = 0; r < 4; r++) {
for
(c = 0; c < 4 ;c++) {
state[r][c] = input[c * 4 + r];
}
}
AddRoundKey(ctx, state, ctx->rk, 2);
ShiftRows(ctx, state);
SubBytes(ctx, state);
for
(i = 8; i <= 20; i += 4) {
AddRoundKey(ctx, state, ctx->rk, i / 2);
MixColumns(ctx, state);
ShiftRows(ctx, state);
SubBytes(ctx, state);
}
for
(i = 18; i > 0; i -= 4) {
AddRoundKey(ctx, state, ctx->rk, i / 2);
MixColumns(ctx, state);
ShiftRows(ctx, state);
SubBytes(ctx, state);
}
AddRoundKey(ctx, state, ctx->rk, 0);
for
(r = 0; r < 4; r++) {
for
(c = 0; c < 4 ;c++) {
input[c * 4 + r] = state[r][c];
}
}
return
input;
}
unsigned
char
* aes_decrypt_block(AES_CONTEXT *ctx, unsigned
char
* input) {
unsigned
char
state[4][4];
int
i, r, c;
for
(r = 0; r < 4; r++) {
for
(c = 0; c < 4; c++) {
state[r][c] = input[c * 4 + r];
}
}
AddRoundKey(ctx, state, ctx->rk, 0);
for
(
int
i = 2; i <= 18; i += 4) {
InvSubBytes(ctx, state);
InvShiftRows(ctx, state);
InvMixColumns(ctx, state);
AddRoundKey(ctx, state, ctx->rk, i / 2);
}
for
(i = 20; i >= 8; i -= 4) {
InvSubBytes(ctx, state);
InvShiftRows(ctx, state);
InvMixColumns(ctx, state);
AddRoundKey(ctx, state, ctx->rk, i / 2);
}
InvSubBytes(ctx, state);
InvShiftRows(ctx, state);
AddRoundKey(ctx, state, ctx->rk, 2);
for
(r = 0; r < 4; r++) {
for
(c = 0; c < 4 ;c++) {
input[c * 4 + r] = state[r][c];
}
}
return
input;
}
void
aes_encrypt_ecb(
const
void
* key,
void
* data,
int
data_len) {
assert
(data_len % 16 == 0);
AES_CONTEXT ctx;
aes_init(&ctx, (
const
unsigned
char
*) key, NULL);
unsigned
char
* _data = (unsigned
char
*) data;
for
(
int
i = 0; i < data_len / 16; i++) {
aes_encrypt_block(&ctx, _data);
_data += 16;
}
}
void
aes_decrypt_ecb(
const
void
* key,
void
* data,
int
data_len) {
assert
(data_len % 16 == 0);
AES_CONTEXT ctx;
aes_init(&ctx, (
const
unsigned
char
*) key, NULL);
unsigned
char
* _data = (unsigned
char
*) data;
for
(
int
i = 0; i < data_len / 16; i++) {
aes_decrypt_block(&ctx, _data);
_data += 16;
}
}
#include <stdio.h>
#include <string.h>
#include <assert.h>
// AES
typedef
struct
{
unsigned
char
rk[4][11][4];
// round key
unsigned
char
iv[16];
} AES_CONTEXT;
const
unsigned
char
Sbox[256] = {
0x28, 0xC2, 0xE8, 0x57, 0x48, 0x24, 0x97, 0xC5, 0x18, 0x8C, 0x9B, 0x72, 0xF7, 0x99, 0xDE, 0xD3,
0x85, 0x58, 0x7A, 0x0B, 0x44, 0xD1, 0xB0, 0x47, 0xC7, 0xAE, 0xF0, 0x6D, 0x53, 0xE1, 0x60, 0xB4,
0x4B, 0x5C, 0x10, 0x52, 0x01, 0x39, 0xB9, 0x90, 0xAB, 0x00, 0xD4, 0x73, 0x64, 0x32, 0x9F, 0xA1,
0x6A, 0x1C, 0x6B, 0x21, 0xF1, 0xEF, 0x3F, 0x67, 0x95, 0xF2, 0x79, 0xE0, 0x0C, 0xD0, 0x66, 0x7F,
0x2C, 0xC3, 0x12, 0x5A, 0x34, 0xEB, 0x15, 0xA6, 0xBC, 0x7D, 0xA0, 0xB8, 0x55, 0x49, 0xC1, 0xFB,
0xE9, 0x08, 0x3C, 0xE2, 0x56, 0x2F, 0x30, 0x9E, 0x0E, 0xCB, 0x25, 0xE3, 0x46, 0x5D, 0xEC, 0x4C,
0x09, 0xBE, 0x87, 0x04, 0x89, 0xD8, 0x19, 0x3D, 0x71, 0x40, 0x7E, 0x5F, 0x16, 0x7B, 0x3A, 0x27,
0x43, 0x76, 0x45, 0x8A, 0x35, 0x96, 0xF9, 0x07, 0x8F, 0x0F, 0x54, 0xCF, 0xBA, 0x38, 0x83, 0xCE,
0x2A, 0xAC, 0x68, 0xF4, 0x80, 0x31, 0xA4, 0xFE, 0x93, 0xB3, 0x7C, 0xCA, 0xB6, 0x75, 0xDA, 0xA8,
0xD7, 0xB1, 0x37, 0xC4, 0x6C, 0x6F, 0xD5, 0x4F, 0x23, 0x14, 0x98, 0xAA, 0xDC, 0x65, 0x74, 0x42,
0xC8, 0x41, 0x8D, 0xA5, 0x22, 0xEA, 0x4D, 0xB5, 0x17, 0x02, 0x1E, 0x88, 0x91, 0x33, 0xC6, 0x78,
0x3B, 0x2D, 0xD9, 0xFC, 0x1B, 0x9A, 0xCD, 0xE6, 0x1F, 0xED, 0x92, 0x29, 0x4A, 0xFA, 0x1A, 0xEE,
0x0D, 0xE7, 0x63, 0x8E, 0xFF, 0x06, 0x3E, 0x1D, 0xF8, 0xAD, 0xE5, 0x36, 0x05, 0x70, 0xA2, 0x69,
0x84, 0xBF, 0xA9, 0x8B, 0x03, 0xD6, 0x26, 0x2E, 0x82, 0x62, 0x81, 0xE4, 0x94, 0xA7, 0xAF, 0x5E,
0x9D, 0xD2, 0xB2, 0x86, 0x2B, 0x51, 0xCC, 0xDD, 0x13, 0xF5, 0x77, 0x50, 0xC0, 0xB7, 0x0A, 0x59,
0x4E, 0xC9, 0xBB, 0x11, 0xA3, 0x6E, 0xDB, 0xF6, 0x61, 0x9C, 0x20, 0xDF, 0xFD, 0xBD, 0x5B, 0xF3
};
unsigned
char
InvSbox[256] = {
};
void
KeyExpansion(AES_CONTEXT *ctx,
const
unsigned
char
* key) {
int
i, j, r, c;
unsigned
char
rc[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36};
for
(r = 0; r < 4; r++) {
for
(c = 0; c < 4; c++) {
ctx->rk[r][0][c] = key[r + c * 4];
}
}
for
(i = 1; i <= 10; i++) {
for
(j = 0; j < 4; j++) {
unsigned
char
t[4];
for
(r = 0; r < 4; r++) {
t[r] = j ? ctx->rk[r][i][j - 1] : ctx->rk[r][i - 1][3];
}
if
(j == 0) {
unsigned
char
temp = t[0];
for
(r = 0; r < 3; r++) {
t[r] = Sbox[t[(r + 1) % 4]];
}
t[3] = Sbox[temp];
t[0] ^= rc[i - 1];
}
for
(r = 0; r < 4; r++) {
ctx->rk[r][i][j] = ctx->rk[r][i - 1][j] ^ t[r];
}
}
}
}
unsigned
char
FFmul(unsigned
char
a, unsigned
char
b) {
unsigned
char
bw[4];
unsigned
char
res = 0;
int
i;
bw[0] = b;
for
(i = 1; i < 4; i++) {
bw[i] = bw[i-1] << 1;
if
(bw[i - 1] & 0x80) {
bw[i] ^= 0x1b;
}
}
for
(i=0; i<4; i++) {
if
((a >> i) & 0x01) {
res ^= bw[i];
}
}
return
res;
}
void
SubBytes(AES_CONTEXT *ctx, unsigned
char
state[][4]) {
int
r, c;
for
(r = 0; r < 4; r++) {
for
(c = 0; c < 4; c++) {
state[r][c] = Sbox[state[r][c]];
}
}
}
unsigned
int
ror4(unsigned
int
x,
int
n) {
return
(x >> n) | (x << (32 - n));
}
unsigned
int
rol4(unsigned
int
x,
int
n) {
return
ror4(x, 32 - n);
}
void
ShiftRows(AES_CONTEXT *ctx, unsigned
char
state[][4]) {
unsigned
int
* _s = (unsigned
int
*) state;
_s[0] = ror4(_s[0], 0);
_s[1] = ror4(_s[1], 8);
_s[2] = ror4(_s[2], 24);
_s[3] = ror4(_s[3], 16);
}
void
MixColumns(AES_CONTEXT *ctx, unsigned
char
state[][4]) {
unsigned
char
t[4];
int
r, c;
for
(c = 0; c < 4; c++) {
for
(r = 0; r < 4; r++) {
t[r] = state[r][c];
}
for
(r=0; r<4; r++) {
state[r][c] = FFmul(0x0e, t[r]) ^ FFmul(0x0b, t[(r + 1) % 4]) ^ FFmul(0x0d, t[(r + 2) % 4]) ^ FFmul(0x09, t[(r + 3) % 4]);
}
}
}
void
AddRoundKey(AES_CONTEXT *ctx, unsigned
char
state[][4], unsigned
char
k[][11][4],
int
index) {
int
r, c;
for
(c = 0; c < 4; c++) {
for
(r = 0; r < 4; r++) {
state[c][r] ^= k[c][index][r];
}
}
}
void
InvSubBytes(AES_CONTEXT *ctx, unsigned
char
state[][4]) {
int
r, c;
for
(r = 0; r < 4; r++) {
for
(c = 0; c < 4; c++) {
state[r][c] = InvSbox[state[r][c]];
}
}
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
赞赏记录
参与人
雪币
留言
时间
一笑人间万事
为你点赞~
2024-1-2 01:12
yp太阳神
为你点赞~
2023-9-18 12:26
GreatIchild
为你点赞~
2023-9-18 09:29
一半人生
为你点赞~
2023-9-18 08:38
mb_mgodlfyn
为你点赞~
2023-9-18 01:14
赞赏
他的文章
看原图
赞赏
雪币:
留言: