[羊城杯 2020]Bytecode [UTCTF2020]babymips

本文详细介绍了如何将Python字节码转换为可读代码,并使用Z3约束解决CTF挑战。文章通过实例展示了字节码解释、Z3脚本的关键点,如BINARY_SUBTRACT和BINARY_SUBSCR操作。同时,提到了在jeb和IDA中分析MIPS代码的注意事项,包括地址解析和长度验证。最后,提供了解密字符串的方法和最终的解密结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

[羊城杯 2020]Bytecode

查看题目

在这里插入图片描述
python字节码,需要把它转为python代码,如下:

python代码

import dis

def main():
    en=[3,37,72,9,6,132]
    output=[101,96,23,68,112,42,107,62,96,53,176,179,98,53,67,29,41,120,60,106,51,101,178,189,101,48]
    print("welcome to GWHT2020")
    flag=raw_input("please input your flag:")
    str=flag
    a=len(str)
    if a>=38:
        print('lenth wrong!')
        exit(0)
    if((((ord(str[0])*2020+ord(str[1]))*2020+ord(str[2]))*2020+ord(str[3]))*2020+ord(str[4]))*2020==1182843538814603:
        print('good!continue\xe2\x80\xa6\xe2\x80\xa6')
        x=[]
        k=5
        for i in range(13):
            b=ord(str[k])
            c=ord(str[k+1])
            a11=c^(en[i%6])
            a22=b^(en[i%6])
            x.append(a11)
            x.append(a22)
            k+=2
        if x==output:
            print("good!continue\xe2\x80\xa6\xe2\x80\xa6")
            l=len(str)
            a1=ord(str[l-7])
            a2=ord(str[l-6])
            a3=ord(str[l-5])
            a4=ord(str[l-4])
            a5=ord(str[l-3])
            a6=ord(str[l-2])
            if a1*3+a2*2+a3*5==1003:
                if a1*4+a2*7+a3*9==2013:
                    if a1+a2*8+a3*2==1109:
                        if a4*3+a5*2+a6*5==671:
                            if a4*4+a5*7+a6*9==1252:
                                if a4+a5*8+a6*2==644:
                                    print('congraduation!you get the right flag!')
                                    
                                    
                                

字节码解释文章:
https://forgo7ten.github.io/2020/01/28/2020012801/#%E8%B7%B3%E8%BD%AC
https://docs.python.org/zh-cn/3/library/dis.html#python-bytecode-instructions

看了python代码后,紧接着需要用z3约束来进行解答,更加简便

注意点:

BINARY_SUBTRACT 这个是减法

BINARY_SUBSCR 这个是索引

Z3约束脚本

from z3 import *
def main():
    s=Solver()
    flag=[]
    for i in range(5):
        flag.append(Int("flag%i"%i))
    s.add(((((flag[0] * 2020 + flag[1]) * 2020 + flag[2]) * 2020 + flag[3]) * 2020 +
       flag[4]) == 1182843538814603)
    for i in range(5):
        s.add(flag[i]>30)
        s.add(flag[i]<128)
    if s.check()==sat:
        print(s.model())
    en=[3,37,72,9,6,132]
    output=[101,96,23,68,112,42,107,62,96,53,176,179,98,53,67,29,41,120,60,106,51,101,178,189,101,48]
    ss=Solver()
    flag2=[]
    j=0
    for i in range(13):
        flag2.append(output[j+1]^en[i%6])
        flag2.append(output[j]^en[i%6])
        j+=2
    print(flag2)
    sss=Solver()
    flag3=[]
    for i in range(6):
        flag3.append(Int("flag3%i"%i))
    sss.add((flag3[0]*3+flag3[1]*2+flag3[2]*5)==1003)
    sss.add((flag3[0]*4+flag3[1]*7+flag3[2]*9)==2013)
    sss.add((flag3[0]*1+flag3[1]*8+flag3[2]*2)==1109)
    sss.add((flag3[3]*3+flag3[4]*2+flag3[5]*5)==671)
    sss.add((flag3[3]*4+flag3[4]*7+flag3[5]*9)==1252)
    sss.add((flag3[3]*1+flag3[4]*8+flag3[5]*2)==644)
    for i in range(5):
        sss.add(flag3[i]>30)
        sss.add(flag3[i]<128)
    if sss.check()==sat:
        print(sss.model())
        
