零地址挂页

news2024/11/27 16:17:28

零地址

如果我们有比较好的C编程基础,我们就会知道,我们在代码中定义了一个零地址或者空指针,那么它实际上会指向虚拟内存的零地址,多数操作系统,包括Win,在进程创建的时候,都会空出前64k的空间大小,来确保NULL等值不指向任何地方。

我们使用CE来打开一个记事本,可以看见0地址处确实被分配了64k的大小(0x10000),这里提一下,操作系统的内存分配最低是64k,哪怕你只是申请一个字节,那么也会至少给你64k。

在这里插入图片描述

这个零地址处,我们正常来说是不能利用的,这里随便写一段代码试一试

// 0_Address_Page_Alloc.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include<windows.h>

int* x = 0;

int _tmain(int argc, _TCHAR* argv[])
{
	system("pause");

	*x = 100;

	return 0;
}

我们正常运行这段代码,报错C0005,再看下面的内存全部是??,这就是说明这一块内存并没有被挂上页

在这里插入图片描述

那么,针对这一块内存,我们既然之前学习了页的一些知识,我们是不是可以想办法利用一下呢?

实操

思路

修改我们的代码,申请一块内存空间之后,用这块已经挂上页的内存空间的PTE写入到我们零地址对应的PTE处,实现可以修改零地址处的值(实际上还是共享了页)

// 0_Address_Page_Alloc.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include<windows.h>

int* x = 0;

int _tmain(int argc, _TCHAR* argv[])
{
	int* Base =(int*) VirtualAlloc(NULL,0x1000,MEM_COMMIT,PAGE_READWRITE);
	memset(Base,0,0x1000);
	printf("%x\r\n",Base);
	system("pause");

	*x = 100;
	system("pause");
	printf("Base is %d\r\n",*Base);

	return 0;
}

我们首先知道了地址是d0000

在这里插入图片描述

先看看我们的零地址处,果不其然没挂页

1: kd> !process 0 0
**** NT ACTIVE PROCESS DUMP ****
PROCESS 86cdd8e8  SessionId: none  Cid: 0004    Peb: 00000000  ParentCid: 0000
    DirBase: 00185000  ObjectTable: 8ec01b28  HandleCount: 524.
    Image: System
................................................

PROCESS 9525cc50  SessionId: 1  Cid: 0cb8    Peb: 7ffd7000  ParentCid: 02b8
    DirBase: 8872c000  ObjectTable: b5fcfa98  HandleCount:  24.
    Image: 0_Address_Page_Alloc.exe

PROCESS 8780d3a8  SessionId: 1  Cid: 0de0    Peb: 7ffdc000  ParentCid: 01a8
    DirBase: 2875c000  ObjectTable: c6538298  HandleCount:  62.
    Image: conhost.exe

PROCESS 87591c08  SessionId: 1  Cid: 0f50    Peb: 7ffdf000  ParentCid: 0cb8
    DirBase: 2d9d6000  ObjectTable: ba055e68  HandleCount:  30.
    Image: cmd.exe

1: kd> !dd 8872c000
#8872c000 3e885867 25abb867 1d784867 00000000
#8872c010 00000000 00000000 00000000 00000000
#8872c020 00000000 00000000 00000000 00000000
#8872c030 00000000 00000000 00000000 00000000
#8872c040 00000000 00000000 00000000 00000000
#8872c050 00000000 00000000 00000000 00000000
#8872c060 00000000 00000000 00000000 00000000
#8872c070 00000000 00000000 00000000 00000000
1: kd> !dd 3e885000
#3e885000 00000000 00000000 00000000 00000000
#3e885010 00000000 00000000 00000000 00000000
#3e885020 00000000 00000000 00000000 00000000
#3e885030 00000000 00000000 00000000 00000000
#3e885040 261a0867 00000000 00000000 00000000
#3e885050 00000000 00000000 00000000 00000000
#3e885060 00000000 00000000 00000000 00000000
#3e885070 00000000 00000000 00000000 00000000

然后再看我们申请的内存,相关区域以及全部被置为了0

