Deprecated: imwpcache\f884414bce24ee67f\f73723ec7b1919fa5::__construct(): Implicitly marking parameter $YECBGYFECGEAFWHA as nullable is deprecated, the explicit nullable type must be used instead in /www/wwwroot/www.chuangxiangniao.com/wp-content/plugins/imwpcache-dist/build/f884414bce24ee67ff73723ec7b1919fa5.php on line 2

Deprecated: imwpcache\f884414bce24ee67f\f73723ec7b1919fa5::__construct(): Implicitly marking parameter $BBWFDDBHHYHDXXAB as nullable is deprecated, the explicit nullable type must be used instead in /www/wwwroot/www.chuangxiangniao.com/wp-content/plugins/imwpcache-dist/build/f884414bce24ee67ff73723ec7b1919fa5.php on line 2
浅谈 Windows Syscall_创想鸟

浅谈 Windows Syscall

本文由团队成员 ryze-t 贡献给安全客,原文链接如下:https://www.php.cn/link/dde5af7b91bd434afa39458775de50ff 点击阅读原文即可跳转至作者博客。

0x00 syscall 基础概念

在 Windows 操作系统中,有两种处理器访问模式:用户模式(user mode)和内核模式(kernel mode)。在用户模式下运行的应用程序会由 Windows 创建一个新的进程,为其提供一个私有的虚拟地址空间和一个私有的句柄表。由于这种私有性,一个应用程序无法修改另一个应用程序的私有虚拟地址空间的数据。而在内核模式下,所有运行的代码共享一个虚拟地址空间,因此内核中的驱动程序可能因为写入错误的地址空间而导致其他驱动程序甚至整个系统出现错误。

内核中包含了大部分操作系统的内部数据结构,因此用户模式下的应用程序在访问这些数据结构或调用内部 Windows 例程以执行特权操作时,必须先从用户模式切换到内核模式,这就涉及到系统调用。

在 x86 Windows 中,系统调用通过 sysenter 指令实现。

在 x64 Windows 中,系统调用通过 syscall 指令实现。

0x01 syscall 运行机制

以创建线程的函数 CreateThread() 为例,函数结构如下:

HANDLE WINAPI CreateThread(    _In_opt_  LPSECURITY_ATTRIBUTES  lpThreadAttributes,    _In_      SIZE_T                 dwStackSize,    _In_      LPTHREAD_START_ROUTINE lpStartAddress,    _In_opt_  LPVOID                 lpParameter,    _In_      DWORD                  dwCreationFlags,    _Out_opt_ LPDWORD                lpThreadId);

示例代码如下:

#includeDWORD WINAPI Thread(LPVOID p){    MessageBox(0, 0, 0, 0);    return 0;}void main(){    //DebugBreak();    CreateThread(NULL, 0, Thread, 0, 0, 0); // 创建线程    Sleep(1000);}

使用 Procmon 查看创建线程的堆栈:

浅谈 Windows Syscall

可以看到在用户层 CreateThread 的调用栈为:

kernel32.dll!CreateThread → KernelBase.dll!CreateRemoteThreadEx → ntdll.dll!ZwCreateThreadEx

其本质是 ntdll.dll 中保存着执行功能的函数以及系统服务调用存根,ntdll.dll 导出了 Windows Native API,其具体实现其实在 ntoskrnl.exe 中。

IDA 查看 ntdll.dll!ZwCreateThreadEx:

浅谈 Windows Syscall

可以看到,调用 ZwCreateThreadEx 实际上调用的是 NtCreateThreadEx,然后通过判断机器是否支持 syscall 后,会执行 syscall 或 int 2E。

如果熟悉 ntdll.dll 的话会知道,ntdll.dll 中的一部分导出函数都是采用这种形式,如 NtCreateProcess:

浅谈 Windows Syscall

代码几乎一样,区别在于 mov eax 0B4h,也就是在执行 syscall 前,传入 eax 的值不同。即 eax 中存储的是系统调用号,基于 eax 所存储的值的不同,syscall 进入内核调用的内核函数也不同。

0x02 NtCreateThreadEx

2.1 CreateThread 调用流程

跟随调用栈来解析一下 CreateThread() 真实运行流程。

