当前位置: 首页 > news >正文

pwn学习笔记(12)--Chunk Extend and Overlapping

pwn学习笔记(12)–Chunk Extend and Overlapping

​ chunk extend 是堆漏洞的一种常见利用手法,通过 extend 可以实现 chunk overlapping(块重叠) 的效果。这种利用方法需要以下的时机和条件:

  • 程序中存在基于堆的漏洞
  • 漏洞可以控制 chunk header 中的数据

1、对inuse的fastbin进行extend:

 int main(void)
{void *ptr,*ptr1;ptr=malloc(0x10);//分配第一个0x10的chunkmalloc(0x10);//分配第二个0x10的chunk*(long long *)((long long)ptr-0x8)=0x41;// 修改第一个块的size域free(ptr);ptr1=malloc(0x30);// 实现 extend,控制了第二个块的内容return 0;
}

​ 首先进行两次malloc,之后看看heap的状态:

In file: /mnt/hgfs/sharedict/ChunkExtend/extend.c3     void *ptr,*ptr1;4 5     ptr=malloc(0x10);//分配第一个0x10的chunk6     malloc(0x10);//分配第二个0x10的chunk78     *(long long *)((long long)ptr-0x8)=0x41;// 修改第一个块的size域9 10     free(ptr);11     ptr1=malloc(0x30);// 实现 extend,控制了第二个块的内容12     return 0;13 }
─────────────────────────────────────────────────────────[ STACK ]─────────────────────────────────────────────────────────
00:0000│ rsp 0x7fffffffde30 —▸ 0x555555758010 ◂— 0x0
01:0008│     0x7fffffffde38 ◂— 0x0
02:0010│ rbp 0x7fffffffde40 —▸ 0x5555555546e0 (__libc_csu_init) ◂— push   r15
03:0018│     0x7fffffffde48 —▸ 0x7ffff7a2d840 (__libc_start_main+240) ◂— mov    edi, eax
04:0020│     0x7fffffffde50 ◂— 0x1
05:0028│     0x7fffffffde58 —▸ 0x7fffffffdf28 —▸ 0x7fffffffe2ac ◂— '/mnt/hgfs/sharedict/ChunkExtend/test'
06:0030│     0x7fffffffde60 ◂— 0x1f7ffcca0
07:0038│     0x7fffffffde68 —▸ 0x55555555468a (main) ◂— push   rbp
───────────────────────────────────────────────────────[ BACKTRACE ]───────────────────────────────────────────────────────► f 0   0x5555555546aa main+32f 1   0x7ffff7a2d840 __libc_start_main+240
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
pwndbg> heap
Allocated chunk | PREV_INUSE
Addr: 0x555555758000
Size: 0x21Allocated chunk | PREV_INUSE
Addr: 0x555555758020
Size: 0x21Top chunk | PREV_INUSE
Addr: 0x555555758040
Size: 0x20fc1pwndbg> bins
fastbins
0x20: 0x0
0x30: 0x0
0x40: 0x0
0x50: 0x0
0x60: 0x0
0x70: 0x0
0x80: 0x0
unsortedbin
all: 0x0
smallbins
empty
largebins
empty

​ 有地址的话,就去读一下两个堆的内容:

pwndbg> x/30gx 0x555555758000
0x555555758000: 0x0000000000000000  0x0000000000000021		<======Chunk1
0x555555758010: 0x0000000000000000  0x0000000000000000
0x555555758020: 0x0000000000000000  0x0000000000000021		<======Chunk2
0x555555758030: 0x0000000000000000  0x0000000000000000
0x555555758040: 0x0000000000000000  0x0000000000020fc1		<======Top Chunk
0x555555758050: 0x0000000000000000  0x0000000000000000
0x555555758060: 0x0000000000000000  0x0000000000000000
0x555555758070: 0x0000000000000000  0x0000000000000000
0x555555758080: 0x0000000000000000  0x0000000000000000
0x555555758090: 0x0000000000000000  0x0000000000000000
0x5555557580a0: 0x0000000000000000  0x0000000000000000
0x5555557580b0: 0x0000000000000000  0x0000000000000000
0x5555557580c0: 0x0000000000000000  0x0000000000000000
0x5555557580d0: 0x0000000000000000  0x0000000000000000
0x5555557580e0: 0x0000000000000000  0x0000000000000000

​ 下一步开始释放,看一看修改chunk1的size域大小:

pwndbg> heap
Allocated chunk | PREV_INUSE
Addr: 0x555555758000
Size: 0x41Top chunk | PREV_INUSE
Addr: 0x555555758040
Size: 0x20fc1pwndbg> bins
fastbins
0x20: 0x0
0x30: 0x0
0x40: 0x0
0x50: 0x0
0x60: 0x0
0x70: 0x0
0x80: 0x0
unsortedbin
all: 0x0
smallbins
empty
largebins
empty

​ 发现chunk2被修改后增大了的chunk1给那占了,heap里就只有一个Chunk了,看看内存:

pwndbg> x/30gx 0x555555758000
0x555555758000: 0x0000000000000000  0x0000000000000041			<======原Chunk1
0x555555758010: 0x0000000000000000  0x0000000000000000
0x555555758020: 0x0000000000000000  0x0000000000000021			<======原Chunk2
0x555555758030: 0x0000000000000000  0x0000000000000000
0x555555758040: 0x0000000000000000  0x0000000000020fc1			<======Top Chunk
0x555555758050: 0x0000000000000000  0x0000000000000000
0x555555758060: 0x0000000000000000  0x0000000000000000
0x555555758070: 0x0000000000000000  0x0000000000000000
0x555555758080: 0x0000000000000000  0x0000000000000000
0x555555758090: 0x0000000000000000  0x0000000000000000
0x5555557580a0: 0x0000000000000000  0x0000000000000000
0x5555557580b0: 0x0000000000000000  0x0000000000000000
0x5555557580c0: 0x0000000000000000  0x0000000000000000
0x5555557580d0: 0x0000000000000000  0x0000000000000000
0x5555557580e0: 0x0000000000000000  0x0000000000000000

​ 除去chunk1的size域变化了以外,似乎没有其他变化,但是,逻辑上来说,现在的堆里只有一个chunk了,之后free掉chunk1看看:

pwndbg> heap
Free chunk (fastbins) | PREV_INUSE
Addr: 0x555555758000
Size: 0x41
fd: 0x00Top chunk | PREV_INUSE
Addr: 0x555555758040
Size: 0x20fc1pwndbg> bins
fastbins
0x20: 0x0
0x30: 0x0
0x40: 0x555555758000 ◂— 0x0
0x50: 0x0
0x60: 0x0
0x70: 0x0
0x80: 0x0
unsortedbin
all: 0x0
smallbins
empty
largebins
empty

​ 之后读取下内存:

pwndbg> x/30gx 0x555555758000
0x555555758000: 0x0000000000000000  0x0000000000000041
0x555555758010: 0x0000000000000000  0x0000000000000000
0x555555758020: 0x0000000000000000  0x0000000000000021
0x555555758030: 0x0000000000000000  0x0000000000000000
0x555555758040: 0x0000000000000000  0x0000000000020fc1
0x555555758050: 0x0000000000000000  0x0000000000000000
0x555555758060: 0x0000000000000000  0x0000000000000000
0x555555758070: 0x0000000000000000  0x0000000000000000
0x555555758080: 0x0000000000000000  0x0000000000000000
0x555555758090: 0x0000000000000000  0x0000000000000000
0x5555557580a0: 0x0000000000000000  0x0000000000000000
0x5555557580b0: 0x0000000000000000  0x0000000000000000
0x5555557580c0: 0x0000000000000000  0x0000000000000000
0x5555557580d0: 0x0000000000000000  0x0000000000000000
0x5555557580e0: 0x0000000000000000  0x0000000000000000

​ 下一步是重头戏,试想,如果原chunk1的size域没有真正变化,那么我们进行malloc一个0x30大小的堆块的时候,就不会分配到这个地址上,而是从Top Chunk里拆分,那么事实上是怎么样的呢?实践出真知,看一下吧:

pwndbg> heap
Allocated chunk | PREV_INUSE
Addr: 0x555555758000
Size: 0x41Top chunk | PREV_INUSE
Addr: 0x555555758040
Size: 0x20fc1pwndbg> bins
fastbins
0x20: 0x0
0x30: 0x0
0x40: 0x0
0x50: 0x0
0x60: 0x0
0x70: 0x0
0x80: 0x0
unsortedbin
all: 0x0
smallbins
empty
largebins
empty
pwndbg> x/30gx 0x555555758000
0x555555758000: 0x0000000000000000  0x0000000000000041
0x555555758010: 0x0000000000000000  0x0000000000000000
0x555555758020: 0x0000000000000000  0x0000000000000021
0x555555758030: 0x0000000000000000  0x0000000000000000
0x555555758040: 0x0000000000000000  0x0000000000020fc1			<======Top Chunk
0x555555758050: 0x0000000000000000  0x0000000000000000
0x555555758060: 0x0000000000000000  0x0000000000000000
0x555555758070: 0x0000000000000000  0x0000000000000000
0x555555758080: 0x0000000000000000  0x0000000000000000
0x555555758090: 0x0000000000000000  0x0000000000000000
0x5555557580a0: 0x0000000000000000  0x0000000000000000
0x5555557580b0: 0x0000000000000000  0x0000000000000000
0x5555557580c0: 0x0000000000000000  0x0000000000000000
0x5555557580d0: 0x0000000000000000  0x0000000000000000
0x5555557580e0: 0x0000000000000000  0x0000000000000000

​ 显然,Top Chunk并未被拆分,这里确定了,似乎malloc(0x30)得到的堆块是原Chunk1的地址,这里说明了,这里的原chunk1因为size域被修改了之后成为了一个新的更大的堆块,这里也就造成了所谓的堆重叠了,chunk1因为修改了size域后,生成的那个新的chunk和chunk2部分重叠了,这也就导致了,有的对原chunk1的修改可以修改到chunk2的地方,如果chunk2保留了指针,那就可以对chunk2进行伪造,可以结合类似off by one和UAF形成很多种利用方式。

2、对inuse的smallbin进行extend:

//gcc -g 2.c
//注意把之前那个a.out给删掉
int main()
{void *ptr,*ptr1;ptr=malloc(0x80);//分配第一个 0x80 的chunk1malloc(0x10); //分配第二个 0x10 的chunk2malloc(0x10); //防止与top chunk合并*(long *)((long)ptr-0x8)=0xb1;free(ptr);ptr1=malloc(0xa0);
}

​ 首先进行三次分配,其中,第三次分配是防止extend后,chunk与topchunk进行合并,无需关注。先看看经过三次malloc之后的堆空间是啥样的:

pwndbg> heap
Allocated chunk | PREV_INUSE
Addr: 0x555555758000
Size: 0x91Allocated chunk | PREV_INUSE
Addr: 0x555555758090
Size: 0x21Allocated chunk | PREV_INUSE
Addr: 0x5555557580b0
Size: 0x21Top chunk | PREV_INUSE
Addr: 0x5555557580d0
Size: 0x20f31pwndbg> bin
fastbins
0x20: 0x0
0x30: 0x0
0x40: 0x0
0x50: 0x0
0x60: 0x0
0x70: 0x0
0x80: 0x0
unsortedbin
all: 0x0
smallbins
empty
largebins
empty
pwndbg> x/40gx 0x555555758000
0x555555758000: 0x0000000000000000  0x0000000000000091			<======Chunk1
0x555555758010: 0x0000000000000000  0x0000000000000000
0x555555758020: 0x0000000000000000  0x0000000000000000
0x555555758030: 0x0000000000000000  0x0000000000000000
0x555555758040: 0x0000000000000000  0x0000000000000000
0x555555758050: 0x0000000000000000  0x0000000000000000
0x555555758060: 0x0000000000000000  0x0000000000000000
0x555555758070: 0x0000000000000000  0x0000000000000000
0x555555758080: 0x0000000000000000  0x0000000000000000
0x555555758090: 0x0000000000000000  0x0000000000000021			<======Chunk2
0x5555557580a0: 0x0000000000000000  0x0000000000000000
0x5555557580b0: 0x0000000000000000  0x0000000000000021			<======Chunk3
0x5555557580c0: 0x0000000000000000  0x0000000000000000
0x5555557580d0: 0x0000000000000000  0x0000000000020f31			<======Top Chunk
0x5555557580e0: 0x0000000000000000  0x0000000000000000
0x5555557580f0: 0x0000000000000000  0x0000000000000000
0x555555758100: 0x0000000000000000  0x0000000000000000
0x555555758110: 0x0000000000000000  0x0000000000000000
0x555555758120: 0x0000000000000000  0x0000000000000000
0x555555758130: 0x0000000000000000  0x0000000000000000

​ 估摸一下,chunk1的大小似乎有点大,导致free掉的chunk1并不会进入fastbin,而是进入smallbin,那么修改了size域后,原本三个chunk在gdb里的heap指令下依旧少了一个:

pwndbg> heap
Allocated chunk | PREV_INUSE
Addr: 0x555555758000
Size: 0xb1Allocated chunk | PREV_INUSE
Addr: 0x5555557580b0
Size: 0x21Top chunk | PREV_INUSE
Addr: 0x5555557580d0
Size: 0x20f31pwndbg> bins
fastbins
0x20: 0x0
0x30: 0x0
0x40: 0x0
0x50: 0x0
0x60: 0x0
0x70: 0x0
0x80: 0x0
unsortedbin
all: 0x0
smallbins
empty
largebins
empty
pwndbg> x/40gx 0x555555758000
0x555555758000: 0x0000000000000000  0x00000000000000b1			<======Chunk1
0x555555758010: 0x0000000000000000  0x0000000000000000
0x555555758020: 0x0000000000000000  0x0000000000000000
0x555555758030: 0x0000000000000000  0x0000000000000000
0x555555758040: 0x0000000000000000  0x0000000000000000
0x555555758050: 0x0000000000000000  0x0000000000000000
0x555555758060: 0x0000000000000000  0x0000000000000000
0x555555758070: 0x0000000000000000  0x0000000000000000
0x555555758080: 0x0000000000000000  0x0000000000000000
0x555555758090: 0x0000000000000000  0x0000000000000021			<======Chunk2
0x5555557580a0: 0x0000000000000000  0x0000000000000000
0x5555557580b0: 0x0000000000000000  0x0000000000000021			<======Chunk3
0x5555557580c0: 0x0000000000000000  0x0000000000000000
0x5555557580d0: 0x0000000000000000  0x0000000000020f31			<======Top Chunk
0x5555557580e0: 0x0000000000000000  0x0000000000000000
0x5555557580f0: 0x0000000000000000  0x0000000000000000
0x555555758100: 0x0000000000000000  0x0000000000000000
0x555555758110: 0x0000000000000000  0x0000000000000000
0x555555758120: 0x0000000000000000  0x0000000000000000
0x555555758130: 0x0000000000000000  0x0000000000000000