1: kd> !dd 3e885000 + d0*4
#3e885340 419d3867 00000000 00000000 00000000
#3e885350 00000000 00000000 00000000 00000000
#3e885360 00000000 00000000 00000000 00000000
#3e885370 00000000 00000000 00000000 00000000
#3e885380 00000000 00000000 00000000 00000000
#3e885390 00000000 00000000 00000000 00000000
#3e8853a0 00000000 00000000 00000000 00000000
#3e8853b0 00000000 00000000 00000000 00000000
1: kd> !dd 419d3867
#419d3864 00000000 00000000 00000000 00000000
#419d3874 00000000 00000000 00000000 00000000
#419d3884 00000000 00000000 00000000 00000000
#419d3894 00000000 00000000 00000000 00000000
#419d38a4 00000000 00000000 00000000 00000000
#419d38b4 00000000 00000000 00000000 00000000
#419d38c4 00000000 00000000 00000000 00000000
#419d38d4 00000000 00000000 00000000 00000000

这时候,把我们的PTE(419d3867),放到零地址对应的PTT里面

1: kd> !ed 3e885000 419d3867
1: kd> !dd 3e885000
#3e885000 419d3867 00000000 00000000 00000000
#3e885010 00000000 00000000 00000000 00000000
#3e885020 00000000 00000000 00000000 00000000
#3e885030 00000000 00000000 00000000 00000000
#3e885040 261a0867 00000000 00000000 00000000
#3e885050 00000000 00000000 00000000 00000000
#3e885060 00000000 00000000 00000000 00000000
#3e885070 00000000 00000000 00000000 00000000

继续放行程序,可以看见我们的代码就没有报错,成功将0地址处的值改为了100

在这里插入图片描述

所以我们就知道,在10-10-12分页的条件下,MMU本身并不会直接验证所接收到的地址的合法性,只要指向的物理页是真实存在的即可

继续深入的想想

上面我们通过了手动修改PTE向零地址里面存储字节,那么这个存储的字节能不能是一段shellcode呢,我们先手动得到MessageBox的地址,然后用硬编码来调用

#include "stdafx.h"
#include<windows.h>
#include<cstdio>

typedef void(__stdcall * FuncProc)();