if __name__=="__main__":
    main()

注意点:

for i in range(13):
        flag2.append(output[j+1]^en[i%6])
        flag2.append(output[j]^en[i%6])

这里不能当成range(26)来算,因为en下标同一组是一样的

在这里插入图片描述

 a=[71,87,72,84,123,99,102,97,50,98,56,55,98,51,102,55,52,54,97,56,102,48,97,99,53,99,53,57,54,51,102,97,101,102,102,55,51]   

注意最后五个顺序

在这里插入图片描述

GWHT{cfa2b87b3f746a8f0ac5c5963faeff73

加上最后一半}

GWHT{cfa2b87b3f746a8f0ac5c5963faeff73}

总结:

此次题目不难,flag分成三部分来看待即可,最主要就是了解python字节码,懂得如何把Python字节码转换成python伪代码,紧接着再来进行下一步的分析

[UTCTF2020]babymips

jeb:

在这里插入图片描述
4199924这玩意是个地址,是我万万没想到的。。。
在这里插入图片描述
按下键盘d后,就转换回地址了,然后即可进行分析
在这里插入图片描述
jeb跟ida比起来是真的一言难尽。。。

在这里插入图片描述
内部函数,简直一团乱麻。

ida:

在这里插入图片描述
在这里插入图片描述

ida这玩意分析得多棒,清秀简洁

unsigned char ida_chars[] =
{
  0x62, 0x6C, 0x7F, 0x76, 0x7A, 0x7B, 0x66, 0x73, 0x76, 0x50, 
  0x52, 0x7D, 0x40, 0x54, 0x55, 0x79, 0x40, 0x49, 0x47, 0x4D, 
  0x74, 0x19, 0x7B, 0x6A, 0x42, 0x0A, 0x4F, 0x52, 0x7D, 0x69, 
  0x4F, 0x53, 0x0C, 0x64, 0x10, 0x0F, 0x1E, 0x4A, 0x67, 0x03, 
  0x7C, 0x67, 0x02, 0x6A, 0x31, 0x67, 0x61, 0x37, 0x7A, 0x62, 
  0x2C, 0x2C, 0x0F, 0x6E, 0x17, 0x00, 0x16, 0x0F, 0x16, 0x0A, 
  0x6D, 0x62, 0x73, 0x25, 0x39, 0x76, 0x2E, 0x1C, 0x63, 0x78, 
  0x2B, 0x74, 0x32, 0x16, 0x20, 0x22, 0x44, 0x19
};
a=[
  0x62, 0x6C, 0x7F, 0x76, 0x7A, 0x7B, 0x66, 0x73, 0x76, 0x50, 
  0x52, 0x7D, 0x40, 0x54, 0x55, 0x79, 0x40, 0x49, 0x47, 0x4D, 
  0x74, 0x19, 0x7B, 0x6A, 0x42, 0x0A, 0x4F, 0x52, 0x7D, 0x69, 
  0x4F, 0x53, 0x0C, 0x64, 0x10, 0x0F, 0x1E, 0x4A, 0x67, 0x03, 
  0x7C, 0x67, 0x02, 0x6A, 0x31, 0x67, 0x61, 0x37, 0x7A, 0x62, 
  0x2C, 0x2C, 0x0F, 0x6E, 0x17, 0x00, 0x16, 0x0F, 0x16, 0x0A, 
  0x6D, 0x62, 0x73, 0x25, 0x39, 0x76, 0x2E, 0x1C, 0x63, 0x78, 
  0x2B, 0x74, 0x32, 0x16, 0x20, 0x22, 0x44, 0x19
]
flag=""
for i in range(len(a)):
    flag+=chr(a[i]^(i+23))
print(flag)

在这里插入图片描述

utflag{mips_cpp_gang_5VDm:~`N]ze;\)5%vZ=C'C(r#$q=*efD"ZNY_GX>6&sn.wF8$v*mvA@'}

总结:

jeb中注意4199924形式的数据可能是地址

在这里插入图片描述

(v2 ^ 78) > 0

这个v2是长度,长度异或78,结果大于0就报错,说明它的长度就等于78(因为相同异或为0,不同异或为1)。。
这点jeb挺好玩的

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

寻梦&之璐

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

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

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

打赏作者

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

抵扣说明:

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

余额充值