​ 下一步,free掉chunk1:

pwndbg> heap
Free chunk (unsortedbin) | PREV_INUSE
Addr: 0x555555758000
Size: 0xb1
fd: 0x7ffff7dd1b78
bk: 0x7ffff7dd1b78Allocated chunk
Addr: 0x5555557580b0
Size: 0x20Top chunk | PREV_INUSE
Addr: 0x5555557580d0
Size: 0x20f31pwndbg> bin
fastbins
0x20: 0x0
0x30: 0x0
0x40: 0x0
0x50: 0x0
0x60: 0x0
0x70: 0x0
0x80: 0x0
unsortedbin
all: 0x555555758000 —▸ 0x7ffff7dd1b78 (main_arena+88) ◂— 0x555555758000
smallbins
empty
largebins
empty
pwndbg> x/40gx 0x555555758000
0x555555758000: 0x0000000000000000  0x00000000000000b1			<======Chunk1
0x555555758010: 0x00007ffff7dd1b78  0x00007ffff7dd1b78
0x555555758020: 0x0000000000000000  0x0000000000000000
0x555555758030: 0x0000000000000000  0x0000000000000000
0x555555758040: 0x0000000000000000  0x0000000000000000
0x555555758050: 0x0000000000000000  0x0000000000000000
0x555555758060: 0x0000000000000000  0x0000000000000000
0x555555758070: 0x0000000000000000  0x0000000000000000
0x555555758080: 0x0000000000000000  0x0000000000000000
0x555555758090: 0x0000000000000000  0x0000000000000021			<======Chunk2
0x5555557580a0: 0x0000000000000000  0x0000000000000000
0x5555557580b0: 0x00000000000000b0  0x0000000000000020			<======Chunk3
0x5555557580c0: 0x0000000000000000  0x0000000000000000
0x5555557580d0: 0x0000000000000000  0x0000000000020f31			<======Top Chunk
0x5555557580e0: 0x0000000000000000  0x0000000000000000
0x5555557580f0: 0x0000000000000000  0x0000000000000000
0x555555758100: 0x0000000000000000  0x0000000000000000
0x555555758110: 0x0000000000000000  0x0000000000000000
0x555555758120: 0x0000000000000000  0x0000000000000000
0x555555758130: 0x0000000000000000  0x0000000000000000

​ 这里发现了一个点需要注意,就是free掉size域修改了之后的那个chunk1之后,chunk3的size域的最低为,也就是p位,变成了0,这也就说明,chunk1没有放在fastbin里,上面也看到了,被放在了unsortedbin里。

​ 那么为啥会被放入unsortedbin内而不是smallbin呢?估计有一下几种可能:

  • 当一个较大的chunk被分割成两半后,如果剩下的部分大于MINSIZE,就会被放到unsortedbin中。
  • 释放一个不属于fastbin的chunk,并且该chunk不和top chunk紧邻时,该chunk就会被放到unsorted bin 中,当第二次分配的时候,没有在unsortedbin中找到合适的,才会被放入到其对应的bin中。

​ 之后进行分配,分配0xa0大小的堆块,就会发现,原chunk1的地址依旧拿去用了:

pwndbg> heap
Allocated chunk | PREV_INUSE
Addr: 0x555555758000
Size: 0xb1Allocated chunk | PREV_INUSE
Addr: 0x5555557580b0
Size: 0x21Top chunk | PREV_INUSE
Addr: 0x5555557580d0
Size: 0x20f31pwndbg> bin
fastbins
0x20: 0x0
0x30: 0x0
0x40: 0x0
0x50: 0x0
0x60: 0x0
0x70: 0x0
0x80: 0x0
unsortedbin
all: 0x0
smallbins
empty
largebins
empty
pwndbg> x/40gx 0x555555758000
0x555555758000: 0x0000000000000000  0x00000000000000b1
0x555555758010: 0x00007ffff7dd1b78  0x00007ffff7dd1b78
0x555555758020: 0x0000000000000000  0x0000000000000000
0x555555758030: 0x0000000000000000  0x0000000000000000
0x555555758040: 0x0000000000000000  0x0000000000000000
0x555555758050: 0x0000000000000000  0x0000000000000000
0x555555758060: 0x0000000000000000  0x0000000000000000
0x555555758070: 0x0000000000000000  0x0000000000000000
0x555555758080: 0x0000000000000000  0x0000000000000000
0x555555758090: 0x0000000000000000  0x0000000000000021
0x5555557580a0: 0x0000000000000000  0x0000000000000000
0x5555557580b0: 0x00000000000000b0  0x0000000000000021
0x5555557580c0: 0x0000000000000000  0x0000000000000000
0x5555557580d0: 0x0000000000000000  0x0000000000020f31
0x5555557580e0: 0x0000000000000000  0x0000000000000000
0x5555557580f0: 0x0000000000000000  0x0000000000000000
0x555555758100: 0x0000000000000000  0x0000000000000000
0x555555758110: 0x0000000000000000  0x0000000000000000
0x555555758120: 0x0000000000000000  0x0000000000000000
0x555555758130: 0x0000000000000000  0x0000000000000000

3、对free的smallbin进行extend:

//gcc -g 3.c
int main()
{void *ptr,*ptr1;ptr=malloc(0x80);//分配第一个0x80的chunk1malloc(0x10);//分配第二个0x10的chunk2free(ptr);//首先进行释放,使得chunk1进入unsorted bin*(long *)((long)ptr-0x8)=0xb1;ptr1=malloc(0xa0);
}

​ 首先是两次malloc:

pwndbg> heap
Allocated chunk | PREV_INUSE
Addr: 0x555555758000
Size: 0x91Allocated chunk | PREV_INUSE
Addr: 0x555555758090
Size: 0x21Top chunk | PREV_INUSE
Addr: 0x5555557580b0
Size: 0x20f51pwndbg> bins
fastbins
0x20: 0x0
0x30: 0x0
0x40: 0x0
0x50: 0x0
0x60: 0x0
0x70: 0x0
0x80: 0x0
unsortedbin
all: 0x0
smallbins
empty
largebins
empty
pwndbg> x/30gx 0x555555758000
0x555555758000: 0x0000000000000000  0x0000000000000091			<======Chunk1
0x555555758010: 0x0000000000000000  0x0000000000000000
0x555555758020: 0x0000000000000000  0x0000000000000000
0x555555758030: 0x0000000000000000  0x0000000000000000
0x555555758040: 0x0000000000000000  0x0000000000000000
0x555555758050: 0x0000000000000000  0x0000000000000000
0x555555758060: 0x0000000000000000  0x0000000000000000
0x555555758070: 0x0000000000000000  0x0000000000000000
0x555555758080: 0x0000000000000000  0x0000000000000000
0x555555758090: 0x0000000000000000  0x0000000000000021			<======Chunk2
0x5555557580a0: 0x0000000000000000  0x0000000000000000
0x5555557580b0: 0x0000000000000000  0x0000000000020f51			<======Top Chunk
0x5555557580c0: 0x0000000000000000  0x0000000000000000
0x5555557580d0: 0x0000000000000000  0x0000000000000000
0x5555557580e0: 0x0000000000000000  0x0000000000000000

​ 之后直接free掉chunk1:

pwndbg> heap
Free chunk (unsortedbin) | PREV_INUSE
Addr: 0x555555758000
Size: 0x91
fd: 0x7ffff7dd1b78
bk: 0x7ffff7dd1b78Allocated chunk
Addr: 0x555555758090
Size: 0x20Top chunk | PREV_INUSE
Addr: 0x5555557580b0
Size: 0x20f51pwndbg> bin
fastbins
0x20: 0x0
0x30: 0x0
0x40: 0x0
0x50: 0x0
0x60: 0x0
0x70: 0x0
0x80: 0x0
unsortedbin
all: 0x555555758000 —▸ 0x7ffff7dd1b78 (main_arena+88) ◂— 0x555555758000
smallbins
empty
largebins
empty
pwndbg> x/30gx 0x555555758000
0x555555758000: 0x0000000000000000  0x0000000000000091			<======Chunk1
0x555555758010: 0x00007ffff7dd1b78  0x00007ffff7dd1b78
0x555555758020: 0x0000000000000000  0x0000000000000000
0x555555758030: 0x0000000000000000  0x0000000000000000
0x555555758040: 0x0000000000000000  0x0000000000000000
0x555555758050: 0x0000000000000000  0x0000000000000000
0x555555758060: 0x0000000000000000  0x0000000000000000
0x555555758070: 0x0000000000000000  0x0000000000000000
0x555555758080: 0x0000000000000000  0x0000000000000000
0x555555758090: 0x0000000000000090  0x0000000000000020			<======Chunk2
0x5555557580a0: 0x0000000000000000  0x0000000000000000
0x5555557580b0: 0x0000000000000000  0x0000000000020f51			<======Top Chunk
0x5555557580c0: 0x0000000000000000  0x0000000000000000
0x5555557580d0: 0x0000000000000000  0x0000000000000000
0x5555557580e0: 0x0000000000000000  0x0000000000000000

​ 这里还是能看出来存在两个chunk的,当修改了size域大小后:

pwndbg> heap
Free chunk (unsortedbin) | PREV_INUSE
Addr: 0x555555758000
Size: 0xb1
fd: 0x7ffff7dd1b78
bk: 0x7ffff7dd1b78Top chunk | PREV_INUSE
Addr: 0x5555557580b0
Size: 0x20f51pwndbg> bin
fastbins
0x20: 0x0
0x30: 0x0
0x40: 0x0
0x50: 0x0
0x60: 0x0
0x70: 0x0
0x80: 0x0
unsortedbin
all: 0x555555758000 —▸ 0x7ffff7dd1b78 (main_arena+88) ◂— 0x555555758000
smallbins
empty
largebins
empty
pwndbg> x/30gx 0x555555758000
0x555555758000: 0x0000000000000000  0x00000000000000b1
0x555555758010: 0x00007ffff7dd1b78  0x00007ffff7dd1b78
0x555555758020: 0x0000000000000000  0x0000000000000000
0x555555758030: 0x0000000000000000  0x0000000000000000
0x555555758040: 0x0000000000000000  0x0000000000000000
0x555555758050: 0x0000000000000000  0x0000000000000000
0x555555758060: 0x0000000000000000  0x0000000000000000
0x555555758070: 0x0000000000000000  0x0000000000000000
0x555555758080: 0x0000000000000000  0x0000000000000000
0x555555758090: 0x0000000000000090  0x0000000000000020
0x5555557580a0: 0x0000000000000000  0x0000000000000000
0x5555557580b0: 0x0000000000000000  0x0000000000020f51
0x5555557580c0: 0x0000000000000000  0x0000000000000000
0x5555557580d0: 0x0000000000000000  0x0000000000000000
0x5555557580e0: 0x0000000000000000  0x0000000000000000

​ 原本的三个chunk变成了两个,并且chunk2还是allocated状态,重叠之后,chunk1是free状态,所以整个chunk依旧是free状态。之后malloc(0xa0)试试:

pwndbg> heap
Allocated chunk | PREV_INUSE
Addr: 0x555555758000
Size: 0xb1Top chunk | PREV_INUSE
Addr: 0x5555557580b0
Size: 0x20f51pwndbg> bin
fastbins
0x20: 0x0
0x30: 0x0
0x40: 0x0
0x50: 0x0
0x60: 0x0
0x70: 0x0
0x80: 0x0
unsortedbin
all: 0x0
smallbins
empty
largebins
empty
pwndbg> x/30gx 0x555555758000
0x555555758000: 0x0000000000000000  0x00000000000000b1
0x555555758010: 0x00007ffff7dd1b78  0x00007ffff7dd1b78
0x555555758020: 0x0000000000000000  0x0000000000000000
0x555555758030: 0x0000000000000000  0x0000000000000000
0x555555758040: 0x0000000000000000  0x0000000000000000
0x555555758050: 0x0000000000000000  0x0000000000000000
0x555555758060: 0x0000000000000000  0x0000000000000000
0x555555758070: 0x0000000000000000  0x0000000000000000
0x555555758080: 0x0000000000000000  0x0000000000000000
0x555555758090: 0x0000000000000090  0x0000000000000020
0x5555557580a0: 0x0000000000000000  0x0000000000000000
0x5555557580b0: 0x0000000000000000  0x0000000000020f51
0x5555557580c0: 0x0000000000000000  0x0000000000000000
0x5555557580d0: 0x0000000000000000  0x0000000000000000
0x5555557580e0: 0x0000000000000000  0x0000000000000000

4、extend前向overlapping:

//gcc -g 4.c
int main()
{void *ptr,*ptr1;ptr=malloc(0x10);//分配第1个 0x80 的chunk1malloc(0x10); //分配第2个 0x10 的chunk2malloc(0x10); //分配第3个 0x10 的chunk3malloc(0x10); //分配第4个 0x10 的chunk4    *(long *)((long)ptr-0x8)=0x61;free(ptr);ptr1=malloc(0x50);
}

​ 还是老样子,进行4次malloc,看下heap和bin以及chunk的内容:

