首页
课程
问答
CTF
社区
招聘
峰会
发现
排行榜
知识库
工具下载
看雪20年
看雪商城
证书查询
登录
注册
首页
社区
课程
招聘
发现
问答
CTF
排行榜
知识库
工具下载
峰会
看雪商城
证书查询
社区
CTF对抗
发新帖
1
0
[原创]KCTF2026 第二题:巳时·绿光幽语
发表于: 2026-8-12 01:29
661
[原创]KCTF2026 第二题:巳时·绿光幽语
SydzI
1
2026-8-12 01:29
661
附件是python打包程序,运行后提示输入key  pyinstxtractor解包后对main.pyc进行反编译发现没有实际内容  分析剩余pyc文件均未发现异常,base_library.zip中的内容也无异常,最终在python313.dll中找到my_function字样  让ai将这部分内容提取成pyc文件,使用工具反编译pyc文件就可以得到如下内容: ``` x = 0 if x < 20: def my_function(): print(666) try: x += 1 buffer = b''.join([b'\xb3\xda\xc5\xb2\xf1\xef\xba\xe9\xd9\xbc\xc9\xd5\xbd\xf3\xd4\xbd', b'\xea\xcd\xb0\xdb\xca\xb2\xcf\xd1\xb1\xee\xf6\xb2\xf5\xd4X_', b'103u8,\n3 ;6!<:;}', b"|oX_\\%'<;!}w\xb3\xd4\xf8\xb0", b'\xc3\xc9\xb3\xdd\xc5\xb0\xdf\xca\xba\xe9\xd4w|X_\xbd', b'\xfa\xe2\xbd\xeb\xc6\xb0\xd0\xf0>0,\xbd\xea\xcd\xb0\xdb', b'\xca\xb1\xee\xf6\xb2\xf5\xd4\xba\xe9\xdd\xbd\xfa\xe2\xbd\xeb\xc6', b'\xb0\xd0\xf0c\xb1\xed\xff\xb0\xf8\xc2\xb2\xf9\xf3\xba\xe9\xdc']) w = b'' for i in buffer: b = i ^ 85 w += b.to_bytes(1) print(w.decode('utf-8')) key = input() else: c = b'\xecbmucryb6tcr*c\x03ucryb6tCr\x1eb' buf = b'' for i in range(len(c)): buf += (c[i] ^ b_key[i % len(b_key)]).to_bytes(1) my = my_function.__code__ my = my.replace(co_code=buf) buf = b'' succ = b'\x9f\xe3\x9b\x91\xf5\xee\x9f\xea\xa6\x91\xe9\xed\x96\xde\xb7' for i in range(len(succ)): buf += (succ[i] ^ b_key[i % len(b_key)]).to_bytes(1) my = my.replace(co_consts=(None, buf.decode('utf-8'))) my_function.__code__ = my my_function() except Exception as e: pass ``` 反编译结果不是很正确,交给ai梳理纠正一下就可以得到 ``` x = 0 while x < 20: def my_function(): print(666) try: x += 1 buffer = b"".join( [ b"\xb3\xda\xc5\xb2\xf1\xef\xba\xe9\xd9\xbc\xc9\xd5\xbd\xf3\xd4\xbd", b"\xea\xcd\xb0\xdb\xca\xb2\xcf\xd1\xb1\xee\xf6\xb2\xf5\xd4X_", b"103u8,\n3 ;6!<:;}", b"|oX_\\%'<;!}w\xb3\xd4\xf8\xb0", b"\xc3\xc9\xb3\xdd\xc5\xb0\xdf\xca\xba\xe9\xd4w|X_\xbd", b"\xfa\xe2\xbd\xeb\xc6\xb0\xd0\xf0>0,\xbd\xea\xcd\xb0\xdb", b"\xca\xb1\xee\xf6\xb2\xf5\xd4\xba\xe9\xdd\xbd\xfa\xe2\xbd\xeb\xc6", b"\xb0\xd0\xf0c\xb1\xed\xff\xb0\xf8\xc2\xb2\xf9\xf3\xba\xe9\xdc", ] ) w = b"" for i in buffer: b = i ^ 85 w += b.to_bytes(1) print(w.decode("utf-8")) key = input() if len(key) != 6: continue b_key = key.encode() c = b"\xecbmucryb6tcr*c\x03ucryb6tCr\x1eb" buf = b"" for i in range(len(c)): value = c[i] ^ b_key[i % len(b_key)] buf += value.to_bytes(1) my = my_function.__code__ my = my.replace(co_code=buf) succ = b"\x9f\xe3\x9b\x91\xf5\xee\x9f\xea\xa6\x91\xe9\xed\x96\xde\xb7" buf = b"" for i in range(len(succ)): value = succ[i] ^ b_key[i % len(b_key)] buf += value.to_bytes(1) my = my.replace( co_consts=(None, buf.decode("utf-8")) ) my_function.__code__ = my my_function() except Exception: continue ``` 复现print(w.decode())这一段可以得到运行程序时得到的提示,由此可知找到了程序真正的执行逻辑。 后续输入的key作为异或参数解密c和succ,而c和succ解密后被替换进了my_function.__code__中的co_code和co_consts,由于提示中字符串常量是“恭喜成功!”,可以利用这点,结合succ得到异或使用的key ``` cipher = b"\x9f\xe3\x9b\x91\xf5\xee\x9f\xea\xa6\x91\xe9\xed\x96\xde\xb7" known = "恭喜成功!".encode("utf-8") key = bytes( c ^ p for c, p in zip(cipher, known) ) print(key) #b'yb6tcryb6tcryb6' ``` 最终得到key=yb6tcr 本题实际上是利用了python 3.11后的版本所支持的frozen modules技术,该技术可以将某些模块预编译并直接嵌入到解释器中,而非从.pyc文件动态加载。这也解释了python程序解包后的*.pyc里都无法找到相关线索的问题。 参考: frozen modules技术介绍:<mark class="encrypted">a05K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2U0L8X3u0D9L8$3N6K6i4K6u0W2j5$3!0E0i4K6u0r3M7$3#2S2M7Y4c8D9K9Y4W2Q4x3V1k6H3i4K6u0r3x3e0R3$3z5e0V1^5y4K6R3`.</mark> python字节码__code__介绍:<mark class="encrypted">ceaK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6U0N6r3k6H3P5i4u0W2j5X3!0G2K9#2)9J5k6h3N6A6N6r3S2#2j5W2)9J5k6h3W2G2i4K6u0r3b7#2c8r3f1s2W2d9k6f1u0G2L8$3E0Q4x3V1j5J5i4K6u0W2x3#2m8&6b7$3!0V1k6f1!0T1K9X3g2U0N6q4)9J5k6h3S2@1L8h3H3`.</mark> pyc反编译工具:<mark class="encrypted">4ebK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6H3P5h3I4A6L8X3N6#2j5h3I4Q4x3X3g2A6L8#2)9J5c8R3`.`.</mark> python313.dll提取pyc脚本: ``` import dis import importlib._bootstrap_external import marshal import pathlib import types def main() -> None: root = next(p for p in pathlib.Path(".").iterdir() if p.name.endswith("exe_extracted") and p.is_dir()) dll_path = root / "python313.dll" dll = dll_path.read_bytes() anchor = dll.find(b"OS routines for NT or Posix depending on what system we're on.") if anchor < 0: raise RuntimeError("failed to locate os module docstring in python313.dll") outer = None outer_off = None for start in range(anchor - 0x2000, anchor): if dll[start] not in (0x63, 0xE3): continue try: obj = marshal.loads(dll[start:]) except Exception: continue if not isinstance(obj, types.CodeType): continue if obj.co_name == "<module>" and obj.co_filename == "<frozen os>" and "my_function" in obj.co_names: outer = obj outer_off = start break if outer is None or outer_off is None: raise RuntimeError("failed to locate outer malicious <frozen os> code object") print("dll =", dll_path) print("outer module offset =", hex(outer_off)) print("co_name =", outer.co_name) print("co_filename =", outer.co_filename) print("co_firstlineno =", outer.co_firstlineno) print("len(co_code) =", len(outer.co_code)) print("len(co_consts) =", len(outer.co_consts)) print("len(co_names) =", len(outer.co_names)) print("tail names =", outer.co_names[-20:]) out = pathlib.Path("outer_module_dis.txt") with out.open("w", encoding="utf-8") as f: f.write(f"offset: {hex(outer_off)}\n") f.write(f"co_name: {outer.co_name}\n") f.write(f"co_filename: {outer.co_filename}\n") f.write(f"co_firstlineno: {outer.co_firstlineno}\n") f.write(f"len(co_code): {len(outer.co_code)}\n") f.write(f"len(co_consts): {len(outer.co_consts)}\n") f.write(f"len(co_names): {len(outer.co_names)}\n") f.write(f"tail names: {outer.co_names[-20:]}\n\n") dis.dis(outer, file=f) pyc_out = pathlib.Path("outer_frozen_os.pyc") pyc_out.write_bytes( importlib._bootstrap_external._code_to_timestamp_pyc(outer, mtime=0, source_size=0) ) marshal_out = pathlib.Path("outer_frozen_os.marshal") marshal_out.write_bytes(marshal.dumps(outer, 5)) print("wrote", out) print("wrote", pyc_out) print("wrote", marshal_out) if __name__ == "__main__": main() ```
登录后可查看完整内容
传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!!
收藏
・
1
点赞
・
0
打赏
分享
分享到微信
分享到QQ
分享到微博
赞赏记录
参与人
雪币
留言
时间
查看更多
赞赏
×
1 雪花
5 雪花
10 雪花
20 雪花
50 雪花
80 雪花
100 雪花
150 雪花
200 雪花
支付方式:
微信支付
赞赏留言:
快捷留言
感谢分享~
精品文章~
原创内容~
精彩转帖~
助人为乐~
感谢分享~
最新回复
(
0
)
游客
登录
|
注册
方可回帖
回帖
表情
雪币赚取及消费
高级回复
返回
SydzI
1
3
发帖
0
回帖
60
RANK
关注
私信
他的文章
[原创]KCTF2026 第二题:巳时·绿光幽语
661
从NCTF2026-NoMyBank!到Godot新特性下的游戏逆向分析破解
3608
[原创][新手向]Moectf2025 Reverse方向全解
12105
关于我们
联系我们
企业服务
看雪公众号
专注于PC、移动、智能设备安全研究及逆向工程的开发者社区
看原图
赞赏
×
雪币:
+
留言:
快捷留言
为你点赞!
返回
顶部