freeBuf
主站

分类

云安全 AI安全 开发安全 终端安全 数据安全 Web安全 基础安全 企业安全 关基安全 移动安全 系统安全 其他安全

特色

热点 工具 漏洞 人物志 活动 安全招聘 攻防演练 政策法规

点我创作

试试在FreeBuf发布您的第一篇文章 让安全圈留下您的足迹
我知道了

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

详解pwn-内核相关知识(2)
星云博创 2021-06-02 16:59:24 205655

0x00:前言

本篇文章接着内核中断(1)来进行源码的分析,文章难度较大,需要一定的汇编基础。中断分为两种:有错误码中断和无错误码中断,接下来我们来看正文部分。

0x01:源码

/* linux/kernel/asm.s */
.globl _divide_error,_debug,_nmi,_int3,_overflow,_bounds,_invalid_op
.globl _double_fault,_coprocessor_segment_overrun
.globl _invalid_TSS,_segment_not_present,_stack_segment
.globl _general_protection,_coprocessor_error,_irq13,_reserved

_divide_error:
  pushl $_do_divide_error

no_error_code:
  xchgl %eax,(%esp)
  pushl %ebx
  pushl %ecx
  pushl %edx
  pushl %edi
  pushl %esi
  pushl %ebp
  push %ds
  push %es
  push %fs
  pushl $0    # "error code"
  lea 44(%esp),%edx
  pushl %edx
  movl $0x10,%edx
  mov %dx,%ds
  mov %dx,%es
  mov %dx,%fs
  call *%eax
  addl $8,%esp
  pop %fs
  pop %es
  pop %ds
  popl %ebp
  popl %esi
  popl %edi
  popl %edx
  popl %ecx
  popl %ebx
  popl %eax
  iret

_debug:
  pushl $_do_int3    # _do_debug
  jmp no_error_code

_nmi:
  pushl $_do_nmi
  jmp no_error_code

_int3:
  pushl $_do_int3
  jmp no_error_code

_overflow:
  pushl $_do_overflow
  jmp no_error_code

_bounds:
  pushl $_do_bounds
  jmp no_error_code

_invalid_op:
  pushl $_do_invalid_op
  jmp no_error_code

_coprocessor_segment_overrun:
  pushl $_do_coprocessor_segment_overrun
  jmp no_error_code

_reserved:
  pushl $_do_reserved
  jmp no_error_code

_irq13:
  pushl %eax
  xorb %al,%al
  outb %al,$0xF0
  movb $0x20,%al
  outb %al,$0x20
  jmp 1f
1:  jmp 1f
1:  outb %al,$0xA0
  popl %eax
  jmp _coprocessor_error

_double_fault:
  pushl $_do_double_fault

error_code:
  xchgl %eax,4(%esp)    # error code <-> %eax
  xchgl %ebx,(%esp)    # &function <-> %ebx
  pushl %ecx
  pushl %edx
  pushl %edi
  pushl %esi
  pushl %ebp
  push %ds
  push %es
  push %fs
  pushl %eax      # error code
  lea 44(%esp),%eax    # offset
  pushl %eax
  movl $0x10,%eax
  mov %ax,%ds
  mov %ax,%es
  mov %ax,%fs
  call *%ebx
  addl $8,%esp
  pop %fs
  pop %es
  pop %ds
  popl %ebp
  popl %esi
  popl %edi
  popl %edx
  popl %ecx
  popl %ebx
  popl %eax
  iret
_invalid_TSS:
  pushl $_do_invalid_TSS
  jmp error_code
_segment_not_present:
  pushl $_do_segment_not_present
  jmp error_code
_stack_segment:
  pushl $_do_stack_segment
  jmp error_code
_general_protection:
  pushl $_do_general_protection
  jmp error_code

0x02:分析

该文件主要是定义了CPU异常产生的中断函数的调用。

分成2类:

带返回错误码的中断调用

不带返回错误码的中断调用

v2-5cf8047241a2a2c13aa2863ffa3a6355_720w.png

v2-9a1c5dd357e24cb31a592ca014af8068_720w.png

将所有的寄存器值入栈

SS:存放栈顶的段地址
SP:存放栈顶的偏移地址

一个栈也就是一块内存区域,我们必须要有基地址(也就是段地址左移4位)和偏移地址。

