吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 14610|回复: 46
收起左侧

[CTF] 2020网鼎杯青龙组部分逆向题

  [复制链接]
zsky 发表于 2020-5-11 17:09
本帖最后由 L15263458908 于 2020-5-12 21:53 编辑

2020网鼎杯青龙组部分逆向题

signal
方法一
打开程序,可以很明显的看到,这是一个虚拟机指令的逆向

1.png


进入关键函数进行分析

2.png


进行观察,可以发现,v4 与 a1[v10 + 1]比较 是判断条件
a1是输入的opcode, 而v4来自v5,v5由flag进行运算得到
flag--->v5---->v4
所以我们要得到v4,然后推v5,在得到flag

我们复制IDA中的代码,进行修改,来得到v4的值和执行顺序,即上图的V10

3.png

代码如下
[C++] 纯文本查看 复制代码
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#include "pch.h"
#include <stdio.h>
#include <string.h>
 
unsigned char vmcode[] =
{
  0x0A, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00,
  0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
  0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00,
  0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
  0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00,
  0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
  0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x01, 0x00,
  0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
  0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00,
  0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
  0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x21, 0x00,
  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00,
  0x08, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x01, 0x00,
  0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
  0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00,
  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
  0x51, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00,
  0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
  0x0C, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0B, 0x00,
  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
  0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00,
  0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
  0x02, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x08, 0x00,
  0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00,
  0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00,
  0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
  0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x00,
  0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
  0x02, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x01, 0x00,
  0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
  0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x20, 0x00,
  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
  0x41, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x0C, 0x00,
  0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
  0x22, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3F, 0x00,
  0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
  0x07, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x00, 0x07, 0x00,
  0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
  0x33, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x18, 0x00,
  0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xA7, 0xFF, 0xFF, 0xFF,
  0x07, 0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x07, 0x00,
  0x00, 0x00, 0xF1, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00,
  0x28, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x84, 0xFF,
  0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0xC1, 0xFF, 0xFF, 0xFF,
  0x07, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x07, 0x00,
  0x00, 0x00, 0x7A, 0x00, 0x00, 0x00
};
 
int * a = (int *)vmcode;
 
int __cdecl vm_operad(int *opcode, int len_114)
{
        char order[114] = {};        //顺序         即i
        char flag[100]; // [esp+13h] [ebp-E5h]
        char v4[100]; // [esp+77h] [ebp-81h]
        char v5; // [esp+DBh] [ebp-1Dh]
        int j; // [esp+DCh] [ebp-1Ch]
        int m; // [esp+E0h] [ebp-18h]
        int k; // [esp+E4h] [ebp-14h]
        int n; // [esp+E8h] [ebp-10h]
        int i; // [esp+ECh] [ebp-Ch]
        int s = 0;
 
        i = 0;
        n = 0;
        k = 0;
        m = 0;
        j = 0;
        while (1)
        {
                if (i >= len_114)                         // 成功的地方
                        break;
                switch (opcode[i])
                {
                case 1:
                        v4[m] = v5;
                        ++i;
                        ++m;
                        ++n;
                        break;
                case 2:
                        v5 = opcode[i + 1] + flag[n];
                        i += 2;
                        break;
                case 3:
                        v5 = flag[n] - opcode[i + 1];
                        i += 2;
                        break;
                case 4:
                        v5 = opcode[i + 1] ^ flag[n];
                        i += 2;
                        break;
                case 5:
                        v5 = opcode[i + 1] * flag[n];
                        i += 2;
                        break;
                case 6:
                        ++i;
                        break;
                case 7:
                        v4[k] = opcode[i + 1];                        // 打印关键数据V4
                        printf("%#X, ", v4[k]);               
                        ++k;
                        i += 2;
                        break;
                case 8:
                        flag[j] = v5;
                        ++i;
                        ++j;
                        break;
                case 10:
                        scanf("%s", flag);                                // 输入flag                //长度是15
                        ++i;
                        break;
                case 11:
                        v5 = flag[n] - 1;
                        ++i;
                        break;
                case 12:
                        v5 = flag[n] + 1;
                        ++i;
                        break;
                }
                order[s++] = i;
        }
        printf("执行顺序是: ");
        for (int ss = 0; ss < strlen(order); ss++) {
                printf("%d, ", order[ss]);
        }
 
        return 0;
}
 
