调用门

Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html

调用门

问题索引:

1. 调用门的"门"这字的含义。
2. 如果通过这扇门走?
3. 为什么需要调用门?
4. 为何构造call时数组前四位随便写?
5. 调用门构造实验
6. 远调用的特点?
7. 远调用带参数实验
8. 远调用提权实验
9. 权限的CALL指令的门权限检查
10.call调用门提权,iretd降权实验

问题解答:

1. 调用门的"门"这字的含义。

  门-通往另外一个世界的通道,同时也是一种控制的阻碍。2. 如果通过这扇门走?

 

  Segment - 段选择子,通过这个段选择子来替换代码段寄存器。
  Offset in Segment - 段内偏移,段只能提供基地址,但怎么走还是要看在基地址基础上计算偏移量的。
3. 为什么需要调用门?

  方便权限控制,可以不改变R3层的调用方式的基础上改变调用权限来实现控制效果(写好的代码不变,但我可以让你不通过)。

4. 为何构造call时数组前四位随便写?

  这四位应该本应该写偏移量的,但是调用门中自带着段内偏移,因此我们并不需要这四位,直接随便填写即可。

  

5. 调用门构造实验

  实验原理:构造调用门,然后执行调用门中指向的函数。

    #include "stdafx.h"
    #include <stdlib.h>
    __declspec(naked) void callgate(){
        __asm{
            int 3;
            retf;
        
        }
    }
    int main(int argc, char* argv[])
    {
        char buf[6] = {0};
        *(int*)&buf[0] = 0x12345678;
        *(short*)&buf[4] = 0x4b;
        printf("%x
",callgate);
        getchar();
        __asm{
            call fword ptr buf;
        }
        system("pause");
        return 0;
    }

  windbg进行如下修改
  eq 8003f090 00cf9b00`0000ffff (代码段描述符)
  eq 8003f048 0040ec00`00901005 (调用门,指向代码段)

6. 远调用的特点?
    call far,当使用调用门时,就是远程调用。
    远程调用即需要切换环境,至少保存四个值 ret,cs,ss,esp
    只要执行远call,其就会切换堆栈(下面实验我们就可以看出)


7. 远调用带参数实验

  实验思路:我们在0环读取gdtr表,如果提权成功则可以读取,否则不可以读取。

    #include "stdafx.h"
    #include <stdlib.h>
    __declspec(naked) void callgate(){
        __asm{
            int 3;
            retf 0x4;
        
        }
    }
    int main(int argc, char* argv[])
    {
        char buf[6] = {0};
        *(int*)&buf[0] = 0x12345678;
        *(short*)&buf[4] = 0x4b;
        printf("%x
",callgate);
        getchar();
        __asm{
            push 0x12345678;
            call fword ptr buf;
        }
        system("pause");
        return 0;
    }

  windbg 修改 调用门参数 (承接上个实验)
  eq 8003f048 0040ec01`00901005 (添加一个参数)

  堆栈如下:

  

      从中我们可以看出,只要通过调用门,其会另其一套堆栈,同时还需要记住参数的压栈顺序,参数是在中间部分。
      另外,retf 0x4, 不仅平衡三环的堆栈,也是平衡零环的堆栈。


8. 远调用提权实验

  实验思路:我们在0环读取gdtr表,如果提权成功则可以读取,否则不可以读取。

    // callgate.cpp : Defines the entry point for the console application.
    //
    
    #include "stdafx.h"
    #include <stdlib.h>
    
    int value = 0;
    __declspec(naked) void callgate(){
        __asm{
            //int 3;
            pushad;
            pushfd;
            mov eax,dword ptr ds:[0x8003f008];
            mov value,eax;
            popfd;
            popad;
            retf 0x4;
        }
    }
    int main(int argc, char* argv[])
    {
        char buf[6] = {0};
        *(int*)&buf[0] = 0x12345678;
        *(short*)&buf[4] = 0x48;
        printf("%x
",callgate);
        getchar();
        __asm{
            push 0x12345678;
            call fword ptr buf;
        }
        printf("%x
",value);
        system("pause");
        return 0;
    }

  实验效果


9. 权限的CALL指令的门权限检查

    其需要经过两关来检查:
    门检查 max(CPL,RPL) <= DPL
    CPL >= 代码段的DPL
  
10.call调用门提权,iretd降权实验
  iretd用于其中断返回的,注意其堆栈的变化。

  

    
    #include "stdafx.h"
    #include <stdlib.h>
    
    int value = 0;
    __declspec(naked) void callgate(){
        __asm{
            //int 3;
            pushad;
            pushfd;
            mov eax,dword ptr ds:[0x8003f008];
            mov value,eax;
            popfd;
            popad;
    
            
            pop eax;
            pop ebx;
            pushfd;
            push ebx;
            push  eax;
            
            iretd;
        }
    }
    int main(int argc, char* argv[])
    {
        char buf[6] = {0};
        *(int*)&buf[0] = 0x12345678;
        *(short*)&buf[4] = 0x48;
        printf("%x
",callgate);
        getchar();
        __asm{
            call fword ptr buf;
        }
        printf("%x
",value);
        system("pause");
        return 0;
}
原文地址:https://www.cnblogs.com/onetrainee/p/12430549.html