吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 23083|回复: 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] 纯文本查看 复制代码
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] 纯文本查看 复制代码
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] 纯文本查看 复制代码
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#] 纯文本查看 复制代码
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] 纯文本查看 复制代码
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] 纯文本查看 复制代码
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#] 纯文本查看 复制代码
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, 2024-12-22 16:24

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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