int main()
{       
        vm_operad(a, 114);
         
        return 0;
}


得到结果

4.png
v4 = { 0X22, 0X3F, 0X34, 0X32, 0X72, 0X33, 0X18, 0XFFFFFFA7, 0X31, 0XFFFFFFF1, 0X28, 0XFFFFFF84, 0XFFFFFFC1, 0X1E, 0X7A };
order[100] = { 1, 3, 4, 6, 7, 9, 10, 12, 13, 15, 16, 17, 18, 19, 20, 22, 23, 25, 26, 28, 29, 30, 31, 32, 33, 35, 36, 38, 39, 41, 42, 44, 45, 46, 47, 48, 49, 51, 52, 54, 55, 57, 58, 60, 61, 63, 64, 66, 67, 69, 70, 72, 73, 75, 76, 78, 79, 81, 82, 83, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114 };
再写解密函数逆推flag
[C++] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
int decode(int * opcode, int len_114)
{
        int i;
        //获取flag 的关键数据
        unsigned char v4[] = { 0X22, 0X3F, 0X34, 0X32, 0X72, 0X33, 0X18, 0XFFFFFFA7, 0X31, 0XFFFFFFF1, 0X28, 0XFFFFFF84, 0XFFFFFFC1, 0X1E, 0X7A };
        //执行opcode 的索引,即执行顺序
        char order[100] = { 1, 3, 4, 6, 7, 9, 10, 12, 13, 15, 16, 17, 18, 19, 20, 22, 23, 25, 26, 28, 29, 30, 31, 32, 33, 35, 36, 38, 39, 41, 42, 44, 45, 46, 47, 48, 49, 51, 52, 54, 55, 57, 58, 60, 61, 63, 64, 66, 67, 69, 70, 72, 73, 75, 76, 78, 79, 81, 82, 83, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114 };
        unsigned char flag[100] = {};
        int m = 15;
        int n = 15;
        int j = 15;
        int v5;
        for (int k = strlen(order) - 1; k >= 0 ; k--)
        {
                i = order[k];
                switch (opcode[i])                                // 倒序执行
                {
                case 1:
                        --m;
                        --n;
                        v5 = v4[m];
                        break;
                case 2:
                        flag[n] = v5 - char(opcode[i + 1]) ;
                        break;
                case 3:
                    flag[n] = v5 + char(opcode[i + 1]);
                        break;
                case 4:
                        flag[n] = (v5 ^ opcode[i + 1]) & 0XFF;
                        break;
                case 5:
                        flag[n] = v5 / opcode[i + 1];
                        break;
                case 6:
                        break;
                case 8:
                        v5 = flag[--j];
                        break;
                case 11:
                        flag[n] = v5 + 1;
                        break;
                case 12:
                        flag[n] = v5 - 1;
                        break;
                }
        }
 
        printf("%s", flag);
        return 0;
}


得到flag是 757515121f3d478
方法二:
通过Ponce插件符号执行来一步步获取flag
5.png

6.png

关于Ponce插件下介绍及下载->https://github.com/illera88/Ponce
方法三: 使用python angr符号执行解决
代码如下
[Python] 纯文本查看 复制代码
1
2
3
4
5
6
import angr
p = angr.Project('signal.exe')
st = p.factory.entry_state()
sm = p.factory.simulation_manager(st)
sm.explore(find=0x40175E, avoid=0x4016E6)
print(sm.found[0].posix.dumps(0))


QQ截图20200512215220.png

jocker
打开程序,找到main函数,F5发现无法反编译

7.png



手动修复下栈指针

8.png


问题出现在401838那里

9.png

对401833那个位置按ALT+ K

10.png

修改栈偏移

11.png

F5看伪代码

12.png
wrong是对flag进行了一个简单的加密
omg对加密的flag进行判断,得到flag为flag{fak3_alw35_sp_me!!} 提交发现错误
然后调试起来,进入下面的encrypt函数

13.png

一个简单的异或判断
写脚本打印出flag的前一半
[Python] 纯文本查看 复制代码
1
2
3
4
a = [0XE, 0XD, 9, 6, 0X13, 5, 0X58, 0X56, 0X3E, 6, 0XC, 0X3C, 0X1F, 0X57, 0X14, 0X6B, 0X57, 0X59, 0XD]
b = "hahahaha_do_you_find_me?"
c = [chr((a[i] ^ ord(b[i]))& 0xff) for i in range(len(a))]
print "".join(c)

