吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 23533|回复: 91
收起左侧

[CTF] (原创)第十二届全国大学生信息安全竞赛strange_int题解

  [复制链接]
lizhirui 发表于 2019-4-21 21:12
本帖最后由 lizhirui 于 2019-4-26 11:01 编辑

本题的原理是虚拟机
题目下载链接如下:
strange_int_740dfa57eab289ada9d30380ef4393d5.zip (1.13 KB, 下载次数: 102)
本题下载之后发现一个Image.bin文件,使用Winhex打开后,可以很容易发现在偏移0x1FE处有55 AA,表示这是一个分区,联合一些经验,可以初步判断这是软盘镜像的MBR,因此,使用IDA以16位方式加载这个Binary,可以得到这样的代码:
[Asm] 纯文本查看 复制代码
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
seg000:0000                 jmp     far ptr 7C0h:5
seg000:0005 ; ---------------------------------------------------------------------------
seg000:0005                 mov     ax, cs
seg000:0007                 mov     ds, ax
seg000:0009                 mov     ss, ax
seg000:000B                 mov     sp, 400h
seg000:000E                 cld
seg000:000F                 mov     ax, 3
seg000:0012                 int     10h            ; - VIDEO - SET VIDEO MODE
seg000:0012                                        ; AL = mode
seg000:0014                 mov     dx, 0
seg000:0017                 mov     cx, 2
seg000:001A                 mov     ax, 1000h
seg000:001D                 mov     es, ax
seg000:001F                 assume es:nothing
seg000:001F                 xor     bx, bx
seg000:0021                 mov     ax, 228h
seg000:0024                 int     13h            ; DISK - READ SECTORS INTO MEMORY
seg000:0024                                        ; AL = number of sectors to read, CH = track, CL = sector
seg000:0024                                        ; DH = head, DL = drive, ES:BX -> buffer to fill
seg000:0024                                        ; Return: CF set on error, AH = status, AL = number of sectors read
seg000:0026                 jnb     short loc_2A
seg000:0028
seg000:0028 loc_28:                                ; CODE XREF: seg000:loc_28j
seg000:0028                 jmp     short loc_28
seg000:002A ; ---------------------------------------------------------------------------
seg000:002A
seg000:002A loc_2A:                                ; CODE XREF: seg000:0026j
seg000:002A                 cli
seg000:002B                 mov     ax, 1000h
seg000:002E                 mov     ds, ax
seg000:0030                 assume ds:nothing
seg000:0030                 xor     ax, ax
seg000:0032                 mov     es, ax
seg000:0034                 assume es:nothing
seg000:0034                 mov     cx, 2000h
seg000:0037                 sub     si, si
seg000:0039                 sub     di, di
seg000:003B                 rep movsb
seg000:003D                 mov     ax, 7C0h
seg000:0040
seg000:0040 loc_40:                                ; DATA XREF: seg000:0012r
seg000:0040                 mov     ds, ax
seg000:0042                 assume ds:nothing
seg000:0042                 lidt    fword ptr ds:6Fh ; 初始化GDT和IDT
seg000:0047                 lgdt    fword ptr ds:75h
seg000:004C
seg000:004C loc_4C:                                ; DATA XREF: seg000:0024r
seg000:004C                 mov     ax, 1
seg000:004F                 lmsw    ax             ; 开启保护模式
seg000:0052                 jmp     far ptr 8:0

其中第一行的jmp far ptr 7c0h:5,由于MBR的加载地址是0x7C00处,联合Intel处理器实模式的寻址规则,可以得出,这个跳转的目标地址是0x7C05,也就是紧接着的下一条指令,下面的代码很明显在初始化段寄存器和栈指针。
紧接着int 10h调用BIOS中断设置了一下显示模式,接下来的int13h加载软盘的0磁道0柱面2扇区开始的28个扇区到内存的1000:0000h处,然后跳到loc_2A处,这部分代码再将刚才读入的扇区数据移动到内存的0x00000000处,紧接着初始化GDT和IDT,并开启保护模式,此时GDT表中包含一个Code段和一个Data段,基址都是0x00000000。

seg000:0052处的跳转利用段选择子跳入了32位代码段,因此接下来的代码用IDA以32位代码的形式重加载,可以得到以下的代码:
[Asm] 纯文本查看 复制代码
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
mov     eax, 10h
seg000:00000205                 mov     ds, eax
seg000:00000207                 assume ds:nothing
seg000:00000207                 lss     esp, large ds:0B5Ch
seg000:0000020E                 call    IDT_Init
seg000:00000213
seg000:00000213 loc_213:
seg000:00000213                 call    GDT_Init
seg000:00000218                 mov     eax, 10h
seg000:0000021D                 mov     ds, eax
seg000:0000021F                 mov     es, eax
seg000:00000221                 assume es:nothing
seg000:00000221                 mov     fs, eax        ; DATA XREF: GDT_Init r
seg000:00000223                 assume fs:nothing
seg000:00000223                 mov     gs, eax
seg000:00000225                 assume gs:nothing
seg000:00000225                 lss     esp, large ds:0B5Ch
seg000:0000022C                 xor     ebx, ebx
seg000:0000022E
seg000:0000022E loc_22E:                               ; CODE XREF: seg000:0000025D j
seg000:0000022E                 nop
seg000:0000022F                 cmp     ebx, 10h
seg000:00000232                 jge     short loc_25F
seg000:00000234                 mov     eax, 80000h
seg000:00000239                 lea     edx, ds:0D08h[ebx*4]
seg000:00000240                 mov     edx, [edx]
seg000:00000242                 mov     ax, dx
seg000:00000245                 mov     dx, 8E00h
seg000:00000249                 mov     ecx, 21h ; '!'
seg000:0000024E                 add     ecx, ebx
seg000:00000250                 lea     esi, ds:128h[ecx*8]
seg000:00000257                 mov     [esi], eax
seg000:00000259                 mov     [esi+4], edx
seg000:0000025C                 inc     ebx
seg000:0000025D                 jmp     short loc_22E
seg000:0000025F ; ---------------------------------------------------------------------------
seg000:0000025F
seg000:0000025F loc_25F:                               ; CODE XREF: seg000:00000232 j
seg000:0000025F                                        ; seg000:00000266 j
seg000:0000025F                 call    JumpToNextHandler
seg000:00000264                 int     21h            ; DOS -
seg000:00000266                 jmp     short loc_25F

