Day22 用C語言編譯應用程序

文章目錄

      • 1. 保護操作系統5(harib19a)
      • 2. 幫助發現bug(harib19b)
      • 3. 強制結束應用程序(harib19c)
      • 4. 用C語言顯示字符串(harib19e)
      • 5. 顯示窗口(harib19f)

1. 保護操作系統5(harib19a)

上一章節已經對“應用軟件在系統內存上動手腳”這一case做了防護。不過定時器上還是存在安全漏洞的,接下來crack3的目的是使光標閃爍變慢,使任務切換的速度變慢。

# crack3.nas 文件
[INSTRSET "i486p"]
[BITS 32]MOV		AL,0x34OUT		0x43,ALMOV		AL,0xffOUT		0x40,ALMOV		AL,0xffOUT		0x40,AL# 	上述代碼的功能與下列相當
#	io_out8(PIT_CTRL, 0x34);
#	io_out8(PIT_CNT0, 0xff);
#	io_out8(PIT_CNT0, 0xff);MOV		EDX,4INT		0x40

但這并不會針對性的影響到定時器,因為直接再應用程序中使用IN和OUT指令的話,會產生一般保護異常,然后就在屏幕上顯示“General Protected Exception”。
簡單粗暴的crack4,目的是直接禁止中斷,那么就會不再產生定時器中斷,任務切換也會停止,鍵盤鼠標中斷也會停止。

# crack4.nas 文件
[INSTRSET "i486p"]
[BITS 32]CLI
fin:HLTJMP		fin

但其實,應用程序中也不能直接使用CLI, STI和HLT指令,這些也會產生一般保護異常。可以嘗試CALL操作系統函數(_io_cli)的地址,通過查看map文件可以該函數地址。

# crack5.nas 文件
[INSTRSET "i486p"]
[BITS 32]CALL	2*8:0xac1MOV		EDX,4INT		0x40

但是還忽略了一點,應用程序的地址的CALL并不是任意的,只能CALL設置好的地址。所以crack5程序還是會產生一般保護異常。應用程序期望調用操作系統只能才做INT 0x40的方式。
臨時修改hrb_api,使它可以處理一個臨時的edx用于破壞操作系統,并在應用程序中INT 0x40,但是對定時器或鍵盤鼠標中斷下手,確實并不簡單。

// console.c 文件
int *hrb_api(int edi, int esi, int ebp, int esp, int ebx, int edx, int ecx, int eax)
{int cs_base = *((int *) 0xfe8);struct TASK *task = task_now();struct CONSOLE *cons = (struct CONSOLE *) *((int *) 0x0fec);if (edx == 1) {cons_putchar(cons, eax & 0xff, 1);} else if (edx == 2) {cons_putstr0(cons, (char *) ebx + cs_base);} else if (edx == 3) {cons_putstr1(cons, (char *) ebx + cs_base, ecx);} else if (edx == 4) {return &(task->tss.esp0);} else if (edx == 123456789) {*((char *) 0x00102600) = 0;}return 0;
}
# crack6.nas 文件
[INSTRSET "i486p"]
[BITS 32]MOV		EDX,123456789INT		0x40MOV		EDX,4INT		0x40

2. 幫助發現bug(harib19b)

CPU的異常處理功能,除了可以保護操作系統免遭應用程序的破壞,還可以幫助在編寫程序時及時發現bug,例如數組越界訪問等。
當一個局部數組變量被越界訪問時,就有可能產生棧異常。棧異常的中斷號為0x0c。0x0c的中斷函數類似0x0d,只是改一下異常時的信息打印就好。

# naskfunc.nas 文件
_asm_inthandler0c:STIPUSH	ESPUSH	DSPUSHADMOV		EAX,ESPPUSH	EAXMOV		AX,SSMOV		DS,AXMOV		ES,AXCALL	_inthandler0cCMP		EAX,0JNE		end_appPOP		EAXPOPADPOP		DSPOP		ESADD		ESP,4			# 類似 INT 0x0d IRETD
// console.c 文件
int *inthandler0c(int *esp)
{struct CONSOLE *cons = (struct CONSOLE *) *((int *) 0x0fec);struct TASK *task = task_now();char s[30];cons_putstr0(cons, "\nINT 0C :\n Stack Exception.\n");sprintf(s, "EIP = %08X\n", esp[11]);cons_putstr0(cons, s);return &(task->tss.esp0);	/* 強制結束程序 */
}
// dsctbl.c 文件
void init_gdtidt(void)
{set_gatedesc(idt + 0x2c, (int) asm_inthandler2c, 2 * 8, AR_INTGATE32);	// 注冊給idt
}

