《Windows PE》5.1 导出表

导出表(Export Table)是一个在可执行文件或动态链接库(DLL)中的数据结构,用于描述该文件中导出的函数、变量和其他符号。导出表通常位于DLL动态链接库中。

本节必须掌握的知识点:

        导入表数据结构

        PE中的导入表

        IAT函数地址表

        手工重构导入表

5.1.1 导出表数据结构

导出表由以下三个主要部分组成:

●导出地址表(Export Address Table,EAT):导出地址表是一个指向导出函数地址的指针数组。每个导出函数在导出地址表中有一个对应的指针。在运行时,当其他模块调用这个DLL中的导出函数时,将使用该表中的指针来定位和调用函数。

●导出名称表(Export Name Table,ENT):导出名称表是一个字符串数组,包含了所有导出函数的名称。每个导出函数名称在导出名称表中都有一个对应的字符串。导出地址表中的指针与导出名称表中的字符串是一一对应的。

●导出函数序号表(Export Function Ordinal Table)是PE文件中导出表的一部分,用于映射导出函数的序号和地址。导出函数序号表是一个由WORD类型的数组组成,每个元素对应一个导出函数。序号表的长度等于导出函数的数量。

导出表的结构和内容由编译器和链接器在构建可执行文件或DLL时生成。导出表允许其他模块(可执行文件、DLL或其他)通过导入表来引用和调用这些导出的函数和符号。

在Windows平台上,您可以使用一些工具来查看PE文件的导出表,例如Dependency Walker、dumpbin工具或PE浏览器等。

 注意

导出表只包含被明确定义为导出的符号。如果某个符号未被明确导出,它将不会出现在导出表中。您可以使用关键字 __declspec(dllexport) 或者通过.def文件来指定哪些符号应该被导出。

导出表数据结构

导入表描述符IMAGE_IMPORT_DESCRIPTOR的个数与调用的动态链接库个数相等,而导出表描述符IMAGE_EXPORT_DIRECTORY的个数只有一个。

typedef struct _IMAGE_EXPORT_DIRECTORY {

    DWORD   Characteristics;               // 导出表的特征标志

    DWORD   TimeDateStamp;              // 时间戳

    WORD    MajorVersion;               // 主版本号

    WORD    MinorVersion;               // 次版本号

    DWORD   Name;                       // 模块名称的RVA

    DWORD   Base;                     // 导出函数序号的基准值

    DWORD   NumberOfFunctions;          // 导出函数的数量

    DWORD   NumberOfNames;             // 导出函数名称的数量

    DWORD   AddressOfFunctions;         // 导出函数地址表的RVA

    DWORD   AddressOfNames;              // 导出函数名称表的RVA

    DWORD   AddressOfNameOrdinals;      // 导出函数序号表的RVA

} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;

这个结构用于描述PE文件中的导出表。下面是对各个成员的注释:

Characteristics:导出表的特征标志,例如是否按序号导出。

TimeDateStamp:导出表的时间戳,表示导出表生成的时间。

MajorVersion 和 MinorVersion:导出表的版本号,用于指示导出表的版本信息。

Name:指向导出模块名称的指针(RVA)。

Base:导出函数的序号基准值。导出函数编号的起始值。DLL中的第一个导出函数并不是从0开始的,某导出函数的编号等于从AddressOfFunctions开始的顺序号加上这个值。

NumberOfFunctions:导出函数的数量。

NumberOfNames:导出函数名称的数量。

AddressOfFunctions:导出函数地址表的指针(RVA),包含导出函数的地址。该指针指向了全部导出函数的入口地址的起始。从入口地址开始为双字数组,数组的个数由字段IMAGE_EXPORT_DIRECTORY.NumberOfFimctions决定。导出函数的每一个地址按函数的编号顺序依次往后排开。在内存中,我们可以通过函数编号来定位某个函数的地址。

AddressOfNames:导出函数名称表的指针(RVA),包含导出函数的名称。该指针指向的位置是一连串的双字值,这些双字值均指向了对应的定义了函数名的函数的字符串地址。这一连串的双字个数为 NumberOfNames。