其中,seg000:0000022E到seg000:0000025D处是一个执行16次的循环,目的是填充0x21~0x30的中断向量描述符,其镜像中的中断向量映射到内存的原始存储位置保存在0x00000D08处,中断向量从0x00000128开始存储,这里列出全部的中断向量:
  中断编号  
入口地址
0x21
0x00000B7C
0x22
0x00000B8A
0x23
0x00000BA1
0x24
0x00000BC1
0x25
0x00000BE1
0x26
0x00000BFC
0x27
0x00000C17
0x28
0x00000C32
0x29
0x00000C4F
0x2A
0x00000C6C
0x2B
0x00000C84
0x2C
0x00000C96
0x2D
0x00000CB5
0x2E
0x00000CF7
0x2F
0x00000CE0
0x30
0x00000CD4

以上也可以在bochs虚拟机的调试模式通过info idt命令查看。
seg000:0000025F处的call    JumpToNextHandler代码如下:
[Asm] 纯文本查看 复制代码
1
2
3
4
5
6
7
8
9
seg000:00000268 JumpToNextHandler proc near            ; CODE XREF: seg000:loc_25F p
seg000:00000268                 mov     edi, large ds:0B78h
seg000:0000026E                 lea     edi, ds:0D48h[edi*4]
seg000:00000275                 mov     eax, [edi]
seg000:00000277                 mov     large ds:65h, al
seg000:0000027C                 mov     ecx, [edi+4]
seg000:0000027F                 mov     eax, [edi+8]
seg000:00000282                 retn
seg000:00000282 JumpToNextHandler endp


该部分代码中的ds:0D48h对应的物理地址是0x00000D48,经过分析,该部分存储的其实是虚拟机的一系列指令(关于虚拟机的具体内容下面再说),此处就相当于是用虚拟机的指令集编写的程序,每条指令的长度为12个字节,其中前四个字节表示指令OpCode,后面两个字节分别表示两个操作数,或者说是指令的两个参数。
然后我们在bochs下调试的时候,发现int21h这个地方的21h经常会变为各种各样的数值。
然后我们就分析刚才的那16个中断的处理代码。 得到了如下的结论:
0x00000B64是一个长达20个字节的缓冲处理区,相当于一个拥有五个成员的int(4字节长度)数组。
0x00000D48包含了虚拟机的一系列指令以及一些附加数据。
我们假设0x0000B64的数组叫做buf,0x00000D48为code,两个数组均为int类型。
指令的两个参数分别叫做a和b。
假设指令指针为index(即指向下一指令的指针,例如X86架构中的EIP寄存器)。
则十六个中断的作用分别如下:
  中断编号  
功能描述
0x21
buf[a]  = b
0x22
buf[a]  = buf
0x23
buf[a]  = code[buf]
0x24
code[buf[a]]  = buf
0x25
buf[a]  += buf
0x26
buf[a]  -= buf
0x27
buf[a]  ^= buf
0x28
buf[a]  <<= (buf& 0xFF)
0x29
buf[a]  >>= (buf& 0xFF)
0x2A
buf[a]  &= buf
0x2B
index  = a
0x2C
if(buf  == 0){index = a}
0x2D
if(buf  != 0){index = a}
0x2E
终止CPU运行,即hlt指令
0x2F
输出flag正确提示
0x30
输出flag错误提示

