官术网_书友最值得收藏!

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結構的緩沖區溢出都能達到這個目的。

主站蜘蛛池模板: 五华县| 武胜县| 西林县| 太仓市| 抚宁县| 昌平区| 隆德县| 定西市| 内江市| 衡阳县| 确山县| 遵化市| 石渠县| 漳平市| 新竹市| 黔江区| 南汇区| 平乐县| 石台县| 油尖旺区| 梁平县| 突泉县| 大宁县| 四会市| 定结县| 陈巴尔虎旗| 长葛市| 留坝县| 桦南县| 东莞市| 久治县| 黄浦区| 招远市| 陆丰市| 夹江县| 平江县| 溆浦县| 思南县| 孟村| 梁河县| 临洮县|