分享一下昨天刚打的上海市大学生网络安全大赛的Re
ida开始直接搜索字符串,找到关键函数,简单修复一下栈指针,直接F5。
开始总感觉自己看到的是假的流程,把程序翻了个遍,没发现其它的流程,但是发现了几个反调试,但是调试发现程序都没有使用。。。其中二个:
然后确定这就是一个虚拟机逆向。静态分析一下后直接让程序跑起来。
这里我做的时候和复现的时候,ida识别的竟然不一样,复现分析的更简洁。记得做的时候,每次赋值操作码与数据的时候是使用一个四字节数据来保存的,其中L0BYTE,Byte1,Byte2,HIByte都是不同的含义:
做的时候的一些笔记:
然后程序中使用了的一个反调试(时钟检测):简单patch了即可。
乍一看程序流程有点复杂,感觉输入的数据会决定下一步操作码,这个其实就是一个加密操作。
总结一下程序的加密操作(对所有字符串的加密都是这个操作):首先从操作码中取出一个数据op_data ,然后temp = input[i]^op_data,再让op_data &= input[i],input[i] = temp,一直这个循环直到op_data == 0,最后取出input[i+1]进行input[i] ^= input[i+1]。一直这样对所有的input加密2遍,就是使用op_data不同。
使用ida_python导出我们要用的op_data。
按照程序的算法,逆二次即可:第一次解密过程我进行了注释。
从题目名字可知道是虚拟机逆向。在linux中运行一下,看见字符串信息。
ida中搜索一圈并没有发现任何相关字符串,那就是程序运行时解密出相关字符串。从入口点找到main函数,可以看到464行的代码,分支极其多。。
静态分析是不可能了,直接动调。
开始慢慢的调试看哪里解密字符串的,但实在是冗长,直接在while循环下断,然后F9一直跑,直到程序等待我们输入。
随便输入后,开始慢慢跟进熟悉一些函数的功能,发现开始就是在以此取我们输入的字符存入一个大数组中
继续跟踪,分析到我们输入的字符长度要是38,虽然读取了最后的回车符,但是没有使用的。
其中程序中这个内存区域类似就是vm使用的寄存器。
接下来判断我们输入最后一位是不是 ‘}‘ 字符,再把除了flag{ }中的内容复制到与程序最后做比较的字符串的下面,
接着判断我们开始的5位是不是 flag{。
最后就是以依次出我们flag{}中每一位,(0xFB*input[i])&0xff
,然后以此与上面的比较字符串比较。解密:
/
/
测试flag。
flag{
0123456789012345678901234567890
}
/
/
最后比较的数据。
unsigned char ida_chars[]
=
{
31
,
24
,
15
,
250
,
184
,
99
,
100
,
137
,
24
,
104
,
124
,
25
,
20
,
45
,
125
,
88
,
0
,
30
,
84
,
106
,
65
,
60
,
54
,
62
,
86
,
19
,
4
,
59
,
46
,
75
,
121
,
67
,
122
,
34
,
69
,
110
,
58
,
117
,
38
,
200
,
192
,
142
};
LOBYTE:
%
64
index
BYTE2: 开始与LOBYTE值相同,做运算完的赋值index
BYTE1: xor
input
[] opcode:
2
3
:BYTE1 &
=
LOBYTE;
/
/
测试flag。
flag{
0123456789012345678901234567890
}
/
/
最后比较的数据。
unsigned char ida_chars[]
=
{
31
,
24
,
15
,
250
,
184
,
99
,
100
,
137
,
24
,
104
,
124
,
25
,
20
,
45
,
125
,
88
,
0
,
30
,
84
,
106
,
65
,
60
,
54
,
62
,
86
,
19
,
4
,
59
,
46
,
75
,
121
,
67
,
122
,
34
,
69
,
110
,
58
,
117
,
38
,
200
,
192
,
142
};
LOBYTE:
%
64
index
BYTE2: 开始与LOBYTE值相同,做运算完的赋值index
BYTE1: xor
input
[] opcode:
2
3
:BYTE1 &
=
LOBYTE;
unsigned char ida_chars[]
=
{
31
,
24
,
15
,
250
,
184
,
99
,
100
,
137
,
24
,
104
,
124
,
25
,
20
,
45
,
125
,
88
,
0
,
30
,
84
,
106
,
65
,
60
,
54
,
62
,
86
,
19
,
4
,
59
,
46
,
75
,
121
,
67
,
122
,
34
,
69
,
110
,
58
,
117
,
38
,
200
,
192
,
142
};
unsigned char a1[]
=
{
9
,
2
,
7
,
8
,
6
,
9
,
11
,
10
,
4
,
11
,
12
,
4
,
7
,
7
,
10
,
4
,
3
,
9
,
4
,
6
,
3
,
12
,
11
,
13
,
4
,
10
,
7
,
7
,
2
,
6
,
6
,
12
,
9
,
14
,
7
,
8
,
11
,
13
,
14
,
12
,
4
,
7
};
unsigned char b[]
=
{
13
,
8
,
12
,
10
,
3
,
9
,
5
,
12
,
13
,
11
,
12
,
7
,
6
,
10
,
8
,
9
,
13
,
8
,
5
,
10
,
7
,
13
,
4
,
13
,
2
,
12
,
10
,
12
,
9
,
7
,
14
,
5
,
11
,
7
,
13
,
7
,
13
,
11
,
5
,
14
,
6
,
10
};
unsigned char c[]
=
{
3
,
15
,
15
,
20
,
228
,
95
,
11
,
116
,
9
,
14
,
113
,
1
,
17
,
3
,
32
,
85
,
6
,
19
,
5
,
94
,
2
,
72
,
105
,
91
,
86
,
14
,
9
,
23
,
24
,
15
,
93
,
18
,
84
,
37
,
14
,
94
,
11
,
34
,
88
,
123
,
65
,
135
};
int
main(void)
{
/
*
int
i
=
0
, j
=
0
;
ida_chars[
41
]
=
135
;
for
(j
=
40
; j >
=
0
; j
-
-
)
{
ida_chars[j] ^
=
ida_chars[j
+
1
];
for
(i
=
0
; i <
255
; i
+
+
)
{
unsigned char temp
=
i, temp1
=
i;
unsigned char a
=
b[j];
while
(
1
)
{
temp1 ^
=
a;
a &
=
temp;
a
*
=
2
;
temp
=
temp1;
if
(a
=
=
0
)
break
;
}
if
(temp
=
=
ida_chars[j])
{
ida_chars[j]
=
i;
break
;
}
}
}
for
(i
=
0
; i <
42
; i
+
+
)
printf(
"%d, "
, ida_chars[i]);
*
/
int
i
=
0
, j
=
0
;
c[
41
]
=
125
;
for
(j
=
40
; j >
=
0
; j
-
-
)
{
c[j] ^
=
c[j
+
1
];
for
(i
=
0
; i <
255
; i
+
+
)
{
unsigned char temp
=
i, temp1
=
i;
unsigned char a
=
a1[j];
while
(
1
)
{
temp1 ^
=
a;
a &
=
temp;
a
*
=
2
;
temp
=
temp1;
if
(a
=
=
0
)
break
;
}
if
(temp
=
=
c[j])
{
c[j]
=
i;
break
;
}
}
}
for
(i
=
0
; i <
42
; i
+
+
)
printf(
"%c"
, c[i]);
}
/
/
flag{e1750505
-
7a05
-
4de9
-
a333
-
72ec8cd26a78
}
unsigned char ida_chars[]
=
{
31
,
24
,
15
,
250
,
184
,
99
,
100
,
137
,
24
,
104
,
124
,
25
,
20
,
45
,
125
,
88
,
0
,
30
,
84
,
106
,
65
,
60
,
54
,
62
,
86
,
19
,
4
,
59
,
46
,
75
,
121
,
67
,
122
,
34
,
69
,
110
,
58
,
117
,
38
,
200
,
192
,
142
};
unsigned char a1[]
=
{
9
,
2
,
7
,
8
,
6
,
9
,
11
,
10
,
4
,
11
,
12
,
4
,
7
,
7
,
10
,
4
,
3
,
9
,
4
,
6
,
3
,
12
,
11
,
13
,
4
,
10
,
7
,
7
,
2
,
6
,
6
,
12
,
9
,
14
,
7
,
8
,
11
,
13
,
14
,
12
,
4
,
7
};
unsigned char b[]
=
{
13
,
8
,
12
,
10
,
3
,
9
,
5
,
12
,
13
,
11
,
12
,
7
,
6
,
10
,
8
,
9
,
13
,
8
,
5
,
10
,
7
,
13
,
4
,
13
,
2
,
12
,
10
,
12
,
9
,
7
,
14
,
5
,
11
,
7
,
13
,
7
,
13
,
11
,
5
,
14
,
6
,
10
};
unsigned char c[]
=
{
3
,
15
,
15
,
20
,
228
,
95
,
11
,
116
,
9
,
14
,
113
,
1
,
17
,
3
,
32
,
85
,
6
,
19
,
5
,
94
,
2
,
72
,
105
,
91
,
86
,
14
,
9
,
23
,
24
,
15
,
93
,
18
,
84
,
37
,
14
,
94
,
11
,
34
,
88
,
123
,
65
,
135
};
int
main(void)
{
/
*
int
i
=
0
, j
=
0
;
ida_chars[
41
]
=
135
;
for
(j
=
40
; j >
=
0
; j
-
-
)
{
ida_chars[j] ^
=
ida_chars[j
+
1
];
for
(i
=
0
; i <
255
; i
+
+
)
{
unsigned char temp
=
i, temp1
=
i;
unsigned char a
=
b[j];
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2020-11-15 21:35
被Bxb0编辑
,原因: