2020网鼎杯青龙组_re_signal
2020-05-23 11:36:46 Author: bbs.pediy.com(查看原文) 阅读量:460 收藏

直接IDA分析,将表0x403040拷贝到opcode_table中拷贝了456个字节,将opcode_table传入vm_operad中,并传入一个114,可以发现456时114的4倍,因此114就是opcode以int大小索引的长度

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]

进入vm_operad分析,可以发现从op表中取值进行不同的操作

这里有几个case还是比较好分析的,case10进入read函数跟进后发现就是输入,且输入的长度必须时15个,最终的值时放在v3中,可以确定v3数组就是保存就是input

case7也比较好分析,即使判断v4[v8]与opcode中的值进行判断,如果不满足则失败,这里通过对v8这个索引进行搜索,发现就这里一处带引用了,因此v4从一开始便要与opcode中的相等。

下面打印出opcode表,这里可以明显的看到从7开始的地方后面就是与v4比对的值,并且刚好15个

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]

有些操作数后面跟的数据而非运算数值

v4 需要满足:[34,63,52,50,114,51,24,167,49,241,40,132,193,30,122]

下面就有几个问题要分析:

  1. v4如何产生的?
  2. v3如何参与计算的?

通过分析case 1可以发现v4[v7]=v5,v4的产生是由v5赋值而来,v7初始化为0,其他并无赋值,由此可知,case1控着这v4从开始的生成,可以从op表中发现1就是有15个,该case中的v9,v5则可以判断处分别为:input的运算取值索引,v5运算结果。

接下来就要还原v3的计算流程的,根据opcode分析,这里可以知道case 2,3,4,5都是进行的op_code_table_index + 1取值op_code_table_index += 2迭代,因此这几个操作数后面跟的一定时运算的数值并非操作数


通过分析可以根据比较,写出脚本自动还原,(逆过程+逆运算)

public class Main {
    public static void main(String[] args) {
        char re[] = {34,63,52,50,114,51,24,167,49,241,40,132,193,30,122};
        // int opcode[] = {  //原始code
        // 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
        // };
        int opcode[] = { //调整code顺序
                3,5,8,4,16,1,
                5,3,8,4,32,1,
                11,8,3,2,1,
                4,4,8,12,1,
                3,33,8,5,3,1,
                11,8,11,1,
                3,32,8,4,9,1,
                4,36,8,2,81,1,
                11,8,12,1,
                2,37,8,5,2,1,
                4,65,8,2,54,1,
                5,1,8,2,32,1,
                2,37,8,5,3,1,
                3,32,8,4,9,1,
                12,8,2,65,1
        };
        char tmp = 0;
        int tmp_index = 0;
        int opcode_index = 0;
        int re_index = 0;
        char flag[] = new char[15];
        int flag_index = 0;
        while(opcode_index < 83){

            switch(opcode[opcode_index]){
                case 1:
                    flag[flag_index] = tmp;
                    ++opcode_index;
                    ++flag_index;
                    ++re_index;
                    break;
                case 2:
                    tmp = (char) (re[re_index] - (char)(opcode[opcode_index + 1]& 0xff));
                    opcode_index += 2;
                    break;
                case 3:
                    tmp = (char) (re[re_index] + (opcode[opcode_index + 1]& 0xff ));
                    opcode_index += 2;
                    break;
                case 4:
                    tmp = (char) ((opcode[opcode_index + 1] & 0xff) ^ re[re_index]);
                    opcode_index += 2;
                    break;
                case 5:
                    tmp = (char) (re[re_index] / (opcode[opcode_index + 1] & 0xff));
                    opcode_index += 2;
                    break;
                case 6:
                    ++opcode_index;
                    break;
                case 8:
                    re[tmp_index] = tmp;
                    ++opcode_index;
                    ++tmp_index;
                    break;
                case 11:
                    tmp = (char) (re[re_index] + 1);
                    ++opcode_index;
                    break;
                case 12:
                    tmp = (char) (re[re_index] - 1);
                    ++opcode_index;
                    break;
                default:
                    continue;

            }

        }
        System.out.println(new String(flag)); //757515121f3d478
    }
}

[培训]科锐逆向工程师培训班38期--远程教学预课班将于 2020年5月28日 正式开班!

最后于 4天前 被Craft_A编辑 ,原因:


文章来源: https://bbs.pediy.com/thread-259595.htm
如有侵权请联系:admin#unsafe.sh