pwndbg> heap
Allocated chunk | PREV_INUSE
Addr: 0x555555758000
Size: 0x21Allocated chunk | PREV_INUSE
Addr: 0x555555758020
Size: 0x21Allocated chunk | PREV_INUSE
Addr: 0x555555758040
Size: 0x21Allocated chunk | PREV_INUSE
Addr: 0x555555758060
Size: 0x21Top chunk | PREV_INUSE
Addr: 0x555555758080
Size: 0x20f81pwndbg> bin
fastbins
0x20: 0x0
0x30: 0x0
0x40: 0x0
0x50: 0x0
0x60: 0x0
0x70: 0x0
0x80: 0x0
unsortedbin
all: 0x0
smallbins
empty
largebins
empty
pwndbg> x/30gx 0x555555758000
0x555555758000: 0x0000000000000000  0x0000000000000021			<======Chunk1
0x555555758010: 0x0000000000000000  0x0000000000000000
0x555555758020: 0x0000000000000000  0x0000000000000021			<======Chunk2
0x555555758030: 0x0000000000000000  0x0000000000000000
0x555555758040: 0x0000000000000000  0x0000000000000021			<======Chunk3
0x555555758050: 0x0000000000000000  0x0000000000000000
0x555555758060: 0x0000000000000000  0x0000000000000021			<======Chunk4
0x555555758070: 0x0000000000000000  0x0000000000000000
0x555555758080: 0x0000000000000000  0x0000000000020f81			<======Top Chunk
0x555555758090: 0x0000000000000000  0x0000000000000000
0x5555557580a0: 0x0000000000000000  0x0000000000000000
0x5555557580b0: 0x0000000000000000  0x0000000000000000
0x5555557580c0: 0x0000000000000000  0x0000000000000000
0x5555557580d0: 0x0000000000000000  0x0000000000000000
0x5555557580e0: 0x0000000000000000  0x0000000000000000

​ 之后修改size域:

pwndbg> heap
Allocated chunk | PREV_INUSE
Addr: 0x555555758000
Size: 0x61Allocated chunk | PREV_INUSE
Addr: 0x555555758060
Size: 0x21Top chunk | PREV_INUSE
Addr: 0x555555758080
Size: 0x20f81pwndbg> bin
fastbins
0x20: 0x0
0x30: 0x0
0x40: 0x0
0x50: 0x0
0x60: 0x0
0x70: 0x0
0x80: 0x0
unsortedbin
all: 0x0
smallbins
empty
largebins
empty
pwndbg> x/30gx 0x555555758000
0x555555758000: 0x0000000000000000  0x0000000000000061
0x555555758010: 0x0000000000000000  0x0000000000000000
0x555555758020: 0x0000000000000000  0x0000000000000021
0x555555758030: 0x0000000000000000  0x0000000000000000
0x555555758040: 0x0000000000000000  0x0000000000000021
0x555555758050: 0x0000000000000000  0x0000000000000000
0x555555758060: 0x0000000000000000  0x0000000000000021
0x555555758070: 0x0000000000000000  0x0000000000000000
0x555555758080: 0x0000000000000000  0x0000000000020f81
0x555555758090: 0x0000000000000000  0x0000000000000000
0x5555557580a0: 0x0000000000000000  0x0000000000000000
0x5555557580b0: 0x0000000000000000  0x0000000000000000
0x5555557580c0: 0x0000000000000000  0x0000000000000000
0x5555557580d0: 0x0000000000000000  0x0000000000000000
0x5555557580e0: 0x0000000000000000  0x0000000000000000

​ 之后free:

pwndbg> heap
Allocated chunk | PREV_INUSE
Addr: 0x555555758000
Size: 0x61Allocated chunk | PREV_INUSE
Addr: 0x555555758060
Size: 0x21Top chunk | PREV_INUSE
Addr: 0x555555758080
Size: 0x20f81pwndbg> bin
fastbins
0x20: 0x0
0x30: 0x0
0x40: 0x0
0x50: 0x0
0x60: 0x0
0x70: 0x0
0x80: 0x0
unsortedbin
all: 0x0
smallbins
empty
largebins
empty
pwndbg> x/30gx 0x555555758000
0x555555758000: 0x0000000000000000  0x0000000000000061
0x555555758010: 0x0000000000000000  0x0000000000000000
0x555555758020: 0x0000000000000000  0x0000000000000021
0x555555758030: 0x0000000000000000  0x0000000000000000
0x555555758040: 0x0000000000000000  0x0000000000000021
0x555555758050: 0x0000000000000000  0x0000000000000000
0x555555758060: 0x0000000000000000  0x0000000000000021
0x555555758070: 0x0000000000000000  0x0000000000000000
0x555555758080: 0x0000000000000000  0x0000000000020f81
0x555555758090: 0x0000000000000000  0x0000000000000000
0x5555557580a0: 0x0000000000000000  0x0000000000000000
0x5555557580b0: 0x0000000000000000  0x0000000000000000
0x5555557580c0: 0x0000000000000000  0x0000000000000000
0x5555557580d0: 0x0000000000000000  0x0000000000000000
0x5555557580e0: 0x0000000000000000  0x0000000000000000

​ 之后重新malloc:

pwndbg> heap
Allocated chunk | PREV_INUSE
Addr: 0x555555758000
Size: 0x61Allocated chunk | PREV_INUSE
Addr: 0x555555758060
Size: 0x21Top chunk | PREV_INUSE
Addr: 0x555555758080
Size: 0x20f81pwndbg> bin
fastbins
0x20: 0x0
0x30: 0x0
0x40: 0x0
0x50: 0x0
0x60: 0x0
0x70: 0x0
0x80: 0x0
unsortedbin
all: 0x0
smallbins
empty
largebins
empty
pwndbg> x/30gx 0x555555758000
0x555555758000: 0x0000000000000000  0x0000000000000061
0x555555758010: 0x0000000000000000  0x0000000000000000
0x555555758020: 0x0000000000000000  0x0000000000000021
0x555555758030: 0x0000000000000000  0x0000000000000000
0x555555758040: 0x0000000000000000  0x0000000000000021
0x555555758050: 0x0000000000000000  0x0000000000000000
0x555555758060: 0x0000000000000000  0x0000000000000021
0x555555758070: 0x0000000000000000  0x0000000000000000
0x555555758080: 0x0000000000000000  0x0000000000020f81
0x555555758090: 0x0000000000000000  0x0000000000000000
0x5555557580a0: 0x0000000000000000  0x0000000000000000
0x5555557580b0: 0x0000000000000000  0x0000000000000000
0x5555557580c0: 0x0000000000000000  0x0000000000000000
0x5555557580d0: 0x0000000000000000  0x0000000000000000
0x5555557580e0: 0x0000000000000000  0x0000000000000000

5、通过extend前向overlapping:

//gcc -g 5.c
int main(void)
{void *ptr1,*ptr2,*ptr3,*ptr4;ptr1=malloc(128);//smallbin1ptr2=malloc(0x10);//fastbin1ptr3=malloc(0x10);//fastbin2ptr4=malloc(128);//smallbin2malloc(0x10);//防止与top合并free(ptr1);*(int *)((long long)ptr4-0x8)=0x90;//修改pre_inuse域*(int *)((long long)ptr4-0x10)=0xd0;//修改pre_size域free(ptr4);//unlink进行前向extendmalloc(0x150);//占位块
}