AddressOfNameOrdinals:导出函数序号表的指针(RVA),用于匹配导出函数的名称和地址。该值也是一个指针,与AddressOfNames是一一对应关系,所不同的是,AddressOfNames指向的是字符串的指针数组,而AddressOfNameOrdinals则指向了该函数在AddressOfFunctions中的索引值。

 注意

索引值是一个字,而非双字。该值与函数编号是两个不同的概念,两者之间的关系为:

索引值=编号 - nBase

导入表描述各个字段之间的关系可以用下图来描述:

                                         图5-1 PE导出表结构

5.1.2 定位导出表

导出表位于PE文件的数据目录第0项中,位于导入表之前。接下来我们通过一个实例具体分析导出表的结构。

首先我们要写一个包含导出表的DLL动态链接库,然后再写一个EXE执行文件调用导出函数。

实验三十三:延迟加载版本2示例

       以下是一个使用延迟加载版本2的C语言示例代码:

       ●源代码:

winResult.h

/*

; winResult.dll 导出函数:

; 1、AnimateOpen(DWORD)

;   窗口抖动进入效果

; 2、AnimateClose(DWORD)

;   窗口抖动退出效果

; 3、FadeInOpen(DWORD)

;   窗口淡入效果,仅运行在2000/XP以上操作系统

; 4、FadeOutClose(DWORD)

;   窗口淡出效果,仅运行在2000/XP以上操作系统

; ******************************************************************** /

*/

#pragma once

#include <windows.h>

#ifdef _cplusplus //如果C++模式编译

    #ifdef API_EXPORT

        #define EXPORT   extern "C" __declspec(dllexport)  

    #else

        #define EXPORT    extern "C" __declspec(dllimport

    #endif

#else

    #ifdef API_EXPORT

        #define EXPORT   __declspec(dllexport

    #else

        #define EXPORT   __declspec(dllimport

    #endif

#endif

EXPORT  void AnimateOpen(HWND);

EXPORT  void AnimateClose(HWND);

EXPORT  void FadeInOpen(HWND);

EXPORT  void FadeOutClose(HWND);

winResult.c

/*------------------------------------------------------------------------

 FileName:winResult.c

 实验33:一个简单的动态链接库例子

 (c) bcdaren, 2024

-----------------------------------------------------------------------*/

#include <windows.h>

#define API_EXPORT

#include "winResult.h"

#define MAX_XYSTEPS     50

#define DELAY_VALUE     50  //动画效果使用的步长

#define X_STEP_SIZE     10

#define Y_STEP_SIZE     9

#define X_START_SIZE    20

#define Y_START_SIZE    10

#define LMA_ALPHA       2

#define LMA_COLORKEY    1

//入口和退出点

int WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)

{

    return TRUE;

}

//私有函数:本函数在dll内部使用

DWORD TopXY(DWORD wDim,DWORD sDim)

{

    return (sDim / 2 - wDim / 2);

}

//窗口抖动进入效果

EXPORT  void AnimateOpen(HWND hWin)

{

    RECT rect;

    DWORD Xsize, Ysize,Xplace,Yplace;

    int sWth,sHth,counts;

    GetWindowRect(hWin, &rect);

    Xsize = X_START_SIZE;

    Ysize = Y_START_SIZE;

    sWth = GetSystemMetrics(SM_CXSCREEN);

    Xplace = TopXY(Xsize, sWth);

    sHth = GetSystemMetrics(SM_CYSCREEN);

    Yplace = TopXY(Ysize, sHth);

    counts = MAX_XYSTEPS;

    while (counts--)

    {

        MoveWindow(hWin, Xplace, Yplace, Xsize, Ysize, FALSE);

        ShowWindow(hWin, SW_SHOWNA);

        Sleep(DELAY_VALUE);

        ShowWindow(hWin, SW_HIDE);

        Xsize += X_STEP_SIZE;

        Ysize += Y_STEP_SIZE;

        Xplace = TopXY(Xsize, sWth);

        Yplace = TopXY(Ysize, sHth);

    }

    Xsize = rect.right - rect.left;

    Ysize = rect.bottom - rect.top;

    Xplace = TopXY(Xsize,sWth);

    Yplace = TopXY(Ysize,sHth);

    MoveWindow(hWin,Xplace,Yplace,Xsize,Ysize,TRUE);

    ShowWindow(hWin, SW_SHOW);

}

//窗口抖动退出效果

EXPORT void AnimateClose(HWND hWin)

{

    RECT rect;

    DWORD Xsize, Ysize, Xplace, Yplace;

    int sWth, sHth, counts;

    ShowWindow(hWin, SW_HIDE);

    GetWindowRect(hWin, &rect);

    Xsize = rect.right - rect.left;

    Ysize = rect.bottom - rect.top;

    sWth = GetSystemMetrics(SM_CXSCREEN);

    Xplace = TopXY(Xsize, sWth);

    sHth = GetSystemMetrics(SM_CYSCREEN);

    Yplace = TopXY(Ysize, sHth);

    counts = MAX_XYSTEPS;

    while (counts--)

    {

        MoveWindow(hWin, Xplace, Yplace, Xsize, Ysize, FALSE);

        ShowWindow(hWin, SW_SHOWNA);

        Sleep(DELAY_VALUE);

        ShowWindow(hWin, SW_HIDE);

        Xsize -= X_STEP_SIZE;

        Ysize -= Y_STEP_SIZE;

        Xplace = TopXY(Xsize, sWth);

        Yplace = TopXY(Ysize, sHth);

    }

}

//窗口淡入效果,仅运行在2000/XP以上操作系统

EXPORT void FadeInOpen(HWND hWin)

{

    const TCHAR User32[] = TEXT("user32.dll");

    const CHAR SLWA[] = "SetLayeredWindowAttributes";//函数名使用ASCII码字符

    FARPROC pSLWA;

    int Value = 90;

    LONG stl = GetWindowLong(hWin, GWL_EXSTYLE);//检索扩展的窗口样式

    // 增加“分层窗口”样式

    stl |= WS_EX_LAYERED;  

    SetWindowLong(hWin,GWL_EXSTYLE,stl);

    //获取SetLayeredWindowAttributes在user32.dll中的地址

    pSLWA = GetProcAddress(GetModuleHandle(User32), (LPCSTR)SLWA);

    //设置分层窗口的不透明度和透明度颜色键

    pSLWA(hWin,0,0,LMA_ALPHA);

    ShowWindow(hWin, SW_SHOWNA);

    while (Value != 255)

    {

        pSLWA(hWin,Value,Value,LMA_COLORKEY + LMA_ALPHA);

        Sleep(DELAY_VALUE);

        Value += 15;

    }

    pSLWA(hWin,0,255,LMA_ALPHA);

}

//窗口淡出效果,仅运行在2000/XP以上操作系统

EXPORT void FadeOutClose(HWND hWin)

{

    const TCHAR User32[] = TEXT("user32.dll");

    const CHAR SLWA[] = "SetLayeredWindowAttributes";

    FARPROC pSLWA;

    int Value = 255;

    LONG stl = GetWindowLong(hWin, GWL_EXSTYLE);//检索扩展的窗口样式

    // 增加“分层窗口”样式

    stl |= WS_EX_LAYERED;

    SetWindowLong(hWin, GWL_EXSTYLE, stl);

    //获取SetLayeredWindowAttributes在user32.dll中的地址

    pSLWA = GetProcAddress(GetModuleHandle(User32), (LPCSTR)SLWA);

    //设置分层窗口的不透明度和透明度颜色键

    pSLWA(hWin, 0,255, LMA_ALPHA);

    while (Value != 0)

    {

        pSLWA(hWin, Value, Value, LMA_COLORKEY + LMA_ALPHA);

        Sleep(DELAY_VALUE);

        Value -= 15;

    }

}

FirstWindow.c

/*------------------------------------------------------------------------

 FileName:FirstWindow.c

 实验33:执行文件

 ;功能:简单窗口程序

;具有窗口的大部分基本特性,其中显示和退出使用了渐入和渐出效果

;该程序主要演示自己制作的dll的函数调用

 (c) bcdaren, 2024

-----------------------------------------------------------------------*/

#include <windows.h>

#include "resource.h"

#include "winResult.h"

