• 任务段call 与jmp实验


    任务段

    前言

    在调用门和中断门还有陷阱门中,会有压栈操作,由于cs和cpl会发生改变,导致ss也必须切换,切换时候,esp和ss是从任务段中获得的,也及时TSS

    TSS结构

     大小共104字节

    TR寄存器

    了解任务段一定要知道TR寄存器,这是CPU找到TSS的关键,TR寄存器总共有98个位(其实是16位,跟段选择子一样)

    流程:

    1、tr寄存器通过段选择子

    2、在gdt表里面找到段描述符,并且通过段描述符的结构,找到BaseAddress地址,找到BaseAddress地址后,相当于找到了TSS任务段

    3、并且从段描述符中还获得了lmit其实就是TSS段的大小在32位的情况下一般是0x68字节的,如图

     TSS段描述符结构

    其实这里本应该在放一张开发Intel手册的图的,这样更清晰

    Type 1001代表着是可用的任务段,如果B为1则是繁忙状态

     TR寄存器的读写

    将段描述符加载到TR寄存器

    LTR指令

    说明:

    1、用LTR指令去装载的话,仅仅是改变TR寄存器的值(96位),并没有真正改变TSS(原来的TSS还在那)

    2、LTR指令只能在系统层使用

    3、加载后TSS段描述符会状态位会发生改变

    读TR寄存器

    STR指令

    说明:

    如果用STR去读的话,只读了TR寄存器的16为,也就是选择子

    实验流程

    先构造TSS任务段,然后在将任务段的eip改为你要执行函数的地址,其他的可以根据你自己的改,其次就是需要让cs和ss指向的是同一个(因为他们是一对),在去执行就可以调用成功了,不过我这里有个问题,希望有大佬可以指出

    放代码,如下:

     1 // Task_Segment.cpp : Defines the entry point for the console application.
     2 //
     3 
     4 #include "stdafx.h"
     5 #include<windows.h>
     6 DWORD dwOK;
     7 DWORD dwESP;
     8 DWORD dwCS;
     9 __declspec(naked) void func()
    10 {
    11     dwOK=1;
    12     __asm{
    13         int 3
    14         mov eax,esp
    15         mov dwESP,eax
    16         mov ax,cs
    17         mov word ptr [dwCS],ax
    18         iretd
    19         //go back code don't write
    20     }
    21 }
    22 
    23 int main(int argc, char* argv[])
    24 {
    25     char bu[0x10];//0x12ff70
    26     int iCr3;
    27     printf("input CR3:
    ");
    28     scanf("%x",&iCr3);
    29 
    30     DWORD iTss[0x68]={
    31         0x00000000,//link
    32         (DWORD)bu,//esp0
    33         0x00000010,//ss0
    34         0x00000000,//esp1
    35         0x00000000,//ss1
    36         0x00000000,//esp2
    37         0x00000000,//ss2
    38         (DWORD)iCr3,//cr3
    39         0x00401020,//eip
    40         0x00000000,//eflags
    41         0x00000000,//eax
    42         0x00000000,//ecx
    43         0x00000000,//edx
    44         0x00000000,//ebx
    45         (DWORD)bu,//esp
    46         0x00000000,//ebp
    47         0x00000000,//esi
    48         0x00000000,//edi
    49         0x00000023,//es
    50         0x00000008,//cs 0x0000001B
    51         0x00000010,//ss 0x00000023
    52         0x00000023,//ds
    53         0x00000030,//fs 0x0000003B
    54         0x00000000,//ldt
    55         0x20ac0000
    56     };
    57     printf("iTss: %x
    ",iTss);
    58     /*
    59     __asm{
    60         int 0x20
    61       }
    62     */
    63     char buff[6];
    64 
    65     *(DWORD*)&buff[0]=0x12345678;
    66     *(WORD*)&buff[4]=0x48;
    67     _asm
    68     {
    69         call fword ptr [buff]
    70     }
    71     printf("ok = %d ESP = %x CS = %x 
    ",dwOK,dwESP,dwCS);
    72     return 0;
    73 }

    根据函数地址,创建段描述符

    修改段描述符

     通过指令!process 0 0输入CR3

    输入0aac0320 

     输入g运行,可以看到,已经运行了

     为了方便在来看下寄存器

     

     观察寄存器可以发现,所有的寄存器已经被换掉了

    但不知道为啥 运行到这里之后,运行了in3后,接着运行到iretd就开始报错了,所以我怀疑我跳回去的代码是有问题的,如果不是用iretd这个指令跳回去,那我应该怎么跳回去呢?

    在网上也查了别人的执行流程,感觉是一个道理,沉淀依然不够,得把实验实力加深点,再来看看这个错误了,还得接着实验才行了

    提问

     1:)8号中断是什么?

    8003f440  00008500`00501198
    将其分解

     在去查找其相对应的段选择子

     8003f050  80008955`27000068

    接着分解

     可以知道base

    用命令dt  _KTSS 查看该地址检查

    0: kd> dt _KTSS 80552700
    nt!_KTSS
       +0x000 Backlink         : 0
       +0x002 Reserved0        : 0
       +0x004 Esp0             : 0x8054f700
       +0x008 Ss0              : 0x10
       +0x00a Reserved1        : 0
       +0x00c NotUsed1         : [4] 0
       +0x01c CR3              : 0xb0d000
       +0x020 Eip              : 0x80544509
       +0x024 EFlags           : 0
       +0x028 Eax              : 0
       +0x02c Ecx              : 0
       +0x030 Edx              : 0
       +0x034 Ebx              : 0
       +0x038 Esp              : 0x8054f700
       +0x03c Ebp              : 0
       +0x040 Esi              : 0
       +0x044 Edi              : 0
       +0x048 Es               : 0x23
       +0x04a Reserved2        : 0
       +0x04c Cs               : 8
       +0x04e Reserved3        : 0
       +0x050 Ss               : 0x10
       +0x052 Reserved4        : 0
       +0x054 Ds               : 0x23
       +0x056 Reserved5        : 0
       +0x058 Fs               : 0x30
       +0x05a Reserved6        : 0
       +0x05c Gs               : 0
       +0x05e Reserved7        : 0
       +0x060 LDT              : 0
       +0x062 Reserved8        : 0
       +0x064 Flags            : 0
       +0x066 IoMapBase        : 0x20ac
       +0x068 IoMaps           : [1] _KiIoAccessMap
       +0x208c IntDirectionMap  : [32]  ""

    2:)做了什么事情?

    替换当前环境的值

    3:)替换了哪些寄存器?

    查看了idtr表后可以知道,其切换了cs段,在学习调用门的时候就知道,提权会保存之前的环境的,所以在运行时,可以知道寄存器更改了cs、ss、esp、ip

    在来看看任务门替换的,可以发现都是由于ss与ds必须是一对,cs又都是一样的,所以只有ip变了

    4:)替换后的值是多少?

    0x80544509

    5:)为什么这样设计

    程序出现异常,进行任务的切换

  • 相关阅读:
    Django之信号
    Django缓存
    git简介
    Django request.path
    Django loaction.pathname 属性
    Ajax
    Anaconda 执行命令报ssl错误
    几行代码快速去掉迅雷临时文件的后缀
    win7 64 位安装 python,提示: 0x80240017-未指定的错误
    系统变量 %USERPROFILE%
  • 原文地址:https://www.cnblogs.com/pppyyyzzz/p/13820623.html
Copyright © 2020-2023  润新知