- C和C++安全編碼(原書第2版)
- (美)Robert C.Seacord
- 542字
- 2020-10-30 17:56:50
3.9 longjmp()函數
C標準定義了setjmp()宏、longjmp()函數,以及jmp_buf類型,它們可以用來繞過正常的函數調用和返回規則。
setjmp()宏為稍后將會調用的longjmp()函數保存其調用環境。longjmp()則恢復最后一次由setjmp()宏保存的調用環境。例3.13展示了longjmp()是如何將程序控制權返回到setjmp()調用點的。
例3.13 longjmp()函數使用示例
01 #include <setjmp.h> 02 jmp_buf buf; 03 void g(int n); 04 void h(int n); 05 int n = 6; 06 07 void f(void) { 08 setjmp(buf); 09 g(n); 10 } 11 12 void g(int n) { 13 h(n); 14 } 15 16 void h(int n){ 17 longjmp(buf, 2); 18 }
例3.14展示了Linux中jmp_buf數據結構的實現及其相關定義。jmp_buf結構(第11~15行)包含3個域。調用環境存儲于__jmp_buf(于第1行聲明)中。__jmp_buf類型是一個包含了6個元素的整數數組。#define語句指明每個數組元素中保存的值。例如,基址指針(Base Pointer,BP)存儲于__jmp_buf[3]中,而程序計數器(Program Counter,PC)則存儲于__jmp_buf[5]中。
例3.14 jmp_buf結構的Linux實現
01 typedef int __jmp_buf[6]; 02 03 #define JB_BX 0 04 #define JB_SI 1 05 #define JB_DI 2 06 #define JB_BP 3 07 #define JB_SP 4 08 #define JB_PC 5 09 define JB_SIZE 24 10 11 typedef struct __jmp_buf_tag { 12 __jmp_buf __jmpbuf; 13 int __mask_was_saved; 14 __sigset_t __saved_mask; 15 } jmp_buf[1];
例3.15展示了Linux上為longjmp()產生的匯編指令。第2行的movl指令恢復BP,第3行的movl指令恢復棧指針(SP),第4行則將程序控制權轉移到保存的PC。
例3.15 在Linux上為longjmp()生成的匯編指令
1 movl i, %eax /* 返回 i */ 2 movl env.__jmpbuf[JB_BP], %ebp 3 movl env.__jmpbuf[JB_SP], %esp 4 jmp (env.__jmpbuf[JB_PC])
可以通過將jmp_buf緩沖區中PC的值覆寫為外殼代碼的起始地址的方法來利用longjmp()函數。任意內存寫或者直接針對jmp_buf結構的緩沖區溢出都能達到這個目的。
推薦閱讀
- Reporting with Visual Studio and Crystal Reports
- Instant Apache Stanbol
- Oracle 12c中文版數據庫管理、應用與開發實踐教程 (清華電腦學堂)
- C++程序設計基礎教程
- SQL Server 2012數據庫管理與開發項目教程
- 零基礎輕松學SQL Server 2016
- Java EE核心技術與應用
- 編程與類型系統
- App Inventor創意趣味編程進階
- Raspberry Pi Robotic Projects(Third Edition)
- RubyMotion iOS Develoment Essentials
- IBM Cognos TM1 Developer's Certification guide
- 交互式程序設計(第2版)
- Puppet:Mastering Infrastructure Automation
- ASP.NET Core and Angular 2