​ 经过五次malloc之后:

pwndbg> heap
Allocated chunk | PREV_INUSE
Addr: 0x555555758000
Size: 0x91Allocated chunk | PREV_INUSE
Addr: 0x555555758090
Size: 0x21Allocated chunk | PREV_INUSE
Addr: 0x5555557580b0
Size: 0x21Allocated chunk | PREV_INUSE
Addr: 0x5555557580d0
Size: 0x91Allocated chunk | PREV_INUSE
Addr: 0x555555758160
Size: 0x21Top chunk | PREV_INUSE
Addr: 0x555555758180
Size: 0x20e81pwndbg> bin
fastbins
0x20: 0x0
0x30: 0x0
0x40: 0x0
0x50: 0x0
0x60: 0x0
0x70: 0x0
0x80: 0x0
unsortedbin
all: 0x0
smallbins
empty
largebins
empty
pwndbg> x/54gx 0x555555758000
0x555555758000: 0x0000000000000000  0x0000000000000091
0x555555758010: 0x0000000000000000  0x0000000000000000
0x555555758020: 0x0000000000000000  0x0000000000000000
0x555555758030: 0x0000000000000000  0x0000000000000000
0x555555758040: 0x0000000000000000  0x0000000000000000
0x555555758050: 0x0000000000000000  0x0000000000000000
0x555555758060: 0x0000000000000000  0x0000000000000000
0x555555758070: 0x0000000000000000  0x0000000000000000
0x555555758080: 0x0000000000000000  0x0000000000000000
0x555555758090: 0x0000000000000000  0x0000000000000021
0x5555557580a0: 0x0000000000000000  0x0000000000000000
0x5555557580b0: 0x0000000000000000  0x0000000000000021
0x5555557580c0: 0x0000000000000000  0x0000000000000000
0x5555557580d0: 0x0000000000000000  0x0000000000000091
0x5555557580e0: 0x0000000000000000  0x0000000000000000
0x5555557580f0: 0x0000000000000000  0x0000000000000000
0x555555758100: 0x0000000000000000  0x0000000000000000
0x555555758110: 0x0000000000000000  0x0000000000000000
0x555555758120: 0x0000000000000000  0x0000000000000000
0x555555758130: 0x0000000000000000  0x0000000000000000
0x555555758140: 0x0000000000000000  0x0000000000000000
0x555555758150: 0x0000000000000000  0x0000000000000000
0x555555758160: 0x0000000000000000  0x0000000000000021
0x555555758170: 0x0000000000000000  0x0000000000000000
0x555555758180: 0x0000000000000000  0x0000000000020e81
0x555555758190: 0x0000000000000000  0x0000000000000000
0x5555557581a0: 0x0000000000000000  0x0000000000000000

​ free了chunk1之后,chunk2的p位已经变成0了:

pwndbg> heap
Free chunk (unsortedbin) | PREV_INUSE
Addr: 0x555555758000
Size: 0x91
fd: 0x7ffff7dd1b78
bk: 0x7ffff7dd1b78Allocated chunk
Addr: 0x555555758090
Size: 0x20Allocated chunk | PREV_INUSE
Addr: 0x5555557580b0
Size: 0x21Allocated chunk | PREV_INUSE
Addr: 0x5555557580d0
Size: 0x91Allocated chunk | PREV_INUSE
Addr: 0x555555758160
Size: 0x21Top chunk | PREV_INUSE
Addr: 0x555555758180
Size: 0x20e81pwndbg> bin
fastbins
0x20: 0x0
0x30: 0x0
0x40: 0x0
0x50: 0x0
0x60: 0x0
0x70: 0x0
0x80: 0x0
unsortedbin
all: 0x555555758000 —▸ 0x7ffff7dd1b78 (main_arena+88) ◂— 0x555555758000
smallbins
empty
largebins
empty
pwndbg> x/54gx 0x555555758000
0x555555758000: 0x0000000000000000  0x0000000000000091			<======Chunk1
0x555555758010: 0x00007ffff7dd1b78  0x00007ffff7dd1b78
0x555555758020: 0x0000000000000000  0x0000000000000000
0x555555758030: 0x0000000000000000  0x0000000000000000
0x555555758040: 0x0000000000000000  0x0000000000000000
0x555555758050: 0x0000000000000000  0x0000000000000000
0x555555758060: 0x0000000000000000  0x0000000000000000
0x555555758070: 0x0000000000000000  0x0000000000000000
0x555555758080: 0x0000000000000000  0x0000000000000000
0x555555758090: 0x0000000000000090  0x0000000000000020
0x5555557580a0: 0x0000000000000000  0x0000000000000000
0x5555557580b0: 0x0000000000000000  0x0000000000000021			<======Chunk2
0x5555557580c0: 0x0000000000000000  0x0000000000000000
0x5555557580d0: 0x0000000000000000  0x0000000000000091			<======Chunk3
0x5555557580e0: 0x0000000000000000  0x0000000000000000
0x5555557580f0: 0x0000000000000000  0x0000000000000000
0x555555758100: 0x0000000000000000  0x0000000000000000
0x555555758110: 0x0000000000000000  0x0000000000000000
0x555555758120: 0x0000000000000000  0x0000000000000000
0x555555758130: 0x0000000000000000  0x0000000000000000
0x555555758140: 0x0000000000000000  0x0000000000000000
0x555555758150: 0x0000000000000000  0x0000000000000000
0x555555758160: 0x0000000000000000  0x0000000000000021			<======Chunk4
0x555555758170: 0x0000000000000000  0x0000000000000000
0x555555758180: 0x0000000000000000  0x0000000000020e81			<======Top Chunk
0x555555758190: 0x0000000000000000  0x0000000000000000
0x5555557581a0: 0x0000000000000000  0x0000000000000000

​ 之后修改了chunk3的pre_inuse,也就是size的最低为P位为0,然后修改pre_size位为0xd8,