首先是 Kernel32.dll!CreateThread,直接在 IDA function 窗口并不能搜到这个函数,查看导出表:

浅谈 Windows Syscall

进入后知道,CreateThread 实际上是 CreateThreadStub:

浅谈 Windows Syscall

CreateThreadStub 会调用 Kernelbase!CreateRemoteThreadEx

CreateRemoteThread 结构如下:

HANDLE CreateRemoteThreadEx(    [in]            HANDLE                       hProcess,    [in, optional]  LPSECURITY_ATTRIBUTES        lpThreadAttributes,    [in]            SIZE_T                       dwStackSize,    [in]            LPTHREAD_START_ROUTINE       lpStartAddress,    [in, optional]  LPVOID                       lpParameter,    [in]            DWORD                        dwCreationFlags,    [in, optional]  LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList,    [out, optional] LPDWORD                      lpThreadId);

IDA 查看该函数找到 NtCreateThreadEx:

浅谈 Windows Syscall

v13 = NtCreateThreadEx(          &ThreadHandle,          0x1FFFFFi64,          v39,          hProcess,          v37,          v38,          v14,          0i64,          v34 & -(__int64)((dwCreationFlags & 0x10000) == 0),          v15,          v46);

2.2 NtCreateThread 参数结构

解析一下 NtCreateThread 参数结构,先看一下定义过的变量:

浅谈 Windows Syscall

第一个参数是 &ThreadHandle,ThreadHandle = 0

第二个参数是0x1FFFFF

第三个参数是 v39

浅谈 Windows Syscall

跟进该函数

浅谈 Windows Syscall

由于原程序中代码为 CreateThread(NULL, 0, Thread, 0, 0, 0),因此 lpThreadAttributes = NULL,所以传到 BaseFormatObjectAttributes 中的参数 (int)a2 = 0,a3 = 0。

因此根据程序逻辑 v39 = *a4 = 0

第四个参数是 hProcess

第五个参数是 lpStartAddress

第六个参数是 lpParameter

第七个参数是 v14,代码逻辑如下:

浅谈 Windows Syscall

因此要找到程序运行逻辑,是进入哪一个 LABEL。

结合 Windbg 查看,在 ntdll!NtCreateThreadEx 处下断点,根据 fastcall 调用约定,前四个参数由寄存器传递( RCX、RDX、R8、R9),其他参数由 RSP+0x20 开始压栈,因此第七个参数位置应是 RSP+0x30,由于此时已经执行 CALL 指令,由于返回地址入栈,RSP-8,因此参数应该由 RSP+0x28 开始:

浅谈 Windows Syscall

浅绿色滑动手风琴 浅绿色滑动手风琴

浅绿色滑动手风琴是一款基于jquery+css3实现的动画效果手风琴切换特效。

浅绿色滑动手风琴 59 查看详情 浅绿色滑动手风琴

