• 2_多核复杂性


    前置知识

    为了防止中断嵌套会自动 cli

    在中断能处理的时候会自动 cli -- 清除中断标记位 if。 这样如果在if = 0 的时候 ,0环死循环 那么就会造成系统假死崩溃。

    实际代码验证

    我们把前一次的代码设置成死循环

    void _declspec(naked) IdtEntry()
    {// 这里是裸函数,所以不会有函数头 push ebp,mov ebp,esp,,和 ret x / sub esp,x 来平衡堆栈;
    // 这样的好处是 我们能控制全部的代码。
    __asm
    {
    //mov eax, dword ptr ds : [0x8003f500];// 注意 : 行内 汇编(内联汇编,要求严格,需要把ds 这些都明确,不然会意想不到)
    //mov g_iData, eax;//
    label:
    jmp label;
    iretd;//iret 是实地址模式 16位的中断返回
    }


    }

    效果:

    系统假死,---实际也死了,,,windbg 也下中断不下来 因为if = 0. 实际 windbg 发送请求给子系统,然后处理。但是这下处理不下来了。

    windbg ctrl+break 失效 虚拟机也动不了

    1570071477586

    2 多核的复杂性 实验1

    2.1 每个核 有独立的idt、gdt 所以你每次做的时候在多核情况下得都修改

    使用windbg 在每一个cpu的 idt 的 0x20向量中添加不同的中断处理。

    这里使用的如下:

    在 0号处理器中:

    1570072345677

    在 1号处理器中(~在内核中是切换cpu 在3环中是切换线程):

    1570072597830

    2.2 代码展示多核中断提权处理区别

    注意:使用windbg 设置双核的每个cpu idt 0x20项 修改成 IdtEntry1 地址 和 IdtEntry2地址

    ~0 : 在内核中是切换cpu 在3环是切换线程

    evoid _ declspec (naked) IdtEntry1()
    _ asm{
    mov eax, 1
    mov g_ 1d, eax
    iretd
    I}
    }
    //0x401010
    avold__ declspec (naked) IdtEntry2()
    {
    _asm{
    mov eax, 2
    mov g_ 1d, eax
    iretd
    }
    }
    avoid go()
    {
    asm int 0x20
    }

    2.3 效果

    是每次点击 可能所处的cpu不同导致 调用的idt 处理不同,所以全局变量的修改也不同,所以输出的数据每次点击可能不一致。

    由于每次所处的cpu 不同,所以中断处理不同:

    1570072070679

    1570072146736

    完整代码:

    前提:

    使用windbg 在每一个cpu的 idt 的 0x20向量中添加不同的中断处理。

    这里使用的如下:

    在 0号处理器中:

    1570072345677[1]

    在 1号处理器中(~在内核中是切换cpu 在3环中是切换线程):

    1570072597830[1]

    #include"pch.h"
    #include <stdio.h>
    #include<stdlib.h>
    #include<Windows.h>
    // release 版本会比较好一点,debug会填充一些空间,release会比较稳定

    DWORD g_iData = 0;//定义一个全局变量,来存储 0 环数据

    void _declspec(naked) IdtEntry()
    {// 这里是裸函数,所以不会有函数头 push ebp,mov ebp,esp,,和 ret x / sub esp,x 来平衡堆栈;
    // 这样的好处是 我们能控制全部的代码。
    __asm
    {
    //mov eax, dword ptr ds : [0x8003f500];// 注意 : 行内 汇编(内联汇编,要求严格,需要把ds 这些都明确,不然会意想不到)
    //mov g_iData, eax;//
    label:
    jmp label; // 中断默认 会cli 清除中断if标记位,避免中断嵌套(但是陷阱可以嵌套)
    iretd;//iret 是实地址模式 16位的中断返回
    }


    }
    // 0x401050
    void _declspec(naked) IdtEntry1()
    {
    __asm
    {
    mov g_iData, 1;
    iretd;
    }
    }
    // 0x401060
    void _declspec(naked) IdtEntry2()
    {
    __asm
    {
    mov g_iData, 2;
    iretd;
    }
    }

    void go()
    {
    __asm {
    int 0x20;// 产生中断请求,调用对应中断处理
    }
    }

    void main()
    {
    if ((DWORD)IdtEntry != 0x401040)// code : there is not same as the past, there some crt func takes the place401000 ~401040
    {
    printf("WRONG ADDR");
    //exit(0);
    }
    go();// 产生中断请求,调用对应中断处理
    printf("Addr:%p; Addr:%p; ", IdtEntry1,IdtEntry2);
    printf("Data: %d ", g_iData);
    system("pause");
    }

    3 多核复杂性 实验2

    实验环境: 还是双核、xp

    cr0 的第16位 : 0x10000 是页写保护属性WP;WP 位控制是否允许处理器向标记为只读的内存也写入数据;

    写保护修改wp :

    • 0 --- 禁用写保护功能

      关闭 写保护 功能的代码

      asm
      {
      // 修改写保护 WP
      cli;//将处理器标志寄存器的中断标志位清0 ,不允许中断
      mov eax, cr0
      and eax, not 0x10000
      mov cr0, eax
      }
    • 1 --- 开启写保护功能

      恢复 写保护功能 代码

      _ asm
      {
      mov eax, cr0
      or eax, 0x10000
      mov cr0, eax
      sti;//将中断恢复
      }

    !pte 0xaddr // 是查看对应地址所在的页目录、页表物理页保护属性

    3.1 实验2: 多核复杂性 HOOK KiFastCallEntry()

    使用 pchunter 查看 驱动 模块的 的地址 ntkrnlpa.exe(注意在以前老系统中分ntkrnlpa.exe 分了单核、多核、开了pae、未开pae等版本组合;2个2进制位所以有4个不同的ntkrnlpa.exe;这里注意定位你当前使用的是哪一个ntkrnlpa.exe),然后使用 IDA 分析并加载符号;

    注意: 修改ida 的加载基址为 pchunter 里面显示的基址,这样便于查看分析。

    查看 KiFastCallEntry 函数;

    3.2 实验代码

    分析:

    多核的时候,在 0 号核 中处理蓝屏代码;但是这里我们修改了KiFastCallEntry() 之后 把0号处理器进入了一个死循环, 使得 1号核 时间片中程序 3环进入0环调用KiFastCall ,执行我们Hook的错误代码产生的异常没有被 0 号处理器蓝屏处理。但是 使用windbg 查看 的确 1号处理器 异常产生了。

    void __declspec(naked)IdtEntry()
    {

    __asm{
    mov eax,cr0
    and eax, not 10000h // not 即 将 cr0 第16位 置为0 关闭写保护
    mov cr0, eax
               
    mOveax, FFFFFFFF
    mov ds: [0x80542520],eax// 这里这个地址 是kifastcallentry里面的起始地址;所以造成其他3环进0环回出错
    L:
    jmp L;
    iretd
    }
    }


  • 相关阅读:
    Servlet学习(三)——实例:用户登录并记录登陆次数
    Servlet学习(二)——ServletContext对象
    Servlet学习(一)——Servlet的生命周期、执行过程、配置
    Tomcat学习(一)——使用Eclipse绑定Tomcat并发布应用
    Http请求和响应
    MySQL学习(六)——自定义连接池
    MySQL学习(五)——使用JDBC完成用户表CRUD的操作
    SQLServer -------- 连接失败 错误代码126
    java ------ I/O (四) 读写文本文件
    C# ------- 二维表变成一行数据存储,使用后如何分别获取
  • 原文地址:https://www.cnblogs.com/leibso-cy/p/11718826.html
Copyright © 2020-2023  润新知