pwndbg> heap
Free chunk (unsortedbin) | PREV_INUSE
Addr: 0x555555758000
Size: 0x91
fd: 0x7ffff7dd1b78
bk: 0x7ffff7dd1b78Allocated chunk
Addr: 0x555555758090
Size: 0x20Allocated chunk | PREV_INUSE
Addr: 0x5555557580b0
Size: 0x21Allocated chunk
Addr: 0x5555557580d0
Size: 0x90Allocated chunk | PREV_INUSE
Addr: 0x555555758160
Size: 0x21Top chunk | PREV_INUSE
Addr: 0x555555758180
Size: 0x20e81pwndbg> bin
fastbins
0x20: 0x0
0x30: 0x0
0x40: 0x0
0x50: 0x0
0x60: 0x0
0x70: 0x0
0x80: 0x0
unsortedbin
all: 0x555555758000 —▸ 0x7ffff7dd1b78 (main_arena+88) ◂— 0x555555758000
smallbins
empty
largebins
empty
pwndbg> x/54gx 0x555555758000
0x555555758000: 0x0000000000000000  0x0000000000000091			<======Chunk1
0x555555758010: 0x00007ffff7dd1b78  0x00007ffff7dd1b78
0x555555758020: 0x0000000000000000  0x0000000000000000
0x555555758030: 0x0000000000000000  0x0000000000000000
0x555555758040: 0x0000000000000000  0x0000000000000000
0x555555758050: 0x0000000000000000  0x0000000000000000
0x555555758060: 0x0000000000000000  0x0000000000000000
0x555555758070: 0x0000000000000000  0x0000000000000000
0x555555758080: 0x0000000000000000  0x0000000000000000
0x555555758090: 0x0000000000000090  0x0000000000000020
0x5555557580a0: 0x0000000000000000  0x0000000000000000
0x5555557580b0: 0x0000000000000000  0x0000000000000021			<======Chunk2
0x5555557580c0: 0x0000000000000000  0x0000000000000000
0x5555557580d0: 0x00000000000000d0  0x0000000000000090			<======Chunk3
0x5555557580e0: 0x0000000000000000  0x0000000000000000
0x5555557580f0: 0x0000000000000000  0x0000000000000000
0x555555758100: 0x0000000000000000  0x0000000000000000
0x555555758110: 0x0000000000000000  0x0000000000000000
0x555555758120: 0x0000000000000000  0x0000000000000000
0x555555758130: 0x0000000000000000  0x0000000000000000
0x555555758140: 0x0000000000000000  0x0000000000000000
0x555555758150: 0x0000000000000000  0x0000000000000000
0x555555758160: 0x0000000000000000  0x0000000000000021			<======Chunk4
0x555555758170: 0x0000000000000000  0x0000000000000000
0x555555758180: 0x0000000000000000  0x0000000000020e81			<======Top Chunk
0x555555758190: 0x0000000000000000  0x0000000000000000
0x5555557581a0: 0x0000000000000000  0x0000000000000000

​ 可以看出来,chunk3的pre_size域的大小刚好能够包含到完chunk1和chunk2。之后free掉了chunk3:

pwndbg> heap
Free chunk (unsortedbin) | PREV_INUSE
Addr: 0x555555758000
Size: 0x161
fd: 0x7ffff7dd1b78
bk: 0x7ffff7dd1b78Allocated chunk
Addr: 0x555555758160
Size: 0x20Top chunk | PREV_INUSE
Addr: 0x555555758180
Size: 0x20e81pwndbg> bin
fastbins
0x20: 0x0
0x30: 0x0
0x40: 0x0
0x50: 0x0
0x60: 0x0
0x70: 0x0
0x80: 0x0
unsortedbin
all: 0x555555758000 —▸ 0x7ffff7dd1b78 (main_arena+88) ◂— 0x555555758000
smallbins
empty
largebins
empty

会发现,前面的三个chunk都被合并成了一个,这里主要是因为unlink的原因,导致了chunk3和前面的两个(主要是pre_size指定的大小范围内的)chunk发生了合并。之后再进行malloc,会分配走新的那个chunk1:

pwndbg> heap
Allocated chunk | PREV_INUSE
Addr: 0x555555758000
Size: 0x161Allocated chunk | PREV_INUSE
Addr: 0x555555758160
Size: 0x21Top chunk | PREV_INUSE
Addr: 0x555555758180
Size: 0x20e81pwndbg> bin
fastbins
0x20: 0x0
0x30: 0x0
0x40: 0x0
0x50: 0x0
0x60: 0x0
0x70: 0x0
0x80: 0x0
unsortedbin
all: 0x0
smallbins
empty
largebins
empty

相关文章:

pwn学习笔记(12)--Chunk Extend and Overlapping

pwn学习笔记&#xff08;12&#xff09;–Chunk Extend and Overlapping ​ chunk extend 是堆漏洞的一种常见利用手法&#xff0c;通过 extend 可以实现 chunk overlapping&#xff08;块重叠&#xff09; 的效果。这种利用方法需要以下的时机和条件&#xff1a; 程序中存在…...

java基础面试题六集合框架

目录 1. List&#xff0c;Set&#xff0c;Map是否继承自collection接口&#xff1f; 2. 说说List,Set,Map三者的区别 3. 写出list、map、set接口的实现类&#xff0c;并说出其特点 4. 常见集合类的区别和适用场景 5. 集合的父类是谁&#xff1f;哪些安全的&#xff1f; 6…...

2024年12月一区SCI-指数-三角优化算法ETO-附Matlab免费代码

引言 本期介绍了一种基于数学概念的元启发式优化算法&#xff0c;称为指数-三角优化算法Exponential-trigonometric optimization algorithm&#xff0c;ETO。该算法基于指数函数和三角函数的复杂组合&#xff0c;于2024年12月最新发表在中JCR1区、 中科院1区 SCI期刊Computer…...

设置服务器ssh连接超时时间

在Linux服务器上&#xff0c;您可以通过修改SSH服务器配置文件来设置SSH连接的超时时间。以下是设置SSH连接超时时间的一些步骤&#xff1a; 打开SSH服务器配置文件。这个文件通常是/etc/ssh/sshd_config。sudo nano /etc/ssh/sshd_config在配置文件中&#xff0c;您可以设置以…...

Dubbo分布式日志跟踪实现

前言 随着越来越多的应用逐渐微服务化后&#xff0c;分布式服务之间的RPC调用使得异常排查的难度骤增&#xff0c;最明显的一个问题&#xff0c;就是整个调用链路的日志不在一台机器上&#xff0c;往往定位问题就要花费大量时间。如何在一个分布式网络中把单次请求的整个调用日…...

EPSON机械手与第三方相机的校准功能设计By python

EPSON机械手与第三方相机的校准功能设计By python 使用Python来实现EPSON机械手与第三方相机的校准功能是一个复杂但可行的任务。这通常涉及以下几个步骤:硬件接口通信、图像处理、标定算法实现和控制逻辑编写。 1. 环境准备 首先,库 pip install numpy opencv-python pyse…...

探索 Java 23:新时代的编程利器

一、引言 随着技术的不断发展&#xff0c;Java 作为一种广泛应用的编程语言也在不断演进。Java 23 的推出带来了许多令人兴奋的新特性和改进&#xff0c;为开发者提供了更多的工具和功能&#xff0c;以应对日益复杂的软件开发挑战。本文将深入介绍 Java 23 的各个方面。 二、J…...

CSS3_3D变换(七)

1、CSS3_3D变换 1.1 3D空间与景深 3D空间&#xff1a;在父元素中将属性transform-style设置为preserve-3d开启3D空间&#xff0c;默认值为flat&#xff08;开启2D空间&#xff09;&#xff1b; 景深&#xff1a;人眼与平面的距离&#xff0c;产生透视效果&#xff0c;使得效果…...

Mesh网格