在inthandler0c函數中,企圖打印esp[11],即EIP,會將下一條將要被執行的指令在內存中的地址打印出來。因此inthandler0c的含義就是在發生異常時,把異常產生的指令地址打印出來。然后再根據.map文件和.lst文件就能定位到產生異常的具體位置。
在這里插入圖片描述

3. 強制結束應用程序(harib19c)

如果一個應用程序中存在一個毫不間歇的死循環,那么系統整體的速度就會變慢。為了防止類似死循環這種程序,可以將某一個按鍵作為強制結束鍵,按一下就可以結束程序。
將強制結束任務寫在bootpack.c文件的HariMain函數的鍵盤中斷處理中:

// bootpack.c 文件
void HariMain(void)
{/* 省略 */i = fifo32_get(&fifo);io_sti();if (256 <= i && i <= 511){if (i == 256 + 0x3b && key_shift != 0 && task_cons->tss.ss0 != 0) {	/* Shift+F1 */cons = (struct CONSOLE *) *((int *) 0x0fec);cons_putstr0(cons, "\nBreak(key) :\n");io_cli();task_cons->tss.eax = (int) &(task_cons->tss.esp0);task_cons->tss.eip = (int) asm_end_app;io_sti();}}/* 省略 */
}
# naskfunc.nas 文件
# asm_end_app是end_app函數的修改
_asm_end_app:
#	EAX為tss.esp0的地址MOV		ESP,[EAX]MOV		DWORD [EAX+4],0POPADRET		# 返回cmd_app

當 按下強制結束鍵時,改寫命令行窗口任務的寄存器值,并goto到asm_end_app函數,如此便可以強制結束程序。

// mtask.c 文件
struct TASK *task_alloc(void)
{/* 省略 */for (i = 0; i < MAX_TASKS; i++) {if (taskctl->tasks0[i].flags == 0) {task = &taskctl->tasks0[i];/* 省略 */task->tss.ss0 = 0;return task;}}return 0;
}

還需要確保task_cons->tss.ss0不為0時采取調用結束程序,為防止應用程序還未運行(task_cons->tss.ss0為0)進行調用。

4. 用C語言顯示字符串(harib19e)

第一個供c語言調用的api:

# a_nask.nas 文件
_api_putstr0:	; void api_putstr0(char *s);PUSH	EBXMOV		EDX,2MOV		EBX,[ESP+8]		; sINT		0x40POP		EBXRET

但此時如果直接在c語言中調用api_putstr0函數,應該是無法在屏幕上顯示參數s的。
調試api之前,先解釋一下可執行程序.hrb文件的內容。可執行程序.hrb文件由兩部分組成:代碼部分和數據部分。其中,數據部分在位于代碼部分的開頭一塊區域中。當應用程序啟動時,數據部分被傳送到應用程序使用的數據段中。
對于.hrb文件:
在這里插入圖片描述
0x0000 存放的是應用程序啟動后數據段的大小,當前固定大小為64KB。
0x0004 存放的是“Hari”這四個字符,讀取文件的時候會先判斷這四個字節,判斷一致才會當作可執行程序處理。
0x0008 存放的是數據段預備空間的大小。暫時沒有使用。
0x000c 存放的是應用程序啟動時,ESP的初始值。也就是說,0x000c位置的內容表示棧指針,調用api_putstr0的時候所傳入的參數s就會放在0x000c的內容所代表的內存地址處。例如,可執行程序hello4.hrb被執行時char *參數s的地址是0x0400,就是文件hello4.hrb的0x000c處寫的0x0400。而這個值之前的部分會作為棧來使用,也就是1024字節(十六進制就是0x0400),這個值在編譯的時候已經確定好了。

# Makefile 文件
hello4.bim : hello4.obj a_nask.obj Makefile$(OBJ2BIM) @$(RULEFILE) out:hello4.bim stack:1k map:hello4.map \hello4.obj a_nask.obj

0x0010和0x0014 的目的是當.hrb文件被加載時,告訴操作系統該可執行文件的數據大小和在文件中的位置。
0x0018 在內存中的放置應該是“00 00 00 E9”,其中E9是JMP指令的機器碼,這就相當于在0x001b位置存放了一個JMP指令。
0x001c 的程序入口結合0x001b的JMP指令,就可以運行可執行文件了。(但是程序入口地址-0x20是為啥,不太清楚)
0x0020 存放對應用程序使用的malloc函數調用之后的返回地址。
根據以上內容需要修改console.c文件。

