日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

【网络安全】Linux内核部分文件分析

發布時間:2025/3/21 linux 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【网络安全】Linux内核部分文件分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

對于操作系統的分析,是一個復雜且枯燥的過程,其中包括中斷、調用等一系列的問題,需要從原理和代碼兩層的角度進行分析,包含匯編、C語言等較為難理解的知識,以及算法的思維。

【學習資料】

啟動流程


setup模塊扇區長度為4個扇區,各個模塊存放在內存的地址。

這里的ROOT_DEV=0x306表示第二個硬盤的第一個扇區。

基礎

設備號 = 主設備號 * 256 + 次設備號

主設備號是定義好的:

1-內存

2-磁盤

3-硬盤

PC機的BIOS把bootsect的一個固定地址拿到了內存中某個固定地址(0x90000),

并且進行硬件初始化和參數設置。

bootsect中的代碼首先移動到0X7C00,之后又轉移到0X90000。

代碼分析

bootsect模塊移入內存

start: mov ax,#BOOTSEG mov ds,ax mov ax,#INITSEG mov es,ax mov cx,#256 sub si,si sub di,di rep movw jmpi go,INITSEG

把bootsect中代碼移動到內存中0X90000中,
可以看到此時的ds 存儲0x07c0 地址:es 0x90000。

利用寄存器從ds:si到es:di

jmpi go,INITSEG

INITSEG是段地址,go是偏移地址,跳轉到程序執行的地方(0x90000)。

bootsect.s作用

1.首先加載bootsect的代碼(磁盤引導塊程序,在磁盤中第一個扇區的程序)

2.將setup.s中代碼加載到bootsect.s中代碼之后

3.將system模塊加載到0x10000地方,最后跳轉到setup.s中運行


棧的位置

go: mov ax,cs mov ds,ax mov es,ax ! put stack at 0x9ff00. mov ss,ax mov sp,#0xFF00 ! arbitrary value >>512 設置ds、es、ss、sp

對棧的設置 es:sp =0x90000:0xff00

setup模塊移入內存

load_setup: mov dx,#0x0000 ! drive 0, head 0 //驅動器號0;磁頭號0 mov cx,#0x0002 ! sector 2, track 0 //起始扇區2;磁道0 mov bx,#0x0200 ! address = 512, in INITSEG mov ax,#0x0200+SETUPLEN ! service 2, nr of sectors int 0x13 ! read it jnc ok_load_setup ! ok - continue mov dx,#0x0000 mov ax,#0x0000 ! reset the diskette int 0x13 j load_setup

setup模塊加載到0x90200中。

setup.s作用

  • 解析BIOS傳遞過來的參數;
  • 設置系統內核運行的局部描述符,中斷描述寄存器,全局描述符;
  • 設置中斷控制芯片,進入保護模式;
  • 跳轉到system模塊中head.s中代碼執行。

system模塊移入內存

! we want to load the system (at 0x10000) mov ax,#SYSSEG mov es,ax ! segment of 0x010000 call read_it call kill_motor

把system模塊加載0x10000處,

關閉驅動器。
【學習資料】

head.s作用

  • 加載內核運行時的各種數據段寄存器,重新設置中斷描述表;
  • 開啟內核正常運行時的協處理器;
  • 設置內存管理的分頁機制;
  • 跳轉到main.c開始運行。

中斷調用:

有出錯號、無出錯號

中斷范圍:

int0 ~ int255。

int0 ~ int31 : 軟件中斷,由Intel固定設置的。

int32 ~ int255: 可由用戶自己設置。其中int32 ~ int47 對應8259A的IRQ0 ~ IRQ15中斷。

特殊的一個:int128 為系統調用中斷(system_call)。

#int7 – 設備不存在。

#int14 – 頁錯誤。

#int16 – 協處理器錯誤。

#int 0x20 – 時鐘中斷。

#int 0x80 – 系統調用。

asm.s分析

寄存器入棧:

no_error_code:xchgl %eax,(%esp)pushl %ebxpushl %ecxpushl %edxpushl %edipushl %esipushl %ebppush %dspush %espush %fs

異常碼入棧:
pushl $0 # “error code”

函數返回值入棧:
lea 44(%esp),%edx //把中斷的地方壓棧pushl %edxmovl $0x10,%edxmov %dx,%dsmov %dx,%esmov %dx,%fs

調用中斷服務函數:
call *%eax //調用中斷打印函數

出棧函數返回值:
addl $8,%esp //函數參數出棧pop %fspop %espop %dspopl %ebppopl %esipopl %edipopl %edxpopl %ecxpopl %ebxpopl %eaxiret
error_code:
xchgl %eax,4(%esp) # error code <-> %eax //中斷錯誤碼xchgl %ebx,(%esp) # &function <-> %ebx //中斷函數pushl %ecxpushl %edxpushl %edipushl %esipushl %ebppush %dspush %espush %fspushl %eax # error code //出錯號入棧lea 44(%esp),%eax # offsetpushl %eaxmovl 0x10,8,%esp pop %fspop %espop %dspopl %ebppopl %esipopl %edipopl %edxpopl %ecxpopl %ebxpopl %eaxiret

trap.c分析

本程序用來處理硬件陷阱和故障。

asm.s和traps.c 兩個程序文件的關系:

asm.s 是匯編文件,主要實現大部分硬件中斷(異常)引起的中斷處理過程;trap.c
是C語言源文件,內部是各種中斷處理的C函數,這些函數在asm.s中進行調用。