结果为:
flag{d07abccf8a410c

最后进入finally函数
14.png
根据提示说 我隐藏了后一半部分,,前面
flag{d07abccf8a410c是19个字符,而flag是24个字符,还差5个,最后一个肯定是 “}”
于是将v7 与 } 异或得到 71
写个脚本,将37,116,112,38,58 全部异或71
[Python] 纯文本查看 复制代码
1
2
3
a = [37,116,112,38,58]
flag = "".join([chr(i ^ 71) for i in a])
print flag


得到flag的后半部分
b37a}
拼接,即为flag--->flag{d07abccf8a410cb37a}

------------------------------
题目链接:
链接:https://pan.baidu.com/s/1atclBURdY8msXE889elidg
提取码:gemn

免费评分

参与人数 21吾爱币 +20 热心值 +20 收起 理由
世不待 + 1 用心讨论,共获提升!
晓``~dong东 + 1 + 1 用心讨论,共获提升!
Peppermint + 1 谢谢@Thanks!
Sins + 1 + 1 谢谢@Thanks!
温柔的一哥 + 1 + 1 用心讨论,共获提升!
gaosld + 1 + 1 用心讨论,共获提升!
zuohaoda + 1 + 1 热心回复!
BrainFlower + 1 + 1 热心回复!
deoplljj + 1 + 1 谢谢@Thanks!
Ginobili + 1 + 1 谢谢@Thanks!
SinnerDusk + 1 + 1 用心讨论,共获提升!
soyiC + 1 + 1 用心讨论,共获提升!
镇北看雪 + 1 + 1 我很赞同!
smile5 + 1 热心回复!
FinchK + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
笙若 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
Hotspur + 1 + 1 我很赞同!
Oohuo + 1 + 1 用心讨论,共获提升!
2008yxp + 1 + 1 用心讨论,共获提升!
Ps出来的小赵 + 3 + 1 赶在黑米之前加分再说
fishinwhater + 1 虽然我看不太懂,但确实大佬牛逼

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

IBinary 发表于 2020-5-12 11:01
xmhwws 发表于 2020-5-11 18:55
大佬,这个是怎么操作的?还是通过插件实现的?

请详细说说

Shife + E  Expore Data  IDA 自带的. 可以 Edit选项中看到.
 楼主| zsky 发表于 2020-5-11 18:59
xmhwws 发表于 2020-5-11 18:55
大佬,这个是怎么操作的?还是通过插件实现的?

请详细说说

变成数组类型之后 shift +e

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
xmhwws + 1 + 1 谢谢@Thanks!

查看全部评分

赤座灯里 发表于 2020-5-11 17:51
我傻傻地把十五个方程列出来了,浪费太多时间
xmhwws 发表于 2020-5-11 18:55
大佬,这个是怎么操作的?还是通过插件实现的?
2020-05-11_18-53-23.png
请详细说说
FinchK 发表于 2020-5-11 19:09
厉害了,学到了。
victoryang00 发表于 2020-5-11 19:40
大佬牛逼,这joker是个双线程的,我同伴弄了个假的flag
 楼主| zsky 发表于 2020-5-11 19:48
victoryang00 发表于 2020-5-11 19:40
大佬牛逼,这joker是个双线程的,我同伴弄了个假的flag

这题最难的是flag后5位,,,,,脑洞题,
wh1sper 发表于 2020-5-11 21:10
本帖最后由 wh1sper 于 2020-5-11 21:13 编辑

这次逆向好像很难,不过最后半小时就看别人垂直上分
新手12138 发表于 2020-5-11 22:02
L15263458908 发表于 2020-5-11 19:48
这题最难的是flag后5位,,,,,脑洞题,

脑洞题我就很难受
 楼主| zsky 发表于 2020-5-11 22:10
wh1sper 发表于 2020-5-11 21:10
这次逆向好像很难,不过最后半小时就看别人垂直上分

逆向除了第二道都很简单,,,,难的是杂项,,那个汉信码我拼了得1个多小时,硬是没扫出来,,,
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2025-4-12 20:53

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表