要在一个栈中寻址的话,也需要段地址和偏移地址。

-------------------------------------------------------------------------------------------------------------------

CS:代码段寄存器
IP:指令段寄存器

CS:IP 指向可执行程序的起始地址

此后CPU从这个起始地址开始读取内存中的指令,并且执行。

CS:IP指向

1.你想让 CPU 执行哪行指令,你就让 CS:IP 指向保存有指令的那块内存即可。

2.任何时候,CS:IP 指向的地址中的内容都是 CPU 当前执行的指令。

-------------------------------------------------------------------------------------------------

前四步:

v2-854cdd4985a1b91351243924de887403_720w.png

===================================================

xchgl %eax,(%esp)

将eax的值保存在栈上,将中断处理函数的地址保存在eax寄存器中

xchg 交换eax 和esp的值

ESP 专门用作堆栈指针,被形象地称为栈顶指针

EAX是累加器,AX是算术的主要寄存器

asm.s包含着CPU探测到故障异常的底层代码程序,与traps.c关系密切,调用traps.c的程序打印出错信息,并退出。

v2-24be3b8fde9d7123d39e4ce88aae4b34_720w.png

对于不带出错号的中断过程,堆栈指针位置变化情况请参照图(a)。

在开始执行相应中断服务程序之前,堆栈指针esp指在中断返回地址一栏(图中 esp0处)。

当把将要调用的C函数do_ _divide_ error()或其他C函数地址入栈后,指针位置是esp1处,此时程序使用交换指令把该函数的地址放入eax寄存器中,而原来eax的值则被保存到堆栈上。

此后程序在把一些寄存器入栈后,堆栈指针位置处于esp2处。

当正式调用do_ divide_ error()之前, 程序会将开始执行中断程序时的原eip 保存位置(即堆栈指针esp0值)压入堆栈,放到esp3位置处,并在中断返回弹出入栈的寄存器之前指针通过加上8又回到esp2处。

对于CPU会产生错误号的中断过程,堆栈指针位置变化情况请参照图(b)。

在刚开始执行中断服务程序之前,堆栈指针指向图中esp0处。

在把将要调用的C函数do_ double_ fault()或其 他C函数地址入栈后,栈指针位置是esp1处。

此时程序通过使用两个交换指令分别把eax、ebx寄存器的值保存在esp0、esp1位置处,而把出错号交换到eax寄存器中:函数地址交换到了ebx寄存器中。随后的处理过程则和无错误号一样。

----------------------------------------------------------------------------------------

一般寄存器:AX、BX、CX、DX

AX:累积暂存器,BX:基底暂存器,CX:计数暂存器,DX:资料暂存器

索引暂存器:SI、DI

SI:来源索引暂存器,DI:目的索引暂存器

堆叠、基底暂存器:SP、BP

SP:堆叠指标暂存器,BP:基底指标暂存器

cs是代码段寄存器

ds是数据段寄存器

ss是堆栈段寄存器

es是扩展段寄存器

fs是标志段寄存器

gs是全局段寄存器

----------------------------------------------------------------------------------------

把这些寄存器入栈保护

pushl %ebx

pushl %ecx

pushl %edx

pushl %edi

pushl %esi

pushl %ebp

push %ds

push %es

push %fs

v2-698ed2aca088fe2fe0d381cccb314074_720w.png

-----------------------------------------------------------------------------------------------

无错误号的代码:

核心代码:xchg1  %eax,(%esp)  交换ax和sp
                  push  $0     0作为错误号压栈
                  lea 44(%esp), %edx  把中断的地方压栈
                  call  *%eax   调用中断打印函数
                  add1 $8  %esp   函数的参数出栈

v2-ece3dbd783b28fd75f0ae9278ea91837_720w.png

----------------------------------------------------------------------------------------

有错误号的代码:

error_code:

0x03:小结

此篇文章主要讲解了中断的工作原理,下篇文章我们一起来看8086 PC机的8259A中断原理。

# pwn
本文为 星云博创 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
星云博创 LV.7
星云博创科技有限公司
  • 96 文章数
  • 76 关注者
【技术分享】记某项目漏洞挖掘
2024-01-16
【技术分享】短信验证码的相关利用方法与技巧
2023-11-23
【技术分享】业务逻辑漏洞案例剖析
2023-10-18
文章目录