Linux x86平台获取sys_call_table

文章目录

  • 前言
  • 一、根据call *sys_call_table来获取
  • 二、使用dump_stack
  • 三、根据MSR_LSTAR寄存器
  • 四、使用sys_close
  • 参考资料

前言

Linux 3.10.0 – x86_64

最简单获取sys_call_table符号的方法:

# cat /proc/kallsyms | grep sys_call_table
ffffffff816beee0 R sys_call_table

内核模块使用 kallsyms_lookup_name(推荐) 或者 kprobe:

 unsigned long * __sys_call_table = (unsigned long *)kallsyms_lookup_name("sys_call_table");

下面举例说明一下x86_64平台下其他获取sys_call_table的方案。

一、根据call *sys_call_table来获取

(1)

// linux-3.10/arch/x86/kernel/entry_64.S/** Register setup:* rax  system call number* rdi  arg0* rcx  return address for syscall/sysret, C arg3* rsi  arg1* rdx  arg2* r10  arg3 	(--> moved to rcx for C)* r8   arg4* r9   arg5* r11  eflags for syscall/sysret, temporary for C* r12-r15,rbp,rbx saved by C code, not touched.** Interrupts are off on entry.* Only called from user space.** XXX	if we had a free scratch register we could save the RSP into the stack frame*      and report it properly in ps. Unfortunately we haven't.** When user can change the frames always force IRET. That is because* it deals with uncanonical addresses better. SYSRET has trouble* with them due to bugs in both AMD and Intel CPUs.*/ENTRY(system_call)
......
system_call_fastpath:......movq %r10,%rcxcall *sys_call_table(,%rax,8)  # XXX:	 rip relativemovq %rax,RAX-ARGOFFSET(%rsp)......

在进入system_call时,中断被禁用。system_call仅从用户空间调用。系统调用通过指令syscall来执行。

在x86_64架构的用户空间下进行系统调用时,常用的寄存器如下:

rax:系统调用号(syscall number)放置在rax寄存器中,用于指定要调用的特定系统调用。
rdi:第一个参数(arg0)。在系统调用期间,用户提供的第一个参数通常存储在rdi寄存器中。
rsi:第二个参数(arg1)。用户提供的第二个参数通常存储在rsi寄存器中。
rdx:第三个参数(arg2)。用户提供的第三个参数通常存储在rdx寄存器中。
r10、r8、r9:第四、五、六个参数(arg3、arg4、arg5)。用户提供的第四、五、六个参数通常存储在r10、r8和r9寄存器中。

rcx:系统调用的返回地址。在进行系统调用时,将返回地址存储在rcx寄存器中,以便在系统调用完成后返回到正确的位置。
r11:用于存储eflags寄存器的值。在进行系统调用前,将当前eflags寄存器的值保存在r11寄存器中,以便在系统调用完成后恢复它。

用户空间函数调用:

rax:返回值  参数传递:rdi,rsi,rdx,rcx,r8,r9

用户空间系统调用:

rax:系统调用号  参数传递:rdi,rsi,rdx,r10、r8、r9  (rcx -> r10)

(2)
在x86_64架构中,调用sys_call_table的机器码操作是通过间接调用(indirect call)指令来实现的。具体的操作码是ff 14 c5,其表示的汇编指令是callq *%rax。

这条指令的作用是从rax寄存器中获取一个指针地址,然后跳转到该地址执行代码。在这种情况下,我们假设rax寄存器中存储了sys_call_table的地址,以便通过间接调用来调用相应的系统调用函数。

我们通过crash调试便可以获取到sys_call_table的地址:
在这里插入图片描述
由上面的汇编代码:

system_call-->system_call_fastpath-->call *sys_call_table(,%rax,8)

我们反汇编system_call_fastpath:

crash> dis system_call_fastpath
0xffffffff816b4fb3 <system_call_fastpath>:      cmp    $0x146,%rax
0xffffffff816b4fb9 <system_call_fastpath+6>:    ja     0xffffffff816b5081 <badsys>
0xffffffff816b4fbf <system_call_fastpath+12>:   mov    %r10,%rcx
0xffffffff816b4fc2 <system_call_fastpath+15>:   callq  *-0x7e941120(,%rax,8)
0xffffffff816b4fc9 <system_call_fastpath+22>:   mov    %rax,0x20(%rsp)

可以看到在地址0xffffffff816b4fc2,调用call *sys_call_table(,%rax,8),然后读取内存地址0xffffffff816b4fc2的值:

crash> rd -64 0xffffffff816b4fc2
ffffffff816b4fc2:  48816beee0c514ff                    .....k.H

call的操作码是0xff14c5,后面就是sys_call_table的地址0x816beee0
因此sys_call_table的地址是0xffffffff816beee0。

备注:第三节使用了rdmsr来获取 system_call 符号的值。

(3)
我们也可以借助vmlinux来objdump来获取其地址:

# ./extract-vmlinux vmlinuz-3.10.0-693.el7.x86_64 > vmlinux
# objdump -d vmlinux > vmlinux.txt
# vim vmlinux.txt

我们根据 ff 14 c5 指令码来搜索,上一条指令且是movq %r10,%rcx:

	movq %r10,%rcxcall *sys_call_table(,%rax,8)  # XXX:	 rip relative
ffffffff816b4fbf:       4c 89 d1                mov    %r10,%rcx
ffffffff816b4fc2:       ff 14 c5 e0 ee 6b 81    callq  *-0x7e941120(,%rax,8)

可以看到 ff 14 c5 机器码后面的地址就是sys_call_table的地址0x816beee0(x86_64是小端机器)。
因此sys_call_table的地址是0xffffffff816beee0。

二、使用dump_stack

#include <linux/module.h>
#include <linux/kallsyms.h>
#include <linux/kernel.h>static int __init lkm_init(void)
{dump_stack();return 0;
}static void __exit lkm_exit(void)
{}module_init(lkm_init);
module_exit(lkm_exit);MODULE_LICENSE("GPL");
[ 7666.386756] Call Trace:
[ 7666.386761]  [<ffffffff816a3d91>] dump_stack+0x19/0x1b
[ 7666.386762]  [<ffffffffc01f3009>] lkm_init+0x9/0x1000 [sys_call_table]
[ 7666.386764]  [<ffffffff810020e8>] do_one_initcall+0xb8/0x230
[ 7666.386766]  [<ffffffff81100734>] load_module+0x1f64/0x29e0
[ 7666.386769]  [<ffffffff8134bbf0>] ? ddebug_proc_write+0xf0/0xf0
[ 7666.386770]  [<ffffffff810fcdd3>] ? copy_module_from_fd.isra.42+0x53/0x150
[ 7666.386772]  [<ffffffff81101366>] SyS_finit_module+0xa6/0xd0
[ 7666.386774]  [<ffffffff816b4fc9>] system_call_fastpath+0x16/0x1b

我们就可以看到 system_call_fastpath+0x16 的地址是0xffffffff816b4fc9,因此system_call_fastpath的地址是:

0xffffffff816b4fc9 - 0x16 = 0xffffffff816b4fb3

我们可以从/proc/kallsyms验证:

# cat /proc/kallsyms | grep system_call_fastpath
ffffffff816b4fb3 t system_call_fastpath
system_call_fastpath:
#if __SYSCALL_MASK == ~0cmpq $__NR_syscall_max,%rax
#elseandl $__SYSCALL_MASK,%eaxcmpl $__NR_syscall_max,%eax
#endifja badsysmovq %r10,%rcxcall *sys_call_table(,%rax,8)  # XXX:	 rip relative

这里我们简单点,从上面的crash可以看到:

crash> dis system_call_fastpath
0xffffffff816b4fb3 <system_call_fastpath>:      cmp    $0x146,%rax
0xffffffff816b4fb9 <system_call_fastpath+6>:    ja     0xffffffff816b5081 <badsys>
0xffffffff816b4fbf <system_call_fastpath+12>:   mov    %r10,%rcx
0xffffffff816b4fc2 <system_call_fastpath+15>:   callq  *-0x7e941120(,%rax,8)

