QQ登录

只需一步,快速开始

切换到宽版 切换风格

电脑疯子技术论坛|电脑极客社区

详解pwn-内核相关知识

[复制链接]
42 0
0x00:前言

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

0x01:源码
  1. /* linux/kernel/asm.s */
  2. .globl _divide_error,_debug,_nmi,_int3,_overflow,_bounds,_invalid_op
  3. .globl _double_fault,_coprocessor_segment_overrun
  4. .globl _invalid_TSS,_segment_not_present,_stack_segment
  5. .globl _general_protection,_coprocessor_error,_irq13,_reserved

  6. _divide_error:
  7.   pushl $_do_divide_error

  8. no_error_code:
  9.   xchgl %eax,(%esp)
  10.   pushl %ebx
  11.   pushl %ecx
  12.   pushl %edx
  13.   pushl %edi
  14.   pushl %esi
  15.   pushl %ebp
  16.   push %ds
  17.   push %es
  18.   push %fs
  19.   pushl $0    # "error code"
  20.   lea 44(%esp),%edx
  21.   pushl %edx
  22.   movl $0x10,%edx
  23.   mov %dx,%ds
  24.   mov %dx,%es
  25.   mov %dx,%fs
  26.   call *%eax
  27.   addl $8,%esp
  28.   pop %fs
  29.   pop %es
  30.   pop %ds
  31.   popl %ebp
  32.   popl %esi
  33.   popl %edi
  34.   popl %edx
  35.   popl %ecx
  36.   popl %ebx
  37.   popl %eax
  38.   iret
  39. _debug:
  40.   pushl $_do_int3    # _do_debug
  41.   jmp no_error_code
  42. _nmi:
  43.   pushl $_do_nmi
  44.   jmp no_error_code
  45. _int3:
  46.   pushl $_do_int3
  47.   jmp no_error_code
  48. _overflow:
  49.   pushl $_do_overflow
  50.   jmp no_error_code
  51. _bounds:
  52.   pushl $_do_bounds
  53.   jmp no_error_code
  54. _invalid_op:
  55.   pushl $_do_invalid_op
  56.   jmp no_error_code
  57. _coprocessor_segment_overrun:
  58.   pushl $_do_coprocessor_segment_overrun
  59.   jmp no_error_code
  60. _reserved:
  61.   pushl $_do_reserved
  62.   jmp no_error_code
  63. _irq13:
  64.   pushl %eax
  65.   xorb %al,%al
  66.   outb %al,$0xF0
  67.   movb $0x20,%al
  68.   outb %al,$0x20
  69.   jmp 1f
  70. 1:  jmp 1f
  71. 1:  outb %al,$0xA0
  72.   popl %eax
  73.   jmp _coprocessor_error
  74. _double_fault:
  75.   pushl $_do_double_fault
  76. error_code:
  77.   xchgl %eax,4(%esp)    # error code <-> %eax
  78.   xchgl %ebx,(%esp)    # &function <-> %ebx
  79.   pushl %ecx
  80.   pushl %edx
  81.   pushl %edi
  82.   pushl %esi
  83.   pushl %ebp
  84.   push %ds
  85.   push %es
  86.   push %fs
  87.   pushl %eax      # error code
  88.   lea 44(%esp),%eax    # offset
  89.   pushl %eax
  90.   movl $0x10,%eax
  91.   mov %ax,%ds
  92.   mov %ax,%es
  93.   mov %ax,%fs
  94.   call *%ebx
  95.   addl $8,%esp
  96.   pop %fs
  97.   pop %es
  98.   pop %ds
  99.   popl %ebp
  100.   popl %esi
  101.   popl %edi
  102.   popl %edx
  103.   popl %ecx
  104.   popl %ebx
  105.   popl %eax
  106.   iret
  107. _invalid_TSS:
  108.   pushl $_do_invalid_TSS
  109.   jmp error_code
  110. _segment_not_present:
  111.   pushl $_do_segment_not_present
  112.   jmp error_code
  113. _stack_segment:
  114.   pushl $_do_stack_segment
  115.   jmp error_code
  116. _general_protection:
  117.   pushl $_do_general_protection
  118.   jmp error_code
复制代码

0x02:分析

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

分成2类:
带返回错误码的中断调用
不带返回错误码的中断调用

QQ截图20210610160610.png

QQ截图20210610160639.png

将所有的寄存器值入栈
SS:存放栈顶的段地址
SP:存放栈顶的偏移地址

一个栈也就是一块内存区域 我们必须要有基地址 也就是段地址左移4位和偏移地址。
要在一个栈中寻址的话 也需要段地址和偏移地址。
---------------------------------------------------------
----------------------------------------------------------
CS:代码段寄存器
IP:指令段寄存器

CS:IP 指向可执行程序的起始地址
此后CPU从这个起始地址开始读取内存中的指令 并且执行。
CS:IP指向

1.你想让CPU 执行哪行指令 你就让 CS:IP指向保存有指令的那块内存即可。
2.任何时候 CS:IP 指向的地址中的内容都是CPU当前执行的指令。
-------------------------------------------------------------------
------------------------------

前四步:

69.png

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

xchgl %eax,(%esp)
将eax的值保存在栈上 将中断处理函数的地址保存在eax寄存器中
xchg 交换eax 和esp的值
ESP 专门用作堆栈指针 被形象地称为栈顶指针
EAX是累加器AX是算术的主要寄存器
asm.s包含着CPU探测到故障异常的底层代码程序 与traps.c关系密切
调用traps.c的程序打印出错信息 并退出。

39.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

29.png

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

无错误号的代码:

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

28.png

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

有错误号的代码:

error_code:

6.png


0x03:小结

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

您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

关注

0

粉丝

7489

主题
精彩推荐
热门资讯
网友晒图
图文推荐
Pcgho! X3.4

© 2020 Comsenz Inc.