• defcon-quals 2023 crackme.tscript.dso wp


    dso文件放到data/ExampleModule目录下,编辑ExampleModule.tscript文件

    function ExampleModule::onCreate(%this) { trace(true); exec("./crackme"); __main("aaaaaaaa"); quit(); }

    然后点击主目录下的Torque3D-debug.bat就可以在生成的console.log文件里看到输出,发现使用的是getc获取输入,putc输出。

    下载源码,在Engine\source\console\console.cpp中找到执行dso文件的位置

    另外在CodeBlock这个类里面看到了一个dumpInstructions函数可以dump指令于是在code->read后面加上一个code->dumpInstructions语句来查看指令码,结果发现其他函数都有输出,只有我们的dso文件没有输出,麻,看代码。

    发现造成没有输出的原因是codeSize为0;

    再看看read函数发现果然读取文件后没有改变codeSize,有点小坑。

    在这里加上一句改写codeSize。

    这样就可以输出dso文件字节码了,由于字节码过长这里就不放了。

    首先查找getc被调用的位置,发现在getc后面有一些OP_CMPNE指令,猜测这里是比较的地方,查看exec函数里实现OP_CMPNE的位置,发现是用doFloatMathOperation函数处理的,加上一句把比较的数据打印出来。

    发现在IP=4125的地方有一个比较97与102的cmpne,97就是a的ascii码,102是f的ascii码,再看一下打印出的字节码发现结构很类似,首先getc然后再getc的地址+101处比较,然后比较处+18再次getc,这样就可以该写代码来获取flag,更改处如下
     


     

    然后再log中发现了

    看来不是简单的比较,接着看后面的字节码

    简单讲一下指令的作用,其他指令基本一看就知道干嘛的。

    OP_LOAD_LOCAL_VAR_UINT stk=+1 reg=4 --> push reg[4]; OP_SAVE_LOCAL_VAR_UINT stk=0 reg=7 --> mov reg[7], stack[sp]; OP_POP_STK --> sp--

    发现后面的处理其实跟前面差不多只是把cmpne变成了sub,偏移变成了103,再修改一下代码得到第二部分的flag

    接着看后面的指令,重点关注调用了doIntOperation和doFloatMathOperation的指令

    而后面每两个getc之间的指令就变得特别多了达到了几万条,有限时间内肉眼看是基本上看不出来了,开始乱猜大法。

    发现一个可疑的指令后面load了一个108,查找规律,发现应该是这个,偏移为距getc+61处,然后发现其实上面的也可以在这里获取到。

    获取到第三部分flag

     
    

    Copy

    flag{vmprotect?_where_we_re_going_we_ll_need_protecti

    再看下后面的指令,发现先将所有的数据全加起来跟减去1327

    添加以下代码仔细观察数据操作指令

    将输入改为flag{vmprotect?_where_we_re_going_we_ll_need_protecti0123456789abcdefghijklmnopq}输出为

    再往后发现每次从输入中去除一个然后累加再减去以下数据然后判断等不等于0,这里的16776909等是因为signed类型的负数与0xffffff与得到结果,所以是个解方程问题,z3一把梭

     
    

    Copy

    [1327, 1394, 1332, 1347, 1372, 1360, 1394, 1365, 1333, 1347, 1326, 1338, 1391, 1347, 1324, 1333]

     
    

    Copy

    from z3 import * sub = [1327, 1394, 1332, 1347, 1372, 1360, 1394, 1365, 1333, 1347, 1326, 1338, 1391, 1347, 1324, 1333] s = Solver() flag = Ints("flag%d" %i for i in range(16)) for i in range(16): s.add(flag[i] >0) s.add(flag[i] <128) exceptIndex = 14 for i in range(16): result = 0 exceptIndex = (exceptIndex + 1) % 16 for j in range(16): if j != exceptIndex: result += flag[j] s.add(result == sub[i]) if s.check() == sat: print("find") m = s.model() f = "" for i in range(16): f += chr(m[flag[i]].as_long()) print(f)

    得到flag

     
    

    Copy

    flag{vmprotect?_where_we_re_going_we_ll_need_protecti0n_FR0Mm_th3_vms}

    只要跟踪每个getc后面的指令就可以分析清楚整个流程。 

  • 相关阅读:
    Linux——生产者消费者模型
    【百度AI_人脸识别】图片对比相似度、人脸对比登录(调摄像头)
    webp动图转gif
    计算机图形学-GAMES101-3
    〖Python 数据库开发实战 - MySQL篇㉞〗- 综合案例 - 新闻管理系统数据库设计的基本属性
    go记录之——slice
    Centos7安装ELK
    C++11 lambda表达式 已完成未发布
    新开普智慧校园系统RCE漏洞 [附POC]
    【IP SSL】内网IP SSL证书Nginx部署
  • 原文地址:https://blog.csdn.net/2301_77550592/article/details/133236680