call *sys_call_table 在 system_call_fastpath 的 0xf(15)处。

#include <linux/module.h>
#include <linux/kallsyms.h>
#include <linux/kernel.h>static int __init lkm_init(void)
{int i;unsigned char *ptr;ptr = (unsigned char *)(0xffffffff816b4fc9 - 0x16 + 0xf);for (i = 0; i < 8; i ++) {//printk("%02x ", (unsigned char)ptr[i]);printk("%02x ", (unsigned char)*(ptr + i));}return 0;
}static void __exit lkm_exit(void)
{}module_init(lkm_init);
module_exit(lkm_exit);MODULE_LICENSE("GPL");
(unsigned char)ptr[i]) = (unsigned char)*(ptr + i))
# insmod sys_call_table.ko
[# dmesg -c
[ 8416.858466] ff 14 c5 e0 ee 6b 81 48

可以看到 ff 14 c5 机器码后面的地址就是sys_call_table的地址0x816beee0(x86_64是小端机器)。
因此sys_call_table的地址是0xffffffff816beee0。

或者直接搜索:

#include <linux/module.h>
#include <linux/kallsyms.h>
#include <linux/kernel.h>static int __init lkm_init(void)
{int i, j;unsigned char *ptr;ptr = (unsigned char *)(0xffffffff816b4fc9 - 0x16 + 0xf);for (i = 0; i < 20; i ++) {if( ((unsigned char)ptr[i] == 0xff) && ((unsigned char)ptr[i + 1] == 0x14) && ((unsigned char)ptr[i +2] == 0xc5) ){printk("0x%x ", *(unsigned int *)(ptr+i+3));break;}} return 0;
}static void __exit lkm_exit(void)
{}module_init(lkm_init);
module_exit(lkm_exit);MODULE_LICENSE("GPL");
# insmod sys_call_table.ko
# dmesg -c
[  280.502659] 0x816beee0

因此sys_call_table的地址是0xffffffff816beee0。

三、根据MSR_LSTAR寄存器

我们来看一下内核的启动过程:

start_kernel()-->trap_init()-->cpu_init()-->syscall_init()
#define MSR_STAR		0xc0000081 /* legacy mode SYSCALL target */
#define MSR_LSTAR		0xc0000082 /* long mode SYSCALL target */
#define MSR_CSTAR		0xc0000083 /* compat mode SYSCALL target */

| Register

AddressArchitectural MSR Name / Bit Fields (Former MSR Name)MSR/Bit Description
C000_0081HIA32_STARSystem Call Target Address (R/W)
C000_0082HIA32_LSTARIA-32e Mode System Call Target Address (R/W)
Target RIP for the called procedure when SYSCALL is executed in 64-bit mode.
C000_0083HIA32_CSTARIA-32e Mode System Call Target Address (R/W)
Not used, as the SYSCALL instruction is not recognized in compatibility mode.

我们主要看MSR_LSTAR寄存器:
IA32_LSTAR 是 IA-32e 模式下的系统调用目标地址寄存器,用于存储在 64 位模式下执行 SYSCALL 指令时被调用过程的目标 RIP(指令指针)。

当在 64 位模式下执行 SYSCALL 指令时,系统将从 IA32_LSTAR 寄存器中加载 RIP 的值,以跳转至相应的系统调用处理程序。

为了使内核接收传入的系统调用,它必须通过将其地址写入IA32_LSTAR MSR寄存器 来注册将在发生系统调用时执行的代码的地址。

/* May not be marked __init: used by software suspend */
void syscall_init(void)
{/** LSTAR and STAR live in a bit strange symbiosis.* They both write to the same internal register. STAR allows to* set CS/DS but only a 32bit target. LSTAR sets the 64bit rip.*/wrmsrl(MSR_STAR,  ((u64)__USER32_CS)<<48  | ((u64)__KERNEL_CS)<<32);wrmsrl(MSR_LSTAR, system_call);wrmsrl(MSR_CSTAR, ignore_sysret);....../* Flags to clear on syscall */wrmsrl(MSR_SYSCALL_MASK,X86_EFLAGS_TF|X86_EFLAGS_DF|X86_EFLAGS_IF|X86_EFLAGS_IOPL|X86_EFLAGS_AC);
}

这行代码把system_call入口地址存入到MSR_LSTAR寄存器。syscall指令会把该地址加载到到%rip寄存器,从该地址开始执行。

syscall指令:
在这里插入图片描述
SYSCALL 指令用于在特权级别 0(内核模式)下调用操作系统的系统调用处理程序。它通过从 IA32_LSTAR MSR 寄存器加载 RIP(同时将 SYSCALL 指令后面的指令地址保存在 RCX 中)来实现这一功能。IA32_LSTAR MSR 寄存器的值是一个规范地址(canonical address),通过 WRMSR 指令确保其始终包含一个规范地址。

SYSCALL 指令:RIP = IA32_LSTAR MSR 寄存器 = system_call

过程如下:
在这里插入图片描述

特别说明一下,因为初始化时,掩码中包含中断标志位X86_EFLAGS_IF,所以syscall指令执行时,中断是禁止的。

我们可以看到在syscall_init中将 system_call 的地址写入了 MSR_LSTAR 寄存器:

wrmsrl(MSR_LSTAR, system_call);

那么我们读取MSR_LSTAR寄存器就可以获取到system_call的地址,进入获取到sys_call_table的地址。

#include <linux/module.h>
#include <linux/kallsyms.h>
#include <linux/kernel.h>static int __init lkm_init(void)
{unsigned long msr_lstar;rdmsrl(MSR_LSTAR, msr_lstar);printk("MSR_LSTAR = %lx\n", msr_lstar);return 0;
}static void __exit lkm_exit(void)
{}module_init(lkm_init);
module_exit(lkm_exit);MODULE_LICENSE("GPL");
]# cat /proc/kallsyms | grep '\<system_call\>'
ffffffff816b4f50 T system_call
# insmod get_msr.ko
# dmesg -c
[ 1474.209016] MSR_LSTAR = ffffffff816b4f50