Mesh(网格) 定义&#xff1a;Mesh 是一个包含顶点、三角形、顶点法线、UV坐标、颜色和骨骼权重等数据的对象。它定义了3D模型的几何形状。 功能&#xff1a; 顶点&#xff08;Vertices&#xff09;&#xff1a;构成3D模型的点。 三角形&#xff08;Triangles&#xff09;&…...

LeetCode 509.斐波那契数

动态规划思想 五步骤&#xff1a; 1.确定dp[i]含义 2.递推公式 3.初始化 4.遍历顺序 5.打印dp数组 利用状态压缩&#xff0c;简化空间复杂度。在原代码中&#xff0c;dp 数组保存了所有状态&#xff0c;但实际上斐波那契数列的计算只需要前两个状态。因此&#xff0c;我们…...

SQL Server 数据太多如何优化

大家好&#xff0c;我是 V 哥。讲了很多数据库&#xff0c;有小伙伴说&#xff0c;SQL Server 也讲一讲啊&#xff0c;好吧&#xff0c;V 哥做个听话的门童&#xff0c;今天要聊一聊 SQL Server。 在 SQL Server 中&#xff0c;当数据量增大时&#xff0c;数据库的性能可能会受…...

关于word 页眉页脚的一些小问题

去掉页眉底纹&#xff1a; 对文档的段落边框和底纹进行设置&#xff0c;也是页眉横线怎么删除的一种解决方式&#xff0c;具体操作如下&#xff1a; 选中页眉中的横线文本&#xff1b; 点击【开始】选项卡&#xff0c;在【段落】组中点击【边框】按钮的下拉箭头&#xff1b; …...

【高等数学学习记录】连续函数的运算与初等函数的连续性

一、知识点 &#xff08;一&#xff09;连续函数的和、差、积、商的连续性 定理1 设函数 f ( x ) f(x) f(x) 和 g ( x ) g(x) g(x) 在点 x 0 x_0 x0​ 连续&#xff0c;则它们的和&#xff08;差&#xff09; f g f\pm g fg、积 f ⋅ g f\cdot g f⋅g 及商 f g \frac{f…...

【抖音直播间弹幕】protobuf协议分析

将Uint8Array变成 PushFrame格式&#xff0c;里面的payload就存放着弹幕消息 点进去就可以看到其定义的proto结构 headers是一个自定义类型 将测试数据保存一下&#xff0c;等下做对比 先将PushFrame的 payload 内容进行gzip解压 然后再解析为响应 可以看到里面有对应的消…...

Swift 开发教程系列 - 第11章:内存管理和 ARC(Automatic Reference Counting)

在 Swift 中&#xff0c;内存管理由 ARC&#xff08;自动引用计数&#xff09;机制自动处理。ARC 通过追踪和管理对象的引用计数来确保分配的内存得到有效释放。尽管 ARC 在大多数情况下能够高效地管理内存&#xff0c;但理解其工作原理仍然十分重要&#xff0c;因为不当的引用…...

C#中 layout的用法

在C#中&#xff0c;layout并不是一个直接用于C#语言本身的关键字或特性。然而&#xff0c;layout在与C#紧密相关的某些上下文中确实有其用途&#xff0c;特别是在涉及用户界面&#xff08;UI&#xff09;设计和数据展示时。以下是几个常见的与layout相关的用法场景&#xff1a;…...

【编程概念基础知识】

、编程基础 一、面向对象的三大特性 1、封装&#xff1a; 盒子、零件、按钮 隐藏对象 的内部状态&#xff0c;并且只通过对象的方法来访问数据 想象你有一个小盒子&#xff08;这个盒子就是一个类&#xff09;&#xff0c;里面装着一些零件&#xff08;这些零件就是数据&a…...

【React】深入理解 JSX语法

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 深入理解 JSX语法1. JSX 简介2. JSX 的基本语法2.1 基本结构2.2 与普通 JavaScr…...

【Linux】从零开始使用多路转接IO --- 理解EPOLL的 LT水平触发模式 与 ET边缘触发模式

当你偶尔发现语言变得无力时&#xff0c; 不妨安静下来&#xff0c; 让沉默替你发声。 --- 里则林 --- 从零开始认识多路转接 1 EPOLL优缺点2 EPOLL工作模式 1 EPOLL优缺点 poll 的优点(和 select 的缺点对应) 接口使用方便&#xff1a;虽然拆分成了三个函数&#xff0c;…...

QtLua

描述 QtLua 库旨在使用 Lua 脚本语言使 Qt4/Qt5 应用程序可编写脚本。它是 QtScript 模块的替代品。 QtLua 不会为 Qt 生成或使用生成的绑定代码。相反&#xff0c;它提供了有用的 C 包装器类&#xff0c;使 C 和 lua 对象都可以从 lua 和 C 访问。它利用 Qt 元对象系统将 QOb…...

基于算法竞赛的c++编程(28)结构体的进阶应用

结构体的嵌套与复杂数据组织 在C中&#xff0c;结构体可以嵌套使用&#xff0c;形成更复杂的数据结构。例如&#xff0c;可以通过嵌套结构体描述多层级数据关系&#xff1a; struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

业务系统对接大模型的基础方案:架构设计与关键步骤

业务系统对接大模型&#xff1a;架构设计与关键步骤 在当今数字化转型的浪潮中&#xff0c;大语言模型&#xff08;LLM&#xff09;已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中&#xff0c;不仅可以优化用户体验&#xff0c;还能为业务决策提供…...

Xshell远程连接Kali(默认 | 私钥)Note版

前言:xshell远程连接&#xff0c;私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

Rust 异步编程

Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...

Java多线程实现之Thread类深度解析

Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...

Angular微前端架构:Module Federation + ngx-build-plus (Webpack)

以下是一个完整的 Angular 微前端示例&#xff0c;其中使用的是 Module Federation 和 npx-build-plus 实现了主应用&#xff08;Shell&#xff09;与子应用&#xff08;Remote&#xff09;的集成。 &#x1f6e0;️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...

C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...

上位机开发过程中的设计模式体会(1):工厂方法模式、单例模式和生成器模式

简介 在我的 QT/C 开发工作中&#xff0c;合理运用设计模式极大地提高了代码的可维护性和可扩展性。本文将分享我在实际项目中应用的三种创造型模式&#xff1a;工厂方法模式、单例模式和生成器模式。 1. 工厂模式 (Factory Pattern) 应用场景 在我的 QT 项目中曾经有一个需…...

使用SSE解决获取状态不一致问题

使用SSE解决获取状态不一致问题 1. 问题描述2. SSE介绍2.1 SSE 的工作原理2.2 SSE 的事件格式规范2.3 SSE与其他技术对比2.4 SSE 的优缺点 3. 实战代码 1. 问题描述 目前做的一个功能是上传多个文件&#xff0c;这个上传文件是整体功能的一部分&#xff0c;文件在上传的过程中…...

FOPLP vs CoWoS

以下是 FOPLP&#xff08;Fan-out panel-level packaging 扇出型面板级封装&#xff09;与 CoWoS&#xff08;Chip on Wafer on Substrate&#xff09;两种先进封装技术的详细对比分析&#xff0c;涵盖技术原理、性能、成本、应用场景及市场趋势等维度&#xff1a; 一、技术原…...