抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

中断门

中断门知识点

前期准备

  • int 32的计算: 80b98100 - 80b98000 = 100(16进制) / 8 = 20 => 32(10进制)

  • 填充中断门描述符, 函数地址是: 00401080;
    0040ee00`00081080

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    kd> r idtr
    idtr=80b98000
    kd> dq 80b98000 L30
    ReadVirtual: 80b98000 not properly sign extended
    80b98000 83e58e00`00085210 83e58e00`0008557c
    80b98010 00008500`00580000 83e5ee00`00085fc0
    80b98020 83e5ee00`00086338 83e58e00`00086688
    80b98030 83e58e00`000869ec 83e58e00`000876f8
    80b98040 00008500`00500000 83e58e00`00087d3c
    80b98050 83e58e00`00088050 83e58e00`00088380
    80b98060 83e58e00`000887f0 83e58e00`00088cfc
    80b98070 83e58e00`000899b8 83e58e00`00089e40
    80b98080 83e58e00`0008a154 83e58e00`0008a488
    80b98090 00008500`00a00000 83e58e00`0008a7e4
    80b980a0 83e58e00`00089e40 83e58e00`00089e40
    80b980b0 83e58e00`00089e40 83e58e00`00089e40
    80b980c0 83e58e00`00089e40 83e58e00`00089e40
    80b980d0 83e58e00`00089e40 83e58e00`00089e40
    80b980e0 83e58e00`00089e40 83e58e00`00089e40
    80b980f0 83e58e00`00089e40 83e58e00`0008abb0
    80b98100 00000000`00080000 00000000`00080000

    kd> eq 80b98100 0040ee00`00081080
    kd> dq 80b98000 L30
    ReadVirtual: 80b98000 not properly sign extended
    80b98000 83e58e00`00085210 83e58e00`0008557c
    80b98010 00008500`00580000 83e5ee00`00085fc0
    80b98020 83e5ee00`00086338 83e58e00`00086688
    80b98030 83e58e00`000869ec 83e58e00`000876f8
    80b98040 00008500`00500000 83e58e00`00087d3c
    80b98050 83e58e00`00088050 83e58e00`00088380
    80b98060 83e58e00`000887f0 83e58e00`00088cfc
    80b98070 83e58e00`000899b8 83e58e00`00089e40
    80b98080 83e58e00`0008a154 83e58e00`0008a488
    80b98090 00008500`00a00000 83e58e00`0008a7e4
    80b980a0 83e58e00`00089e40 83e58e00`00089e40
    80b980b0 83e58e00`00089e40 83e58e00`00089e40
    80b980c0 83e58e00`00089e40 83e58e00`00089e40
    80b980d0 83e58e00`00089e40 83e58e00`00089e40
    80b980e0 83e58e00`00089e40 83e58e00`00089e40
    80b980f0 83e58e00`00089e40 83e58e00`0008abb0
    80b98100 0040ee00`00081080 00000000`00080000
  • 中断门0环堆栈压了五个值, eip, cs, eflags, esp, ss, 3环堆栈无内容;
    3环寄存器:
    EAX = 00000000 EBX = 7FFD5000 ECX = BFBDF6C4 EDX = 005F0178 ESI = 0012FE3C EDI = 0012FF08 EIP = 004011A7 ESP = 0012FE3C EBP = 0012FF08 EFL = 00000246
    CS = 001B DS = 0023 ES = 0023 SS = 0023 FS = 003B GS = 0000
    0环寄存器:
    eax=00000000 ebx=7ffd5000 ecx=bfbdf6c4 edx=005f0178 esi=0012fe3c edi=0012ff08
    eip=00401080 esp=94e63c9c ebp=0012ff08 iopl=0 nv up di pl zr na pe nc
    cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000046

1
2
3
4
5
6
7
8
9
10
11
kd> dds 94e63c9c
94e63c9c 004011a9 <== eip
94e63ca0 0000001b <== cs
94e63ca4 00000246 <== eflags
94e63ca8 0012fe3c <== esp
94e63cac 00000023 <== ss
94e63cb0 00000000
94e63cb4 00000000
94e63cb8 00000000
94e63cbc 00000000
94e63cc0 0000027f

代码实验

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// 10_11_InterruptGate(中断门).cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <Windows.h>

#pragma pack(1)
typedef struct _GDTINFO
{
short limit;
ULONG table;
}GDTINFO;
#pragma pack(0)

void __declspec(naked) test()
{
__asm
{
int 3;

iretd;
}
}

int main()
{
printf("%p\r\n", test);

//char bufgdt[6];
//char bufidt[6];
GDTINFO gdts;
GDTINFO idts;

__asm
{
/*sgdt bufgdt;
sidt bufidt;*/
sgdt gdts; // 获取gdtr
sidt idts; // 获取idtr
}

system("pause");

__asm
{
push fs;
int 32;
pop fs;
}

system("pause");
return 0;
}

