CTF Pwn堆内存利用入门:从glibc malloc原理到UAF实战
1. 项目概述为什么Pwn选手必须啃下堆内存这块硬骨头如果你刚接触CTF Pwn可能还在跟栈溢出、格式化字符串这些“老朋友”打交道。但当你开始挑战一些中等难度的题目尤其是那些来自现实世界软件如浏览器、服务器软件漏洞改编的题目时一个绕不开的“大魔王”就会出现在你面前——堆内存利用。很多新手看到堆利用就头疼感觉它比栈溢出复杂十倍各种链表、chunk、bins、malloc、free的机制让人眼花缭乱。这种感觉我懂当初我也是一头雾水。但我想告诉你堆利用是Pwn从“玩具题”迈向“真实漏洞”的关键一步也是衡量一个Pwn选手水平的重要分水岭。为什么堆这么重要因为现代软件尤其是那些大型、长期运行的服务几乎都重度依赖堆来动态管理内存。栈空间有限且生命周期固定而堆提供了运行时按需分配、释放内存的灵活性。因此堆上的漏洞如Use-After-Free, Double Free, Heap Overflow是现实世界中高危漏洞的“重灾区”。CTF中的堆题目正是这些真实漏洞的缩影和简化。理解Linux的堆内存管理机制主要是glibc的ptmalloc2分配器就像拿到了一张堆世界的“地图”。没有这张地图你就是在黑暗中乱撞有了它你就能理解每一块内存chunk的“前世今生”预测分配器的行为进而精心构造数据去“欺骗”分配器实现任意地址读写或代码执行。本次我们不搞虚的就从一个最简单的“Hello World”级别的堆程序开始用GDB这把“手术刀”一步步解剖malloc和free背后到底发生了什么。我们的目标不是背下一堆晦涩的术语而是建立直观的“内存画面感”。当你再看到malloc(0x20)时脑海里能立刻浮现出它在内存中实际占用了多少字节、它的前后有什么特殊结构、free之后它去了哪里。这种画面感是后续学习各种高级堆利用技巧如unlink, tcache poisoning, house of系列的基石。我会假设你已有基本的Linux命令行和C语言基础并且初步了解GDB的break,run,print这些命令。准备好了吗让我们开始这次堆内存的探索之旅。2. 实验环境搭建与目标程序分析工欲善其事必先利其器。为了获得稳定的实验环境和清晰的视图我们需要做一些准备工作。我强烈建议你不要在自己的主力机上折腾而是使用虚拟机。Ubuntu 20.04 LTS或22.04 LTS都是不错的选择它们搭载的glibc版本2.31/2.35涵盖了近年来CTF比赛的主流环境。如果你喜欢更轻量级或定制的环境Arch Linux或Debian也可以。关键是要知道你自己用的glibc版本因为不同版本的堆管理策略尤其是tcache机制有差异。在终端输入ldd --version即可查看。接下来是编译工具。我们需要gcc和gdb。确保你的gdb是带了pwndbg或gef插件的它们能极大提升堆调试体验比如用heap命令直观查看堆布局。以pwndbg为例安装后在gdb里输入heap就能看到所有已分配的chunk比肉眼解析内存地址友好太多了。如果你还没装花十分钟按照其GitHub主页的说明安装这十分钟的投资在后续会为你节省数小时。现在我们来创建本次实验的“小白鼠”——一个超级简单的C程序。打开编辑器创建一个名为heap_basic.c的文件#include stdio.h #include stdlib.h #include unistd.h int main() { // 1. 分配第一个chunk char *chunk1 (char *)malloc(24); printf(chunk1 地址: %p\n, chunk1); if(chunk1) { sprintf(chunk1, 这是第一个chunk的数据); printf(chunk1 内容: %s\n, chunk1); } // 2. 分配第二个chunk char *chunk2 (char *)malloc(32); printf(chunk2 地址: %p\n, chunk2); if(chunk2) { sprintf(chunk2, 这是第二个chunk的数据更长一点); printf(chunk2 内容: %s\n, chunk2); } // 3. 释放第一个chunk printf(释放 chunk1\n); free(chunk1); chunk1 NULL; // 良好习惯释放后置空防止UAF // 4. 再分配一个同样大小的chunk char *chunk3 (char *)malloc(24); printf(chunk3 地址: %p\n, chunk3); if(chunk3) { // 猜猜chunk3的内容是什么 printf(chunk3 内容未初始化: %s\n, chunk3); sprintf(chunk3, 这是第三个chunk的新数据); printf(chunk3 新内容: %s\n, chunk3); } // 5. 释放剩余chunk free(chunk2); free(chunk3); printf(程序结束所有内存已理论上释放。\n); // 注意这里为了观察内存我们不让程序立刻退出方便调试 pause(); // 程序在此暂停等待信号 return 0; }注意程序末尾的pause()函数是为了让程序挂起保持内存状态不变方便我们仔细用GDB检查堆布局。在实际CTF题目中不会这样但对我们学习至关重要。编译这个程序时我们需要关闭一些现代编译器的保护机制让我们能专注于堆本身。使用如下命令gcc -g -no-pie -fno-stack-protector -z execstack heap_basic.c -o heap_basic-g加入调试信息这样GDB里可以看到变量名和行号。-no-pie关闭位置无关可执行文件让每次运行的地址固定便于观察。-fno-stack-protector关闭栈保护虽然我们这次不搞栈但保持环境干净。-z execstack让栈可执行同样是为了简化环境。现在运行./heap_basic你会看到程序打印一些地址后停住了。别担心这是正常的它正在执行pause()。我们打开另一个终端用GDB来附着attach到这个进程上。3. 堆内存管理的核心chunk结构与基础操作在深入GDB之前我们必须先建立核心概念在ptmalloc2管理的内存世界里基本单位不是字节而是chunk。无论你调用malloc申请多少字节分配器都会给你一个“包装好”的chunk。这个chunk的尺寸比你申请的要大因为它包含了管理自身所必需的元数据。一个chunk在内存中的结构可以简单分为两部分chunk头和用户数据区。你通过malloc拿到的指针指向的是用户数据区的起始地址。而chunk头就在这个指针的前面更低地址处。对于正在使用中的chunkallocated chunk其chunk头主要包含一个字段前一个chunk的大小。等等为什么是“前一个”chunk的大小这是因为堆内存是一个连续的地址空间分配器需要知道每个chunk的边界在哪里。通过当前chunk的地址减去它头里存储的“前一个chunk的大小”就能找到前一个chunk的起始位置。这个设计是为了方便chunk的合并。那么当前chunk自己的大小存在哪里呢它存在于用户数据区末尾、下一个chunk头开始之前的一个位置吗并不是。这里有一个巧妙或者说令人困惑的设计当前chunk的大小存储在下一個chunk的chunk头里。更准确地说每个chunk头里存储的“size”字段既是“前一个chunk的大小”同时也被当前chunk用来判断“前一个chunk是否正在被使用”。这是通过size字段的最低三个比特位作为标志位来实现的。其中最关键的两位是PREV_INUSE (P): 位0。如果为1表示前一个chunk正在被使用allocated如果为0表示前一个chunk是空闲的freed。记住这个标志位是关于前一个chunk的IS_MMAPPED (M): 位1。如果为1表示这个chunk是通过mmap直接分配的对于非常大的请求不纳入普通的堆链表管理。NON_MAIN_ARENA (N): 位2。表示这个chunk是否不属于主分配区涉及多线程。对于空闲chunkfreed chunk它的结构更复杂一些。因为空闲下来了分配器需要用它来组织链表bins。所以在用户数据区的位置它会额外存储两个指针fdforward pointer指向链表中下一个空闲chunk和bkbackward pointer指向链表中上一个空闲chunk。这就是著名的fd/bk指针很多堆利用技巧都围绕着篡改它们展开。让我们用GDB来验证一下。在另一个终端找到我们暂停的heap_basic进程的PID可以用ps aux | grep heap_basic然后启动gdb并附着gdb -p PID或者更简单的方式是直接调试gdb ./heap_basic然后在gdb内run程序会运行并在pause()处停下。在gdb中首先查看我们分配的指针pwndbg p chunk1 $1 0x5555555592a0 pwndbg p chunk2 $2 0x5555555592c0 这是第二个chunk的数据更长一点 pwndbg p chunk3 $3 0x5555555592a0 这是第三个chunk的新数据一个非常有趣的现象出现了chunk1和chunk3的地址一模一样这就是我们程序设计的“陷阱”我们free了chunk1然后又malloc了一个同样大小的chunk3。分配器把刚刚释放的、正好大小合适的chunk1的内存又分配给了chunk3。这引出了堆利用中一个至关重要的概念Use-After-Free (UAF)的潜在可能性。如果我们在free(chunk1)后没有将其指针置为NULL并且错误地继续使用了chunk1那么实际上我们操作的就是chunk3的内存这会导致数据混乱或更严重的安全问题。我们程序中chunk1 NULL;这行代码就是一个良好的防御性编程习惯。现在让我们窥探chunk头的秘密。既然chunk1也就是现在的chunk3的地址是0x5555555592a0那么它的chunk头应该在它前面8字节64位系统下。在gdb中查看内存pwndbg x/4gx 0x5555555592a0 - 0x10 0x555555559290: 0x0000000000000000 0x0000000000000031 0x5555555592a0: 0x20756f7920b8aea4 0x000000000a617473x/4gx表示以16进制格式x查看4个巨型字g8字节。我们看到0x555555559290地址处即chunk3指针-0x10有两个8字节的值0x0和0x31。第一个0x0这是“前一个chunk的大小”。因为这是堆上第一个chunk更准确地说是第一个由用户malloc申请的chunk前面还有堆的起始块所以前一个chunk大小为0。第二个0x31这就是当前chunk即chunk3所在chunk的大小。注意0x31是十六进制十进制是49。我们申请了24字节为什么是49首先chunk大小必须是2*SIZE_SZ的整数倍64位下SIZE_SZ是8即16字节对齐。24字节对齐到16的倍数是32字节。但这32字节只是用户数据区吗不还要加上chunk头的大小8字节的prev_size和8字节的size共16字节。所以总chunk大小是321648字节。0x31的十六进制是49对不上48别急size字段存储的值其最低三位被用作标志位。0x31的二进制是0011 0001最低三位是001。这意味着位0(P)1前一个chunk即0x0大小的那个“虚拟”前chunk被标记为“正在使用”。这符合预期。位1(M)0这个chunk不是mmap分配的。位2(N)0这个chunk属于主分配区。 所以实际的大小是0x31 ~0x7 0x30也就是48字节。完美匹配我们的计算。实操心得在调试时看到size字段像0x31、0x41这样末尾是1、3、5、7、9、b、d、f的奇怪数字不要慌。先把它和~0x7即0xfffffffffffffff8做按位与操作得到的就是真正的对齐后chunk大小。pwndbg的heap命令会自动帮你解析并显示这个信息。4. 深入GDB实战追踪malloc与free的全过程理解了静态结构我们来看动态过程。让我们重新开始在关键步骤设置断点一步步观察堆的变化。退出当前gdb或开一个新终端重新编译并带参数启动gdbgdb ./heap_basic在gdb中设置断点(gdb) break 8 # 在第一个malloc之后 (gdb) break 12 # 在第二个malloc之后 (gdb) break 17 # 在free(chunk1)之后 (gdb) break 21 # 在第三个malloc之后 (gdb) run程序会在第8行第一个malloc之后停下。此时我们使用pwndbg的魔法命令pwndbg heap输出会显示当前堆的整体情况。你可能会看到类似这样的结构Allocated chunk | PREV_INUSE | Size: 0x31 Addr: 0x555555559290 ...这验证了我们刚才的分析。记下这个chunk的地址比如0x555555559290。然后我们continue到第二个断点第二个malloc之后。再次heap你会看到两个已分配的chunk。注意看第二个chunk的地址。它应该紧接着第一个chunk。计算一下第一个chunk从0x555555559290开始大小0x30所以它的用户数据区结束于0x5555555592c00x555555559290 0x30。而第二个chunk的起始地址很可能就是0x5555555592c0。这就是堆内存的连续性。分配器会从一个叫做“top chunk”的大块内存中切割出你需要的大小。现在执行continue到第三个断点即free(chunk1)之后。这是最精彩的部分。再次heap观察变化。你可能会看到第一个chunk的状态变成了“Free chunk (tcache)”或者“Free chunk (fastbin)”。这取决于你glibc的版本和chunk的大小。对于小chunk通常小于0x410字节free操作会优先将其放入tcache线程本地缓存或fastbins快速链表。这是两种管理空闲小chunk的单向链表。tcache (per-thread cache): glibc 2.26引入每个线程有一个tcache用于加速小内存分配。它比fastbin优先级更高。tcache是一个数组每个元素是一个单链表存放相同大小的chunk。大小范围一般是0x20到0x410字节可能因版本而异。我们的chunk大小是0x30正好在tcache范围内。fastbins: 更早的机制也是一个单链表数组但管理的内存大小范围更小比如0x20到0x80并且chunk的P位标志前一个chunk在使用始终保持为1这是为了防止合并保持快速分配。用heap bins命令可以查看所有bins的情况pwndbg heap bins你应该能看到tcachebins或fastbins里有一个大小为0x30的chunk它的地址正是我们之前free掉的chunk1的地址。此时这个空闲chunk的用户数据区原本存着我们写的字符串的地方已经被fd指针覆盖指向链表中的下一个空闲chunk目前是NULL。这就是UAF漏洞的根源如果这个指针被攻击者控制就能引导分配器将内存分配到任意地址。最后continue到第四个断点即第三个malloc(24)之后。再次heap和heap bins。你会发现tcachebins或fastbins里那个大小为0x30的空闲chunk消失了而新分配的chunk3的地址正是之前chunk1的地址。分配器从对应的空闲链表中直接取出了第一个可用的chunk重新分配给了我们。这就是为什么chunk3一开始打印会有残留数据我们之前写的“这是第一个chunk的数据”因为分配器并不会清空原有数据这导致了信息泄露。在我们的程序中我们立刻写入了新数据覆盖了它但在漏洞利用中我们可以先分配、再释放、再分配然后读取之前残留的指针数据这可能泄露堆地址或libc地址是攻击的重要一步。5. 从理论到攻击理解Double Free与tcache poisoning通过上面的实验我们看到了free和malloc的基本行为。现在让我们把这些知识串联起来理解两个基础的堆利用原语Double Free和tcache poisoning。这两个是现代CTF堆题目的“常客”。Double Free顾名思义就是同一个指针被free了两次。根据标准这是未定义行为但ptmalloc2的实现中如果不对其进行检测就会导致严重问题。想象一下你把同一个chunk放进了空闲链表两次。那么当你两次申请这个大小的内存时你可能会拿到同一个地址更糟糕的是链表的结构被破坏了。在早期没有tcache的版本中double free可能会触发unlink操作导致任意地址写。在tcache中由于它是单链表double free会形成一个循环链表。攻击者可以通过精心构造在后续的malloc中让分配器返回一个指向任意地址的“chunk”从而实现任意地址读写。我们来模拟一个简单的、不严谨的double free场景注意在实际漏洞利用中需要绕过一些检查比如tcache的key机制void *a malloc(0x20); void *b malloc(0x20); free(a); free(a); // Double Free! // 此时tcache的0x30链表中a出现了两次。 void *c malloc(0x20); // 第一次取拿到a void *d malloc(0x20); // 第二次取还是拿到a现在c和d指向同一块内存。 // 通过c和d我们可以修改这块内存的fd指针...注意现代glibc对tcache的double free有简单的检测每个chunk有一个key指针指向tcache结构直接连续free同一个指针可能会触发崩溃。实际的利用需要先free一个其他chunk隔开或者利用其他漏洞修改key值来绕过。这里只是为了说明概念。tcache poisoning是double free的一个直接利用。目标是控制tcache链表中某个空闲chunk的fd指针。因为tcache分配时只是简单地从链表头部取出第一个chunk。如果我们能修改这个fd让它指向一个我们想要的位置比如__free_hook或malloc_hook的地址那么下次分配相应大小的内存时分配器就会把那个位置当作一个chunk返回给我们。我们在那个位置伪造好chunk头主要是size字段要匹配就能向那个地址写入数据从而劫持控制流。如何修改fd指针这就需要另一个漏洞比如堆溢出Heap Overflow。假设我们有两个相邻的chunkA和B。我们先free(B)让它进入tcache。然后我们利用A的堆溢出漏洞覆盖B的fd指针因为B是空闲的它的用户数据区开头就是fd。这样我们就“毒化”了tcache链表。下次分配B的大小时分配器会先返回B再返回我们伪造的地址。6. 实战调试构造一个简单的堆溢出场景理论说再多不如动手试一下。我们修改一下之前的程序模拟一个最简单的堆溢出并观察内存变化。创建一个新文件heap_overflow.c#include stdio.h #include stdlib.h #include string.h #include unistd.h int main() { // 分配两个相邻的chunk char *buffer1 (char *)malloc(16); char *buffer2 (char *)malloc(16); printf(buffer1 %p\n, buffer1); printf(buffer2 %p\n, buffer2); // 在buffer1中写入数据故意越界写入buffer2的chunk头 // 计算从buffer1到buffer2 chunk头size字段的偏移 // buffer1的用户区起始地址是 p1 // buffer2的chunk头size字段地址是 p2 - 0x8 // 偏移 (p2 - 0x8) - p1 // 我们先填充buffer1的16字节然后继续写就会溢出到buffer2的元数据区 memset(buffer1, A, 32); // 写入32个A远超buffer1的16字节容量 printf(After overflow:\n); // 查看buffer2 chunk头部的值 size_t *size_ptr (size_t *)(buffer2 - 8); printf(buffer2 size field (at %p): 0x%lx\n, size_ptr, *size_ptr); // 此时buffer2的size字段已经被覆盖为0x4141414141414141 (AAAAAAA) // 如果我们现在尝试free buffer2会发生什么 // free(buffer2); // 取消注释这行会导致崩溃因为size字段异常 pause(); return 0; }编译并运行用gdb附着。在memset之后设置断点查看buffer2地址之前的内存pwndbg x/8gx buffer2 - 0x10你应该会看到一片0x4141414141414141。这证明了我们的溢出成功覆盖了buffer2的chunk头。size字段被篡改其最低位的标志位P位也被覆盖了。如果此时free(buffer2)分配器会尝试根据这个被破坏的size去寻找下一个chunk并进行合并等操作几乎必然导致程序崩溃segmentation fault。但在精心构造的情况下攻击者可以控制size字段使其指向一个伪造的、更大的chunk从而进行后续的利用比如overlapping chunks堆块重叠即让两个分配出去的chunk在内存上重叠从而通过一个chunk修改另一个chunk的数据。7. 进阶之路从入门到精通的资源与心态走完上面的流程你应该对堆内存的基本管理、chunk结构、malloc/free的流程以及简单的溢出和double free概念有了直观的认识。但这仅仅是堆利用世界的冰山一角。要成为真正的Pwn手你需要沿着以下路径继续深入1. 系统学习glibc malloc源码与机制核心数据结构深入理解malloc_state(arena),malloc_chunk以及binsfastbins, smallbins, largebins, unsorted_bin的组织方式。特别是unsorted_bin它是大小不一空闲chunk的暂存地很多高级技巧都围绕它展开。关键操作流程仔细阅读_int_malloc和_int_free的源码。理解分配和释放时分配器如何查找合适的chunk、如何分割chunk、如何将chunk插入和取出bins、如何进行前后chunk的合并。这能让你预测分配器的行为。安全机制与绕过了解glibc引入的各种保护机制如tcache_key(防止double free)、unlink时的完整性检查、size与prev_size的校验等。学习经典的绕过方法如poison null byte、house of系列技巧。2. 刻意练习与题目复盘从易到难刷题在pwn.college,CTFtime的过往赛事题目或how2heap仓库中找题目练习。how2heap是学习堆利用的宝库它提供了大量不同glibc版本下的利用技巧示例代码。不要只看要自己编译、调试、理解每一行。调试与画图遇到复杂题目一定要用GDB配合pwndbg/gef并动手在纸上画图。画出堆的布局、chunk的状态、bins的链表结构。这能极大帮助你理清思路。编写利用脚本使用pwntools库编写自动化利用脚本exploit。从计算偏移、泄露地址到构造payload、发送交互完整走通整个流程。失败是常态分析为什么失败是偏移算错是检查没绕过比成功一次更重要。3. 建立知识体系与思维模型漏洞模型化将各种堆漏洞UAF, Double Free, Heap Overflow, Off-by-One抽象成对堆元数据size,fd,bk,prev_size的特定篡改操作。利用目标链条化明确你的利用链每一步要达成什么目标如泄露libc地址、劫持__free_hook、构造ROP chain并知道如何通过堆操作去实现。适应版本变化关注glibc的更新了解新版本引入了哪些新机制如tcache或加固了哪些检查。CTF题目往往会使用特定版本的glibc你需要能快速适应。最后分享一点个人体会。堆利用的学习曲线确实陡峭初期充满了挫败感。我至今记得第一次独立解出一道堆题目时那种“山重水复疑无路柳暗花明又一村”的兴奋。关键在于保持耐心和好奇心。不要试图一天吃成胖子每天搞懂一个概念、一个机制、一道小题目的一个环节积少成多。多和社区交流多看别人的writeup解题报告但一定要自己动手复现。当你能够不依赖writeup独立分析并利用一个陌生的堆漏洞时你就真正入门了。这条路没有捷径但每一步都算数。拿起GDB从下一个malloc开始吧。

