10-调用门(有参)实验

来源:互联网 发布:在线c语言编译器 编辑:程序博客网 时间:2024/05/11 19:37

上一篇重点讲解了没有参数的调用门实验,本节讲解有参数的调用门实验。

编写R0函数

int g_a, g_b, g_c;__declspec(naked) void getParam(int a, int b, int c) {    __asm {        // int 3 // 取消注释可以在WinDbg中看R0栈数据        pushad // 0x20 B        pushfd // 0x04 B        //             .- 8 个通用寄存器和标志寄存器占用大小        //             |     .- cs 和 eip 占用大小        //             |     |        mov eax, [esp+0x24+0x08+0x08] // 参数 a        mov g_a, eax        mov eax, [esp+0x24+0x08+0x04] // 参数 b        mov g_b, eax        mov eax, [esp+0x24+0x08+0x00] // 参数 c        mov g_c, eax        popfd        popad        retf 0x0c    }}int main(int argc, char* argv[]){    // 构造cs:eip    char cs_eip[6] = {0, 0, 0, 0, 0x48, 0};    __asm {        push 1        push 2        push 3        call fword ptr [cs_eip];    }    printf("g_a = %d\ng_b = %d\ng_c = %d\n", g_a, g_b, g_c);    return 0;}

记录getParam函数地址


这里写图片描述

可以看到地址为 0x00401020

构造带3个参数的调用门描述符

调用门描述符结构:|   7    |     6  |     5     |    4    |   3    |   2    |   1    |   0    |  字节|76543210|76543210|7 65 4 3210|765 43210|76543210|76543210|76543210|76543210|  比特|-----------------|1|--|0|1100|000|-----|--------|--------|--------|--------|  占位|offset in segment|P|D |S|TYPE|   |param|segment selector |offset in segment|  含义|     31-16         |P |          |nums |                 |       15-0      |                    |L |注意有些比特位是固定的。

根据调用门描述符结构,可以构造出描述符 0040ec03`00081020,然后安装到gdt表的8003f048的位置。


这里写图片描述

执行结果


这里写图片描述

查看R0栈数据

这里需要取消 int 3那行注释,这样会在 WinDbg 下中断。可以看到CS/SS都已经是R0的段了,esp也指向了高2G的地址。(为什么会这样?CPU需要始终保持 cs 中的 CPL 和 ss 中的 CPL 一致)


这里写图片描述

可以看到这时候 esp 的值为 0xb2391dc4,去看一下栈内存数据

这里写图片描述

总结

当使用调用门进行提权的时候,程序由3环进入0环,这时候需要切换栈,也就是说要更改 ss 段选择子和 esp 的值。这时候 CPU 会自动的帮我们把原始 3 环的 ss, esp, 参数(如果有的话), cs 和 eip 复制到这个 0 环栈中去。

一定要注意,这是 CPU 自动帮我们做的事情,和 OS 没有任何关系。

引起注意的地方是,切换栈,需要 0 环 ss 段选择子和 esp ,这些值 CPU 是如何找到了呢?这个问题先放在这儿,后续文章解决会揭晓答案。这里,只给出一个线索——TSS.

0 0
原创粉丝点击