// console.c 文件
int cmd_app(struct CONSOLE *cons, int *fat, char *cmdline)
{/* 省略 */if (finfo != 0) {/* 找到文件 */p = (char *) memman_alloc_4k(memman, finfo->size);file_loadfile(finfo->clustno, finfo->size, p, fat, (char *) (ADR_DISKIMG + 0x003e00));if (finfo->size >= 36 && strncmp(p + 4, "Hari", 4) == 0 && *p == 0x00) {segsiz = *((int *) (p + 0x0000));esp    = *((int *) (p + 0x000c));datsiz = *((int *) (p + 0x0010));	// 數據部分的大小dathrb = *((int *) (p + 0x0014));	// 數據部分在文件中的位置q = (char *) memman_alloc_4k(memman, segsiz);	// 根據hrb文件確定數據段大小*((int *) 0xfe8) = (int) q;set_segmdesc(gdt + 1003, finfo->size - 1, (int) p, AR_CODE32_ER + 0x60);set_segmdesc(gdt + 1004, segsiz - 1,      (int) q, AR_DATA32_RW + 0x60);for (i = 0; i < datsiz; i++) {// 執行程序前把數據部分拷貝到數據段q[esp + i] = p[dathrb + i];}start_app(0x1b, 1003 * 8, esp, 1004 * 8, &(task->tss.esp0));memman_free_4k(memman, (int) q, segsiz);} else {// 找不到Hari則報錯cons_putstr0(cons, ".hrb file format error.\n");}memman_free_4k(memman, (int) p, finfo->size);cons_newline(cons);return 1;}/* 未找到文件 */return 0;
}

為啥將“Hari”字符放在文件的0x0004位置,而不是0x0000位置呢?
0x0000位置存放的是應用程序啟動后數據段的大小,bim2hrb會自動將該內容調整為4KB的倍數,所以0x0000位置的字節必定是00。一個普通文件的0x0000位置卻很小可能是00,但是卻有可能是某個字母,所以將“Hari”字符放在文件的0x0004位置可以提高訪問的安全性。

5. 顯示窗口(harib19f)

現在期望實現一個用于顯示窗口的api,暫時這樣設計:
在這里插入圖片描述
調用后返回值:
在這里插入圖片描述
但是當前有個問題,如何將返回值傳遞給應用程序。中斷服務函數會通過IRETD安全的返回應用程序,并且在返回之前會把8個32位寄存器POPAD出去,所以只能依賴POPAD和IRETD。
兩次PUSHAD之后的棧是這樣的:

[高地址]
EAX <— 1st
ECA
EDX
EBX
ESO
EBP
ESI
EDI
EAX <— 2nd, hrb_api使用到的就是這里及以下
ECA
EDX
EBX
ESO
EBP
ESI
EDI

// console.c 文件
int *hrb_api(int edi, int esi, int ebp, int esp, int ebx, int edx, int ecx, int eax)
{int ds_base = *((int *) 0xfe8);		// 來自于bootpack.c的HariMain函數中的shtctl變量struct TASK *task = task_now();struct CONSOLE *cons = (struct CONSOLE *) *((int *) 0x0fec);struct SHTCTL *shtctl = (struct SHTCTL *) *((int *) 0x0fe4);struct SHEET *sht;int *reg = &eax + 1;	/* 參照棧空間可知, &eax+1可以獲取到系統EDI *//* reg[0] : EDI,   reg[1] : ESI,   reg[2] : EBP,   reg[3] : ESP *//* reg[4] : EBX,   reg[5] : EDX,   reg[6] : ECX,   reg[7] : EAX *//* 省略 */if (edx == 5) {sht = sheet_alloc(shtctl);sheet_setbuf(sht, (char *) ebx + ds_base, esi, edi, eax);make_window8((char *) ebx + ds_base, esi, edi, (char *) ecx + ds_base, 0);sheet_slide(sht, 100, 50);sheet_updown(sht, 3);	/* 背景層高度3,位于task_a之上 */reg[7] = (int) sht;	// 把sht賦值給EAX,_asm_hrb_api中POPAD的時候會彈出棧}return 0;
}

再寫一個測試程序:

# a_nask.nas 文件
_api_openwin:	# int api_openwin(char *buf, int xsiz, int ysiz, int col_inv, char *title);PUSH	EDIPUSH	ESIPUSH	EBXMOV		EDX,5MOV		EBX,[ESP+16]	# bufMOV		ESI,[ESP+20]	# xsizMOV		EDI,[ESP+24]	# ysizMOV		EAX,[ESP+28]	# col_invMOV		ECX,[ESP+32]	# titleINT		0x40	# 調用中斷POP		EBXPOP		ESIPOP		EDIRET
// winhello.c 文件
int api_openwin(char *buf, int xsiz, int ysiz, int col_inv, char *title);
void api_end(void);char buf[150 * 50];void HariMain(void)
{int win;win = api_openwin(buf, 150, 50, -1, "hello");api_end();
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/96601.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/96601.shtml
英文地址,請注明出處:http://en.pswp.cn/web/96601.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

簡單學習HTML+CSS+JavaScript

一、HTML HTML被稱為 超文本標記語言&#xff0c;是由一系列標簽構成的語言。 下面介紹HTML中的標簽&#xff1a; &#xff08;一&#xff09;HTML文件基本結構 <!DOCTYPE html><html><head><title>Document</title></head> <body&…

強化學習中重要性采樣

PPO 中重要性采樣 https://github.com/modelscope/ms-swift/blob/main/docs/source/Instruction/GRPO/GetStarted/GRPO.md樂&#xff0c;這個網頁中是的groundtruth是錯誤的&#xff08;可能是為了防止抄襲&#xff09;。一些例子 0. 池塘養魚的一個例子 想象一下&#xff0c;你…

《樹與二叉樹詳解:概念、結構及應用》

目錄 一. 樹的概念和結構 1.1 樹的基本概念 1.2 樹的結構特點 二. 樹的表示方法和實際運用 2.1 孩子 - 兄弟表示法&#xff08;Child-Sibling Representation&#xff09; 2.2 樹的實際應用場景 三. 二叉樹的概念 3.1 二叉樹的核心定義 3.2 二叉樹的基本分類 四. 二叉…

Qt/C++,windows多進程demo

1. 項目概述 最近研究了一下Qt/C框架下&#xff0c;windows版本的多進程編寫方法&#xff0c;實現了一個小demo。下面詳細介紹一下。 MultiProcessDemo是一個基于Qt框架實現的多進程應用程序示例&#xff0c;展示了如何在Windows平臺上通過共享內存和事件機制實現進程間通信。該…

Android SystemServer 系列專題【篇五:UserController用戶狀態控制】

本篇接著SystemServer的啟動流程&#xff0c;圍繞SystemServer最后階段關于主用戶的啟動和解鎖的流程&#xff0c;作為切入點&#xff0c;來看看SystemServer是如何講用戶狀態同步到所有的系統級服務中。ssm.onStartUserssm.onUnlockingUserssm.onUnlockedUser本篇先介紹UserCo…

推薦使用 pnpm 而不是 npm

npm 的局限性 磁盤空間浪費在 npm 早期版本中&#xff0c;每個項目的node_modules目錄都會完整復制所有依賴包&#xff0c;即使多個項目依賴同一個包的相同版本&#xff0c;也會重復存儲。這導致磁盤空間被大量占用&#xff0c;隨著項目數量的增加&#xff0c;存儲成本顯著上升…

Transformer實戰(18)——微調Transformer語言模型進行回歸分析

Transformer實戰&#xff08;18&#xff09;——微調Transformer語言模型進行回歸分析0. 前言1. 回歸模型2. 數據處理3. 模型構建與訓練4. 模型推理小結系列鏈接0. 前言 在自然語言處理領域中&#xff0c;預訓練 Transformer 模型不僅能勝任離散類別預測&#xff0c;也可用于連…

【Linux】【實戰向】Linux 進程替換避坑指南:從理解 bash 阻塞等待,到親手實現能執行 ls/cd 的 Shell

前言&#xff1a;歡迎各位光臨本博客&#xff0c;這里小編帶你直接手撕&#xff0c;文章并不復雜&#xff0c;愿諸君耐其心性&#xff0c;忘卻雜塵&#xff0c;道有所長&#xff01;&#xff01;&#xff01;&#xff01; IF’Maxue&#xff1a;個人主頁&#x1f525; 個人專欄…

linux常用命令 (3)——系統包管理

博客主頁&#xff1a;christine-rr-CSDN博客 ????? ?? hi&#xff0c;大家好&#xff0c;我是christine-rr ! 今天來分享一下linux常用命令——系統包管理 目錄linux常用命令---系統包管理&#xff08;一&#xff09;Debian 系發行版&#xff08;Ubuntu、Debian、Linux …

YOLOv8 mac-intel芯片 部署指南

&#x1f680; 在 Jupyter Notebook 和 PyCharm 中使用 Conda 虛擬環境&#xff08;YOLOv8 部署指南&#xff0c;Python 3.9&#xff09; YOLOv8 是 Ultralytics 開源的最新目標檢測模型&#xff0c;輕量高效&#xff0c;支持分類、檢測、分割等多種任務。 在 Mac&#xff08;…

【高等數學】第十一章 曲線積分與曲面積分——第六節 高斯公式 通量與散度

上一節&#xff1a;【高等數學】第十一章 曲線積分與曲面積分——第五節 對坐標的曲面積分 總目錄&#xff1a;【高等數學】 目錄 文章目錄1. 高斯公式2. 沿任意閉曲面的曲面積分為零的條件3. 通量與散度1. 高斯公式 設空間區域ΩΩΩ是由分片光滑的閉曲面ΣΣΣ所圍成&#x…

IDEA試用過期,無法登錄,重置方法

IDEA過期&#xff0c;重置方法: IntelliJ IDEA 2024.2.0.2 (親測有效) 最新Idea重置辦法!&#xff1a; 方法一&#xff1a; 1、刪除C:\Users\{用戶名}\AppData\Local\JetBrains\IntelliJIdea2024.2 下所有文件(注意&#xff1a;是子目錄全部刪除) 2、刪除C:\Users\{用戶名}\App…

創建用戶自定義橋接網絡并連接容器

1.創建用戶自定義的 alpine-net 網絡[roothost1 ~]# docker network create --driver bridge alpine-net 9f6d634e6bd7327163a9d83023e435da6d61bc6cf04c9d96001d1b64eefe4a712.列出 Docker 主機上的網絡[roothost1 ~]# docker network ls NETWORK ID NAME DRIVER …

Vue3 + Vite + Element Plus web轉為 Electron 應用,解決無法登錄、隱藏自定義導航欄

如何在vue3 Vite Element Plus搭好的架構下轉為 electron應用呢&#xff1f; https://www.electronjs.org/zh/docs/latest/官方文檔 https://www.electronjs.org/zh/docs/latest/ 第一步&#xff1a;安裝 electron相關依賴 npm install electron electron-builder concurr…

qt QAreaLegendMarker詳解

1. 概述QAreaLegendMarker 是 Qt Charts 模塊中的一部分&#xff0c;用于在圖例&#xff08;Legend&#xff09;中表示 QAreaSeries 的標記。它負責顯示區域圖的圖例項&#xff0c;通常包含區域顏色樣例和對應的描述文字。圖例標記和對應的區域圖關聯&#xff0c;顯示區域的名稱…

linux 函數 kstrtoul

kstrtoul 函數概述 kstrtoul 是 Linux 內核中的一個函數&#xff0c;用于將字符串轉換為無符號長整型&#xff08;unsigned long&#xff09;。該函數定義在 <linux/kernel.h> 頭文件中&#xff0c;常用于內核模塊中解析用戶空間傳遞的字符串參數。 函數原型 int kstrtou…

LLM(三)

一、人類反饋的強化學習&#xff08;RLHF&#xff09;微調的目標是通過指令&#xff0c;包括路徑方法&#xff0c;進一步訓練你的模型&#xff0c;使他們更好地理解人類的提示&#xff0c;并生成更像人類的回應。RLHF&#xff1a;使用人類反饋微調型語言模型&#xff0c;使用強…

DPO vs PPO,偏好優化的兩條技術路徑

1. 背景在大模型對齊&#xff08;alignment&#xff09;里&#xff0c;常見的兩類方法是&#xff1a;PPO&#xff1a;強化學習經典算法&#xff0c;OpenAI 在 RLHF 里用它來“用獎勵模型更新策略”。DPO&#xff1a;2023 年提出的新方法&#xff08;參考論文《Direct Preferenc…

BLE6.0信道探測,如何重構物聯網設備的距離感知邏輯?

在物聯網&#xff08;IoT&#xff09;無線通信技術快速滲透的當下&#xff0c;實現人與物、物與物之間對物理距離的感知響應能力已成為提升設備智能高度與人們交互體驗的關鍵所在。當智能冰箱感知用戶靠近而主動亮屏顯示內部果蔬時、當門禁系統感知到授權人士靠近而主動開門時、…

【計算機 UTF-8 轉換為本地編碼的含義】

UTF-8 轉換為本地編碼的含義 詳細解釋一下"UTF-8轉換為本地編碼"的含義以及為什么在處理中文時這很重要。 基本概念 UTF-8 編碼 國際標準&#xff1a;UTF-8 是一種能夠表示世界上幾乎所有字符的 Unicode 編碼方式跨平臺兼容&#xff1a;無論在哪里&#xff0c;UTF-8 …