int _tmain(int argc, _TCHAR* argv[])
{
    FuncProc func = NULL;
    int* Base = (int*)VirtualAlloc(NULL, 0x1000, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    if (Base == NULL) {
        printf("Memory allocation failed!\n");
        return 1;
    }
    memset(Base, 0, 0x1000);

    char bufcode[] = {
        0x6a, 0,             // push 0
        0x6a, 0,             // push 0
        0x6a, 0,             // push 0
        0x6a, 0,             // push 0
        0xb8, 0, 0, 0, 0,     // mov eax, <address of MessageBoxA>
        0xff, 0xd0,          // call eax
        0xc3,                // ret
    };

    // 将 MessageBoxA 的地址写入 bufcode 的适当位置
    *(void**)(&bufcode[9]) = (void*)MessageBoxA;

    // 将 bufcode 复制到 Base
    memcpy(Base, bufcode, sizeof(bufcode));
    
    printf("%x\r\n",Base);
    system("pause");

    // 将 Base 转换为 FuncProc 类型并调用
    func = (FuncProc)Base;
    func();

    // 释放分配的内存
    VirtualFree(Base, 0, MEM_RELEASE);

    return 0;
}

这是能够正常弹出框的

在这里插入图片描述

那我们按照之前的思路,注释掉bufcode对fun的赋值,然后运行程序,修改零地址处的PTE,来调用MessageBoxA

在这里插入图片描述

按照上面的偏移找到我们所申请的地址,里面的硬编码已经存好了

0: kd> !process 0 0
**** NT ACTIVE PROCESS DUMP ****
PROCESS 86cdd8e8  SessionId: none  Cid: 0004    Peb: 00000000  ParentCid: 0000
    DirBase: 00185000  ObjectTable: 8ec01b28  HandleCount: 520.
    Image: System
    ...............................................................
PROCESS 875428a8  SessionId: 1  Cid: 0e34    Peb: 7ffdb000  ParentCid: 02b8
    DirBase: 31f7c000  ObjectTable: aef17ab8  HandleCount:  30.
    Image: 0_Address_Page_Alloc.exe

PROCESS 8779b838  SessionId: 1  Cid: 03b4    Peb: 7ffd5000  ParentCid: 01a8
    DirBase: 6cda0000  ObjectTable: baaaf2d0  HandleCount:  62.
    Image: conhost.exe

PROCESS 873e9d40  SessionId: 1  Cid: 09d4    Peb: 7ffda000  ParentCid: 0e34
    DirBase: 15210000  ObjectTable: c6538298  HandleCount:  30.
    Image: cmd.exe

0: kd> !dd 31f7c000
#31f7c000 8bf9d867 319e4867 2349c867 00000000
#31f7c010 00000000 00000000 00000000 00000000
#31f7c020 00000000 00000000 00000000 00000000
#31f7c030 00000000 00000000 00000000 00000000
#31f7c040 00000000 00000000 00000000 00000000
#31f7c050 00000000 00000000 00000000 00000000
#31f7c060 00000000 00000000 00000000 00000000
#31f7c070 00000000 00000000 00000000 00000000
0: kd> !dd 8bf9d000 + 1f0*4
#8bf9d7c0 1940f867 00000000 00000000 00000000
#8bf9d7d0 00000000 00000000 00000000 00000000
#8bf9d7e0 00000000 00000000 00000000 00000000
#8bf9d7f0 00000000 00000000 00000000 00000000
#8bf9d800 00000000 00000000 00000000 00000000
#8bf9d810 00000000 00000000 00000000 00000000
#8bf9d820 00000000 00000000 00000000 00000000
#8bf9d830 00000000 00000000 00000000 00000000
0: kd> !db 1940f000
#1940f000 6a 00 6a 00 6a 00 6a 00-b8 11 ea f4 75 ff d0 c3 j.j.j.j.....u...
#1940f010 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#1940f020 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#1940f030 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#1940f040 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#1940f050 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#1940f060 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#1940f070 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................

此时我们在代码里面将fun声明为NULL,所以我们还是一样,把我们的PTE填入零地址对应的PTT里面

0: kd> !dd 8bf9d000
#8bf9d000 00000000 00000000 00000000 00000000
#8bf9d010 00000000 00000000 00000000 00000000
#8bf9d020 00000000 00000000 00000000 00000000
#8bf9d030 00000000 00000000 00000000 00000000
#8bf9d040 65fb9847 00000000 00000000 00000000
#8bf9d050 00000000 00000000 00000000 00000000
#8bf9d060 00000000 00000000 00000000 00000000
#8bf9d070 00000000 00000000 00000000 00000000
0: kd> !ed 8bf9d000 1940f867
0: kd> !dd 8bf9d000
#8bf9d000 1940f867 00000000 00000000 00000000
#8bf9d010 00000000 00000000 00000000 00000000
#8bf9d020 00000000 00000000 00000000 00000000
#8bf9d030 00000000 00000000 00000000 00000000
#8bf9d040 65fb9847 00000000 00000000 00000000
#8bf9d050 00000000 00000000 00000000 00000000
#8bf9d060 00000000 00000000 00000000 00000000
#8bf9d070 00000000 00000000 00000000 00000000

之后我们继续放行程序,可以看见被声明为了NULL的函数指针还是调用了我们的shellcode,弹窗成功了

在这里插入图片描述

这更进一步验证了我们的学习,CPU读这些数据的时候不会真的去验证虚拟地址的真实性,只要对应的物理地址是可以被访问的,那么虚拟地址即使被更改只要不触发页异常就不会有问题

更加深入的想想

既然我们已经可以向一块被标记为Free的内存写入字节,那么,我们可不可以向一个进程里面的零地址写入字节然后远程线程跑我们的shellcode呢

先把代码贴出来

#include "stdafx.h"
#include<windows.h>
#include<cstdio>

typedef void(__stdcall * FuncProc)();

int _tmain(int argc, _TCHAR* argv[])
{
    FuncProc func = NULL;
    char* Base = (char*)VirtualAlloc(NULL, 0x1000, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    if (Base == NULL) {
        printf("Memory allocation failed!\n");
        return 1;
    }
    memset(Base, 0, 0x1000);

    char bufcode[] = {
        0x6a, 0,             // push 0
        0x6a, 0,             // push 0
        0x6a, 0,             // push 0
        0x6a, 0,             // push 0
        0xb8, 0, 0, 0, 0,     // mov eax, <address of MessageBoxA>
        0xff, 0xd0,          // call eax
        0xc3,                // ret
    };

    // 将 MessageBoxA 的地址写入 bufcode 的适当位置
    *(void**)(&bufcode[9]) = (void*)MessageBoxA;

    // 将 bufcode 复制到 Base
    memcpy(Base+0x200, bufcode, sizeof(bufcode));

    
    printf("%x\r\n",Base);
    system("pause");

    // 将 Base 转换为 FuncProc 类型并调用
    //func = (FuncProc)Base;
    //func();
	HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,3016);

	HANDLE hThread = CreateRemoteThread(hProcess,NULL,NULL,(LPTHREAD_START_ROUTINE)0x200,NULL,NULL,NULL);
	CloseHandle(hThread);
	CloseHandle(hProcess);
	system("pause");

    // 释放分配的内存
    VirtualFree(Base, 0, MEM_RELEASE);

    return 0;
}

上面的代码打开了一个notepad(3016)进程,然后朝里面写入了一个shellcode

首先还是先查到我们所申请内存的PTE

在这里插入图片描述

1: kd> !process 0 0//找到我们需要的进程
**** NT ACTIVE PROCESS DUMP ****
PROCESS 86cdd8e8  SessionId: none  Cid: 0004    Peb: 00000000  ParentCid: 0000
    DirBase: 00185000  ObjectTable: 8ec01b28  HandleCount: 529.
    Image: System

......................................................

PROCESS 87372b20  SessionId: 1  Cid: 0bc8    Peb: 7ffd5000  ParentCid: 062c
    DirBase: 2e224000  ObjectTable: af7f5fc0  HandleCount:  63.
    Image: notepad.exe

.........................................

PROCESS 878d65f0  SessionId: 1  Cid: 0b10    Peb: 7ffdf000  ParentCid: 02b8
    DirBase: 41ffb000  ObjectTable: b9f3aa50  HandleCount:  30.
    Image: 0_Address_Page_Alloc.exe



我们可以看见,在页中我们也挂到了对应偏移0x200的位置, 这个2c7e0847就是我们要找的值

1: kd> !dd 41ffb000+ 1*4
#41ffb004 00ab5867 ae4e1867 0be6d867 00000000
#41ffb014 00000000 00000000 00000000 00000000
#41ffb024 00000000 00000000 00000000 00000000
#41ffb034 00000000 00000000 00000000 00000000
#41ffb044 00000000 00000000 00000000 00000000
#41ffb054 00000000 00000000 00000000 00000000
#41ffb064 00000000 00000000 00000000 00000000
#41ffb074 00000000 00000000 00000000 00000000
1: kd> !dd 00ab5000 + 4*e0
#  ab5380 2c7e0847 00000000 00000000 00000000
#  ab5390 00000000 00000000 00000000 00000000
#  ab53a0 00000000 00000000 00000000 00000000
#  ab53b0 00000000 00000000 00000000 00000000
#  ab53c0 00000000 00000000 00000000 00000000
#  ab53d0 00000000 00000000 00000000 00000000
#  ab53e0 00000000 00000000 00000000 00000000
#  ab53f0 00000000 00000000 00000000 00000000
1: kd> !dd 2c7e0000
#2c7e0000 00000000 00000000 00000000 00000000
#2c7e0010 00000000 00000000 00000000 00000000
#2c7e0020 00000000 00000000 00000000 00000000
#2c7e0030 00000000 00000000 00000000 00000000
#2c7e0040 00000000 00000000 00000000 00000000
#2c7e0050 00000000 00000000 00000000 00000000
#2c7e0060 00000000 00000000 00000000 00000000
#2c7e0070 00000000 00000000 00000000 00000000
1: kd> !db 2c7e0000+0x200
#2c7e0200 6a 00 6a 00 6a 00 6a 00-b8 11 ea f4 75 ff d0 c3 j.j.j.j.....u...
#2c7e0210 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#2c7e0220 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#2c7e0230 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#2c7e0240 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#2c7e0250 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#2c7e0260 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
#2c7e0270 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................

我们打开notepad的零地址,把这个值填进去

1: kd> !dd 2e224000
#2e224000 3d720867 6c21f867 11cc2867 00000000
#2e224010 3f78c867 7468d847 2e4c8867 40304867
#2e224020 0c707867 06e09867 00000000 00000000
#2e224030 00000000 00000000 00000000 00000000
#2e224040 00000000 00000000 00000000 00000000
#2e224050 00000000 00000000 00000000 00000000
#2e224060 00000000 00000000 00000000 00000000
#2e224070 00000000 00000000 00000000 00000000
1: kd> !dd 3d720000
#3d720000 00000000 00000000 00000000 00000000
#3d720010 00000000 00000000 00000000 00000000
#3d720020 00000000 00000000 00000000 00000000
#3d720030 00000000 00000000 00000000 00000000
#3d720040 41e37847 00000000 00000000 00000000
#3d720050 00000000 00000000 00000000 00000000
#3d720060 00000000 00000000 00000000 00000000
#3d720070 00000000 00000000 00000000 00000000
1: kd> !ed 3d720000 2c7e0847
1: kd> !dd 3d720000
#3d720000 2c7e0847 00000000 00000000 00000000
#3d720010 00000000 00000000 00000000 00000000
#3d720020 00000000 00000000 00000000 00000000
#3d720030 00000000 00000000 00000000 00000000
#3d720040 41e37847 00000000 00000000 00000000
#3d720050 00000000 00000000 00000000 00000000
#3d720060 00000000 00000000 00000000 00000000
#3d720070 00000000 00000000 00000000 00000000

放行程序,继续运行,这时候我们的弹框就跑在notepad的进程中了

在这里插入图片描述

最后

我们现在是用windbg手动去修改PTE,但是随着我们学习的深入,我们就可以使用程序来自动化这一过程,来达到我们注入shellcode的效果

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

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

相关文章

oneplus6线刷、trwp、magisk(apatch)、LSPosed、Shamiko、Hide My Applist

oneplus6线刷android10.0.1 oneplus6线刷包(官方android10.0.1)下载、线刷教程&#xff1a; OnePlus6-brick-enchilada_22_K_52_210716_repack-HOS-10_0_11-zip 启用开发者模式 设置 / 连续点击6次版本号 : 启用开发者模式设置/开发者模式/{打开 usb调试, 打开 网络adb调试,…

树---索引的进化--从二叉搜索树到B+Tree的光荣进化(未完)

平衡二叉树 1. 索引平衡二叉树&#xff08;AVL树&#xff09;是一种自平衡的二叉搜索树&#xff0c;它通过在插入和删除节点时自动调整树的结构&#xff0c;保持树的平衡&#xff0c;从而保证了树的高度始终保持在O(log n)的范围内&#xff0c;这对于提高搜索、插入和删除操作…

FileZilla 报错解决

一、错误:严重错误: 无法连接到服务器 解决方法&#xff1a;FileZilla站点的用户名密码要和linux用户名密码保持一致&#xff0c;出现这个报错大概率是用户名和密码不一致导致的。 二、错误&#xff1a;文件传输失败 解决方法&#xff1a;检查linux下的文件夹是否有可执行权限…

替代Postman ,17.3K star!

现在&#xff0c;许多人都朝着全栈工程师的方向发展&#xff0c;API 接口的编写和调试已成为许多开发人员必备的技能之一。 工欲善其事&#xff0c;必先利其器。拥有一款优秀的 API 工具对于任何工程师来说都是极为重要的&#xff0c;它能够帮助我们高效地完成各种开发任务。 …

Flutter 3.24.5安装配置——2024年11月26日

目录 1️⃣前置安装使用环境配置步骤安装Flutter SDK安装Android SDK修改文件默认安装位置&#xff08;.gradle, AVD&#xff09;开始项目 2️⃣执行结果&#x1fab2;Bug找不到**.jar文件 &#x1f517;参考链接 1️⃣前置安装 使用环境 Windows 11IDEA 2024.2.3Flutter 3.2…

Perforce SAST专家详解:自动驾驶汽车的安全与技术挑战,Klocwork、Helix QAC等静态代码分析成必备合规性工具

自动驾驶汽车安全吗&#xff1f;现代汽车的软件包含1亿多行代码&#xff0c;支持许多不同的功能&#xff0c;如巡航控制、速度辅助和泊车摄像头。而且&#xff0c;这些嵌入式系统中的代码只会越来越复杂。 随着未来汽车的互联程度越来越高&#xff0c;这一趋势还将继续。汽车越…

(计算机组成原理)期末复习

第一章 计算机的基本组成&#xff1a;硬件软件&#xff08;程序&#xff09;计算机系统 软件有系统软件&#xff08;系统管理工具&#xff09;&#xff0c;应用软件 计算机硬件&#xff1a;包括主机和外设&#xff0c;主机包括CPU和内存&#xff0c;***CPU由运算器和控制器所组…

UEFI 中的 Protocol

Protocol 在 UEFI 内核中的表示 typedef VOID *EFI_HANDLE;EFI_HANDLE是指向某种对象的指针&#xff0c;UEFI 用它来表示某个对象。 UEFI 扫描总线后&#xff0c;会为每个设备建立一个 Controller 对象&#xff0c;用于控制设备&#xff0c;所有该设备的驱动以 Protocol 的形式…

量子安全与经典密码学:一些现实方面的讨论

量子安全与经典密码学 背景&#xff1a;量子安全与经典密码学量子计算对传统密码学的威胁 安全性分析经典密码学的数学复杂性假设**量子密码学的物理不可克隆性假设** **性能与实现难度**后量子算法在经典计算机上的运行效率**量子通信设备的技术要求与成本** **可扩展性与适用…

【大模型】LLaMA-Factory的环境配置、微调模型与测试

前言 【一些闲扯】 时常和朋友闲聊&#xff0c;时代发展这么快&#xff0c;在时代的洪流下&#xff0c;我们个人能抓住些什么呢。我问了大模型&#xff0c;文心一言是这样回答的&#xff1a; 在快速发展的时代背景下&#xff0c;个人确实面临着诸多挑战&#xff0c;但同时也充满…

PostgreSQL的学习心得和知识总结(一百五十八)|在线调优工具pgtune的实现原理和源码解析

目录结构 注&#xff1a;提前言明 本文借鉴了以下博主、书籍或网站的内容&#xff0c;其列表如下&#xff1a; 1、参考书籍&#xff1a;《PostgreSQL数据库内核分析》 2、参考书籍&#xff1a;《数据库事务处理的艺术&#xff1a;事务管理与并发控制》 3、PostgreSQL数据库仓库…

汽车渲染领域:Blender 和 UE5 哪款更适用?两者区别?

在汽车渲染领域&#xff0c;选择合适的工具对于实现高质量的视觉效果至关重要。Blender和UE5&#xff08;Unreal Engine 5&#xff09;作为两大主流3D软件&#xff0c;各自在渲染动画方面有着显著的差异。本文将从核心定位与用途、工作流程、渲染技术和灵活性、后期处理与合成四…

机器学习—迁移学习:使用其他任务中的数据

对于一个没有那么多数据的应用程序&#xff0c;迁移学习是一种奇妙的技术&#xff0c;它允许你使用来自不同任务的数据来帮助你的应用程序&#xff0c;迁移学习是如何工作的&#xff1f; 以下是迁移学习的工作原理&#xff0c;假设你想识别手写的数字0到9&#xff0c;但是你没…

LeetCode 3206.交替组 I:遍历

【LetMeFly】3206.交替组 I&#xff1a;遍历 力扣题目链接&#xff1a;https://leetcode.cn/problems/alternating-groups-i/ 给你一个整数数组 colors &#xff0c;它表示一个由红色和蓝色瓷砖组成的环&#xff0c;第 i 块瓷砖的颜色为 colors[i] &#xff1a; colors[i] …

如何通过高效的缓存策略无缝加速湖仓查询

引言 本文将探讨如何利用开源项目 StarRocks 的缓存策略来加速湖仓查询&#xff0c;为企业提供更快速、更灵活的数据分析能力。作为 StarRocks 社区的主要贡献者和商业化公司&#xff0c;镜舟科技深度参与 StarRocks 项目开发&#xff0c;也为企业着手构建湖仓架构提供更多参考…

25A物联网微型断路器 智慧空开1P 2P 3P 4P-安科瑞黄安南

微型断路器&#xff0c;作为现代电气系统中不可或缺的重要组件&#xff0c;在保障电路安全与稳定运行方面发挥着关键作用。从其工作原理来看&#xff0c;微型断路器通过感知电流的异常变化来迅速作出响应。当电路中的电流超过预设的安全阈值时&#xff0c;其内部的电磁感应装置…

目标检测,图像分割,超分辨率重建

目标检测和图像分割 目标检测和图像分割是计算机视觉中的两个不同任务&#xff0c;它们的输出形式也有所不同。下面我将分别介绍这两个任务的输出。图像分割又可以分为&#xff1a;语义分割、实例分割、全景分割。 语义分割&#xff08;Semantic Segmentation&#xff09;&…

16 —— Webpack多页面打包

需求&#xff1a;把 黑马头条登陆页面-内容页面 一起引入打包使用 步骤&#xff1a; 准备源码&#xff08;html、css、js&#xff09;放入相应位置&#xff0c;并改用模块化语法导出 原始content.html代码 <!DOCTYPE html> <html lang"en"><head&…

《PH47 快速开发教程》发布

PDF 教程下载位于CSDN资源栏目&#xff08;网页版本文上方&#xff09; 或Gitee&#xff1a;document ss15/PH47 - 码云 - 开源中国

腾讯云OCR车牌识别实践:从图片上传到车牌识别

在当今智能化和自动化的浪潮中&#xff0c;车牌识别&#xff08;LPR&#xff09;技术已经广泛应用于交通管理、智能停车、自动收费等多个场景。腾讯云OCR车牌识别服务凭借其高效、精准的识别能力&#xff0c;为开发者提供了强大的技术支持。本文将介绍如何利用腾讯云OCR车牌识别…