在每次指令执行后,index会自增3(除了0x2B指令的情形以及0x2C、0x2D指令的跳转条件成立的情形以外)。然后我利用C#做了个虚拟机,并在模拟执行的时候同时输出类C的代码供之后分析。代码如下:
[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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace 虚拟机
{
    class Program
    {
        static int[] data = new int[]
        {
                0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
                0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
                0x01, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x22, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
                0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
                0x04, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
                0x28, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00,
                0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
                0x04, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
                0x27, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00,
                0x04, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
                0x02, 0x00, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
                0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
                0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x01, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x21, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x81, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00,
                0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
                0x09, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
                0x21, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00,
                0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x81, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x21, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
                0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
                0x26, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00,
                0x04, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x2D, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
                0x03, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
                0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00,
                0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
                0x03, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x5A, 0x00, 0x00, 0x00,
                0x2D, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x38, 0x62, 0x64, 0x61, 0x65, 0x34, 0x35, 0x36, 0x2D, 0x35, 0x61, 0x63,
                0x38, 0x2D, 0x31, 0x31, 0x65, 0x39, 0x2D, 0x61, 0x31, 0x63, 0x31, 0x2D, 0x38, 0x38, 0x65, 0x39,
                0x66, 0x65, 0x38, 0x30, 0x66, 0x65, 0x61, 0x66, 0x65, 0x55, 0x63, 0x57, 0x01, 0x04, 0x53, 0x06,
                0x49, 0x49, 0x49, 0x1F, 0x1F, 0x07, 0x57, 0x51, 0x57, 0x43, 0x5F, 0x57, 0x57, 0x5E, 0x43, 0x57,
                0x0A, 0x02, 0x57, 0x43, 0x5E, 0x03, 0x5E, 0x57, 0x00, 0x00, 0x59, 0x0F, 0x77, 0x72, 0x6F, 0x6E,
                0x67, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x63, 0x6F, 0x72, 0x72, 0x65, 0x63, 0x74, 0x20,
                0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x66, 0x6C, 0x61, 0x67, 0x20, 0x69, 0x73, 0x20, 0x66, 0x6C,
                0x61, 0x67, 0x7B, 0x59, 0x6F, 0x75, 0x72, 0x50, 0x61, 0x74, 0x63, 0x68, 0x7D, 0x20, 0x20, 0x20,
                0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
                0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
        };
 
        static void Main(string[] args)
        {
            var buf = new int[5]{0,0,0,0,0};
            var index = 0;
 
            var idata = new int[data.Length / 4];
 
            for(var i = 0;i < idata.Length;i++)
            {
                idata[i] = data[i * 4] | (data[i * 4 + 1] << 8) | (data[i * 4 + 2] << 16) | (data[i * 4 + 3] << 24);
            }
 
            var lastcmd = 0x21;
            var lastindex = 0;
            var cnt = 0;
 
            var stb = new StringBuilder();
 
            while(true)
            {
                start:
                /*Console.WriteLine("Cmd = " + string.Format("{0:X2}",lastcmd));
                Console.WriteLine("Addr = " + string.Format("{0:X2}",lastindex));
                Console.WriteLine("NewAddr = " + string.Format("{0:X2}",index));
                Console.WriteLine("Arg1 = " + string.Format("{0:X2}",idata[lastindex + 1]));
                Console.WriteLine("Arg2 = " + string.Format("{0:X2}",idata[lastindex + 2]));
                 
                for(var i = 0;i < buf.Length;i++)
                {
                    Console.Write(string.Format("{0:X2} {1:X2} {2:X2} {3:X2} ",buf[i] & 0xFF,(buf[i] >> 8) & 0xFF,(buf[i] >> 16) & 0xFF,(buf[i] >> 24) & 0xFF));
                }
 
                Console.WriteLine("");
                Console.WriteLine("第" + cnt + "次");
                Console.WriteLine();
 
                if(lastcmd == 0x29 || lastcmd == 0x2A || lastcmd == 0x2B || lastcmd == 0x2C)
                {
                    Console.ReadKey();
                }
 
                cnt++;
                lastcmd = idata[index];
                lastindex = index;*/
                stb.Append(index + ":\r\n");
 
                switch(idata[index])
                {
                    case 0x21:
                        buf[idata[index + 1]] = idata[index + 2];
                        stb.Append("buf[" + idata[index + 1] + "] = " + idata[index + 2] + ";\r\n");
                        break;
 
                    case 0x22:
                        buf[idata[index + 1]] = buf[idata[index + 2]];
                        stb.Append("buf[" + idata[index + 1] + "] = buf[" + idata[index + 2] + "];\r\n");
                        break;
 
                    case 0x23:
                        buf[idata[index + 1]] = idata[buf[idata[index + 2]]];
                        stb.Append("buf[" + idata[index + 1] + "] = code[buf[" + idata[index + 2] + "]];");
 
                        if(buf[idata[index + 2]] >= (0x204 + 0x6F) / 4)
                        {
                            stb.Append("//读Patch");
                        }
                        else if(buf[idata[index + 2]] >= 0x204 / 4)
                        {
                            stb.Append("//读敏感区域,偏移:" + buf[idata[index + 2]]);
                        }
                        else
                        {
                            stb.Append("//" + buf[idata[index + 2]] + "");
                        }
 
                        stb.Append("\r\n");
                        break;
 
                    case 0x24:
                        idata[buf[idata[index + 1]]] = buf[idata[index + 2]];
                        stb.Append("code[buf[" + idata[index + 1] + "]] = buf[" + idata[index + 2] + "];");
                         
                        if(buf[idata[index + 1]] >= (0x204 + 0x6F) / 4)
                        {
                            stb.Append("//写Patch");
                        }
                        else if(buf[idata[index + 1]] >= 0x204 / 4)
                        {
                            stb.Append("//写敏感区域,偏移:" + buf[idata[index + 1]]);
                        }
                        else
                        {
                            stb.Append("//" + buf[idata[index + 1]] + "");
                        }
 
                        stb.Append("\r\n");
 
                        break;
 
                    case 0x25:
                        buf[idata[index + 1]] += buf[idata[index + 2]];
                        stb.Append("buf[" + idata[index + 1] + "] += buf[" + idata[index + 2] + "];\r\n");
                        break;
 
                    case 0x26:
                        buf[idata[index + 1]] -= buf[idata[index + 2]];
                        stb.Append("buf[" + idata[index + 1] + "] -= buf[" + idata[index + 2] + "];\r\n");
                        break;
 
                    case 0x27:
                        buf[idata[index + 1]] ^= buf[idata[index + 2]];
                        stb.Append("buf[" + idata[index + 1] + "] ^= buf[" + idata[index + 2] + "];\r\n");
                        break;
 
                    case 0x28:
                        buf[idata[index + 1]] <<= buf[idata[index + 2]] & 0xFF;
                        stb.Append("buf[" + idata[index + 1] + "] <<= buf[" + idata[index + 2] + "];\r\n");
                        break;
 
                    case 0x29:
                        buf[idata[index + 1]] >>= buf[idata[index + 2]] & 0xFF;
                        stb.Append("buf[" + idata[index + 1] + "] >>= buf[" + idata[index + 2] + "];\r\n");
                        break;
 
                    case 0x2A:
                        buf[idata[index + 1]] &= buf[idata[index + 2]];
                        stb.Append("buf[" + idata[index + 1] + "] &= buf[" + idata[index + 2] + "];\r\n");
                        break;
 
                    case 0x2B:
                        index = buf[idata[index + 1]];
                        stb.Append("jmp " + buf[idata[index + 1]] + ";\r\n");
                        goto start;
                        break;
 
                    case 0x2C:
                        stb.Append("if(buf[" + idata[index + 2] + "] == 0)\r\n{\r\n\tjmp " + buf[idata[index + 1]] + ";\r\n}\r\n");
 
                        if(buf[idata[index + 2]] == 0)
                        {
                            stb.Append("//上述跳转已成立\r\n\r\n");
                            index = buf[idata[index + 1]];
                            goto start;
                        }                      
 
                        break;
 
                    case 0x2D:
                        stb.Append("if(buf[" + idata[index + 2] + "] != 0)\r\n{\r\n\tjmp " + buf[idata[index + 1]] + ";\r\n}\r\n");
 
                        if(buf[idata[index + 2]] != 0)
                        {
                            //if(buf[idata[index + 1]] != 126)
                            {
                                stb.Append("//上述跳转已成立\r\n\r\n");
                                index = buf[idata[index + 1]];
                                goto start;
                            }
                        }
 
                        break;
 
                    case 0x30:
                        Console.WriteLine("wrong");
                        goto exit;
                        break;
 
                    case 0x2F:
                        Console.WriteLine("correct");
                        Console.WriteLine("flag is flag{YourPatch}");
                        goto exit;
                        break;
 
                    case 0x2E:
                        Console.WriteLine("CPU已终止运行");
                        goto exit;
                        break;
                }
 
                index += 3;
            }
 
            exit:
                Console.WriteLine("代码:");
                Console.WriteLine(stb.ToString());
                File.WriteAllText(@"D:\exercise\CTF\20190421\strange_int_740dfa57eab289ada9d30380ef4393d5\code.txt",stb.ToString());
                while(true);
        }
    }
}


上述代码输出的第一个类C程序如下(已经过人工简化和分析):
[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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
0:
i = 129;
6:
code[0] = 0;//0 t = 0
9:
buf[2] = code[i];//读敏感区域,偏移:129-137
12:
buf[3] = buf[2];//buf[3] = code[i]
15:
buf[4] = 8;
18:
buf[3] <<= buf[4];//buf[3] = code[i] << 8
21:
buf[2] ^= buf[3];//buf[2] = code[i] ^ (code[i] << 8)
24:
buf[3] <<= buf[4];//buf[3] = code[i] << 16;
27:
buf[2] ^= buf[3];//buf[2] = (code[i] ^ (code[i] << 8)) ^ (code[i] << 16)
30:
buf[3] <<= buf[4];//buf[3] = code[i] << 24;
33:
buf[2] ^= buf[3];//buf[2] = (code[i] ^ (code[i] << 8)) ^ (code[i] << 16) ^ (code[i] << 24)
36:
buf[3] ^= buf[3];//buf[3] = 0
39:
buf[4] = code[buf[3]];//0 buf[4] = t
42:
code[buf[3]] = buf[2];//0 t = (code[i] ^ (code[i] << 8)) ^ (code[i] << 16) ^ (code[i] << 24)
45:
buf[2] ^= buf[4];//buf[2] = ((code[i] ^ (code[i] << 8)) ^ (code[i] << 16) ^ (code[i] << 24)) ^ ((code[i - 1] ^ (code[i - 1] << 8)) ^ (code[i - 1] << 16) ^ (code[i - 1] << 24))
48:
code[i] = buf[2];//写敏感区域,偏移:129-137 code[i] = ((code[i] ^ (code[i] << 8)) ^ (code[i] << 16) ^ (code[i] << 24)) ^ ((code[i - 1] ^ (code[i - 1] << 8)) ^ (code[i - 1] << 16) ^ (code[i - 1] << 24))
51:
buf[1] = 1;
54:
i += buf[1];
57:
buf[1] = i;
60:
buf[2] = 129;
63:
buf[1] -= buf[2];
66:
buf[2] = 9;
69:
buf[1] -= buf[2];
72:
buf[2] = 9;
75:
if(buf[1] != 0)
{
        jmp 9;
}
//上述跳转已成立
 
78:
buf[0] = 129;
81:
buf[1] = buf[0];
84:
buf[2] = 9;
87:
buf[1] += buf[2];
90:
buf[3] = code[buf[0]];//读敏感区域,偏移:129
93:
buf[4] = code[buf[1]];//读敏感区域,偏移:138
96:
buf[3] -= buf[4];
99:
buf[4] = 126;
102:
if(buf[3] != 0)
{
        jmp 126;
}
//上述跳转已成立
 
126:


原理已经大致写在了注释中,126处的跳转如果成立,则输出错误信息,如果不成立,就会转入下面的条件判断:
[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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
0:
buf[0] = 129;
3:
buf[1] ^= buf[1];
6:
code[buf[1]] = buf[1];//0
9:
buf[2] = code[buf[0]];//读敏感区域,偏移:129
12:
buf[3] = buf[2];
15:
buf[4] = 8;
18:
buf[3] <<= buf[4];
21:
buf[2] ^= buf[3];
24:
buf[3] <<= buf[4];
27:
buf[2] ^= buf[3];
30:
buf[3] <<= buf[4];
33:
buf[2] ^= buf[3];
36:
buf[3] ^= buf[3];
39:
buf[4] = code[buf[3]];//0
42:
code[buf[3]] = buf[2];//0
45:
buf[2] ^= buf[4];
48:
code[buf[0]] = buf[2];//写敏感区域,偏移:129
51:
buf[1] = 1;
54:
buf[0] += buf[1];
57:
buf[1] = buf[0];
60:
buf[2] = 129;
63:
buf[1] -= buf[2];
66:
buf[2] = 9;
69:
buf[1] -= buf[2];
72:
buf[2] = 9;
75:
if(buf[1] != 0)
{
        jmp 9;
}
//上述跳转已成立
 
9:
buf[2] = code[buf[0]];//读敏感区域,偏移:130
12:
buf[3] = buf[2];
15:
buf[4] = 8;
18:
buf[3] <<= buf[4];
21:
buf[2] ^= buf[3];
24:
buf[3] <<= buf[4];
27:
buf[2] ^= buf[3];
30:
buf[3] <<= buf[4];
33:
buf[2] ^= buf[3];
36:
buf[3] ^= buf[3];
39:
buf[4] = code[buf[3]];//0
42:
code[buf[3]] = buf[2];//0
45:
buf[2] ^= buf[4];
48:
code[buf[0]] = buf[2];//写敏感区域,偏移:130
51:
buf[1] = 1;
54:
buf[0] += buf[1];
57:
buf[1] = buf[0];
60:
buf[2] = 129;
63:
buf[1] -= buf[2];
66:
buf[2] = 9;
69:
buf[1] -= buf[2];
72:
buf[2] = 9;
75:
if(buf[1] != 0)
{
        jmp 9;
}
//上述跳转已成立
 
9:
buf[2] = code[buf[0]];//读敏感区域,偏移:131
12:
buf[3] = buf[2];
15:
buf[4] = 8;
18:
buf[3] <<= buf[4];
21:
buf[2] ^= buf[3];
24:
buf[3] <<= buf[4];
27:
buf[2] ^= buf[3];
30:
buf[3] <<= buf[4];
33:
buf[2] ^= buf[3];
36:
buf[3] ^= buf[3];
39:
buf[4] = code[buf[3]];//0
42:
code[buf[3]] = buf[2];//0
45:
buf[2] ^= buf[4];
48:
code[buf[0]] = buf[2];//写敏感区域,偏移:131
51:
buf[1] = 1;
54:
buf[0] += buf[1];
57:
buf[1] = buf[0];
60:
buf[2] = 129;
63:
buf[1] -= buf[2];
66:
buf[2] = 9;
69:
buf[1] -= buf[2];
72:
buf[2] = 9;
75:
if(buf[1] != 0)
{
        jmp 9;
}
//上述跳转已成立
 
9:
buf[2] = code[buf[0]];//读敏感区域,偏移:132
12:
buf[3] = buf[2];
15:
buf[4] = 8;
18:
buf[3] <<= buf[4];
21:
buf[2] ^= buf[3];
24:
buf[3] <<= buf[4];
27:
buf[2] ^= buf[3];
30:
buf[3] <<= buf[4];
33:
buf[2] ^= buf[3];
36:
buf[3] ^= buf[3];
39:
buf[4] = code[buf[3]];//0
42:
code[buf[3]] = buf[2];//0
45:
buf[2] ^= buf[4];
48:
code[buf[0]] = buf[2];//写敏感区域,偏移:132
51:
buf[1] = 1;
54:
buf[0] += buf[1];
57:
buf[1] = buf[0];
60:
buf[2] = 129;
63:
buf[1] -= buf[2];
66:
buf[2] = 9;
69:
buf[1] -= buf[2];
72:
buf[2] = 9;
75:
if(buf[1] != 0)
{
        jmp 9;
}
//上述跳转已成立
 
9:
buf[2] = code[buf[0]];//读敏感区域,偏移:133
12:
buf[3] = buf[2];
15:
buf[4] = 8;
18:
buf[3] <<= buf[4];
21:
buf[2] ^= buf[3];
24:
buf[3] <<= buf[4];
27:
buf[2] ^= buf[3];
30:
buf[3] <<= buf[4];
33:
buf[2] ^= buf[3];
36:
buf[3] ^= buf[3];
39:
buf[4] = code[buf[3]];//0
42:
code[buf[3]] = buf[2];//0
45:
buf[2] ^= buf[4];
48:
code[buf[0]] = buf[2];//写敏感区域,偏移:133
51:
buf[1] = 1;
54:
buf[0] += buf[1];
57:
buf[1] = buf[0];
60:
buf[2] = 129;
63:
buf[1] -= buf[2];
66:
buf[2] = 9;
69:
buf[1] -= buf[2];
72:
buf[2] = 9;
75:
if(buf[1] != 0)
{
        jmp 9;
}
//上述跳转已成立
 
9:
buf[2] = code[buf[0]];//读敏感区域,偏移:134
12:
buf[3] = buf[2];
15:
buf[4] = 8;
18:
buf[3] <<= buf[4];
21:
buf[2] ^= buf[3];
24:
buf[3] <<= buf[4];
27:
buf[2] ^= buf[3];
30:
buf[3] <<= buf[4];
33:
buf[2] ^= buf[3];
36:
buf[3] ^= buf[3];
39:
buf[4] = code[buf[3]];//0
42:
code[buf[3]] = buf[2];//0
45:
buf[2] ^= buf[4];
48:
code[buf[0]] = buf[2];//写敏感区域,偏移:134
51:
buf[1] = 1;
54:
buf[0] += buf[1];
57:
buf[1] = buf[0];
60:
buf[2] = 129;
63:
buf[1] -= buf[2];
66:
buf[2] = 9;
69:
buf[1] -= buf[2];
72:
buf[2] = 9;
75:
if(buf[1] != 0)
{
        jmp 9;
}
//上述跳转已成立
 
9:
buf[2] = code[buf[0]];//读敏感区域,偏移:135
12:
buf[3] = buf[2];
15:
buf[4] = 8;
18:
buf[3] <<= buf[4];
21:
buf[2] ^= buf[3];
24:
buf[3] <<= buf[4];
27:
buf[2] ^= buf[3];
30:
buf[3] <<= buf[4];
33:
buf[2] ^= buf[3];
36:
buf[3] ^= buf[3];
39:
buf[4] = code[buf[3]];//0
42:
code[buf[3]] = buf[2];//0
45:
buf[2] ^= buf[4];
48:
code[buf[0]] = buf[2];//写敏感区域,偏移:135
51:
buf[1] = 1;
54:
buf[0] += buf[1];
57:
buf[1] = buf[0];
60:
buf[2] = 129;
63:
buf[1] -= buf[2];
66:
buf[2] = 9;
69:
buf[1] -= buf[2];
72:
buf[2] = 9;
75:
if(buf[1] != 0)
{
        jmp 9;
}
//上述跳转已成立
 
9:
buf[2] = code[buf[0]];//读敏感区域,偏移:136
12:
buf[3] = buf[2];
15:
buf[4] = 8;
18:
buf[3] <<= buf[4];
21:
buf[2] ^= buf[3];
24:
buf[3] <<= buf[4];
27:
buf[2] ^= buf[3];
30:
buf[3] <<= buf[4];
33:
buf[2] ^= buf[3];
36:
buf[3] ^= buf[3];
39:
buf[4] = code[buf[3]];//0
42:
code[buf[3]] = buf[2];//0
45:
buf[2] ^= buf[4];
48:
code[buf[0]] = buf[2];//写敏感区域,偏移:136
51:
buf[1] = 1;
54:
buf[0] += buf[1];
57:
buf[1] = buf[0];
60:
buf[2] = 129;
63:
buf[1] -= buf[2];
66:
buf[2] = 9;
69:
buf[1] -= buf[2];
72:
buf[2] = 9;
75:
if(buf[1] != 0)
{
        jmp 9;
}
//上述跳转已成立
 
9:
buf[2] = code[buf[0]];//读敏感区域,偏移:137
12:
buf[3] = buf[2];
15:
buf[4] = 8;
18:
buf[3] <<= buf[4];
21:
buf[2] ^= buf[3];
24:
buf[3] <<= buf[4];
27:
buf[2] ^= buf[3];
30:
buf[3] <<= buf[4];
33:
buf[2] ^= buf[3];
36:
buf[3] ^= buf[3];
39:
buf[4] = code[buf[3]];//0
42:
code[buf[3]] = buf[2];//0
45:
buf[2] ^= buf[4];
48:
code[buf[0]] = buf[2];//写敏感区域,偏移:137
51:
buf[1] = 1;
54:
buf[0] += buf[1];
57:
buf[1] = buf[0];
60:
buf[2] = 129;
63:
buf[1] -= buf[2];
66:
buf[2] = 9;
69:
buf[1] -= buf[2];
72:
buf[2] = 9;
75:
if(buf[1] != 0)
{
        jmp 9;
}
78:
buf[0] = 129;
81:
buf[1] = buf[0];
84:
buf[2] = 9;
87:
buf[1] += buf[2];
90:
buf[3] = code[buf[0]];//读敏感区域,偏移:129
93:
buf[4] = code[buf[1]];//读敏感区域,偏移:138
96:
buf[3] -= buf[4];
99:
buf[4] = 126;
102:
if(buf[3] != 0)
{
        jmp 126;
}
105:
buf[3] = 1;
108:
buf[0] += buf[3];
111:
buf[1] += buf[3];
114:
buf[2] -= buf[3];
117:
buf[4] = 90;
120:
if(buf[2] != 0)
{
        jmp 90;
}
//上述跳转已成立
 
90:
buf[3] = code[buf[0]];//读敏感区域,偏移:130
93:
buf[4] = code[buf[1]];//读敏感区域,偏移:139
96:
buf[3] -= buf[4];
99:
buf[4] = 126;
102:
if(buf[3] != 0)
{
        jmp 126;
}
105:
buf[3] = 1;
108:
buf[0] += buf[3];
111:
buf[1] += buf[3];
114:
buf[2] -= buf[3];
117:
buf[4] = 90;
120:
if(buf[2] != 0)
{
        jmp 90;
}
//上述跳转已成立
 
90:
buf[3] = code[buf[0]];//读敏感区域,偏移:131
93:
buf[4] = code[buf[1]];//读敏感区域,偏移:140
96:
buf[3] -= buf[4];
99:
buf[4] = 126;
102:
if(buf[3] != 0)
{
        jmp 126;
}
105:
buf[3] = 1;
108:
buf[0] += buf[3];
111:
buf[1] += buf[3];
114:
buf[2] -= buf[3];
117:
buf[4] = 90;
120:
if(buf[2] != 0)
{
        jmp 90;
}
//上述跳转已成立
 
90:
buf[3] = code[buf[0]];//读敏感区域,偏移:132
93:
buf[4] = code[buf[1]];//读敏感区域,偏移:141
96:
buf[3] -= buf[4];
99:
buf[4] = 126;
102:
if(buf[3] != 0)
{
        jmp 126;
}
105:
buf[3] = 1;
108:
buf[0] += buf[3];
111:
buf[1] += buf[3];
114:
buf[2] -= buf[3];
117:
buf[4] = 90;
120:
if(buf[2] != 0)
{
        jmp 90;
}
//上述跳转已成立
 
90:
buf[3] = code[buf[0]];//读敏感区域,偏移:133
93:
buf[4] = code[buf[1]];//读敏感区域,偏移:142
96:
buf[3] -= buf[4];
99:
buf[4] = 126;
102:
if(buf[3] != 0)
{
        jmp 126;
}
105:
buf[3] = 1;
108:
buf[0] += buf[3];
111:
buf[1] += buf[3];
114:
buf[2] -= buf[3];
117:
buf[4] = 90;
120:
if(buf[2] != 0)
{
        jmp 90;
}
//上述跳转已成立
 
90:
buf[3] = code[buf[0]];//读敏感区域,偏移:134
93:
buf[4] = code[buf[1]];//读敏感区域,偏移:143
96:
buf[3] -= buf[4];
99:
buf[4] = 126;
102:
if(buf[3] != 0)
{
        jmp 126;
}
105:
buf[3] = 1;
108:
buf[0] += buf[3];
111:
buf[1] += buf[3];
114:
buf[2] -= buf[3];
117:
buf[4] = 90;
120:
if(buf[2] != 0)
{
        jmp 90;
}
//上述跳转已成立
 
90:
buf[3] = code[buf[0]];//读敏感区域,偏移:135
93:
buf[4] = code[buf[1]];//读敏感区域,偏移:144
96:
buf[3] -= buf[4];
99:
buf[4] = 126;
102:
if(buf[3] != 0)
{
        jmp 126;
}
105:
buf[3] = 1;
108:
buf[0] += buf[3];
111:
buf[1] += buf[3];
114:
buf[2] -= buf[3];
117:
buf[4] = 90;
120:
if(buf[2] != 0)
{
        jmp 90;
}
//上述跳转已成立
 
90:
buf[3] = code[buf[0]];//读敏感区域,偏移:136
93:
buf[4] = code[buf[1]];//读敏感区域,偏移:145
96:
buf[3] -= buf[4];
99:
buf[4] = 126;
102:
if(buf[3] != 0)
{
        jmp 126;
}
105:
buf[3] = 1;
108:
buf[0] += buf[3];
111:
buf[1] += buf[3];
114:
buf[2] -= buf[3];
117:
buf[4] = 90;
120:
if(buf[2] != 0)
{
        jmp 90;
}
//上述跳转已成立
 
90:
buf[3] = code[buf[0]];//读敏感区域,偏移:137
93:
buf[4] = code[buf[1]];//读敏感区域,偏移:146
96:
buf[3] -= buf[4];
99:
buf[4] = 126;
102:
if(buf[3] != 0)
{
        jmp 126;
}
105:
buf[3] = 1;
108:
buf[0] += buf[3];
111:
buf[1] += buf[3];
114:
buf[2] -= buf[3];
117:
buf[4] = 90;
120:
if(buf[2] != 0)
{
        jmp 90;
}
123:


很容易看出,上面的算法是首先将前9个四字节整数进行一种很特殊的异或之后,和前一项的异或结果再行异或得到了每个新的整数值,又后面的判断的值,对于一切偏移地址为x的整数(共9个数),其异或后的值如果与偏移地址为(x + 9)处的整数相等,则会触发成功提示分支。

根据上面的条件,我编写了如下的程序来求出真正的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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace 逆向输入求解
{
    class Program
    {
        static void Main(string[] args)
        {
            var data = new int[]{0x38, 0x62, 0x64, 0x61, 0x65, 0x34, 0x35, 0x36, 0x2D, 0x35, 0x61, 0x63,
                0x38, 0x2D, 0x31, 0x31, 0x65, 0x39, 0x2D, 0x61, 0x31, 0x63, 0x31, 0x2D, 0x38, 0x38, 0x65, 0x39,
                0x66, 0x65, 0x38, 0x30, 0x66, 0x65, 0x61, 0x66, 0x65, 0x55, 0x63, 0x57, 0x01, 0x04, 0x53, 0x06,
                0x49, 0x49, 0x49, 0x1F, 0x1F, 0x07, 0x57, 0x51, 0x57, 0x43, 0x5F, 0x57, 0x57, 0x5E, 0x43, 0x57,
                0x0A, 0x02, 0x57, 0x43, 0x5E, 0x03, 0x5E, 0x57, 0x00, 0x00, 0x59, 0x0F, 0x77, 0x72, 0x6F, 0x6E,
                0x67, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x63, 0x6F, 0x72, 0x72, 0x65, 0x63, 0x74, 0x20,
                0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x66, 0x6C, 0x61, 0x67, 0x20, 0x69, 0x73, 0x20, 0x66, 0x6C,
                0x61, 0x67, 0x7B, 0x59, 0x6F, 0x75, 0x72, 0x50, 0x61, 0x74, 0x63, 0x68, 0x7D, 0x20, 0x20, 0x20,
                0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
                0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20};
 
            var idata = new int[data.Length / 4];
 
            for(var i = 0;i < idata.Length;i++)
            {
                idata[i] = data[i * 4] | (data[i * 4 + 1] << 8) | (data[i * 4 + 2] << 16) | (data[i * 4 + 3] << 24);
            }
 
            var t = 0;
            var newdata = new int[idata.Length];
 
            for(var i = 0;i < 9;i++)
            {
                newdata[i] = (idata[i] ^ (idata[i] << 8) ^ (idata[i] << 16) ^ (idata[i] << 24)) ^ t;
                t = (idata[i] ^ (idata[i] << 8) ^ (idata[i] << 16) ^ (idata[i] << 24));
            }
 
            newdata[9] = idata[9];
 
            //var sub = (idata[0] ^ (idata[0] << 8) ^ (idata[0] << 16) ^ (idata[0] << 24)) - ((idata[idata.Length - 2] ^ (idata[idata.Length - 2] << 8) ^ (idata[idata.Length - 2] << 16) ^ (idata[idata.Length - 2] << 24)) ^ (idata[idata.Length - 1] ^ (idata[idata.Length - 1] << 8) ^ (idata[idata.Length - 1] << 16) ^ (idata[idata.Length - 1] << 24)));
            /*var sub = newdata[0] - newdata[newdata.Length - 1];
            Console.WriteLine("差为" + sub);*/
 
            var answer = new int[idata.Length];
 
            for(var i = 0;i < 9;i++)
            {
                var tc = 0;
 
                for(var j = 0;j <= 0x7FFFFFFF;j++)
                {
                    tc = j ^ (j << 8) ^ (j << 16) ^ (j << 24);
 
                    if(i > 0)
                    {
                        tc ^= answer[i - 1] ^ (answer[i - 1] << 8) ^ (answer[i - 1] << 16) ^ (answer[i - 1] << 24);
                    }
 
                    if(tc == idata[i + 9])
                    {
                        answer[i] = j;
                        Console.WriteLine("0x{0:X8}",j);
                        break;
                    }
                }
 
                 
            }
 
 
            while(true);
        }
    }
}

1.png
输出结果如上:根据其特点,只需要从第一个字符开始推导即可,由于式子难以逆向,所以本次采用暴力求解的方式,
首先枚举第一个四字节整数的所有可能性,然后在确定下第一个整数的情况下,暴力求解第二个整数,以此类推,求出全部的9个整数。我的虚拟机的提示如下:
2.png
bochs运行原始镜像的提示如下:
3.jpg
因此其是完全正确的
4.png

由提示可知刚才patch的全部内容即为flag,即flag为flag{e064d5aa-5a72-11e9-9200-88e9fe80feaf}

免费评分

参与人数 40吾爱币 +44 热心值 +35 收起 理由
一寸黑 + 1 + 1 谢谢@Thanks!
kujing + 1 + 1 我很赞同!
magik1227 + 1 用心讨论,共获提升!
浅笑心柔 + 1 + 1 我看不懂,但是觉得好厉害!
zls黑战魔 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
canoa + 1 鼓励转贴优秀软件安全工具和文档!
zzcc5200 + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
hjw45611 + 1 + 1 热心回复!
啥也不会的查理 + 1 我很赞同!
ymy119 + 1 + 1 我很赞同!
brIckZ + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
贡嘎拉 + 1 + 1 谢谢@Thanks!
GenW + 1 + 1 给大佬评分支持!
majoroasis + 1 + 1 用心讨论,共获提升!
winw2 + 1 用心讨论,共获提升!
sysqjszg + 1 牛逼!!
Lugia + 1 + 1 谢谢@Thanks!
虞珂啊 + 1 + 1 谢谢@Thanks!
无疆北月 + 1 + 1 谢谢@Thanks!
我要上天 + 1 + 1 我很赞同!
NB2665597272 + 1 + 1 鼓励转贴优秀软件安全工具和文档!
紫翼蓝閖 + 1 谢谢@Thanks!
静叶流云 + 1 + 1 用心讨论,共获提升!
学无止境no1 + 1 用心讨论,共获提升!
carman881006 + 1 + 1 用心讨论,共获提升!
lncyq + 1 + 1 太牛逼了!虽然我看不懂,但是还是要加热心加分
poisonbcat + 1 + 1 用心讨论,共获提升!
CrazyNut + 3 + 1 不明觉厉
南冥的小鲲 + 1 + 1 用心讨论,共获提升!
XhyEax + 3 + 1 膜拜dalao
zzzain46 + 3 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
shelly1314 + 1 谢谢@Thanks!
gink + 1 + 1 谢谢@Thanks!
yypE + 2 + 1 用心讨论,共获提升!
40m41h42t + 1 + 1 谢谢@Thanks!
Pizza + 2 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
Akesudia + 1 + 1 用心讨论,共获提升!
moril + 1 + 1 sdl,tql,wsl
笙若 + 1 + 1 谢谢@Thanks!
qvq + 1 + 1 谢谢@Thanks!

查看全部评分

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

 楼主| lizhirui 发表于 2019-4-22 21:58
qvq 发表于 2019-4-22 21:54
请问,eg000:0052处的跳转利用段选择子跳入了32位代码段
这里为什么是32位

由于这段代码是MBR,因此启动时CPU还是实模式,此时执行的大部分是16位指令,然后在保护模式切换前后,有几条32位指令,在那行jmp执行前,利用lgdt加载了GDT,利用lmsw切换到了保护模式,而在保护模式下CPU就是正式以32位模式执行了,虽然也可以执行16位程序,但是通过情理上推导以及你可以去查看一下GDT中的第1号项(8是段选择子,对应GDT中的第1号项),描述也显示该段是32位代码段
40m41h42t 发表于 2019-4-25 17:01
52user 发表于 2019-4-25 11:53
ALt+S 设置新区段可以达到类似效果

不知道你的图为啥我看不到。。选择16位的话是乱码&#128514;,我就单独开的16位的段了,大概是这么个效果:
MBR16.png
segment200.png
depy 发表于 2019-4-22 21:45
qvq 发表于 2019-4-22 21:54
请问,eg000:0052处的跳转利用段选择子跳入了32位代码段
这里为什么是32位

点评

由于这段代码是MBR,因此启动时CPU还是实模式,此时执行的大部分是16位指令,然后在保护模式切换前后,有几条32位指令,在那行jmp执行前,利用lgdt加载了GDT,利用lmsw切换到了保护模式,而在保护模式下CPU就是正式  详情 回复 发表于 2019-4-22 21:58
sanjsan 发表于 2019-4-22 21:55
这也太猛了吧

点评

23333干了8个小时,第一次干虚拟机的程序逆向  详情 回复 发表于 2019-4-22 21:59
 楼主| lizhirui 发表于 2019-4-22 21:59

23333干了8个小时,第一次干虚拟机的程序逆向
sanjsan 发表于 2019-4-22 22:12
lizhirui 发表于 2019-4-22 21:59
23333干了8个小时,第一次干虚拟机的程序逆向

我第一道虚拟机就做了5小时,太菜了

点评

666比我做得快这么多啊  详情 回复 发表于 2019-4-22 22:14
 楼主| lizhirui 发表于 2019-4-22 22:14
sanjsan 发表于 2019-4-22 22:12
我第一道虚拟机就做了5小时,太菜了

666比我做得快这么多啊
hxijin 发表于 2019-4-22 23:15
学习学习,谢谢
rbgaoshou 发表于 2019-4-23 07:36
这个确实比较厉害哈!
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2025-5-25 14:38

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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