#pragma comment(lib,"winResult.lib")

HWND hWinMain; //窗口句柄

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

    LPSTR lpCmdLine, int nShowCmd)//默认填写

{

    const TCHAR szClassName[] = TEXT("MyClass");

    const TCHAR szCaptionMain[] = TEXT("窗口特效演示");

    MSG msg;      //MSG 结构变量

    WNDCLASSEX wndclass; //WNDCLASSEX结构变量

    wndclass.style = CS_HREDRAW | CS_VREDRAW;//重叠窗口

    wndclass.lpfnWndProc = WndProc;//回调函数指针

    wndclass.cbClsExtra = 0;

    wndclass.cbWndExtra = 0;

    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);//窗口背景色

    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);

    wndclass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));

    wndclass.lpszMenuName = NULL;//菜单

    wndclass.hInstance = hInstance;//实例句柄

    wndclass.cbSize = sizeof(WNDCLASSEX);

    wndclass.hIconSm = NULL;

    wndclass.lpszClassName = szClassName;

    if (!RegisterClassEx(&wndclass))

    {

        MessageBox(0, TEXT("This program requires Windows NT!"),

            szClassName, MB_ICONERROR);

        return 0;

    }

    hWinMain = CreateWindowEx(WS_EX_CLIENTEDGE,

        szClassName,//窗口类名

        szCaptionMain,//窗口标题

        WS_OVERLAPPEDWINDOW,     //窗口样式

        GetSystemMetrics(SM_CXSCREEN) / 4,

        GetSystemMetrics(SM_CYSCREEN) / 4,

        GetSystemMetrics(SM_CXSCREEN) / 2,

        GetSystemMetrics(SM_CYSCREEN) / 2,

        NULL, // 父窗口句柄

        NULL, // 窗口菜单句柄

        hInstance, // 程序实例句柄

        NULL); // 创建参数

    //ShowWindow(hWinMain, nShowCmd); //显示窗口

    FadeInOpen(hWinMain);//外部链接库函数

    UpdateWindow(hWinMain);

    while (GetMessage(&msg, NULL, 0, 0))

    {

        TranslateMessage(&msg);

        DispatchMessage(&msg);

    }

    return msg.wParam;

}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)

{

    HDC hdc;

    PAINTSTRUCT ps;

    RECT rect;

    const TCHAR szText[] = TEXT("Welocome to 编程达人!");

    switch (message)

    {

    case WM_PAINT:

        hdc = BeginPaint(hwnd, &ps);

        GetClientRect(hwnd,&rect);

        DrawText(hdc,szText,-1,&rect,DT_SINGLELINE | DT_CENTER |DT_VCENTER);

        EndPaint(hwnd, &ps);

        return 0;

    case WM_CLOSE:

        FadeOutClose(hwnd);//外部链接库函数

        DestroyWindow(hwnd);

        return 0;

    case WM_DESTROY:

        PostQuitMessage(0);

        return 0;

    }

    return DefWindowProc(hwnd, message, wparam, lparam);

}

运行

图5-2 FirstWindow窗口程序

       ●winResult.dll中导出表的定位:

    数据目录项:

00000170   10 25 00 00 90 00 00 00  A0 25 00 00 64 00 00 00   .%......?..d...

00000180   00 40 00 00 F8 00 00 00  00 00 00 00 00 00 00 00   .@..?..........

00000190   00 00 00 00 00 00 00 00  00 50 00 00 7C 01 00 00   .........P..|...

000001A0   F0 20 00 00 70 00 00 00  00 00 00 00 00 00 00 00   ?..p...........

000001B0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................

000001C0   60 21 00 00 40 00 00 00  00 00 00 00 00 00 00 00   `!..@...........

000001D0   00 20 00 00 8C 00 00 00  00 00 00 00 00 00 00 00   . ..?..........

000001E0   00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00   ................

   

●导出表位于数据目录项的第0项。导出表RVA为00002510H,大小为90H。

节表:

000001F0   2E 74 65 78 74 00 00 00  A4 0F 00 00 00 10 00 00   .text...?......

00000200   00 10 00 00 00 04 00 00  00 00 00 00 00 00 00 00   ................

00000210   00 00 00 00 20 00 00 60  2E 72 64 61 74 61 00 00   .... ..`.rdata..

