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) # -> %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类:
带返回错误码的中断调用
不带返回错误码的中断调用
将所有的寄存器值入栈
SS:存放栈顶的段地址SP:存放栈顶的偏移地址
一个栈也就是一块内存区域,我们必须要有基地址(也就是段地址左移4位)和偏移地址。
要在一个栈中寻址的话,也需要段地址和偏移地址。
-------------------------------------------------------------------------------------------------------------------
CS:代码段寄存器IP:指令段寄存器
CS:IP 指向可执行程序的起始地址
此后CPU从这个起始地址开始读取内存中的指令,并且执行。
CS:IP指向
1.你想让 CPU 执行哪行指令,你就让 CS:IP 指向保存有指令的那块内存即可。
2.任何时候,CS:IP 指向的地址中的内容都是 CPU 当前执行的指令。
-------------------------------------------------------------------------------------------------
前四步:
===================================================
xchgl %eax,(%esp)
将eax的值保存在栈上,将中断处理函数的地址保存在eax寄存器中
xchg 交换eax 和esp的值
ESP 专门用作堆栈指针,被形象地称为栈顶指针
EAX是累加器,AX是算术的主要寄存器
asm.s包含着CPU探测到故障异常的底层代码程序,与traps.c关系密切,调用traps.c的程序打印出错信息,并退出。
对于不带出错号的中断过程,堆栈指针位置变化情况请参照图(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
-----------------------------------------------------------------------------------------------
无错误号的代码:
核心代码:xchg1 %eax,(%esp) 交换ax和sp push $0 0作为错误号压栈 lea 44(%esp), %edx 把中断的地方压栈 call *%eax 调用中断打印函数 add1 $8 %esp 函数的参数出栈
----------------------------------------------------------------------------------------
有错误号的代码:
error_code:
0x03:小结
此篇文章主要讲解了中断的工作原理,下篇文章我们一起来看8086 PC机的8259A中断原理。
转载请注明来自网盾网络安全培训,本文标题:《详解pwn-内核相关知识(2)》
标签:pwn
- 关于我们