GCC編譯過程:

1.預處理階段

2.編譯階段

3.匯編階段

4.鏈接階段

內聯匯編格式:

asm(“匯編語句” :輸出寄存器 :輸入寄存器 :會被修改的寄存器)

#define get_seg_byte(seg, addr) \ /*宏定義:取段seg中地址addr處的一個字節*/ ({ \ register char __res; \ //定義一個寄存器 __asm__("push %%fs; //保存fs寄存器的原值 mov %%ax, %%fs; //將seg設置到fs movb %%fs:%2, %%a1; //將seg:addr處的一個字節放置到a1寄存器中 pop %%fs "\ : "=a" (__res) \ //輸出寄存器列表 :"0" (seg), "m"(*(addr)));\ //輸入寄存器列表 __res;}) /*輸入:_res;輸出:seg 內存地址* : "=a" (__res) \ //輸出寄存器列表 輸出寄存器,a代表eax,運行結束后把eax的值放入res中 :"0" (seg), "m"(*(addr)));\ //輸入寄存器列表 輸入寄存器,0代表eax(與上面相同),m代表內存地址

取seg段addr處的一個字節。

取seg段addr處的四個字節。

取fs段寄存器的值。

str字符串 esp_ptr 棧指針 nr段號(在哪里出錯)。

static void die(char * str,long esp_ptr,long nr) { long * esp = (long *) esp_ptr; int i; printk("%s: %04x\n\r",str,nr&0xffff); printk("EIP:\t%04x:%p\nEFLAGS:\t%p\nESP:\t%04x:%p\n", esp[1],esp[0],esp[2],esp[4],esp[3]); //打印棧中的一些寄存器 printk("fs: %04x\n",_fs()); printk("base: %p, limit: %p\n",get_base(current->ldt[1]),get_limit(0x17)); if (esp[4] == 0x17) { printk("Stack: "); for (i=0;i<4;i++) printk("%p ",get_seg_long(0x17,i+(long *)esp[3])); printk("\n"); } str(i); printk("Pid: %d, process nr: %d\n\r",current->pid,0xffff & i); for(i=0;i<10;i++) printk("%02x ",0xff & get_seg_byte(esp[1],(i+(char *)esp[0]))); printk("\n\r"); do_exit(11); /* play segment exception */ } //打印當前棧中的內容

trap_init分析

set_trap_gate:優先級為0 ,設置權限較高,只能由用戶程序調用。

set_system_gate :

設置權限較低,用戶和系統所有進程調用。

system_call.s分析

操作系統的進程管理

系統時間:CPU內部有一個RTC(定時器),運行時調用mktime函數,算出時間差。

給MKTIME函數傳來的時間結構體賦值是由初始化時間從RTC中讀出的:

#include <time.h> /* * This isn't the library routine, it is only used in the kernel. * as such, we don't care about years<1970 etc, but assume everything * is ok. Similarly, TZ etc is happily ignored. We just do everything * as easily as possible. Let's find something public for the library * routines (although I think minix times is public). */ /* * PS. I hate whoever though up the year 1970 - couldn't they have gotten * a leap-year instead? I also hate Gregorius, pope or no. I'm grumpy. */ #define MINUTE 60 #define HOUR (60*MINUTE) #define DAY (24*HOUR) #define YEAR (365*DAY) /* interestingly, we assume leap-years */ static int month[12] = { 0, DAY*(31), DAY*(31+29), DAY*(31+29+31), DAY*(31+29+31+30), DAY*(31+29+31+30+31), DAY*(31+29+31+30+31+30), DAY*(31+29+31+30+31+30+31), DAY*(31+29+31+30+31+30+31+31), DAY*(31+29+31+30+31+30+31+31+30), DAY*(31+29+31+30+31+30+31+31+30+31), DAY*(31+29+31+30+31+30+31+31+30+31+30) }; long kernel_mktime(struct tm * tm) { long res; int year; year = tm->tm_year - 70; /* magic offsets (y+1) needed to get leapyears right.*/ res = YEAR*year + DAY*((year+1)/4); res += month[tm->tm_mon]; /* and (y+2) here. If it wasn't a leap-year, we have to adjust */ if (tm->tm_mon>1 && ((year+2)%4)) res -= DAY; res += DAY*(tm->tm_mday-1); res += HOUR*tm->tm_hour; res += MINUTE*tm->tm_min; res += tm->tm_sec; return res; }

main.c中time_init

static void time_init(void) { struct tm time; do { time.tm_sec = CMOS_READ(0); time.tm_min = CMOS_READ(2); time.tm_hour = CMOS_READ(4); time.tm_mday = CMOS_READ(7); time.tm_mon = CMOS_READ(8); time.tm_year = CMOS_READ(9); } while (time.tm_sec != CMOS_READ(0)); BCD_TO_BIN(time.tm_sec); BCD_TO_BIN(time.tm_min); BCD_TO_BIN(time.tm_hour); BCD_TO_BIN(time.tm_mday); BCD_TO_BIN(time.tm_mon); BCD_TO_BIN(time.tm_year); time.tm_mon--; startup_time = kernel_mktime(&time); }

小結

內核源碼的時間片設計是很精妙的,對操作系統的分析同時也需要計算機組成原理的知識,硬件的理解以及利用算法如何更好的為用戶和上層軟件服務。

最后

點擊查看【網絡安全學習資料·攻略】獲取相關書籍與工具

總結

以上是生活随笔為你收集整理的【网络安全】Linux内核部分文件分析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。