00000220   62 09 00 00 00 20 00 00  00 0A 00 00 00 14 00 00   b.... ..........

00000230   00 00 00 00 00 00 00 00  00 00 00 00 40 00 00 40   ............@..@

00000240   2E 64 61 74 61 00 00 00  8C 03 00 00 00 30 00 00   .data...?...0..

00000250   00 02 00 00 00 1E 00 00  00 00 00 00 00 00 00 00   ................

00000260   00 00 00 00 40 00 00 C0  2E 72 73 72 63 00 00 00   ....@..?rsrc...

00000270   F8 00 00 00 00 40 00 00  00 02 00 00 00 20 00 00   ?...@....... ..

00000280   00 00 00 00 00 00 00 00  00 00 00 00 40 00 00 40   ............@..@

00000290   2E 72 65 6C 6F 63 00 00  7C 01 00 00 00 50 00 00   .reloc..|....P..

000002A0   00 02 00 00 00 22 00 00  00 00 00 00 00 00 00 00   ....."..........

000002B0   00 00 00 00 40 00 00 42  00 00 00 00 00 00 00 00   ....@..B........

    ●导出表位于.rdata节区,FOA地址为:2510H-2000H+1400H=1910H。

    导出表描述符:

00001910   00 00 00 00 FF FF FF FF  00 00 00 00 60 25 00 00   ........`%..

00001920   01 00 00 00 04 00 00 00  04 00 00 00 38 25 00 00   ............8%..

00001930   48 25 00 00 58 25 00 00  F0 10 00 00 10 10 00 00   H%..X%..?......

00001940   C0 11 00 00 A0 12 00 00  6E 25 00 00 7B 25 00 00   ?..?..n%..{%..

00001950   87 25 00 00 92 25 00 00  00 00 01 00 02 00 03 00   ?..?..........

00001960   77 69 6E 52 65 73 75 6C  74 2E 64 6C 6C 00 41 6E   winResult.dll.An

00001970   69 6D 61 74 65 43 6C 6F  73 65 00 41 6E 69 6D 61   imateClose.Anima

00001980   74 65 4F 70 65 6E 00 46  61 64 65 49 6E 4F 70 65   teOpen.FadeInOpe

00001990   6E 00 46 61 64 65 4F 75  74 43 6C 6F 73 65 00 00   n.FadeOutClose..

typedef struct _IMAGE_EXPORT_DIRECTORY {

    DWORD   Characteristics;               // 00 00 00 00

    DWORD   TimeDateStamp;              // FF FF FF FF

    WORD    MajorVersion;               // 00 00

    WORD    MinorVersion;               // 00 00

    DWORD   Name;                       // 模块名称的RVA:00002560H

    DWORD   Base;                     // 导出函数序号的基准值:01

    DWORD   NumberOfFunctions;          // 导出函数的数量:04

    DWORD   NumberOfNames;             // 导出函数名称的数量:04

    DWORD   AddressOfFunctions;         // 导出函数地址表的RVA:00002538H

    DWORD   AddressOfNames;              // 导出函数名称表的RVA:00002548H

    DWORD   AddressOfNameOrdinals;      // 导出函数序号表的RVA:00002558H

} IMAGE_EXPORT_DIRECTORY, *PIMAGE_EXPORT_DIRECTORY;

●导出函数地址表的RVA:00002538H对应的FOA地址为00001938。

F0 10 00 00 10 10 00 00 C0 11 00 00 A0 12 00 00

●导出函数名称表的RVA:00002548H对应的FOA地址为00001948。

6E 25 00 00 7B 25 00 00 87 25 00 00 92 25 00 00

0000196E:AnimateClose

0000197B:AnimateOpen

00001987:FadeInOpen

00001992:FadeOutClose

●导出函数序号表的RVA:00002558H对应的FOA地址为00001958。

00 00 01 00 02 00 03 00

●导出函数地址验证

第一步:将FirstWindow.exe拖入OD调试器,找到FadwInOpen函数的调用,F2下断点,如图5-3所示:

图5-3 FadwInOpen函数的调用

第二步:按下F7单步步入,进入FadwInOpen函数,入口地址为0x579511C0,如图5-4所示:

图5-4 FadwInOpen函数的入口

       第三步:打开内存映射窗口,找到winResult.dll模块,模块基址为0x57950000,如图5-5所示:

图5-5winResult.dll模块

FadwInOpen函数入口地址0x579511C0 = 0x57950000(基址)+0x 000011C0(RVA)。

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

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

相关文章

【数据结构与算法】Divide and Conquer

4.4 Divide and Conquer 1) 概述 分治思想 将大问题划分为两个到多个子问题子问题可以继续拆分成更小的子问题&#xff0c;直到能够简单求解如有必要&#xff0c;将子问题的解进行合并&#xff0c;得到原始问题的解 之前学过的一些经典分而治之的例子 二分查找快速排序归并…

九、Drf序列化器

九、序列化器 9.1序列化 从数据库取QuerySet或数据对象转换成JSON 9.1.1序列化器的简易使用 #新建一张部门表 class Depart(models.Model):titlemodels.CharField(verbose_name部门,max_length32)ordermodels.IntegerField(verbose_name顺序)countmodels.IntegerField(verb…

软件测试学习笔记丨allure学习指南

本文转自测试人社区&#xff0c;原文链接&#xff1a;https://ceshiren.com/t/topic/32336 安装与下载 需要下载本地文件&#xff0c;并且添加到环境变量里 windows&#xff1a;下载&#xff0c;解压&#xff0c;并配置环境变量 mac&#xff1a;brew install allure 环境变量…

Docsify搭建个人博客

前提&#xff1a;电脑安装了Node.js 安装到本地 CMD命令下输入node -v查看是否已经安装了Node.js 安装docsify-cli工具&#xff1a;npm i docsify-cli -g 使用git下载docsify-Plus项目&#xff0c;Gitee地址&#xff1a;https://gitee.com/librarycodes/docsify-plus cd…

Linux的启动流程、移植到开发板

1、linux驱动开发与裸机开发的区别 Linux系统驱动和裸机驱动的主要区别在于运行时的环境和依赖。Linux系统驱动依赖于Linux内核提供的API和服务&#xff0c;而裸机驱动则是在没有操作系统支持的情况下直接与硬件交互。因此&#xff0c;两者的开发和调试方法也有很大差异。 2、…

【H2O2|全栈】关于CSS(11)flex——更加优雅的布局

目录 CSS3入门 前言 准备工作 布局优化 如何使用flex布局 容器与成员 概念 轴线 容器的属性 成员的属性 预告和回顾 后话 CSS3入门 前言 本系列博客主要介绍CSS有关知识点&#xff0c;当前章节讲述CSS3相关内容。 本章节讲述flex布局的相关知识。 部分内容仅代…

PCB缺陷检测数据集 xml 可转yolo格式 ,共10688张图片

PCB缺陷检测数据集&#xff08;yolov5,v7,v8&#xff09; 数据集总共有两个文件夹&#xff0c;一个是pcb整体标注&#xff0c;一个是pcb部分截图。 整体标注有6个分类&#xff0c;开路&#xff0c;短路等都已经标注&#xff0c;标注格式为xml&#xff0c;每个文件夹下有100多张…

【实时计算 Flink】SQL作业大状态导致反压的调优原理与方法

状态管理不仅影响应用的性能&#xff0c;还关系到系统的稳定性和资源的有效利用。如果状态管理不当&#xff0c;可能会导致性能下降、资源耗尽&#xff0c;甚至系统崩溃。本文为您介绍SQL作业大状态导致反压的调优原理与方法。 运行原理&#xff1a;状态算子的产生 作为一种特…

【Python】Twisted:让自定义网络应用开发变得简单

Twisted 是 Python 中一个成熟、功能强大的事件驱动网络编程框架。它支持多种协议&#xff0c;如 HTTP、FTP、SMTP 等&#xff0c;可以用于构建高性能的网络应用&#xff0c;包括网络服务器、客户端、代理服务器等。Twisted 的核心是基于事件驱动模型&#xff0c;能够有效处理大…

基于方块编码的图像压缩matlab仿真,带GUI界面

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1 编码单元的表示 4.2编码单元的编码 5.算法完整程序工程 1.算法运行效果图预览 (完整程序运行后无水印) 下图是随着方块大小的变化&#xff0c;图像的压缩率以及对应的图像质量指标PSN…

Python OpenCV精讲系列 - 三维重建深入理解(十七)

&#x1f496;&#x1f496;⚡️⚡️专栏&#xff1a;Python OpenCV精讲⚡️⚡️&#x1f496;&#x1f496; 本专栏聚焦于Python结合OpenCV库进行计算机视觉开发的专业教程。通过系统化的课程设计&#xff0c;从基础概念入手&#xff0c;逐步深入到图像处理、特征检测、物体识…

SpringBoot项目-Thymeleaf安装

SpringBoot项目-Thymeleaf安装 参考文章:SpringBoot 整合Thymeleaf教程及使用方法 参考视频:模板引擎Thymeleaf快速入门 其实,参考的文章和视频,他们丢失了一些细节,我搞的时候还是有错 第1步:pom.xml增加依赖 <!-- SpringBoot集成thymeleaf模板 --><depe

QD1-P6 HTML常用标签:列表

本节视频 https://www.bilibili.com/video/BV1n64y1U7oj?p6 ‍ 本节学习HTML列表标签。HTML 列表有多种形式&#xff0c;最重要的有两种&#xff1a; 有序列表无序列表 一、有序列表 1.1 写法 <ol><li>首先</li><li>其次</li><li>最…

Window11 安装Java21教程

随着Java版本的迭代&#xff0c;最新的长期支持版本已经更新到Java21了&#xff0c;虽然笔者许多代码还是当年用Java8写的&#xff0c;但抱残守缺从来不适合IT人员&#xff0c;该来的我们始终要欣然面对。 其实随着各项技术的发展&#xff0c;Java许多组件现在其实都不需要或者…

Linux shell编程学习笔记86:sensors命令——硬件体温计

0 引言 同事们使用的Windows系统电脑&#xff0c;经常莫名其妙地装上了鲁大师&#xff0c;鲁大师的一项功能是显示系统cpu等硬件的温度。 在Linux系统中&#xff0c;sensors命令可以提供类似的功能。 1 sensors命令 的安装和配置 1.1 sensors命令 的安装 要使用sensors命…

华为OD机试 - 单向链表中间节点(Python/JS/C/C++ 2024 E卷 200分)

华为OD机试 2024E卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试真题&#xff08;Python/JS/C/C&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;私信哪吒&#xff0c;备注华为OD&#xff0c;加入华为OD刷题交流群&#xff0c;…

使用Spring Security实现用户-角色-资源的权限控制

文章目录 一、基于角色的请求控制二、加载用户角色信息三、角色与资源的关联四、测试角色权限控制1. 未登录用户访问受保护资源2. 登录用户访问受保护资源3. 角色不足的用户访问受保护资源&#xff08;把前面改成.roles("USER")&#xff09; 五、自定义异常处理1. 自…

数学建模算法与应用 第3章 非线性规划及其求解方法

目录 3.1 非线性规划概述 3.2 约束优化问题 3.3 无约束优化问题的Matlab求解 3.4 牛顿法与梯度下降法 Matlab代码示例&#xff1a;梯度下降法求解简单非线性问题 3.5 非线性规划在机器学习中的应用 习题 3 总结 非线性规划&#xff08;Nonlinear Programming, NLP&…

华为OD机试 - 人数最多的站点(Java 2024 E卷 100分)

华为OD机试 2024E卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;E卷D卷A卷B卷C卷&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;私信哪吒&#xff0c;备注华为OD&#xff0c;加…

A2P云短信,是什么意思?

中国联通国际公司产品之 A2P 云短信 一站式国际通信服务&#xff0c;助力企业拓展国际业务&#xff0c;轻松触达全球客户 在全球化日益加深的今天&#xff0c;企业要想在竞争激烈的国际市场中脱颖而出&#xff0c;不仅需要优质的产品和服务&#xff0c;更需要高效的沟通渠道来…