相关新闻

Ex ec 增安型防爆连接器完整适用范围(GB/T3836.3-2021)

Ex ec 增安型防爆连接器完整适用范围(GB/T3836.3-2021)

一、核心防爆定义与允许危险区域1. 分区硬性限制(最重要)• 仅适用于:爆炸性气体 2区(Zone 2)• 严禁用于:0区、1区气体环境;所有粉尘20/21/22区不可混用• EPL等级:Gc(设…

2026/8/8 3:17:16 阅读更多 →
Unity工业场景高效搭建:模块化资产、PBR材质与性能优化全攻略

Unity工业场景高效搭建:模块化资产、PBR材质与性能优化全攻略

1. 项目概述:HQ Industrial Mega Kit 是什么?如果你正在为Unity项目构建一个工业风格的场景——无论是废弃的工厂、繁忙的港口、科幻的太空站内部,还是一个需要大量机械细节的关卡——那么你肯定经历过那种“从零开始”的痛苦。建模、贴图、打…

2026/8/11 3:41:37 阅读更多 →
国内诚信的HARTING连接器采购平台哪个好

国内诚信的HARTING连接器采购平台哪个好

HARTING连接器作为工业自动化、轨道交通、通信等领域的核心信号传输辅件,其品质直接决定设备的稳定性与使用寿命。但当前市场渠道鱼龙混杂,正品难辨、交期滞后、技术支持缺失等痛点,让企业采购面临诸多隐性风险。本文结合行业需求与实际案例&…

2026/8/11 10:00:52 阅读更多 →

最新新闻

Ubuntu系统安装配置OpenJDK 8:从环境变量到多版本管理的完整指南

Ubuntu系统安装配置OpenJDK 8:从环境变量到多版本管理的完整指南

1. 从一次部署失败说起:为什么系统默认Java版本如此重要?上周,我正准备在一台新装的Ubuntu 22.04服务器上部署一个老项目。项目依赖明确要求Java 8,我心想这还不简单,apt install openjdk-8-jdk一条命令的事。安装过程…

2026/8/13 9:05:59 阅读更多 →
游戏角色AI生成:原型体1006本地部署与测试全攻略

游戏角色AI生成:原型体1006本地部署与测试全攻略

这次我们来看一个游戏原型体1006的本地部署与测试项目。如果你关注游戏角色建模、本地AI生成、显存占用和批量任务处理,这篇文章可以直接收藏。项目核心是围绕“波比的游戏时间”第五章中的原型体1006角色,提供一套可本地运行的模型或工具,用…

2026/8/13 9:05:59 阅读更多 →
AI时代下.env文件安全实践:分层策略与密钥管理新思路

AI时代下.env文件安全实践:分层策略与密钥管理新思路

1. 一个被忽视的安全隐患:.env 文件为何不再“安全” 最近在重构一个老项目,准备把它部署到云端容器里。像往常一样,我把数据库连接字符串、API密钥这些敏感信息一股脑塞进了 .env 文件,然后习惯性地在 .gitignore 里加上了它…

2026/8/13 9:05:59 阅读更多 →
从打开应用到表达业务意图,Joule Work 正在重写 SAP 的企业交互层

从打开应用到表达业务意图,Joule Work 正在重写 SAP 的企业交互层

2026 年第二季度,SAP 在 Business AI 产品发布中把 Joule Work 推到了一个很特殊的位置。它已经不是传统意义上嵌在某个 SAP 应用右上角的聊天窗口,也不只是一个能回答业务问题的 Copilot。SAP 对 Joule Work 的定位正在变成整个 Joule 体系面向业务人员的用户交互层,也就是…

2026/8/13 9:05:59 阅读更多 →
目标检测违停检测 道路车辆检测与分析 可检测识别 违停车辆数据集 车辆检测

目标检测违停检测 道路车辆检测与分析 可检测识别 违停车辆数据集 车辆检测

深度学习目标检测算法及框架使用 YOLOv5 模型进行目标检测违停检测,道路车辆检测与分析 可检测识别违停车辆数据集及车辆检测 以下文字及代码仅供参考。 文章目录深度学习目标检测算法及框架使用 YOLOv5 模型进行目标检测违停检测,道路车辆检测与分析 可…

2026/8/13 9:05:59 阅读更多 →
新手小白学习计算机的第八天(老王专场)

新手小白学习计算机的第八天(老王专场)

循环编程练习 本文章记录了老王今日关于循环编程的练习 #define _CRT_SECURE_NO_WARNINGS //#include<stdio.h> //int main() //{ // //int v 0; // double v 0; // for (v 36; v > 0; v / 2.0) // printf("%3d", v); // //printf("%.0f"…

2026/8/13 9:04:59 阅读更多 →

日新闻

Visual Studio新建项目解决方案为空:系统性排查与修复指南

Visual Studio新建项目解决方案为空:系统性排查与修复指南

1. 问题现象与本质剖析如果你是一位.NET开发者&#xff0c;或者正准备踏入这个领域&#xff0c;那么Visual Studio&#xff08;后面简称VS&#xff09;绝对是你绕不开的伙伴。但有时候&#xff0c;这个伙伴会跟你开一个不大不小的玩笑&#xff1a;你满怀期待地点击“创建新项目…

2026/8/13 0:00:09 阅读更多 →
长春建设厅网站:普通人买房办事必看的真实指南与避坑攻略

长春建设厅网站:普通人买房办事必看的真实指南与避坑攻略

说实话,每次提起“长春建设厅网站”这几个字,我心里都挺有感触的。不是因为它有多高大上,也不是因为那里藏着什么不可告人的秘密,恰恰相反,是因为它太“接地气”了,或者说,它是咱们普通人想要在这个城市好好生活、安稳买房时,必须得翻过的一座“数据山”。很多新朋友第…

2026/8/13 0:00:09 阅读更多 →
Windows家庭版远程桌面多用户破解完整指南:RDPWrap终极解决方案

Windows家庭版远程桌面多用户破解完整指南:RDPWrap终极解决方案

Windows家庭版远程桌面多用户破解完整指南&#xff1a;RDPWrap终极解决方案 【免费下载链接】rdpwrap.ini RDPWrap.ini for RDP Wrapper Library by StasM 项目地址: https://gitcode.com/GitHub_Trending/rd/rdpwrap.ini 你是否曾为Windows家庭版无法支持多用户远程桌面…

2026/8/13 0:00:09 阅读更多 →

周新闻

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑&#xff1a;baidupankey如何智能破解百度网盘资源锁 【免费下载链接】baidupankey 在线查询网盘提取码&#xff08;维护中 rm repo&#xff09; 项目地址: https://gitcode.com/gh_mirrors/ba/baidupankey 你是否曾经在深夜寻找一份重要资料&#x…

2026/8/13 2:38:34 阅读更多 →
如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片&#xff1a;Python开源工具完整指南 【免费下载链接】chinese_license_plate_generator 中国车牌生成器 项目地址: https://gitcode.com/gh_mirrors/ch/chinese_license_plate_generator 中国车牌生成器是一个基于Python的开源项目&#xff0c…

2026/8/12 1:11:09 阅读更多 →
收藏!小白程序员轻松入门大模型,从Harness工程开始实践

收藏!小白程序员轻松入门大模型,从Harness工程开始实践

文章强调学习大模型不应只关注模型本身&#xff0c;而应重视模型外的系统搭建&#xff0c;即Harness。提出AgentModelHarness的实用公式&#xff0c;详细介绍Harness的四个层次&#xff1a;持久化层、执行层、控制层和观察与验证层。文章还探讨了上下文工程、工具设计、AGENTS.…

2026/8/12 1:11:08 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速&#xff1a;macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/11 17:09:45 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南&#xff1a;3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗&#xff1f;ncmdump解密工具帮你轻松解决这个困…

2026/8/12 1:11:10 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片&#xff1a;为英语学习 App 打造桌面级学习助手适用平台&#xff1a;HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0&#xff08;API 26 Beta&#xff09;新增了 AgentCard 智能体卡片能力&#xff0c;这是继 HMAF&#xff08;鸿蒙智能体框架&#x…

2026/8/11 17:09:45 阅读更多 →