精华内容
下载资源
问答
  • 栈溢出

    2021-02-03 17:24:09
    栈溢出是指在栈内写入超出长度限制的数据,从而破坏程序运行甚至获得系统控制权的攻击手段。 ​ 实现缓冲区溢出,要满足两个条件: 第一,程序要有向栈内写入数据的行为,并且写入长度要大于目标存储长度; 第二...

    缓冲区溢出

    缓冲区溢出简介

    ​ 计算机程序的运行依赖于函数调用栈。栈溢出是指在栈内写入超出长度限制的数据,从而破坏程序运行甚至获得系统控制权的攻击手段。

    ​ 实现缓冲区溢出,要满足两个条件:

    1. 第一,程序要有向栈内写入数据的行为,并且写入长度要大于目标存储长度;
    2. 第二,程序并不限制写入数据的长度

    ​ 历史上第一例被广泛注意的**“莫里斯蠕虫”病毒**就是利用C语言标准库的 gets() 函数并未限制输入数据长度的漏洞,从而实现了栈溢出。

    ​ 缓冲区溢出两种类型:

    1. 基于栈的缓冲区溢出——目标存储在栈中
    2. 基础堆的缓冲区溢出——目标存储在堆中

    ​ 缓冲区溢出导致任意代码执行——通过返回地址覆盖技术。任意代码执行导致,在目标主机上进行一些非法获权操作——生成一个root shell,打开一个新端口或者创建一个新用户。

    栈溢出

    ​ 实现栈溢出,要满足两个条件。第一,程序要有向栈内写入数据的行为;第二,程序并不限制写入数据的长度。历史上第一例被广泛注意的“莫里斯蠕虫”病毒就是利用C语言标准库的 gets() 函数并未限制输入数据长度的漏洞,从而实现了栈溢出。

    背景知识

    函数调用栈

    1. 定义:程序运行时内存一段连续的区域
    2. 作用:用来保存函数运行时的状态信息
    3. 包括:函数参数与局部变量
    4. 称之为“栈”是因为:发生函数调用时,调用函数(caller)的状态被保存在栈内,被调用函数(callee)的状态被压入调用栈的栈顶;在函数调用结束时,栈顶的函数(callee)状态被弹出,栈顶恢复到调用函数(caller)的状态。函数调用栈在内存中从高地址向低地址生长,所以栈顶对应的内存地址在压栈时变小,退栈时变大。

    寄存器

    在这里插入图片描述

    分为通用寄存器特殊寄存器

    1. 通用寄存器:
      1. 一般寄存器e*x(a, b, c, d)
      2. 引索寄存器e*i(s, d)
    2. 特殊寄存器:可以使用MRSMSR特殊寄存器访问指令来访问特殊寄存器
      1. MRS:读特殊寄存器
      2. MSR:写特殊寄存器

    工具准备

    1. 第一步pwntools的安装

    检查kali版本

    查看linux机器是32位还是64位的方法:

     file /sbin/init 或者 file /bin/ls
    
     /sbin/init: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, stripped
    

    如果显示 64-bit 则为64位;

     file /sbin/init
    
     /sbin/init: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), stripped
    

    如果显示为32 bit 则为32bit;

    查看了一下,发现我的kali是64位的

    file /bin/ls
    

    在这里插入图片描述
    不同版本的ubuntu可以应对不同的glibc调试

    开始安装pwntools

    安装的命令很简单

    pip install pwntools
    

    在这里插入图片描述

    关于什么是pwntools ,官方文档中是这样说的: pwntools是一个CTF框架和漏洞利用开发库。它以Python编写,专为快速原型设计和开发而设计,旨在使漏洞利用编写尽可能简单。

    当然也可以这样:
    在中端输入下面的内容

    git clone https://github.com/Gallopsled/pwntools
    cd pwntools
    python setup.py install
    

    打开一个python的小窗口导入一下pwn试试看

    python
    from pwn import *
    asm("xor eax,eax")
    

    如果输出结果如下就说明安装成功:

    '1\xc0'
    

    在这里插入图片描述

    2.安装Capstone

    当然也是差不多的样子

    git clone https://github.com/aquynh/capstone
    cd capstone
    make
    make install
    1234
    

    在这里插入图片描述

    3.安装peda

    gdb-peda:gdb方便调试的工具,类似的工具有gef,gdbinit。
    安装也很简单

     git clone https://github.com/longld/peda.git ~/peda
     echo "source ~/peda/peda.py" >> ~/.gdbinit
    

    装完就可以方便的调试了:
    在这里插入图片描述

    常用命令

    file 文件名
    

    在这里插入图片描述

    展开全文
  • 栈溢出内存溢出Out Of Memory(OOM):指申请内存时,没有足够的内存供其使用。内存泄露Memory Leak:内存泄露,程序申请内存后,无法释放已申请的内存空间。内存泄露的堆积,浪费了内存空间,可能会造成OOM.分析工具...

    栈溢出

    内存溢出Out Of Memory(OOM):指申请内存时,没有足够的内存供其使用。

    内存泄露Memory Leak:内存泄露,程序申请内存后,无法释放已申请的内存空间。内存泄露的堆积,浪费了内存空间,可能会造成OOM.

    分析工具:Eclipse Memory Analyzer

    栈溢出

    HotSpot VM并不区分虚拟机栈和本地方法栈,所以 -Xoss参数(设置本地方法栈大小)在HotSpot无效,只能通过-Xss参数设置栈容量。

    如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出stackoverflowerror异常。

    如果虚拟机在扩展栈时无法申请到足够的空间,抛出OutOfMemoryError异常。

    本质上是同一件事。

    经过验证——在单线程的情况下,无论是栈帧太大还是虚拟机容量太小,当内存无法分配是,抛出的都是StackOverflowError异常。

    分配给栈的内存并不是越大越好,因为栈内存越大,线程多,留给堆的空间就不多了,容易抛出OOM。JVM的默认参数一般情况没有问题(包括递归)。

    方法区和运行时常量池溢出

    运行时常量池是方法区的一部分。

    String.intern()是Native方法。1.8实测

    String sb1 = new stringbuilder("计算机").APPend("软件").toString();

    System.out.println(sb1.intern() == sb1);

    String string = new StringBuilder("Ja").append("va").toString();

    System.out.println(string.intern() == string);

    true

    false

    1.6之前执行intern()会把首次遇到的字符串实例复制到永久代,返回的也是永久代这个实例的引用,而StringBuilder实例在Java堆上,必然不是同一个引用,将返回false。

    1.7之后intern()不会再复制实例,只是在常量池中记录首次出现的实例引用,因此intern返回的引用和由StringBuilder创建的那个字符实例是同一个。由于java这个字符串常量池已经有了,所以intern返回的是常量池的引用,与string并不相等。

    方法区溢出:常见的内存溢出,一个类要被垃圾收集器回收掉,条件比较苛刻。在经常动态生成大量Class的应用中,需要特别注意。

    本机内存直接溢出

    -XX:MaxDirectMemorySize 指定DirectMemory,如果不指定,默认与Java最大值(-Xmx)一样。

    由DirectMemory导致的内存溢出,Heap dump文件不会看到明显的异常,如果OOM之后Dump文件很小,而程序又直接使用了NIO,就要考虑是否是Direct Memory溢出了。

    相关阅读

    1.IteratorIterator的定义如下:public interface Iterator {}Iterator是一个接口,它是集合的迭代器。集合可以通过Iterator去遍

    记录在电脑中同时安装java7和java8的过程

    1.下载并安装jdk1.7 和jdk1.8百度找资源或者直接官网下载:

    https://www.oracle.com/tech

    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'connectionFactory' defined

    in c

    直接放代码了

    public class ImageUtil {

    public static void main(String[] args) throws IOException {

    // 利用当前线程获

    var a = {'age':30,'sex':'male'};

    alert(a.length);会弹出undefined

    可以加入如下函数再计算length

    alert(count(a));

    function

    展开全文
  • 如何构造jvm的堆溢出和栈溢出构造堆溢出和栈溢出Java虚拟机中描述了两种异常:如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError异常;—-栈溢出如果在虚拟机中无法申请到足够多的内存空间...

    如何构造jvm的堆溢出和栈溢出

    构造堆溢出和栈溢出

    Java虚拟机中描述了两种异常:

    如果线程请求的栈深度大于虚拟机所允许的最大深度,将抛出StackOverflowError异常;—-栈溢出

    如果在虚拟机中无法申请到足够多的内存空间,将抛出OutOfMemoryError异常。—-堆溢出

    堆溢出

    在java堆中只会产生OutOfMemoryError异常

    首先,我们知道Java堆内存存放的是对象实例。所以原理上只要我们不断创建对象,并且保证GC Roots到对象之间有可达路径来避免垃圾回收机制清楚这些对象,也就是说当Eden区满的时候,GC被触发时,让GC误以为内存中的对象还存活着,那么在对象数量达到最大堆容量限制的时候就会产生内存溢出的异常。

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11public class 堆溢出{

    static class OOMError{}

    public static void main(String[] args){

    List list = new ArrayList();

    while (true) {

    list.add(new OOMError());

    }

    }

    }

    虽然这里产生了堆溢出,但是我们需要注意产生这个异常的原因是内存溢出还是内存泄露

    首先我们要分清楚产生OutOfMemoryError异常的原因是内存泄露还是内存溢出,如果内存中的对象确实都必须存活着而不像上面那样不断地创建对象实例却不使用该对象,则是内存溢出,而像上面代码中的情况则是内存泄露。

    如果是内存泄露,我们可以通过一些内存查看工具来查看泄露对象到GC Roots的引用链,找到泄露对象是通过怎样的路径与GC Roots相关联并导致GC无法自动回收这些泄露对象,掌握了这些信息,我们就能比较准确地定位出泄露代码的位置。

    如果不是内存泄露,也就是说内存中的对象确实都还必须存活,那么应该检查虚拟机的堆参数,看看是否还可以将机器物理内存调大,同时在代码上检查是否存在某些对象生命周期过长、持有状态时间过长的情况。

    栈溢出

    虚拟机栈用于存储局部变量表、操作数栈、常量池引用等信息。

    所以想让栈溢出,我们只需要定义大量的局部变量,增大此方法帧中本地变量表的长度或者设置-Xss参数减少栈内存容量,又或者无限递归调用方法产生新的栈帧都会产生StackOverflowError异常

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21public class 栈溢出{

    private int stackLength = 1;

    public void addStackLength(){

    stackLength++;

    addStackLength();

    }

    public static void main(String[] args) throws Throwable{

    栈溢出 oom = new 栈溢出();

    try {

    oom.addStackLength();

    } catch (Throwable e) {

    System.out.println("stack length:" + oom.stackLength);

    throw e;

    }

    }

    }

    如果在单线程的情况下,无论是栈帧太大还是虚拟机栈容量太小,当内存无法再分配的时候,虚拟机抛出的是StackOverflowError异常。

    在多线程下,不断地建立线程可能会产生OutOfMemoryError异常

    方法区中的内存溢出

    方法区用于存放已被加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

    根据以上存放的数据,让其内存溢出只需要大量添加其中的数据

    比如比较容易实现的向运行时常量池中的字符串常量池添加字符串常量

    我们可以通过String.intern()方法来构建一个运行时常量池的OutOfMemoryError异常。

    String.intern()是一个Native方法,它的作用是:如果字符串常量池中已经包含了一个等于该String对象的字符串,则返回这个String对象,否则,将此String对象包含的字符串添加到常量池中,并返回这个字符串的String对象的引用。如下面代码:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11public class 方法区溢出{

    public static void main(String[] args){

    List list = new ArrayList();

    int i = 0;

    while (true) {

    list.add(String.valueOf(i++).intern());

    }

    }

    }

    当然,还可以添加大量的类,比如一些框架大量使用反射,如果不具备卸载类的方法,将很快占满方法区

    展开全文
  • java栈溢出_JAVA栈溢出

    2021-02-12 09:48:47
    Java栈溢出小记今天偶然有人问起如何在编写Java代码使其在运行时抛出栈溢出异常,看似简单的问题涉及到了Java虚拟机的知识,特记录于此文。Java虚拟机结构简介根据《Java虚拟机规范》(The Java Virtual Machine ...

    5dde8f08481c1.png

    Java栈溢出小记

    今天偶然有人问起如何在编写Java代码使其在运行时抛出栈溢出异常,看似简单的问题涉及到了Java虚拟机的知识,特记录于此文。

    Java虚拟机结构简介

    根据《Java虚拟机规范》(The Java Virtual Machine Specification)对于Java虚拟机运行时数据区域(Run-Time Data Areas)的描述,虚拟机运行时的描述,其构成图如下所示:

    5dde8f08481c1.png

    图中,PC寄存器、Java虚拟机栈及本地方法栈为各线程私有,方法区(包括运行时常量取)及堆为线程间共享的存储空间。针对问题提出的栈溢出,有两个区域与其相关,包括Java虚拟机栈及本地方法栈。查阅《Java虚拟机规范》,针对栈溢出有如下两段描述:

    对于Java虚拟机栈The following exceptional conditions are associated with Java Virtual Machine stacks:If the computation in a thread requires a larger Java Virtual Machine stack than is permitted, the Java Virtual Machine throws a StackOverflowError.

    If Java Virtual Machine stacks can be dynamically expanded, and expansion is attempted but insufficient memory can be made available to effect the expansion, or if insufficient memory can be made available to create the initial Java Virtual Machine stack for a new thread, the Java Virtual Machine throws an OutOfMemoryError.

    对于本地方法栈The following exceptional conditions are associated with native method stacks:If the computation in a thread requires a larger native method stack than is permitted, the Java Virtual Machine throws a StackOverflowError.

    If native method stacks can be dynamically expanded and native method stack expansion is attempted but insufficient memory can be made available, or if insufficient memory can be made available to create the initial native method stack for a new thread, the Java Virtual Machine throws an OutOfMemoryError.

    由此可见对于Java虚拟机栈与本地方法栈都定义了相似的两种溢出:线程请求栈上分配内存时,内存不足:此溢出一般出现在线程递归调用方法时。在线程调用方法时虚拟机创建栈帧保存方法调用信息,在方法调用完成后销毁栈帧释放存储,如果在方法调用过程中无法创建栈帧则会报出StackOverflowError异常。

    动态扩展栈或线程创建时无法分配足够内存:此溢出一般出现在创建新的线程时。创建新的线程,需要在栈上为其分配存储,如果此时栈上存储不足以分配则会报出OutOfMemoryError异常。

    代码实现

    以下代码在Mac版JDK8中实现及运行,由于HotSpot实现中没有分Java虚拟机栈及本地方法栈-Xss,后续实验均设置-Xss1M,使用Junit4进行测试

    分配栈帧失败(StackOverflowError)

    代码为:1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16public class{

    public void callMyself(int depth){

    System.out.println(depth);

    callMyself(++depth);

    }

    }

    public class StackOverflowTest{

    public void callMyself() throws Exception{

    StackOverflow overflow = new StackOverflow();

    overflow.callMyself(0);

    }

    }

    最终会抛出java.lang.StackOverflowError,且最终能够达到的栈深度主要与栈内存最大大小与栈帧中局部变量占用的空间有关。使用如下代码最大深度会明显变小1

    2

    3

    4

    5

    6

    7

    8public class{

    public void callMyself(int depth){

    int a,b,c,d,e,f,g,h,i,j,k;

    System.out.println(depth+"|");

    callMyself(++depth);

    }

    }

    为线程分配栈上内存失败(OutOfMemoryError)

    代码为:1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20public class OutOfMemory{

    public void createThread(){

    while (true) {

    Thread t = new Thread(() -> {

    while (true) {

    System.out.println(System.currentTimeMillis());

    }

    });

    t.start();

    }

    }

    }

    public class OutOfMemoryTest{

    public void createThread() throws Exception{

    OutOfMemory outOfMemory = new OutOfMemory();

    outOfMemory.createThread();

    }

    }

    最终会抛出OutOfMemoryError。

    针对于OutOfMemoryError的补充

    在HotSpot虚拟机实现中,对于Java线程的创建是映射到操作系统线程中的,如果无法创建操作系统线程也会抛出异常,具体为:java.lang.OutOfMemoryError: unable to create new native thread。

    通过实验在MacOS中,一般小于2048(多次测试为2023),因为默认Mac每个进程最多分配的线程数为2048。可使用sysctl kern.num_taskthreads命令进行查询。如果需要突破限制可以参考官方解决方案。

    在centOS中实验发现max_user_processes及stack size参数都会限制各进程的线程数量。

    参考文献

    [1] 周志明.深入理解Java虚拟机[M].北京:机械工业出版社,53

    展开全文
  • 栈溢出漏洞及栈溢出攻击

    千次阅读 2017-03-13 16:38:14
    1. 栈溢出的原因 栈溢出(stack-based buffer overflows)算是安全界常见的漏洞。一方面因为程序员的疏忽,使用了 strcpy、sprintf 等不安全的函数,增加了栈溢出漏洞的可能。另一方面,因为栈上保存了函数的返回...
  • Java栈溢出小记今天偶然有人问起如何在编写Java代码使其在运行时抛出栈溢出异常,看似简单的问题涉及到了Java虚拟机的知识,特记录于此文。Java虚拟机结构简介根据《Java虚拟机规范》(The Java Virtual Machine ...
  • 栈溢出,堆溢出,永久代溢出,内存泄漏排查JAVA虚拟机1.虚拟机栈和本地方法栈溢出:1.如果线程请求的栈深度大于虚拟机所允许的最大深度,抛出StackOverflowError异常。单线程下,递归太深或方法调用层级过多,使栈帧...
  • V5-306_FreeRTOS实验_任务栈溢出检测方式二 (模拟栈溢出
  • V5-305_FreeRTOS实验_任务栈溢出检测方式一 (模拟栈溢出
  • 栈溢出和栈内存溢出

    2020-03-31 13:55:25
    栈溢出指的是程序向栈中某个变量中写入的字节数超过了这个变量本身所申请的字节数,因而导致与其相邻的栈中的变量的值被改变。 如 char c[10]; memset(c,'a',10); char a[20]; memset(a,'b'...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 11,994
精华内容 4,797
关键字:

栈溢出