获取到了system_call的地址那么解析其后面的字节便可以找到sys_call_table的地址。

完整代码:

#include <linux/module.h>
#include <linux/kernel.h>void *memmem(const void *haystack, size_t haystack_size, const void *needle, size_t needle_size )
{char *p;for (p = (char *)haystack; p <= ((char *)haystack - needle_size + haystack_size); p++ )if (memcmp(p, needle, needle_size) == 0 )return (void *)p;return NULL;
}unsigned long *find_sys_call_table ( void )
{char **p;unsigned long sct_off = 0;unsigned char code[512];rdmsrl(MSR_LSTAR, sct_off);memcpy(code, (void *)sct_off, sizeof(code));p = (char **)memmem(code, sizeof(code), "\xff\x14\xc5", 3);if (p){unsigned long *sct = *(unsigned long **)((char *)p + 3);// Stupid compiler doesn't want to do bitwise math on pointerssct = (unsigned long *)(((unsigned long)sct & 0xffffffff) | 0xffffffff00000000);return sct;}elsereturn NULL;
}static int __init lkm_init(void)
{unsigned long *sys_call_table = find_sys_call_table();printk("The sys_call_table address is:%lx\n",(unsigned long)sys_call_table);return 0;
}static void __exit lkm_exit(void)
{}
module_init(init_get_sys_call_table);
module_exit(exit_get_sys_call_table);MODULE_LICENSE("GPL");
# cat /proc/kallsyms | grep '\<sys_call_table\>'
ffffffff816beee0 R sys_call_table
# insmod sys_call_table.ko
# dmesg -c
[ 2363.360239] The sys_call_table address is:0xffffffff816beee0

四、使用sys_close

// linux-3.10/fs/open.c/** Careful here! We test whether the file pointer is NULL before* releasing the fd. This ensures that one clone task can't release* an fd while another clone is opening it.*/
SYSCALL_DEFINE1(close, unsigned int, fd)
{int retval = __close_fd(current->files, fd);/* can't restart close syscall because file table entry was cleared */if (unlikely(retval == -ERESTARTSYS ||retval == -ERESTARTNOINTR ||retval == -ERESTARTNOHAND ||retval == -ERESTART_RESTARTBLOCK))retval = -EINTR;return retval;
}
EXPORT_SYMBOL(sys_close);
EXPORT_SYMBOL(sys_close);

系统调用函数(sys_close)在内核中是导出的,因此可以直接获取其地址。

// linux-3.10/arch/x86/include/asm/page_64_types.h/** Set __PAGE_OFFSET to the most negative possible address +* PGDIR_SIZE*16 (pgd slot 272).  The gap is to allow a space for a* hypervisor to fit.  Choosing 16 slots here is arbitrary, but it's* what Xen requires.*/
#define __PAGE_OFFSET           _AC(0xffff880000000000, UL)
// linux-3.10/arch/x86/include/asm/page_types.h#define PAGE_OFFSET		((unsigned long)__PAGE_OFFSET)

__PAGE_OFFSET是一个常量,用于表示内核虚拟地址空间的起始地址。

PAGE_OFFSET 是内核内存空间的起始地址。 因为 sys_close 是导出函数 (需要指出的是, sys_open 、 sys_read 等并不是导出的), 我们可以直接得到他的地址;因为系统调用号 (也就是 sys_call_table 这个一维数组的索引) 在同一 ABI (x86 跟 x64 不是同一 ABI)上具有高度的后向兼容性, 更重要的是,我们可以直接使用这个索引(代码中的 __NR_close )!

从内核内存的起始地址开始, 逐一尝试每一个指针大小的内存:把它当成是 sys_call_table 的地址, 用某个系统调用的编号(也就是索引)访问数组中的成员, 如果访问得到的值刚好是是这个系统调用号所对应的系统调用的地址, 那么我们就认为当前尝试的这块指针大小的内存就是我们要找的 sys_call_table 的地址。

#include <linux/module.h>
#include <linux/kallsyms.h>
#include <linux/kernel.h>#include <linux/syscalls.h> //__NR_closeunsigned long **get_sys_call_table(void)
{//内核内存空间的起始地址(PAGE_OFFSET)是已知的,因为它是内核的固定位置。unsigned long **entry = (unsigned long **)PAGE_OFFSET;for ( ; (unsigned long)entry < ULONG_MAX; entry += 1) {if (entry[__NR_close] == (unsigned long *)sys_close) {return entry;}}return NULL;
}static int __init lkm_init(void)
{unsigned long **real_sys_call_table = get_sys_call_table();printk("PAGE_OFFSET = %lx\n", (unsigned long)PAGE_OFFSET);printk("sys_call_table = %lx\n", (unsigned long)real_sys_call_table);return 0;
}static void __exit lkm_exit(void)
{}module_init(lkm_init);
module_exit(lkm_exit);MODULE_LICENSE("GPL");
# insmod sys_call_table.ko
# dmesg -c
[ 7405.938954] PAGE_OFFSET = ffff880000000000
[ 7405.938956] sys_call_table = ffff8800016beee0

从内核内存的起始地址(PAGE_OFFSET)开始,逐一尝试不同大小的内存块。这是因为sys_call_table通常被存储在一块连续的内存区域中。

对于每个尝试的内存地址,使用__NR_close作为索引来访问sys_call_table数组中的成员。

检查返回的值是否与sys_close函数的地址匹配。如果匹配成功,那么当前尝试的内存地址就被认为是sys_call_table的地址。

参考资料

Linux 3.10.0
https://blog.csdn.net/whatday/article/details/100513427
https://juejin.cn/post/7203681024236355639
https://docs-conquer-the-universe.readthedocs.io/zh-cn/latest/linux_rootkit/sys_call_table.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/711631.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

可视化图表:水球图,展示百分比的神器。

Hi&#xff0c;我是贝格前端工场的老司机&#xff0c;本文分享可视化图表设计的水球图设计&#xff0c;欢迎老铁持续关注我们。 一、水球图及其作用 水球图是一种特殊的可视化图表&#xff0c;它主要用于展示百分比或比例的数据&#xff0c;并以水球的形式进行呈现。水球图的作…

【k8s 访问控制--认证与鉴权】

1、身份认证与权限 前面我们在操作k8s的所有请求都是通过https的方式进行请求&#xff0c;通过REST协议操作我们的k8s接口&#xff0c;所以在k8s中有一套认证和鉴权的资源。 Kubenetes中提供了良好的多租户认证管理机制&#xff0c;如RBAC、ServiceAccount还有各种策路等。通…

集合篇之ArrayList

一、源码如何分析&#xff1f; 1.成员变量 2.构造方法 3.关键方法 一些添加的方法。 二、debug看源码 我们给出下面代码&#xff1a; public void test01() {ArrayList<Integer> list new ArrayList<>();list.add(1);for (int i 2; i < 10; i) {list.add(i…

精读《React 高阶组件》

本期精读文章是&#xff1a;React Higher Order Components in depth 1 引言 高阶组件&#xff08; higher-order component &#xff0c;HOC &#xff09;是 React 中复用组件逻辑的一种进阶技巧。它本身并不是 React 的 API&#xff0c;而是一种 React 组件的设计理念&…

【QT+QGIS跨平台编译】之五十三:【QGIS_CORE跨平台编译】—【qgssqlstatementparser.cpp生成】

文章目录 一、Bison二、生成来源三、构建过程一、Bison GNU Bison 是一个通用的解析器生成器,它可以将注释的无上下文语法转换为使用 LALR (1) 解析表的确定性 LR 或广义 LR (GLR) 解析器。Bison 还可以生成 IELR (1) 或规范 LR (1) 解析表。一旦您熟练使用 Bison,您可以使用…

2024年个人护理赛道选品风向在哪?这份赛盈分销选品攻略必看!

2024年还会卷下去吗&#xff1f;看到一位行业大佬分享的内容深有感触&#xff1a;坚定做好产品&#xff0c;不做大卖&#xff0c;就不存在卷不卷。 有人出局&#xff0c;也会有人入局&#xff0c;并且深耕领域做大做强。 专注口腔护理的Bitvae入行不到两年&#xff0c;凭借一款…

C#学习(十四)——垃圾回收、析构与IDisposable

一、何为GC 数据是存储在内存中的&#xff0c;而内存又分为Stack栈内存和Heap堆内存 Stack栈内存Heap堆内存速度快、效率高结构复杂类型、大小有限制对象只能保存简单的数据引用数据类型基础数据类型、值类型- 举个例子 var c new Customer{id: 123,name: "Jack"…

微信小程序手势冲突?不存在的!

原生的应用经常会有页面嵌套列表&#xff0c;滚动列表能够改变列表大小&#xff0c;然后还能支持列表内下拉刷新等功能。看了很多的小程序好像都没有这个功能&#xff0c;难道这个算是原生独享的吗&#xff0c;难道是由于手势冲突无法实现吗&#xff0c;冷静的思考了一下&#…

【InternLM 实战营笔记】XTuner 大模型单卡低成本微调实战

XTuner概述 一个大语言模型微调工具箱。由 MMRazor 和 MMDeploy 联合开发。 支持的开源LLM (2023.11.01) InternLM Llama&#xff0c;Llama2 ChatGLM2&#xff0c;ChatGLM3 Qwen Baichuan&#xff0c;Baichuan2 Zephyr 特色 傻瓜化&#xff1a; 以 配置文件 的形式封装了大…

看待事物的层与次 | DBA与架构的一次对话交流

前言 在计算机软件业生涯中,想必行内人或多或少都能感受到系统架构设计与数据库系统工程的重要性,也能够清晰地认识到在计算机软件行业中技术工程师这个职业所需要的专业素养和必备技能! 背景 通过自研的数据库监控管理工具,发现 SQL Server 数据库连接数在1-2K之间,想…

Yii2中如何使用scenario场景,使rules按不同运用进行字段验证

Yii2中如何使用scenario场景&#xff0c;使rules按不同运用进行字段验证 当创建news新闻form表单时&#xff1a; 添加新闻的时候执行create动作。 必填字段&#xff1a;title-标题&#xff0c;picture-图片&#xff0c;description-描述。 这时候在model里News.php下rules规则…

利用coze 搭建“全功能“微信客服(2)

紧跟上篇 利用coze 搭建"全功能"微信客服&#xff08;1&#xff09;&#xff0c;不知道来龙去脉自行查阅 先表扬下coze: coze 是国内少数开放平台之一&#xff0c;里面提供各种插件还可以开发工作流&#xff0c;让你可以实现多模态全功能大模型 吐槽 没有API开放接口…

2024亚马逊全球开店注册前需要准备什么?

在2023年出海四小龙SHEIN、Temu、速卖通AliExpress、TikTok Shop快速增长扩张&#xff0c;成为了中国跨境卖家“逃离亚马逊”的新选择。但是&#xff0c;跨境电商看亚马逊。当前&#xff0c;亚马逊仍然是跨境电商行业的绝对老大&#xff0c;占有将近70%成以上的业务份额。 作为…

分享fastapi低级错误

我是创建表的时候把__tablename__ 写成__table__然后一直报这个错误

端游如何防破解

在2023年这个游戏大年中&#xff0c;诸多热门大作涌现&#xff0c;作为世界级IP哈利哈利波特的衍生游戏——《霍格沃茨之遗》毫无悬念地成为2023年游戏圈的首款爆款作品&#xff0c;斩获了一众玩家的青睐。 在众多光环的加持下&#xff0c;《霍格沃茨之遗》很快被著名游戏破解…

深入 Starknet 去中心化世界,探秘实用开发利器

Starknet 近期开放空投&#xff0c;面向 130 万地址总量发放超 7 亿枚 Token&#xff0c;让 ECMP 早期贡献者、GitHub 开源开发者、Starknet 用户等各个层面的生态参与者都得以深度参与。 盛宴的背后&#xff0c;是 Starknet 正迎来发展的关键机遇。在今年以太坊坎昆升级的背景…

【漏洞复现】某厂商上网行为管理系统static_convert命令执行漏洞

Nx01 产品简介 天融信上网行为管理系统是天融信公司凭借多年来的安全产品研发经验&#xff0c;为满足各行各业进行网络行为管理和内容审计的专业产品。 Nx02 漏洞描述 天融信上网行为管理系统老版本static_convert.php接口存在RCE漏洞&#xff0c;攻击者利用此漏洞可以获取服务…

超强预测算法:XGBoost预测模型

目录 往期精彩内容&#xff1a; 多变量特征序列、单序列数据预测实战 前言 1 风速数据预处理与数据集制作 1.1 导入数据 1.2 多变量数据预处理与数据集制作 1.3 单序列数据预处理与数据集制作 2超强模型XGBoost——原理介绍 3 模型评估和对比 3.1 随机森林预测模型 3…

基于NeRF/Gaussian的全新SLAM算法

什么是SLAM&#xff1f; SLAM&#xff0c;即同时定位与地图构建技术&#xff0c;SLAM可以让机器人、无人机和其他自动化系统能够在未知环境中同时进行自我定位和环境映射。 为什么是NeRF-Based SLAM&#xff1f; 传统CG将输入图像重新投影再融合到新的视图摄像机中&#xff0c…

InfiniBand 200Gbps QSFP56 高速线缆/光缆和光模块解决方案

随着数据中心和人工智能迅速发展&#xff0c;对高速、低延迟和低功耗的数据传输需求变得至关重要。飞速&#xff08;FS&#xff09;提供针对各种高性能计算场景量身定制的各种InfiniBand线缆和光模块产品。本文旨在概述飞速&#xff08;FS&#xff09;200G InfiniBand HDR 光缆…