在参加网鼎杯之前,还没接触过vm指令的题,姑且是在网上找到好多,接下来几天慢慢做,看看能不能整理到一起。
打开看着还挺简单的,一点进vm_operad人就傻了。
里面是各种操作,太长了就不截图了,我还没学会怎么在word文档里贴代码(对我都是word文档写好之后上传博客的)
这里想说一下我对vm虚拟机这类题的理解。
看起来好像是题目给出一串opcode,然后通关循环switch判断opcode的数,找到对应的操作。
这群opcode里面可以既有代表某一操作的指令,也有需要操作的数据。
我们需要做的就是找到操作的顺序和操作的数据,把他们逆着跑一边。
这里我参考了网上的各种wp,可以手算,可以直接列出步骤机器算,也可以更加只能一点,重写逻辑顺序,我们一个一个来。
第一步,我们要找到程序流程:
用IDA扒下来opcode,但是里面夹杂着一堆零,我不知道怎么去除。于是我的第一步就是把这些零清除,然后输出:
10, 4, 16, 8, 3, 5, 1, 4, 32, 8, 5, 3, 1, 3, 2, 8, 11, 1, 12, 8, 4, 4, 1, 5, 3, 8, 3, 33, 1, 11, 8, 11, 1, 4, 9, 8, 3, 32, 1, 2, 81, 8, 4, 36, 1, 12, 8, 11, 1, 5, 2, 8, 2, 37, 1, 2, 54, 8, 4, 65, 1, 2, 32, 8, 5, 1, 1, 5, 3, 8, 2, 37, 1, 4, 9, 8, 3, 32, 1, 2, 65, 8, 12, 1, 7, 34, 7, 63, 7, 52, 7, 50, 7, 114, 7, 51, 7, 24, 7, 167, 7, 49, 7, 241, 7, 40, 7, 132, 7, 193, 7, 30, 7, 122, 114
先不用管他这些数都是干什么的,我们把操作流程扒下来就好。
下面我们才需要看一下程序逻辑,找到几个关键的点:
当操作码是1的时候,就是向v4数组存入数值。
当操作码是2-5或者11-12的时候,就是对数据进行运算,然后保存。这里面的v5和v3都是临时存放数据用的。
当操作码是7的时候,其实是该对比处理过的flag了,源代码我给删了。
操作码6是跳到下一位。
操作码8是存储临时值,以便下次运算。
这样一来,我把所有的操作过程的代码都删掉,只输出操作码,加上自己的标志,每次以1为结尾。因为1是存储flag然后接着处理下一个数了:
这样一来我们也就知道,操作码7后面跟着的正是需要对比的数据,也是处理flag之后得到的数据。
{0x22,0x3f,0x34,0x32,0x72,0x33,0x18,0xa7,0x31,0xf1,0x28,0x84,0xc1,0x1e,0x7a};
第二步,逆向处理:
先将操作码重写:
然后将每种操作码对应的操作逆向,以2-5为例:
需要注意的是,并不是完全的逆向流程,虽然我们将操作码的顺序反过来了,但是这里的步骤并不需要完全反过来求。
不过这次是以v5和v4作为中介存储数据,v3存放flag:
这里要注意一点,char类型会溢出,所以我加了一点措施,将(char+256)再%256,防止溢出成负数运算。
(这就去看看怎么粘代码)
(算了还是太懒,有人想要的话私聊吧)
总之是可以运算出结果了:
15是长度不要在意。
还有一种做法,直接计算:
这样来的十分之快,但是实用性不高,比赛的时候甚至可以手算,但是做题的话还是自动化吧。