IDT和GDT的关联

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
kd> dq 80b98800
ReadVirtual: 80b98800 not properly sign extended
80b98800 00000000`00000000 00cf9b00`0000ffff
80b98810 00cf9300`0000ffff 00cffb00`0000ffff
80b98820 00cff300`0000ffff 80008bb9`8c0020ab
80b98830 804093b9`b0004fff 0040f300`00000fff
80b98840 0000f200`0400ffff 00000000`00000000
80b98850 800089b9`ad200067 800089b9`acb00067
80b98860 00000000`00000000 00000000`00000000
80b98870 800092b9`880003ff 00000000`00000000
kd> r idtr
idtr=80b98000
kd> dq 80b98000
ReadVirtual: 80b98000 not properly sign extended
80b98000 83e58e00`00085210 83e58e00`0008557c
80b98010 00008500`00580000 83e5ee00`00085fc0
80b98020 83e5ee00`00086338 83e58e00`00086688
80b98030 83e58e00`000869ec 83e58e00`000876f8
80b98040 00008500`00500000 83e58e00`00087d3c
80b98050 83e58e00`00088050 83e58e00`00088380
80b98060 83e58e00`000887f0 83e58e00`00088cfc
80b98070 83e58e00`000899b8 83e58e00`00089e40
  • 在IDT中, int3中的3代表的是索引;
  • 83e5ee0000085fc0(int 3)中段选择子0008表示去查找GDT中00cf9b00`0000ffff;

IDT描述符

5.11 页码123

  • D位(第11位)是指默认操作数, 32位下为1, 16位下为0;

3环获取GDT和IDT的指令

  • 获取GDT/获取IDT: sgdt/sidt(3环下调用);

    获取到gdt的值为ff 03 00 88 b9 80; 其中前两个字节为表的长度, 后四个字节为表的地址;

  • 修改GDT/修改IDT: lgdt/lidt(0环下才能调用);

补充

iretd中的d描述宽度用的; 16位(iret)、32位(iretd)、64位(iretq);

作业

  1. 返回一定要用iretd吗? 使用retf;
  • iretd 解除阻塞;
  • retf 没有解除阻塞;
  • sti 解除阻塞, 并且给eflags.IF = 1;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// InterruptGate_retf.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <windows.h>

// 中断门使用retf返回
// 0040ee00`00081080

void __declspec(naked) test()
{
__asm
{
sti; // 解除阻塞, 并且使eflags.IF = 1
// int 3
retf 4; // 使用 retf 4 是为了确保在中断处理程序返回时,除了恢复 CS:EIP 外,还能从栈中弹出这个附加的 4 字节(通常是错误代码),确保栈平衡
}
}

int main()
{
printf("%p\r\n", test);

__asm
{
// push 0x12345678;
int 32;

push 0x3b;
pop fs;
}

system("pause");
return 0;
}
  1. 构建陷阱门自己调用;
  • TYPE位为f, 0040ee00`00081080;

中断门和陷阱门的区别

1.
进入中断门会清除eflag VM NT IF TF 位
进入陷阱门会清除eflag VM NT TF 位
2.
由于中断门会清除IF位,导致一些中断触发会悬挂,陷阱门则不会

int3_hook

步骤

  1. 第一步:添加一个代码段在0x48位置
  2. 第二步:计算代码段0x48的base
    目标地址 - int 3偏移= base
    写回0x48位置
  3. 第三步:修改int 3中断门的段选择子为0x48
  4. Hook函数编写
    由于有缓存的存在, 可以执行一会, 那么我们在这要做二次跳转
    jmp 0x48: xxx地址
  5. 当调到xxx地址后, 通过调用打印函数, 确定调用成功
  6. jmp回int 3原本的偏移

base:401080 - 83e44fc0(int 3) = 7C5B C0C0

段描述:00cf9b00`0000ffff

修改gdtr 0x48位置
eq 80b98848 7Ccf9b5B`C0C0ffff

修改int 3段选择子为48
eq 80b98018 83e7ee00`0048dfc0

83e11c60

代码实验

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
// 09_24_int3_hook.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

// BASE:401080 - 83e7dfc0(int 3) = 7C58 30C0
// 段描述:00cf9b00`0000ffff
// 修改GDTR:eq 80b98848 7Ccf9b58`30c0ffff
// 修改IDTR:eq 80b98018 83e7ee00`0048dfc0

#include <iostream>
#include <Windows.h>

typedef int(__CRTDECL *DbgPrintProc)(_In_z_ _Printf_format_string_ char const* const _Format, ...);
DbgPrintProc DbgPrint = NULL;

char * xxxstr = NULL;

void __declspec(naked) test()
{
__asm
{
//push 0x8;
//push haha;
sub esp, 8;
lea eax, haha;
mov [esp], eax;
mov [esp+4], 0x8;
jmp fword ptr [esp];
haha:
add esp, 8;
push fs;
mov ax, 0x30;
mov fs, ax;
// 业务逻辑
mov eax, [xxxstr];
push eax;
call DbgPrint;
add esp, 4;

pop fs;
// 跳回int3
mov dword ptr ss:[esp-4], 0x83e44fc0;
jmp dword ptr ss:[esp-4];
}
}

int main()
{
printf("%p\r\n", test);
xxxstr = (char*)malloc(strlen("xxxx__main__xxxx\r\n") + 1);
memcpy(xxxstr, "xxxx__main__xxxx\r\n", strlen("xxxx__main__xxxx\r\n"));
xxxstr[strlen("xxxx__main__xxxx\r\n")] = '\0';
DbgPrint = (DbgPrintProc)0x83e11c60;
system("pause");

__asm
{
int 3;
}
system("pause");
return 0;
}

评论