先使用 pyinstxtractor.py 解包 main.exe
使用 pycdc 查看 main.pyc 代码:
主要逻辑在 CrackMe中, 然而在解包出的文件中并未找到 CrackMe 源文件;
考虑分析一下python import的过程, 于是下载题目所使用的 python 3.8.10 的源代码, 以及安装python 3.8.10 勾选上安装调试文件 得到python38.pdb 开始动态调试python38.dll
在一边看源码下断点, 一边使用pycdc检查解包出的其他文件时发现base64.pyc中有奇怪的代码:
对base64的main函数的code object进行了替换, 可以使用如下代码将其写入文件并用pycdc检查
pycdc -c test.dump -v 3.8
可以发现是替换了字符的base64
修下pycdc代码的lambda .0
部分以及写出解码函数:
之前分析python38源码得知 _PyEval_EvalFrameDefault
为python主要解释执行函数, 结合pdb分析dll可以找到 python38.dll+0x28595
处为_PyEval_EvalFrameDefault
中处理BINARY_XOR
的部分, 通过windbg调试命令
bp python38.dll+0x28595 "db rcx+0x18 rcx+0x1f;db rdx+0x18 rdx+0x1f;g"
可以看到python中执行的每个xor的输入
变种base64代码中有对data中的字符i = i ^ 85
, 85对应0x55, 与它进行xor的字符串QI8F
应该就是KCTF经过之前某种处理的结果
确定xor另一个字符总是0x55之后可以将命令换为bp python38.dll+0x28595 "db rcx+0x18 rcx+0x1f;g"
来检查该种处理结果
从main.py得知dZpKdrsiB6cndrGY
的解码结果+KCTF处理结果QI8F应为变种base64的输入, 解码dZpKdrsiB6cndrGY
得到b"T'00-l5-\x1a0(k"
并在检查字符处理结果时可发现处理类似字符替换, 每个字符会位置无关的变成另一个字符
且检查公开提供的验证码D7CHel419lo 7AFWor080ld!6891
可得到对应HUIT'0X[c0-lUKF5-\x1a\d\0(kVdc[
可找到H对应T e对应' l对应0 等
对照b"T'00-l5-\x1a0(k"
进行替换
即可得到KCTF最终的验证码为Hello World!KCTF
import
CrackMe
print
(
'(账号密码由字母大小写、数字、!、空格组成)'
)
print
(
'请输入账号:'
)
h
=
input
()
z
=
CrackMe.main(h)
if
len
(z) <
20
:
key
=
'dZpKdrsiB6cndrGY'
+
z
else
:
key
=
z[
0
:
4
]
+
'dZpK'
+
z[
4
:
8
]
+
'drsi'
+
z[
8
:
12
]
+
'B6cn'
+
z[
12
:
16
]
+
'drGY'
+
z[
16
:]
print
(
'请输入验证码:'
)
h
=
input
()
m
=
CrackMe.main(h)
if
key
=
=
m:
print
(
'Success'
)
print
(
'Fail'
)
continue
continue
import
CrackMe
print
(
'(账号密码由字母大小写、数字、!、空格组成)'
)
print
(
'请输入账号:'
)
h
=
input
()
z
=
CrackMe.main(h)
if
len
(z) <
20
:
key
=
'dZpKdrsiB6cndrGY'
+
z
else
:
key
=
z[
0
:
4
]
+
'dZpK'
+
z[
4
:
8
]
+
'drsi'
+
z[
8
:
12
]
+
'B6cn'
+
z[
12
:
16
]
+
'drGY'
+
z[
16
:]
print
(
'请输入验证码:'
)
h
=
input
()
m
=
CrackMe.main(h)
if
key
=
=
m:
print
(
'Success'
)
print
(
'Fail'
)
continue
continue
def
main():
Unsupported opcode: BEGIN_FINALLY
import
sys
import
getopt
a
=
main.__code__.replace(
1
, (), b
'd\x01}\x01d\x02}\x02d\x03}\x03d\x04}\x04|\x00D\x00]\x1c}\x05|\x05d\x05A\x00}\x05|\x04|\x05\xa0\x00d\x06d\x07\xa1\x02\x17\x00}\x04q\x14|\x04}\x00t\x01d\x02t\x02|\x00\x83\x01d\x08\x83\x03D\x00]\x90}\x05|\x00|\x05|\x05d\x08\x17\x00\x85\x02\x19\x00}\x06d\x01\xa0\x03d\td\n\x84\x00|\x06D\x00\x83\x01\xa1\x01}\x07t\x01d\x02t\x02|\x07\x83\x01d\x0b\x83\x03D\x00]V}\x08|\x07|\x08|\x08d\x0b\x17\x00\x85\x02\x19\x00}\tt\x02|\t\x83\x01d\x0bk\x00r\xc2|\x02d\x0bt\x02|\t\x83\x01\x18\x007\x00}\x02|\td\x0cd\x0bt\x02|\t\x83\x01\x18\x00\x14\x007\x00}\t|\x01|\x03t\x04|\td\r\x83\x02\x19\x007\x00}\x01q~qF|\x01d\x0e|\x02d\r\x1a\x00\x14\x007\x00}\x01t\x01t\x02|\x01\x83\x01d\r\x1a\x00\x83\x01D\x00]L}\x05|\x01|\x05d\r\x14\x00\x19\x00}\n|\x01|\x05d\r\x14\x00d\x06\x17\x00\x19\x00}\x0b|\x01d\x00|\x05d\r\x14\x00\x85\x02\x19\x00|\x0b\x17\x00|\n\x17\x00|\x01|\x05d\r\x14\x00d\r\x17\x00d\x00\x85\x02\x19\x00\x17\x00}\x01q\xf8|\x01S\x00'
, (
None
, '
', 0, '
ZQ
+
U7tSBEKVzyf5coCwb94Dd6raT0eLNin12Hp8mOxFuvMgIPlhRY3WjksqJAXG
/
', b'
', 85, 1, '
little
', 3, compile('
', '
', '
exec
').replace(1, (), b'
|\x00]\x10}\x01t\x00|\x01d\x00\x83\x02V\x00\x01\x00q\x02d\x01S\x00
', ('
08b
', None), '
', 19, 115, (), 0, b'
', '
', ('
format
',), 2, 0, 4, ('
.
0
', '
byte
'), **('
co_argcount
', '
co_cellvars
', '
co_code
', '
co_consts
', '
co_filename
', '
co_firstlineno
', '
co_flags
', '
co_freevars
', '
co_kwonlyargcount
', '
co_lnotab
', '
co_name
', '
co_names
', '
co_nlocals
', '
co_posonlyargcount
', '
co_stacksize
', '
co_varnames
')), '
', 6, '
0
', 2, '
!
'), '
', 4, 67, (), 0, b'
', '
', ('
to_bytes
', '
range
', '
len
', '
join
', '
int
'), 12, 0, 7, ('
data
', '
encoded_str
', '
padding
', '
base64_chars
', '
ww
', '
i
', '
chunk
', '
binary_str
', '
j
', '
six_bits
', '
a
', '
b
'), **('
co_argcount
', '
co_cellvars
', '
co_code
', '
co_consts
', '
co_filename
', '
co_firstlineno
', '
co_flags
', '
co_freevars
', '
co_kwonlyargcount
', '
co_lnotab
', '
co_name
', '
co_names
', '
co_nlocals
', '
co_posonlyargcount
', '
co_stacksize
', '
co_varnames'))
main.__code__
=
a
def
main():
Unsupported opcode: BEGIN_FINALLY
import
sys
import
getopt
a
=
main.__code__.replace(
1
, (), b
'd\x01}\x01d\x02}\x02d\x03}\x03d\x04}\x04|\x00D\x00]\x1c}\x05|\x05d\x05A\x00}\x05|\x04|\x05\xa0\x00d\x06d\x07\xa1\x02\x17\x00}\x04q\x14|\x04}\x00t\x01d\x02t\x02|\x00\x83\x01d\x08\x83\x03D\x00]\x90}\x05|\x00|\x05|\x05d\x08\x17\x00\x85\x02\x19\x00}\x06d\x01\xa0\x03d\td\n\x84\x00|\x06D\x00\x83\x01\xa1\x01}\x07t\x01d\x02t\x02|\x07\x83\x01d\x0b\x83\x03D\x00]V}\x08|\x07|\x08|\x08d\x0b\x17\x00\x85\x02\x19\x00}\tt\x02|\t\x83\x01d\x0bk\x00r\xc2|\x02d\x0bt\x02|\t\x83\x01\x18\x007\x00}\x02|\td\x0cd\x0bt\x02|\t\x83\x01\x18\x00\x14\x007\x00}\t|\x01|\x03t\x04|\td\r\x83\x02\x19\x007\x00}\x01q~qF|\x01d\x0e|\x02d\r\x1a\x00\x14\x007\x00}\x01t\x01t\x02|\x01\x83\x01d\r\x1a\x00\x83\x01D\x00]L}\x05|\x01|\x05d\r\x14\x00\x19\x00}\n|\x01|\x05d\r\x14\x00d\x06\x17\x00\x19\x00}\x0b|\x01d\x00|\x05d\r\x14\x00\x85\x02\x19\x00|\x0b\x17\x00|\n\x17\x00|\x01|\x05d\r\x14\x00d\r\x17\x00d\x00\x85\x02\x19\x00\x17\x00}\x01q\xf8|\x01S\x00'
, (
None
, '
', 0, '
ZQ
+
U7tSBEKVzyf5coCwb94Dd6raT0eLNin12Hp8mOxFuvMgIPlhRY3WjksqJAXG
/
', b'
', 85, 1, '
little
', 3, compile('
', '
', '
exec
').replace(1, (), b'
|\x00]\x10}\x01t\x00|\x01d\x00\x83\x02V\x00\x01\x00q\x02d\x01S\x00
', ('
08b
', None), '
', 19, 115, (), 0, b'
', '
', ('
format
',), 2, 0, 4, ('
.
0
', '
byte
'), **('
co_argcount
', '
co_cellvars
', '
co_code
', '
co_consts
', '
co_filename
', '
co_firstlineno
', '
co_flags
', '
co_freevars
', '
co_kwonlyargcount
', '
co_lnotab
', '
co_name
', '
co_names
', '
co_nlocals
', '
co_posonlyargcount
', '
co_stacksize
', '
co_varnames
')), '
', 6, '
0
', 2, '
!
'), '
', 4, 67, (), 0, b'
', '
', ('
to_bytes
', '
range
', '
len
', '
join
', '
int
'), 12, 0, 7, ('
data
', '
encoded_str
', '
padding
', '
base64_chars
', '
ww
', '
i
', '
chunk
', '
binary_str
', '
j
', '
six_bits
', '
a
', '
b
'), **('
co_argcount
', '
co_cellvars
', '
co_code
', '
co_consts
', '
co_filename
', '
co_firstlineno
', '
co_flags
', '
co_freevars
', '
co_kwonlyargcount
', '
co_lnotab
', '
co_name
', '
co_names
', '
co_nlocals
', '
co_posonlyargcount
', '
co_stacksize
', '
co_varnames'))
main.__code__
=
a
import
dis
import
marshal
def
f():
return
inner
=
compile
('
', '
', '
exec
').replace(co_argcount=1, co_cellvars=(), co_code=b'
|\x00]\x10}\x01t\x00|\x01d\x00\x83\x02V\x00\x01\x00q\x02d\x01S\x00
', co_consts=('
08b
', None), co_filename='
', co_firstlineno=19, co_flags=115, co_freevars=(), co_kwonlyargcount=0, co_name='
', co_names=('
format
',), co_nlocals=2, co_posonlyargcount=0, co_stacksize=4, co_varnames=('
.
0
', '
byte'))
a
=
f.__code__.replace(co_argcount
=
1
, co_cellvars
=
(), co_code
=
b
'd\x01}\x01d\x02}\x02d\x03}\x03d\x04}\x04|\x00D\x00]\x1c}\x05|\x05d\x05A\x00}\x05|\x04|\x05\xa0\x00d\x06d\x07\xa1\x02\x17\x00}\x04q\x14|\x04}\x00t\x01d\x02t\x02|\x00\x83\x01d\x08\x83\x03D\x00]\x90}\x05|\x00|\x05|\x05d\x08\x17\x00\x85\x02\x19\x00}\x06d\x01\xa0\x03d\td\n\x84\x00|\x06D\x00\x83\x01\xa1\x01}\x07t\x01d\x02t\x02|\x07\x83\x01d\x0b\x83\x03D\x00]V}\x08|\x07|\x08|\x08d\x0b\x17\x00\x85\x02\x19\x00}\tt\x02|\t\x83\x01d\x0bk\x00r\xc2|\x02d\x0bt\x02|\t\x83\x01\x18\x007\x00}\x02|\td\x0cd\x0bt\x02|\t\x83\x01\x18\x00\x14\x007\x00}\t|\x01|\x03t\x04|\td\r\x83\x02\x19\x007\x00}\x01q~qF|\x01d\x0e|\x02d\r\x1a\x00\x14\x007\x00}\x01t\x01t\x02|\x01\x83\x01d\r\x1a\x00\x83\x01D\x00]L}\x05|\x01|\x05d\r\x14\x00\x19\x00}\n|\x01|\x05d\r\x14\x00d\x06\x17\x00\x19\x00}\x0b|\x01d\x00|\x05d\r\x14\x00\x85\x02\x19\x00|\x0b\x17\x00|\n\x17\x00|\x01|\x05d\r\x14\x00d\r\x17\x00d\x00\x85\x02\x19\x00\x17\x00}\x01q\xf8|\x01S\x00'
, co_consts
=
(
None
, '
', 0, '
ZQ
+
U7tSBEKVzyf5coCwb94Dd6raT0eLNin12Hp8mOxFuvMgIPlhRY3WjksqJAXG
/
', b'
', 85, 1, '
little
', 3, inner, '
', 6, '
0
', 2, '
!
'), co_filename='
', co_firstlineno=4, co_flags=67, co_freevars=(), co_kwonlyargcount=0, co_name='
', co_names=('
to_bytes
', '
range
', '
len
', '
join
', '
int
'), co_nlocals=12, co_posonlyargcount=0, co_stacksize=7, co_varnames=('
data
', '
encoded_str
', '
padding
', '
base64_chars
', '
ww
', '
i
', '
chunk
', '
binary_str
', '
j
', '
six_bits
', '
a
', '
b'))
f.__code__
=
a
marshal.dump(f.__code__,
open
(
'test.dump'
,
'wb'
))
import
dis
import
marshal
def
f():
return
inner
=
compile
('
', '
', '
exec
').replace(co_argcount=1, co_cellvars=(), co_code=b'
|\x00]\x10}\x01t\x00|\x01d\x00\x83\x02V\x00\x01\x00q\x02d\x01S\x00
', co_consts=('
08b
', None), co_filename='
', co_firstlineno=19, co_flags=115, co_freevars=(), co_kwonlyargcount=0, co_name='
', co_names=('
format
',), co_nlocals=2, co_posonlyargcount=0, co_stacksize=4, co_varnames=('
.
0
', '
byte'))
a
=
f.__code__.replace(co_argcount
=
1
, co_cellvars
=
(), co_code
=
b
'd\x01}\x01d\x02}\x02d\x03}\x03d\x04}\x04|\x00D\x00]\x1c}\x05|\x05d\x05A\x00}\x05|\x04|\x05\xa0\x00d\x06d\x07\xa1\x02\x17\x00}\x04q\x14|\x04}\x00t\x01d\x02t\x02|\x00\x83\x01d\x08\x83\x03D\x00]\x90}\x05|\x00|\x05|\x05d\x08\x17\x00\x85\x02\x19\x00}\x06d\x01\xa0\x03d\td\n\x84\x00|\x06D\x00\x83\x01\xa1\x01}\x07t\x01d\x02t\x02|\x07\x83\x01d\x0b\x83\x03D\x00]V}\x08|\x07|\x08|\x08d\x0b\x17\x00\x85\x02\x19\x00}\tt\x02|\t\x83\x01d\x0bk\x00r\xc2|\x02d\x0bt\x02|\t\x83\x01\x18\x007\x00}\x02|\td\x0cd\x0bt\x02|\t\x83\x01\x18\x00\x14\x007\x00}\t|\x01|\x03t\x04|\td\r\x83\x02\x19\x007\x00}\x01q~qF|\x01d\x0e|\x02d\r\x1a\x00\x14\x007\x00}\x01t\x01t\x02|\x01\x83\x01d\r\x1a\x00\x83\x01D\x00]L}\x05|\x01|\x05d\r\x14\x00\x19\x00}\n|\x01|\x05d\r\x14\x00d\x06\x17\x00\x19\x00}\x0b|\x01d\x00|\x05d\r\x14\x00\x85\x02\x19\x00|\x0b\x17\x00|\n\x17\x00|\x01|\x05d\r\x14\x00d\r\x17\x00d\x00\x85\x02\x19\x00\x17\x00}\x01q\xf8|\x01S\x00'
, co_consts
=
(
None
, '
', 0, '
ZQ
+
U7tSBEKVzyf5coCwb94Dd6raT0eLNin12Hp8mOxFuvMgIPlhRY3WjksqJAXG
/
', b'
', 85, 1, '
little
', 3, inner, '
', 6, '
0
', 2, '
!
'), co_filename='
', co_firstlineno=4, co_flags=67, co_freevars=(), co_kwonlyargcount=0, co_name='
', co_names=('
to_bytes
', '
range
', '
len
', '
join
', '
int
'), co_nlocals=12, co_posonlyargcount=0, co_stacksize=7, co_varnames=('
data
', '
encoded_str
', '
padding
', '
base64_chars
', '
ww
', '
i
', '
chunk
', '
binary_str
', '
j
', '
six_bits
', '
a
', '
b'))
f.__code__
=
a
marshal.dump(f.__code__,
open
(
'test.dump'
,
'wb'
))
encoded_str
=
''
padding
=
0
base64_chars
=
'ZQ+U7tSBEKVzyf5coCwb94Dd6raT0eLNin12Hp8mOxFuvMgIPlhRY3WjksqJAXG/'
ww
=
b''
for
i
in
data:
i
=
i ^
85
ww
=
ww
+
i.to_bytes(
1
,
'little'
)
data
=
ww
for
i
in
range
(
0
,
len
(data),
3
):
chunk
=
data[i:i
+
3
]
binary_str
=
''.join((
lambda
.
0
:
for
byte
in
.
0
:
format
(byte,
'08b'
))(chunk))
for
j
in
range
(
0
,
len
(binary_str),
6
):
six_bits
=
binary_str[j:j
+
6
]
if
len
(six_bits) <
6
:
padding
+
=
6
-
len
(six_bits)
six_bits
+
=
'0'
*
(
6
-
len
(six_bits))
encoded_str
+
=
base64_chars[
int
(six_bits,
2
)]
encoded_str
+
=
'!'
*
(padding
/
/
2
)
for
i
in
range
(
len
(encoded_str)
/
/
2
):
a
=
encoded_str[i
*
2
]
b
=
encoded_str[i
*
2
+
1
]
encoded_str
=
encoded_str[:i
*
2
]
+
b
+
a
+
encoded_str[i
*
2
+
2
:]
return
encoded_str
encoded_str
=
''
padding
=
0
base64_chars
=
'ZQ+U7tSBEKVzyf5coCwb94Dd6raT0eLNin12Hp8mOxFuvMgIPlhRY3WjksqJAXG/'
ww
=
b''
for
i
in
data:
i
=
i ^
85
ww
=
ww
+
i.to_bytes(
1
,
'little'
)
data
=
ww
for
i
in
range
(
0
,
len
(data),
3
):
chunk
=
data[i:i
+
3
]
binary_str
=
''.join((
lambda
.
0
:
for
byte
in
.
0
:
format
(byte,
'08b'
))(chunk))
for
j
in
range
(
0
,
len
(binary_str),
6
):
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2024-8-21 19:03
被tacesrever编辑
,原因: