首页
社区
课程
招聘
[原创]看雪 KCTF 2024 第四题 神秘信号 Writeup
发表于: 2024-8-22 11:23 3777

[原创]看雪 KCTF 2024 第四题 神秘信号 Writeup

2024-8-22 11:23
3777

此题一看文件就应该是被打包了的PYTHON脚本,解题思路就是拦截PYC文件数据的字节码,并对其反编译,对编译出来的源码分析算法得到注册码.

1.抓取PYC:

用x64dbg加载main.exe,跑起来,等它加载python38.dll,之后在python38.dl中的PyMarshal_ReadObjectFromString下断,重新加载main.exe,再运行,就会在PyMarshal_ReadObjectFromString断下,这时rcx,rdx分别是PYC文件数据的地址和长度,逐一查看加载的被打包了的PYC文件,当数据中出现程序运行时的提示时串(Success, Fail等字符串)时就是主程序的PYC文件数据,就可以将这段PYC文件数据抓出,但这个数据是没有PYC文件头的,随便复制一个_internal\base_library.zip中的PYC文件的前0x10个字节(PYC文件头) 550D0D0A010000000000000000000000插入到抓出的数据前,再另存为main.pyc.这时抓取结束.

2.反编译main.pyc文件:

反编译时出错,不能生成py源码,好在文件比较小:

这时可以得到:

3.算法分析及求解:
由于程序比较简单,分析一下可以得到大致源码是这样的:

可以看到源码中对账号计算后的结果的长度有两种处理方式:
len(z)<20时key = "dZpKdrsiB6cndrGY" + z
否则为key = z[0:4] + ("dZpK") + z[4:8] + ("drsi") + z[8:12] + ("B6cn") + z[12:16] + ("drGY") + z[16:]
之后再对验证码用同账号一样的算法得到另一个z,再同key比较.

结合给出的一组注册码:
账号:D7C4197AF0806891
验证码:D7CHel419lo 7AFWor080ld!6891
对照以上分析的源码分析,这是用的第二种,可以看出CrackMe.main是将输入的串每3一个组来处理(若有余下不足3个的也一组),变成每4个一组. 常量串“dZpK”, ”drsi”, “B6cn”, “drGY” 分别对应的是 “Hel”, “lo “, “Wor”, “ld!”.及”dZpKdrsiB6cndrGY”对应”Hello World!”,而且对账号和验证码用的是同一算法再比较,所以其实就是将输入串和常量串”Hello World!” 3个一组变换得到验证码..根据分析可得到KeyGen代码:

最终得到:

KCTF
Hello World!KCTF

uncompyle6 main.pyc
uncompyle6 main.pyc
pydisasm main.pyc
pydisasm main.pyc
1:           0 LOAD_CONST           (0)
              2 LOAD_CONST           (None)
              4 IMPORT_NAME          (CrackMe)
              6 STORE_NAME           (CrackMe)
 
 3:     >>    8 LOAD_NAME            (print)
             10 LOAD_CONST           ("(账号密码由字母大小写、数字、!、空格组成)")
             12 CALL_FUNCTION        (1 positional argument)
             14 POP_TOP
 
 4:          16 LOAD_NAME            (print)
             18 LOAD_CONST           ("请输入账号:")
             20 CALL_FUNCTION        (1 positional argument)
             22 POP_TOP
 
 5:          24 LOAD_NAME            (input)
             26 CALL_FUNCTION        (0 positional arguments)
             28 STORE_NAME           (h)
 
 6:          30 LOAD_NAME            (CrackMe)
             32 LOAD_METHOD          (main)
             34 LOAD_NAME            (h)
             36 CALL_METHOD          (1 positional argument)
             38 STORE_NAME           (z)
 
 7:          40 LOAD_NAME            (len)
             42 LOAD_NAME            (z)
             44 CALL_FUNCTION        (1 positional argument)
             46 LOAD_CONST           (20)
             48 COMPARE_OP           (<)
             50 POP_JUMP_IF_FALSE    (to 62)
 
 8:          52 LOAD_CONST           ("dZpKdrsiB6cndrGY")
             54 LOAD_NAME            (z)
             56 BINARY_ADD
             58 STORE_NAME           (key)
             60 JUMP_FORWARD         (to 138)
 
