黄河流域公安院校网络空间安全技能挑战赛 QAQ 题解

目录

一.获取pyc文件

二.反编译出.py源码

三.程序逻辑

1.第一个限制条件

2.第二段

3.第三段


这题是对python打包成的可执行程序逆向

如果对如何反编译.pyc和.py文件有疑问可以参考:

Python逆向基本操作步骤——以杭电新生赛hgame week2 reverse stream(python3.10逆向)为例

一.获取pyc文件

在qaq.exe所在目录打开cmd使用命令:python pyinstxtractor.py qaq.exe

成功后会输出一个_extracted文件夹

在文件夹内找到qaq.pyc和struct.pyc这两个文件

 用winhex或者其他软件打开,查看16进制下的信息,前两行是magic head,这里qaq.pyc和struct.pyc文件的前两行相同,所以不需要修复

二.反编译出.py源码

在qaq.pyc文件所在目录打开cmd,使用命令: pycdc.exe qaq.pyc,成功输出源码

en = [
    3,
    37,
    72,
    11,
    6,
    132]
output = [
    105,
    97,
    23,
    78,
    121,
    48,
    108,
    65,
    99,
    52,
    181,
    177,
    98,
    53,
    67,
    29,
    41,
    120,
    60,
    101,
    51,
    103,
    105,
    109,
    121,
    50]
print('welcome to SDPCSEC2023')
flag = input('please input your flag:')
str = flag
a = len(str)    #flag长度>=37
if a < 37:
    print('lenth wrong!')
    exit(0)             #前四个字符的限制条件
if ord(str[0]) + 2023 * ord(str[1]) + 2023 * ord(str[2]) + 2023 * ord(str[3]) == 623186:    #第一个限制条件
    print('good!continue')
else:
    print('bye~')
    exit(0)

# f}Mj bjk2x1Jg2e516a8f0an7a5éí1z
x = []
k = 5           #中间26个,所以flag[4]需要爆破
for i in range(13): #0到12
    b = ord(str[k])     #第六个字符,8,10,12
    c = ord(str[k + 1]) #第七个字符,9,11,13
    a11 = c ^ en[i % 6]
    a22 = b ^ en[i % 6]
    x.append(a11)   #先添加奇数下标对应字符
    x.append(a22)   #每次循环添加两个字符
    k += 2
if x == output:
    print('good!continue')
else:
    print('oh,you are wrong!')
    exit(0)
l = len(str)
v1 = ord(str[l - 7])    #倒数第七个
v2 = ord(str[l - 6])
v3 = ord(str[l - 5])
v4 = ord(str[l - 4])
v5 = ord(str[l - 3])
v6 = ord(str[l - 2])    #倒数第二个
#aef_75
if v1 * 3 + v2 * 2 + v3 * 5 == 1003 and v1 * 4 + v2 * 7 + v3 * 9 == 2013 and v1 + v2 * 8 + v3 * 2 == 1109 and v1 * 3 + v5 * 2 + v6 * 5 == 671 and v4 * 4 + v5 * 7 + v6 * 9 == 1252 and v4 + v5 * 8 + v6 * 2 == 644:
    print('you get the right flag!')

三.程序逻辑

1.第一个限制条件

if ord(str[0]) + 2023 * ord(str[1]) + 2023 * ord(str[2]) + 2023 * ord(str[3]) == 623186:

当时很奇怪的是只有对前四个字符这一条限制条件,这一条方程组如果爆破的话会有很多组解

而且对第五个字符并没有任何操作,后续突然明白前五个字符和最后一个字符是 flag{} 

2.第二段

这段代码的作用是对flag[]下标为5到30的共26个字符进行加密,仔细看是简单的异或操作

x = []
k = 5           #中间26个,所以flag[4]需要爆破
for i in range(13): #0到12
    b = ord(str[k])     #第六个字符,8,10,12
    c = ord(str[k + 1]) #第七个字符,9,11,13
    a11 = c ^ en[i % 6]
    a22 = b ^ en[i % 6]
    x.append(a11)   #先添加奇数下标对应字符
    x.append(a22)   #每次循环添加两个字符
    k += 2
if x == output:

脚本:

out = [
    105,
    97,
    23,
    78,
    121,
    48,
    108,
    65,
    99,
    52,
    181,
    177,
    98,
    53,
    67,
    29,
    41,
    120,
    60,
    101,
    51,
    103,
    105,
    109,
    121,
    50]

en = [
    3,
    37,
    72,
    11,
    6,
    132]

k=0
s=""
for i in range(13):
    a11=out[k]
    a22=out[k+1]
    b=a22^en[i%6]
    c=a11^en[i%6]
    s+=chr(b)
    s+=chr(c)
    k+=2
print(s)

得到中间26个字符:bjk2x1Jg2e516a8f0an7a5éí1z

3.第三段

这段是对倒数第七个到倒数第二个共6个字符进行限制,这里给了6个判断式也就是6组方程组,所以可以解出这6个字符

不过值得一提的是,题目有点问题: 第四个判断条件 v1 * 3 + v5 * 2 + v6 * 5 == 671 是有问题的,询问过出题人得知v1应该改成v4(这里已经修改过了)

l = len(str)
v1 = ord(str[l - 7])    #倒数第七个
v2 = ord(str[l - 6])
v3 = ord(str[l - 5])
v4 = ord(str[l - 4])
v5 = ord(str[l - 3])
v6 = ord(str[l - 2])    #倒数第二个
#aef_75
if v1 * 3 + v2 * 2 + v3 * 5 == 1003 and v1 * 4 + v2 * 7 + v3 * 9 == 2013 and v1 + v2 * 8 + v3 * 2 == 1109 and v4 * 3 + v5 * 2 + v6 * 5 == 671 and v4 * 4 + v5 * 7 + v6 * 9 == 1252 and v4 + v5 * 8 + v6 * 2 == 644:
    print('you get the right flag!')

系数矩阵:

3 2 5 0 0 0 |1003
4 7 9 0 0 0 |2013
1 8 2 0 0 0 |1109
0 0 0 3 2 5 |671
0 0 0 4 7 9 |1252
0 0 0 1 8 2 |644

在线解方程:

这六个字符是:aeff73

所以最后的flag是:flag{bjk2x1Jg2e516a8f0an7a5éí1zaeff73}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

OrientalGlass

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值