可以看到第五个参数为 0007ff6`2b8e4383,这也就是创建的线程的起始地址,第六个参数为0,第七个参数也为0

第八个参数为 0

第九个参数为 v34 & -(__int64)((dwCreationFlags & 0x10000) == 0),根据 windbg 调试结果也为0

第十个参数为 v15,根据 windbg 调试结果也为0

第十一个参数为 v46,是一个数组

2.3 直接调用 NtCreateThreadEx

根据分析参数得到的结果来看,如果想直接调用 NtCreateThreadEx,代码应为:

#include#include typedef NTSTATUS(NTAPI* pfnNtCreateThreadEx)(    OUT PHANDLE hThread,    IN ACCESS_MASK DesiredAccess,    IN PVOID ObjectAttributes,    IN HANDLE ProcessHandle,    IN PVOID lpStartAddress,    IN PVOID lpParameter,    IN ULONG Flags,    IN SIZE_T StackZeroBits,    IN SIZE_T SizeOfStackCommit,    IN SIZE_T SizeOfStackReserve,    OUT PVOID lpBytesBuffer);

DWORD WINAPI Thread(LPVOID p){return 0;}

pfnNtCreateThreadEx NtCreateThreadExFunc(){HMODULE hNtdll = GetModuleHandle(L"ntdll.dll");if (hNtdll == NULL){printf("Load Ntdll.dll error:%dn", GetLastError());return FALSE;}pfnNtCreateThreadEx NtCreateThreadEx = (pfnNtCreateThreadEx)GetProcAddress(hNtdll, "NtCreateThreadEx");if (NtCreateThreadEx == NULL){printf("Load NtCreateThreadEx error:%d n", GetLastError());return FALSE;}return NtCreateThreadEx;}

int main(){//DebugBreak();HANDLE ProcessHandle = NULL;HANDLE ThreadHandle = NULL;ProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, 6396); // 6396是计算器的pidif (ProcessHandle == NULL){printf("OpenProcess error:%dn",GetLastError());return FALSE;}pfnNtCreateThreadEx NtCreateThreadEx = NtCreateThreadExFunc();NtCreateThreadEx(&ThreadHandle, 0x1FFFFF, NULL, ProcessHandle, Thread, NULL, FALSE, NULL, NULL, NULL, NULL);if (ThreadHandle != NULL){printf("Success! ThreadHandle=%dn", GetThreadId(ThreadHandle));}Sleep(10000);CloseHandle(ThreadHandle);CloseHandle(ProcessHandle);return TRUE;}

运行结果如下:

浅谈 Windows Syscall

0x03 syscall 调用

在 VS2019 中新建一个文件为 syscall.asm,右键解决方案生成自定义依赖性:

浅谈 Windows Syscall

选择 masm:

浅谈 Windows Syscall

右键 syscall.asm → 属性,选择 Microsoft Macro Assembler

浅谈 Windows Syscall

在 syscall.asm 中写入如下(win10 1511):

.codeNtCreateThreadEx procmov r10,rcxmov eax,0B4hsyscallretNtCreateThreadEx endpend

保存后新建 main.c

#include

include

EXTERN_C NTSTATUS NtCreateThreadEx(OUT PHANDLE hThread,IN ACCESS_MASK DesiredAccess,IN PVOID ObjectAttributes,IN HANDLE ProcessHandle,IN PVOID lpStartAddress,IN PVOID lpParameter,IN ULONG Flags,IN SIZE_T StackZeroBits,IN SIZE_T SizeOfStackCommit,IN SIZE_T SizeOfStackReserve,OUT PVOID lpBytesBuffer);

DWORD WINAPI Thread(LPVOID p){return 0;}

int main(){//DebugBreak();HANDLE ProcessHandle = NULL;ProcessHandle = GetCurrentProcess(); // 获取当前进程句柄if (ProcessHandle == NULL){printf("OpenProcess error:%dn", GetLastError());return FALSE;}HANDLE ThreadHandle = NULL;NtCreateThreadEx(&ThreadHandle, 0x1FFFFF, NULL, ProcessHandle, Thread, NULL, FALSE, NULL, NULL, NULL, NULL);if (ThreadHandle != NULL){printf("Success! ThreadId=%dn", GetThreadId(ThreadHandle));}else{printf("Fail!");}if (WaitForSingleObject(ThreadHandle, INFINITE) == WAIT_FAILED){printf("[!]WaitForSingleObject errorn");return FALSE;}CloseHandle(ThreadHandle);CloseHandle(ProcessHandle);return TRUE;}

这里注入的是自身进程,所以看起来更加直观,在用户层调用栈中并未出现 CreateThread 相关API:

浅谈 Windows Syscall

0x04 Syscall 项目

由上述可知,syscall 这种方法主要可以应对 EDR 对 Ring3 API 的 HOOK,主要的问题是不同版本的 Windows Ntxxx 函数的系统调用号不同,且调用时需要逆向各 API 的结构方便调用。于是 github 上陆续出现了一些项目,持续更新 syscall table,如 syscalls 或 system Call tables,同时对于未公开 API 的结构就需要通过查找或自己逆向了。

4.1 Syswhispers

基于 Syscall 出现了一个非常方便的项目—Syswhispers,Syswhispers 的原理与上述大致相同,它更加方便的生成 asm 文件以及一个头文件,通过包含头文件就可以进行 syscall。

用法如下:

浅谈 Windows Syscall

可以看到生成了两个文件,在解决方案资源管理器中的头文件中导入这两个文件:

浅谈 Windows Syscall

与之前对 asm 的操作一样,生成 masm 依赖项,然后更改属性→项类型选择 Microsoft Macro Assembler。

在C文件中加上 #include "syscall.h"

示例代码如下:

#include

include

include "syscall.h"

DWORD WINAPI Thread(LPVOID p){return 0;}

int main(){//DebugBreak();HANDLE ProcessHandle = NULL;ProcessHandle = GetCurrentProcess();if (ProcessHandle == NULL){printf("OpenProcess error:%dn", GetLastError());return FALSE;}HANDLE ThreadHandle = NULL;NtCreateThreadEx(&ThreadHandle, 0x1FFFFF, NULL, ProcessHandle, Thread, NULL, FALSE, NULL, NULL, NULL, NULL);if (ThreadHandle != NULL){printf("Success! ThreadId=%dn", GetThreadId(ThreadHandle));}else{printf("Fail!");}if (WaitForSingleObject(ThreadHandle, INFINITE) == WAIT_FAILED){printf("[!]WaitForSingleObject errorn");return FALSE;}CloseHandle(ThreadHandle);CloseHandle(ProcessHandle);return TRUE;}

编译通过后执行:

浅谈 Windows Syscall

查看 asm 文件:

浅谈 Windows Syscall

浅谈 Windows Syscall

在不指定版本的情况下,Syswhispers 会导出指定函数的所有已知版本的系统调用号,根据版本的不同再来指定调用。

4.2 Syswhispers2

在今年原作者对 Syswhispers 进行了些许改进,更新成 Syswhispers2。

Syswhispers2 与 Syswhispers 最大的不同在于 Syswhispers2 不再需要指定 Windows 版本,也不再依赖于以往的系统调用表,而是采用了系统调用地址排序的方法,也就是这篇 Bypassing User-Mode Hooks and Direct Invocation of System Calls for Red Teams。其具体含义是先解析 Ntdll.dll 的 导出地址表 EAT,定位所有以 “Zw” 开头的函数,将开头替换成 “Nt”,将 Code stub 的 hash 和地址存储在 SYSCALL_ENTRY 结构的表中,存储在表中的系统调用的索引是SSN(System Service Numbers,系统服务编号)。

用法与 Syswhispers 大致相同,不同的点在于,在使用时会生成三个文件:

浅谈 Windows Syscall

在导入时要将 syscall.c 也导入到源代码中

浅谈 Windows Syscall

syscall.c 中存储着系统调用地址排序和哈希比较的功能。

编译运行后:

浅谈 Windows Syscall

以上就是浅谈 Windows Syscall的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/478618.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
cad bak文件怎么打开?
上一篇 2025年11月8日 10:25:42
win10系统安全模式黑屏怎么办
下一篇 2025年11月8日 10:25:44

相关推荐

  • 梦幻号虚拟主播电商运营宝典(附新手教程+配套工具清单)

    虚拟主播电商的核心在于“内容驱动销售,人设凝聚用户”,要让“梦幻号”真正动起来并实现带货,必须先赋予其鲜明的人设,包括清晰的定位标签(如美食家、科技宅)、独特的人格魅力(性格、口头禅、小缺点)和与产品的强关联性,使其具备辨识度和故事感,从而建立用户信任;接着通过obs studio、vtube st…

    2026年9月21日
    000
  • win10平板模式下屏幕键盘不自动弹出怎么办_恢复屏幕键盘自动弹出的技巧

    1、检查平板电脑模式设置,确保登录和使用时均启用平板模式并重启;2、在设备→输入中开启“不处于平板模式且未连接键盘时显示触摸键盘”;3、通过注册表编辑器创建InitialKeyboardIndicators值为2(十六进制)以强制启用键盘指示器;4、手动显示触摸键盘按钮并测试各应用兼容性,排查特定软…

    2026年9月21日
    000
  • deepseek下载速度优化_从deepseek下载速度优化官网获取

    deepseek下载速度优化入口在官网https://www.deepseek.com,进入后可通过设置调整响应模式、使用智能路由和数据压缩技术提升速度。 ☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 DeepSeek R1 模型☜☜☜ deepseek下载速度优化入口地址在…

    2026年9月21日
    000
  • Linux如何设置目录的执行权限

    目录的执行权限是访问其内容的“钥匙”,使用chmod命令可通过符号或八进制模式设置,常见权限为755(所有者rwx,组和其他用户rx),递归设置时推荐结合find命令分别处理文件和目录,避免误加执行权限。 在Linux中,设置目录的执行权限( x )并非意味着你可以“运行”这个目录,而是赋予了你进入…

    2026年9月21日
    000
  • Java多线程API调用中Future.get()返回null的解决方案

    本文旨在解决%ignore_a_1%api调用中`future.get()`方法返回`null`的常见问题。当使用`callable`和`executorservice`并发执行api请求并尝试获取结果时,如果流读取逻辑不当,可能导致获取到的数据为空。文章将详细解释问题根源,并提供使用`string…

    2026年9月21日
    000
  • VSCode的自动保存功能如何开启?

    在VSCode中开启自动保存需进入“文件”→“首选项”→“设置”,搜索auto save并选择Files: Auto Save模式,可选afterDelay、onFocusChange或onWindowChange,其中afterDelay可设置延迟时间如1000毫秒,启用后状态栏显示保存状态以确认…

    2026年9月21日
    000
  • 升级后如何检查兼容性

    检查兼容性是升级后确保系统稳定的关键,需先确认硬件配置与驱动支持,再验证软件运行及业务流程正常,最后通过系统日志排查潜在错误,逐步排除风险。 系统或软件升级后,检查兼容性是确保各项功能正常运行的关键步骤。直接进入实际使用前,花时间验证兼容性可以避免数据丢失、服务中断等问题。 检查硬件和驱动支持 某些…

    2026年9月21日
    000
  • windows怎么解决蓝屏问题_windows蓝屏故障排查与修复方法

    蓝屏问题通常由驱动冲突、硬件故障或系统文件损坏引起,需记录错误代码并进入安全模式排查;通过设备管理器检查驱动、使用SFC和DISM修复系统文件,并运行内存与硬盘检测工具确认硬件健康,必要时清洁硬件接触点。 如果您在使用Windows系统时遇到电脑突然黑屏并显示蓝色错误界面,这通常意味着系统遇到了无法…

    2026年9月21日
    000
  • mysql如何排查排序异常

    排查MySQL排序异常需先确认ORDER BY是否生效,检查子查询、UNION及应用层逻辑是否覆盖排序;通过EXPLAIN分析是否使用索引排序,避免Using filesort;确保字段类型、字符集和排序规则(collation)符合预期,处理NULL值和大小写敏感性;关注sort_buffer_s…

    2026年9月21日
    000
  • 如何配置VSCode与Jupyter Notebook进行交互式数据科学编程?

    首先安装Python、VSCode及Python扩展,再通过pip安装jupyter;接着在VSCode中创建或打开.ipynb文件,使用Shift+Enter运行单元格;然后通过Ctrl+Shift+P选择Python解释器并确保安装ipykernel以匹配内核;最后启用变量查看器、代码块分隔符和…

    2026年9月21日
    000
  • 即梦AI运镜控制怎么控制_即梦AI视频镜头移动技巧详解

    掌握即梦AI运镜需四步:一、用“镜头缓慢推进”等预设提示词生成标准运动;二、通过动效画板框选主体并绘制运动路径;三、设置首尾帧引导转场,实现穿越或循环效果;四、结合“希区柯克式变焦”“时间冻结环绕”等高级技巧增强视觉表现。 ☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 免费无限量使用 Dee…

    2026年9月21日
    000
  • windows怎么查看电脑型号_Windows查看电脑硬件型号方法

    通过系统信息工具查看:按Win+R输入msinfo32,查找“系统型号”获取电脑型号;2. 使用命令提示符执行wmic csproduct get name查询型号;3. 在Windows 11设置中进入“系统-关于”,查看“设备规格”下的“设备型号”;4. 利用PowerShell运行Get-Wm…

    2026年9月21日
    100
  • 华为Mate 70优享版明日开启预约 10月20日开售

    华为Mate 70优享版明日开启预约 10月20日开售华为Mate 70优享版明日开启预约 10月20日开售华为Mate 70优享版明日开启预约 10月20日开售华为Mate 70优享版明日开启预约 10月20日开售

    近日,有数码博主透露,华为mate 70优享版将于10月14日启动预约,并在10月20日正式发售。 在核心配置上,消息称该机型将搭载麒麟9010S处理器。 据悉,这款新机的整体硬件规格与标准版Mate 70保持高度一致,配备一块6.7英寸的1.5K OLED直屏,支持120Hz LTPO自适应刷新率…

    2026年9月21日 用户投稿
    000
  • Linux如何检查系统中缺失的依赖库

    使用ldd和readelf检查依赖,通过包管理器安装缺失库。ldd显示not found时,用apt-file或yum provides查找并安装对应软件包,必要时添加库路径至/etc/ld.so.conf并运行ldconfig更新缓存。 在Linux系统中,程序运行时依赖各种共享库(.so文件),…

    2026年9月21日
    000
  • .com网站安全维护_保障.com网站稳定的措施

    答案:保障.com网站稳定需加强安全防护、定期备份、实时监控和应急准备。部署防火墙、更新系统、使用HTTPS、限制端口;制定自动备份并异地存储,定期恢复测试;利用监控工具检测可用性与异常流量,优化加载速度;建立应急流程,严格权限管理,定期演练。细节执行到位才能确保长期安全稳定运行。 确保.com网站…

    2026年9月21日
    100
  • 三星电视携手京东开启艺术视听盛典以科技美学重塑家居生活新模式

    三星电视携手京东开启艺术视听盛典以科技美学重塑家居生活新模式三星电视携手京东开启艺术视听盛典以科技美学重塑家居生活新模式三星电视携手京东开启艺术视听盛典以科技美学重塑家居生活新模式三星电视携手京东开启艺术视听盛典以科技美学重塑家居生活新模式

    随着消费理念升级与需求日益多样化,电视已不再仅仅是观看节目和影音娱乐的工具,而是逐渐演变为承载家居美学、传递情感温度、连接智慧生活的艺术载体。在这一变革浪潮中,三星率先引领艺术电视领域的创新风向,theframe画壁艺术电视与theserif画境艺术电视成功打破科技与艺术之间的界限,将电视升华为可观…

    2026年9月21日 用户投稿
    100
  • 如何在Weka中处理向量属性:ARFF格式的限制与解决方案

    本文探讨了weka中arff格式对直接向量属性表示的限制,并提供了两种主要解决方案。对于时间序列数据,建议利用weka的内置时间序列分析功能。对于非时间序列数据,核心在于通过特征工程(如使用addexpression、multifilter等)将向量拆解并转换为可被weka有效处理的独立特征,以揭示…

    2026年9月21日
    000
  • 哪些Docker扩展能让你在VSCode内轻松管理容器?

    Docker官方扩展是VSCode中管理容器的核心工具,提供容器、镜像、卷、网络的可视化操作,结合Remote-Containers可实现容器内开发,辅以YAML、GitLens等扩展提升效率,需确保本地Docker daemon运行。 在 VSCode 中管理 Docker 容器,最核心的扩展是 …

    2026年9月21日
    000
  • windows10如何解决“找不到恢复环境”的问题_windows10恢复环境修复方法

    首先启用恢复环境,若失败则修复BCD引导配置,最后检查并恢复Winre.wim文件以解决“找不到恢复环境”问题。 如果您尝试在Windows 10系统中使用“重置此电脑”或“高级启动”功能,但收到“找不到恢复环境”的提示,则可能是由于恢复环境被禁用、引导配置错误或核心文件丢失。以下是解决此问题的步骤…

    2026年9月21日
    200
  • PostgreSQL地理位置数据按距离排序的最佳实践:数据库层优化策略

    在处理大量地理位置数据并按距离排序时,将排序逻辑下推至数据库层(如postgresql)是更优的选择。这种方法能有效减少应用层的数据传输和内存消耗,充分利用数据库的计算能力,从而提升整体性能和资源利用率,而非在spring boot应用服务层进行排序。 1. 地理位置排序的需求与挑战 在现代Web应…

    2026年9月21日
    100

发表回复

登录后才能评论
关注微信