10:     >>   62 LOAD_NAME            (z)
             64 LOAD_CONST           (0)
             66 LOAD_CONST           (4)
             68 BUILD_SLICE          2
             70 BINARY_SUBSCR
             72 LOAD_CONST           ("dZpK")
             74 BINARY_ADD
             76 LOAD_NAME            (z)
             78 LOAD_CONST           (4)
             80 LOAD_CONST           (8)
             82 BUILD_SLICE          2
             84 BINARY_SUBSCR
             86 BINARY_ADD
             88 LOAD_CONST           ("drsi")
             90 BINARY_ADD
             92 LOAD_NAME            (z)
             94 LOAD_CONST           (8)
             96 LOAD_CONST           (12)
             98 BUILD_SLICE          2
            100 BINARY_SUBSCR
            102 BINARY_ADD
            104 LOAD_CONST           ("B6cn")
            106 BINARY_ADD
            108 LOAD_NAME            (z)
            110 LOAD_CONST           (12)
            112 LOAD_CONST           (16)
            114 BUILD_SLICE          2
            116 BINARY_SUBSCR
            118 BINARY_ADD
            120 LOAD_CONST           ("drGY")
            122 BINARY_ADD
            124 LOAD_NAME            (z)
            126 LOAD_CONST           (16)
            128 LOAD_CONST           (None)
            130 BUILD_SLICE          2
            132 BINARY_SUBSCR
            134 BINARY_ADD
            136 STORE_NAME           (key)
 
11:     >>  138 LOAD_NAME            (print)
            140 LOAD_CONST           ("请输入验证码:")
            142 CALL_FUNCTION        (1 positional argument)
            144 POP_TOP
 
12:         146 LOAD_NAME            (input)
            148 CALL_FUNCTION        (0 positional arguments)
            150 STORE_NAME           (h)
 
13:         152 LOAD_NAME            (CrackMe)
            154 LOAD_METHOD          (main)
            156 LOAD_NAME            (h)
            158 CALL_METHOD          (1 positional argument)
            160 STORE_NAME           (m)
 
14:         162 LOAD_NAME            (key)
            164 LOAD_NAME            (m)
            166 COMPARE_OP           (==)
            168 POP_JUMP_IF_FALSE    (to 182)
 
15:         170 LOAD_NAME            (print)
            172 LOAD_CONST           ("Success")
            174 CALL_FUNCTION        (1 positional argument)
            176 POP_TOP
 
16:         178 JUMP_ABSOLUTE        (to 194)
            180 JUMP_ABSOLUTE        (to 8)
 
18:     >>  182 LOAD_NAME            (print)
            184 LOAD_CONST           ("Fail")
            186 CALL_FUNCTION        (1 positional argument)
            188 POP_TOP
 
19:         190 JUMP_ABSOLUTE        (to 8)
            192 JUMP_ABSOLUTE        (to 8)
        >>  194 LOAD_CONST           (None)
            196 RETURN_VALUE
1:           0 LOAD_CONST           (0)
              2 LOAD_CONST           (None)
              4 IMPORT_NAME          (CrackMe)
              6 STORE_NAME           (CrackMe)
 
 3:     >>    8 LOAD_NAME            (print)
             10 LOAD_CONST           ("(账号密码由字母大小写、数字、!、空格组成)")
             12 CALL_FUNCTION        (1 positional argument)
             14 POP_TOP
 
 4:          16 LOAD_NAME            (print)
             18 LOAD_CONST           ("请输入账号:")
             20 CALL_FUNCTION        (1 positional argument)
             22 POP_TOP
 
 5:          24 LOAD_NAME            (input)
             26 CALL_FUNCTION        (0 positional arguments)
             28 STORE_NAME           (h)
 
 6:          30 LOAD_NAME            (CrackMe)
             32 LOAD_METHOD          (main)
             34 LOAD_NAME            (h)
             36 CALL_METHOD          (1 positional argument)
             38 STORE_NAME           (z)
 
 7:          40 LOAD_NAME            (len)
             42 LOAD_NAME            (z)
             44 CALL_FUNCTION        (1 positional argument)
             46 LOAD_CONST           (20)
             48 COMPARE_OP           (<)
             50 POP_JUMP_IF_FALSE    (to 62)
 
 8:          52 LOAD_CONST           ("dZpKdrsiB6cndrGY")
             54 LOAD_NAME            (z)
             56 BINARY_ADD
             58 STORE_NAME           (key)
             60 JUMP_FORWARD         (to 138)
 
10:     >>   62 LOAD_NAME            (z)
             64 LOAD_CONST           (0)
             66 LOAD_CONST           (4)
             68 BUILD_SLICE          2
             70 BINARY_SUBSCR
             72 LOAD_CONST           ("dZpK")
             74 BINARY_ADD
             76 LOAD_NAME            (z)
             78 LOAD_CONST           (4)
             80 LOAD_CONST           (8)
             82 BUILD_SLICE          2
             84 BINARY_SUBSCR
             86 BINARY_ADD
             88 LOAD_CONST           ("drsi")
             90 BINARY_ADD
             92 LOAD_NAME            (z)
             94 LOAD_CONST           (8)
             96 LOAD_CONST           (12)
             98 BUILD_SLICE          2
            100 BINARY_SUBSCR
            102 BINARY_ADD
            104 LOAD_CONST           ("B6cn")
            106 BINARY_ADD
            108 LOAD_NAME            (z)
            110 LOAD_CONST           (12)
            112 LOAD_CONST           (16)
            114 BUILD_SLICE          2
            116 BINARY_SUBSCR

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 1
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//