linux2.4内核模块隐藏,Linux环境下的高级隐藏技术

2023-10-30

摘要:本文深入分析了Linux环境下文件、进程及模块的高级隐藏技术,其中包括:Linux可卸载模块编程技术、修改内存映象直接对系统调用进行修改技术,通过虚拟文件系统proc隐藏特定进程的技术。

隐藏技术在计算机系统安全中应用十分广泛,尤其是在网络攻击中,当攻击者成功侵入一个系统后,有效隐藏攻击者的文件、进程及其加载的模块变得尤为重要。本文将讨论Linux系统中文件、进程及模块的高级隐藏技术,这些技术有的已经被广泛应用到各种后门或安全检测程序之中,而有一些则刚刚起步,仍然处在讨论阶段,应用很少。

1.隐藏技术

1.1.Linux下的中断控制及系统调用

Intel x86系列微机支持256种中断,为了使处理器比较容易地识别每种中断源,把它们从0~256编号,即赋予一个中断类型码n,Intel把它称作中断向量。

Linux用一个中断向量(128或者0x80)来实现系统调用,所有的系统调用都通过唯一的入口system_call来进入内核,当用户动态进程执行一条int 0x80汇编指令时,CPU就切换到内核态,并开始执行system_call函数,system_call函数再通过系统调用表sys_call_table来取得相应系统调用的地址进行执行。系统调用表sys_call_table中存放所有系统调用函数的地址,每个地址可以用系统调用号来进行索引,例如sys_call_table[NR_fork]索引到的就是系统调用sys_fork()的地址。

Linux用中断描述符(8字节)来表示每个中断的相关信息,其格式如下:

偏移量31….16  一些标志、类型码及保留位

段选择符      偏移量15….0

所有的中断描述符存放在一片连续的地址空间中,这个连续的地址空间称作中断描述符表(IDT),其起始地址存放在中断描述符表寄存器(IDTR)中,其格式如下:

32位基址值  界限

其中各个结构的相应联系可以如下表示:

通过上面的说明可以得出通过IDTR寄存器来找到system_call函数地址的方法:根据IDTR寄存器找到中断描述符表,中断描述符表的第0x80项即是system_call函数的地址,这个地址将在后面的讨论中应用到。

1.2.Linux 的LKM(可装载内核模块)技术

为了使内核保持较小的体积并能够方便的进行功能扩展,Linux系统提供了模块机制。模块是内核的一部分,但并没有被编译进内核,它们被编译成目标文件,在运行过程中根据需要动态的插入内核或者从内核中移除。由于模块在插入后是作为Linux内核的一部分来运行的,所以模块编程实际上就是内核编程,因此可以在模块中使用一些由内核导出的资源,例如Linux2.4.18版以前的内核导出系统调用表(sys_call_table)的地址,这样就可以根据该地址直接修改系统调用的入口,从而改变系统调用。在模块编程中必须存在初始化函数及清除函数,一般情况下,这两个函数默认为init_module()以及clearup_module(),从2.3.13内核版本开始,用户也可以给这两个函数重新命名,初始化函数在模块被插入系统时调用,在其中可以进行一些函数及符号的注册工作,清除函数则在模块移除系统时进行调用,一些恢复工作通常在该函数中完成。

1.3.Linux下的内存映像

/dev/kmem是一个字符设备,是计算机主存的映像,通过它可以测试甚至修改系统,当内核不导出sys_call_table地址或者不允许插入模块时可以通过该映像修改系统调用,从而实现隐藏文件、进程或者模块的目的。

1.4.proc 文件系统

proc文件系统是一个虚拟的文件系统,它通过文件系统的接口实现,用于输出系统运行状态。它以文件系统的形式,为操作系统本身和应用进程之间的通信提供了一个界面,使应用程序能够安全、方便地获得系统当前的运行状况何内核的内部数据信息,并可以修改某些系统的配置信息。由于proc以文件系统的接口实现,因此可以象访问普通文件一样访问它,但它只存在于内存之中。

2.技术分析

2.1 隐藏文件

Linux系统中用来查询文件信息的系统调用是sys_getdents,这一点可以通过strace来观察到,例如strace ls 将列出命令ls用到的系统调用,从中可以发现ls是通过sys_getedents来执行操作的。当查询文件或者目录的相关信息时,Linux系统用sys_getedents来执行相应的查询操作,并把得到的信息传递给用户空间运行的程序,所以如果修改该系统调用,去掉结果中与某些特定文件的相关信息,那么所有利用该系统调用的程序将看不见该文件,从而达到了隐藏的目的。首先介绍一下原来的系统调用,其原型为:

int sys_getdents(unsigned int fd, struct dirent *dirp,unsigned int count)

其中fd为指向目录文件的文件描述符,该函数根据fd所指向的目录文件读取相应dirent结构,并放入dirp中,其中count为dirp中返回的数据量,正确时该函数返回值为填充到dirp的字节数。下图是修改后的系统调用hacked_getdents执行流程。

108929.gif

图 系统调用hacked_getdents执行流程

图中的hacked_getdents函数实际上就是先调用原来的系统调用,然后从得到的dirent结构中去除与特定文件名相关的文件信息,从而应用程序从该系统调用返回后将看不到该文件的存在。

应该注意的是,一些较新的版本中是通过sys_getdents64来查询文件信息的,但其实现原理与sys_getdents基本相同,所以在这些版本中仍然可以用与上面类似的方法来修改该系统调用,隐藏文件。

2.2 隐藏模块

上面分析了如何修改系统调用以隐藏特定名字的文件,在实际的处理中,经常会用模块来达到修改系统调用的目的,但是当插入一个模块时,若不采取任何隐藏措施,很容易被对方发现,一旦对方发现并卸载了所插入的模块,那么所有利用该模块来隐藏的文件就暴露了,所以应继续分析如何来隐藏特定名字的模块。Linux中用来查询模块信息的系统调用是sys_query_module,所以可以通过修改该系统调用达到隐藏特定模块的目的。首先解释一下原来的系统调用,原来系统调用的原型为:

int sys_query_module(const char *name, int which, void *buf, size_t bufsize , size_t *ret)

如果参数name不空,则访问特定的模块,否则访问的是内核模块,参数which说明查询的类型,当which=QM_MODULES时,返回所有当前已插入的模块名称,存入buff, 并且在ret中存放模块的个数,buffsize是buf缓冲区的大小。在模块隐藏的过程中只需要对which=QM_MODULES的情况进行处理就可以达到目的。修改后的系统调用工作过程如下:

1)调用原来的系统调用,出错则返回错误代码;

2)如果which不等于QM_MODULES,则不需要处理,直接返回。

3)从buf的开始位置进行处理,如果存在特定的名字,则将后面的模块名称向前覆盖该名字。

4)重复3),直到处理处理完所有的名字,正确返回。

2.3 隐藏进程

在Linux中不存在直接查询进程信息的系统调用,类似于ps这样查询进程信息的命令是通过查询proc文件系统来实现的,在背景知识中已经介绍过proc文件系统,由于它应用文件系统的接口实现,因此同样可以用隐藏文件的方法来隐藏proc文件系统中的文件,只需要在上面的hacked_getdents中加入对于proc文件系统的判断即可。由于proc是特殊的文件系统,只存在于内存之中,不存在于任何实际设备之上,所以Linux内核分配给它一个特定的主设备号0以及一个特定的次设备号1,除此之外,由于在外存上没有与之对应的i节点,所以系统也分配给它一个特殊的节点号PROC_ROOT_INO(值为1),而设备上的1号索引节点是保留不用的。通过上面的分析,可以得出判断一个文件是否属于proc文件系统的方法:

1)得到该文件对应的inode结构dinode;

2)if (dinode->i_ino == PROC_ROOT_INO && !MAJOR(dinode->i_dev) && MINOR(dinode->i _dev) == 1) {该文件属于proc文件系统}

通过上面的分析,给出隐藏特定进程的伪代码表示:

hacket_getdents(unsigned int fd, struct dirent *dirp, unsigned int count)

{

调用原来的系统调用;

得到fd所对应的节点;

if(该文件属于proc文件系统&&该文件名需要隐藏)

{从dirp中去掉该文件相关信息}

}

2.4 修改系统调用的方法

现在已经解决了如何修改系统调用来达到隐藏的目的,那么如何用修改后的系统调用来替换原来的呢?这个问题在实际应用中往往是最关键的,下面将讨论在不同的情况下如何做到这一点。

(1)当系统导出sys_call_table,并且支持动态的插入模块的情况下:

在Linux内核2.4.18版以前,这种内核配置是非常普遍的。这种情况下修改系统调用非常容易,只需要修改相应的sys_call_table表项,使其指向新的系统调用即可。下面是相应的代码:

int orig_getdents(unsigned int fd, struct dirent *dirp, unsigned int count)

int init_module(void)

/*初始化模块*/

{

orig_getdents=sys_call_table[SYS_getdents];    //保存原来的系统调用

orig_query_module=sys_call_table[SYS_query_module]

sys_call_table[SYS_getdents]=hacked_getdents;  //设置新的系统调用

sys_call_table[SYS_query_module]=hacked_query_module;

return 0; //返回0表示成功

}

void cleanup_module(void)

/*卸载模块*/

{

sys_call_table[SYS_getdents]=orig_getdents;    //恢复原来的系统调用

sys_call_table[SYS_query_module]=orig_query_module;

}

(2)在系统并不导出sys_call_table的情况下:

linux内核在2.4.18以后为了安全起见不再导出sys_call_table符号,从而无法直接获得系统调用表的地址,那么就必须找到其他的办法来得到这个地址。在背景知识中提到了/dev/kmem是系统主存的映像,可以通过查询该文件来找到sys_call_table的地址,并对其进行修改,来使用新的系统调用。那么如何在系统映像中找到sys_call_table的地址呢?让我们先看看system_call的源代码是如何来实现系统调用的(代码见/arch/i386/kernel/entry.S):

ENTRY(system_call)

pushl %eax      # save orig_eax

SAVE_ALL

GET_CURRENT(%ebx)

cmpl $(NR_syscalls),%eax

jae badsys

testb $0x02,tsk_ptrace(%ebx)  # PT_TRACESYS

jne tracesys

call *SYMBOL_NAME(sys_call_table)(,%eax,4)

movl %eax,EAX(%esp)    # save the return value

ENTRY(ret_from_sys_call)

这段源代码首先保存相应的寄存器的值,然后判断系统调用号(在eax寄存器中)是否合法,继而对设置调试的情况进行处理,在所有这些进行完后,利用call *SYMBOL_NAME(sys_call_table)(,%eax,4) 来转入相应的系统调用进行处理,其中的SYMBOL_NAME(sys_call_table)得出的就是sys_call_table的地址。从上面的分析可以看出,当找到system_call函数之后,利用字符匹配来寻找相应call语句就可以确定sys_call_table的位置,因为call something(,%eax,4)的机器指令码是0xff 0x14 0x85。所以匹配这个指令码就行了。至于如何确定system_call的地址在背景知识中已经介绍了,下面给出相应的伪代码:

struct{ //各字段含义可以参考背景知识中关于IDTR寄存器的介绍

unsigned short limit;

unsigned int base;

}__attribute__((packed))idtr;

struct{ //各字段含义可以参考背景知识中关于中断描述符的介绍

unsigned short off1;

unsigned short sel;

unsigned char none,flags;

unsigned short off2;

}__attribute__((packed))idt;

int kmem;

/ *下面函数用于从kemem对应的文件中偏移量为off处读取sz个字节至内存m处*/

void readkmem(void *m,unsigned off,int sz) {………}

/*下面函数用于从src读取count个字节至dest处*/

void weitekmem(void *src,void *dest,unsigned int count) {………..}

unsigned sct;  //用来存放sys_call_table地址

char buff[100]; //用于存放system_call函数的前100个字节。

char *p;

if((kmem=open(“/dev/kmem”,O_RDONLY))<0)

return 1;

asm(“sidt %0” “:=m” (idtr));          //读取idtr寄存器的值至idtr结构中

readkmem(&idt,idtr.base+8*0x80,sizeof(idt))    //将0x80描述符读至idt结构中

sys_ call_off=(idt.off2<<16)|idt.off1;       //得到system_call函数的地址。

readkmem(buff,sys_call_off,100)   //读取system_call函数的前100字节至buff

p=(char *)memmem(buff,100,”xffx14x85”,3);  //得到call语句对应机器码的地址

sct=(unsigned *)(p+3)            //得到sys_call_table的地址。

至此已经得到了sys_call_table在内存中的位置,这样在根据系统调用号就能够找到相应的系统调用对应的地址,修改该地址就可以使用新的系统调函数,具体的做法如下:

readkmem(&orig_getdents,sct+ SYS_getdents*4,4)//保存原来的系统调用

readkmem(&orig_query_module,sct+SYS_query_module*4,4);

writekmem(hacked_getdents,sct+SYS_getdents*4,4);//设置新的系统调用

writekmem(hacket_query_module,sct+SYS_query_module*4,4);

2.5 其他的相关技术

上面已经完全解决了隐藏的相关技术问题,在实际应用中,可以把启动模块或者进程的代码做成脚本加入到相应的启动目录中,假设你的Linux运行级别为3,则可以加到目录rc3.d中(该目录常存在于/etc/rc.d或者/etc目录下),然后把该脚本的名字改为可以隐藏的名字。另一种方法就是在一些启动脚本中加入启动你的模块或者进程的代码,但这样比较容易被发现,一个解决思路就是进程或模块启动以后马上恢复正常的脚本,由于系统关机时会向所有进程发送SIGHUP信号,可以在进程或模块中处理该信号,使该信号发生时修改启动脚本,重新加入启动模块的代码,这样当系统下次启动时又可以加载这个的模块了,而且管理员察看启动脚本时也不会发现异常。

3.结束语

本文对Linux环境下的一些高级隐藏技术进行了分析研究,其中所涉及的技术不仅可以用在系统安全方面,在其他方面也有重要的借鉴意义。由于Linux的开放特性,使得攻击者一旦获得了root权限就能够对系统进行较多的修改,所以避免第一次被入侵是至关重要的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

linux2.4内核模块隐藏,Linux环境下的高级隐藏技术 的相关文章

  • python读取串口数据 绘图_3.使用串口读取IMU数据并通过话题发布

    0x00 简介 我们的IMU扩展板是支持通过串口方式来读取IMU数据 现在代码已经开发完成 前面文章介绍的都是将IMU板插在树莓派上 然后使用树莓派的IIC接口来数据通信 因此不需要额外接线就可以发布imu话题的 若使用串口进行通信的话 若
  • 在Linux下安装jdk的步骤

    1 下载安装包 http www oracle com technetwork java javase downloads jdk8 downloads 2133151 html 版本 jdk 8u191 linux x64 tar gz
  • 确实卷,公司新来的00后卷王,我们这帮老油条真干不过.....

    都说00后躺平了 但是有一说一 该卷的还是卷 这不 前段时间我们公司来了个00后 工作没两年 跳槽到我们公司起薪18K 都快接近我了 后来才知道人家是个卷王 从早干到晚就差搬张床到工位睡觉了 最近和他聊了一次天 原来这位小老弟家里条件不太好
  • C#反编译工具:ILSpy

    参考 反编译软件ILSpy的使用教程 TONY5388的博客 CSDN博客 ilspy exe 总结 以前以为dnspy是反编译的 结果发现iLSpy是真的好用 可以选择生成不同C 版本的源码
  • SQLite数据库总结

    参考网址 https www cnblogs com stephen liu74 archive 2012 02 29 2328348 html 3种工作模式 1 SQLite完全内存数据库 在SQLite中 数据库通常是存储在磁盘文件中的
  • 【python】KNN模型训练及应用01

    目的应用 让电脑代替人工对图片分类 1 数据加载 from sklearn datasets import load iris from sklearn model selection import train test split fro
  • 今天终于知道了如果用layero获取layer弹窗中的子元素了

    通过layer弹出的ifram 想要获取里面的元素并且绑定相应的事件 以前一直不知道layero是什么意思 可以通过下面的代码自己体会一下 layer open type 2 title 文件管理 shadeClose true shade
  • 基于XStream的JavaBean与XML相互转换

    相对于JAXB XStream更简洁一些 常用注解 XStreamAlias 定义xml节点名 1 引入XStream依赖
  • 数据清洗分析导出遇到的一些问题

    本文简单记录一个学习过程 无技术含量 勿喷 环境 ambari 2 6 1 spark 2 1 python 3 6 oracle 11 2 sqoop 1 4 最近一直在测试数据采集 清洗 分析 导出 展示的一系列的工作 主要数据流程如下
  • 服务器定时重启问题排查

    上周主要处理了 两个生产问题 工作电脑没带 主要简述一下 每天的20 13分linux服务器 centos7 4 重新启动 应用服务接口类交易 耗时20秒 频发 这里先说一下服务器重启的问题 此次重启共发生三天 第一次主要排查管控平台 发现
  • 压缩感知与磁共振成像

    01 压缩感知原理和建模 传统的数据采样和重构需要遵循Nyquist采样定律 即采样频率必须大于信号频率带宽的2倍 才能完整的重建信号 如果采样频率低于2倍的频率带宽 信号在频域频谱搬移后就会发生混叠 产生伪影 压缩感知 Compresse
  • 【千奇百怪】PHP代码质检工具PHPCS分析介绍与使用

    前两天 还是在对一个代码质量检测平台维护的时候 遇到了好几个关于PHP质检的需求 而老平台上支持的php在新平台还未实现 于是简单研究了一下php的质检工具 准备接入新平台 系列文章目录 java自定义spotbugs检测器 PHP代码质检
  • cutlass 第一节:下载 编译 运行 cutlass 的一些备忘信息 ubuntu docker

    v100 cutlass start web site https developer nvidia com blog cutlass linear algebra cuda https github com NVIDIA cutlass
  • Qt开发 之 QWidget 和 QtQuick(QML) 写网页

    文章目录 1 准备工作 1 1 环境配置 1 2 Emsdk配置 1 2 1 配置环境文件 1 2 2 配置Emsdk的编译器 2 写两个简单的QWidget和QtQuick示例 2 1 QWidget 2 2 QtQuick 3 编译运行
  • 【KEIL-MDK】系列——主题配色

    文章目录 前言 一 更改主题配色 1 备份默认主题 2 替换配置文件 二 主题一 Sublime Theme风格 三 主题二 亮色风格 四 自定义主题配色 字体 下载地址 总结 前言 好看的主题 好看的界面 可以潜移默化的帮助我们提高生产力
  • 测试总结:如何写接口测试用例

    目录 一 接口测试用例基础知识 1 接口测试要测的是什么 2 接口测试的意义 二 接口测试用例设计方法 1 功能 检查接口基础功能 是否完成了业务逻辑要求 2 数据 分析接口的输入参数 覆盖各种可能的场景 3 性能 接口是否造成性能瓶颈 能
  • ctf-ping命令执行

    GXYCTF2019 Ping Ping Ping 现在做一下关于常见的绕过ping执行其他命令的姿势 启动环境 连接并输入参数 查看当前目录下都有什么 ls命令没有被过滤 并且知道flag就在这个目录下面 用cat查看的flag的时候发现
  • 降维和特征选择的关键方法介绍及MATLAB实现

    目录 概念理解 降维 特征选择 降维的方法 主成分分析 Principle Component Analysis PCA 方法 偏最小二乘法 Partial Least Squares PLS MATLAB实现 重点函数解读 例 光谱数据主
  • 数字货币DCEP

    上周新闻提到了区块链技术 号召大家学习和利用区块链技术 然后数字货币DCEP就浮出了水面 那么这个DCEP是什么呢 我根据自己的经验介绍下 如有不对请指正 DCEP是什么 DCEP是Digital Currency Electronic P

随机推荐

  • 软文营销创造优质内容才能打开市场产生共鸣

    内容是有效软文营销的基石 可满足多种用途 一般企业宣传都会以内容展现在网络上 形式可能包含新闻媒体 自媒体 论坛 问答 视频和其他形式 这些内容形式可以帮助生成 促进你的品牌知名度提升并增加业务收入 内容为王 只有内容优质才能在营销中产生共
  • Java实现区块链 --- 原理篇

    什么是区块链 区块链是由一个个记录着各种信息的小区块链接起来组成的一串链条 和链表类似 是一种数据结构 应用于未来互联化的社会 区块链特性 去中心化 区块链是分布式存储的 不存在中心点 所有每个节点都可以是中心 在生活中像银行 支付宝就属于
  • FFmpeg中编码类型为rawvideo无须解码直接显示测试代码

    在 https blog csdn net fengbingchun article details 93975325 中介绍过通过FFmpeg可以直接获取usb视频流并解码显示的测试代码 当时通过usb获取到的视频流编码类型为AV COD
  • macos 环境下搭建 windbg 虚拟机双机调试环境

    求职 阿哈哈哈广告来了 博主本人 23届落魄web安全 在线求职 本科学历有一段大厂实习 有缺人的大佬么或者有内推的大佬给个机会吧 求求啦 可以微信联系我给您简历 ocean888 文章底下有二维码 本次使用将在 macos 环境下搭建 w
  • flask入门教程(7) - 会话

    会话 flask提供了session对象 即会话 允许你在不同请求之间储存信息 这个对象相当于用密钥签名加密的cookie 即用户可以查看你的cookie 但是如果没有密钥就无法修改它 这是我的网站词神上的cookie 大家可以打开我的网站
  • blender_(uv应用)................http://digitalman.blog.163.com/blog/static/23874605620174172058299/...

    轻松学习Blender基础入门之九 UV 1 2017 06 21 14 24 49 分类 Blender 举报 字号 订阅 下载LOFTER 我的照片书 前言
  • LittleFs文件系统

    小型文件系统 littlefs 简介 LittleFs设计之初的重点特性是 1 低资源消耗 2 掉电保护 3 擦写均衡 本章节重点讨论第 2 和 3 这两个特性 第 1 个特性则贯穿在整个设计过程中 后文把LittleFs简称为lfs 1
  • FaceForensics++数据集下载,FaceForensics++: Learning to Detect Manipulated Facial Images

    FaceForensics 数据集下载 FaceForensics Learning to Detect Manipulated Facial Images 0 前言 如何运行 主要是前三个超参数 不同压缩率所需的空间需求 code 0 前
  • 数据集批量打标——shell脚本批量生成文件并重命名

    shell脚本批量生成文件并重命名 最近接到一个数据集标注的任务 使用的标注工具是LabelImg 使用前配置了环境Anaconda python 3 7 Linux 并在该环境下配置了pyqt5 数据集里的图片是一段视频逐帧抽图 要求在图
  • CCNA学习笔记九 NAT地址转换及优缺点

    网络地址转换 将很多的私网地址转换成公网IP Telnet 快 可以被拦截 ssh ssl加密 安全 改变IP包头 使目的地址 源地址或两个地址在包头中被不同的地址替换 路由器会保存一个转换表 当数据包回来的时候 还原成正确的私网地址 NA
  • LED数码管数字数据集

    LED数码管数字数据集 结合百度OCR取得很好效果 数据集结合百度的OCR百度的OCR https gitee com paddlepaddle PaddleOCR tree release 2 1 程序对应数据集训练进行目标检测识别 数据
  • 在github上托管属于自己的网页

    文章目录 前言 一 配置github 1 建立新的仓库 repository 二 配置git 1 git与github连接 2 测试git与github的连接 3 通过git上传 删除github仓库中的文件 4 网页显示 5 更换域名 总
  • Anaconda安装、源配置、虚拟环境搭建、及Python常用软件安装详解(详细教程)

    首先先介绍一下各种安装软件的基本介绍和常见命令 基本介绍 Anaconda 是可以便捷获取包且对包能够进行管理 同时对环境可以统一管理的发行版本 Anaconda包含了conda Python在内的超过180个科学包及其依赖项 conda是
  • 山东大学软件学院软件项目管理复习

    考前整理的复习题 有一些考试考到了 分享给下一级吧 1 项目目标的制约因素 项目范围 成本 进度计划 客户满意度 三个约束 范围 成本 时间 项目范围是为使客户满意必须做的工作 成本是完成项目所需要的费用 进度计划安排每项任务的起始时间和所
  • pre标签显示服务器端txt文档,区域设计pre显示标签pre

    区域设计pre显示标签pre 内容精选 换一换 在现场讲解汇报 实时监控等场景下 为了获得更好的演示效果 通常需要将态势感知服务的分析结果展示在大型屏幕上 如果只是单纯将控制台界面放大显示 视觉效果并不是很理想 此时可以利用综合大屏 展示专
  • Java并发修改异常ConcurrentModificationException

    import java util ArrayList import java util Iterator import java util ListIterator public class ConcurrentModificationEx
  • A complete log of this run can be found in:

    npm run dev npm ERR code ENOENT npm ERR syscall open npm ERR path C Users Administrator Desktop 项目名 package json npm ERR
  • 什么是设计模式?程序员如何学好设计模式?

    前几天 我给大家介绍了算法和数据结构的基础知识 后来又有小伙伴私信问我 小灰 你能不能也讲一讲设计模式的相关知识 没问题 对于程序员来说 设计模式也是必须要掌握的一项核心知识 我今天就来给大家重点讲一讲 编程的痛点 那么 到底什么是设计模式
  • 上海市“星光计划”职业院校技能大赛 网络安全竞赛试题任务书

    2023上海市 星光计划 职业院校技能大赛 网络安全竞赛试题任务书 2023上海市 星光计划 职业院校技能大赛 网络安全竞赛试题任务书 A模块基础设施设置 安全加固 200分 A 1 登录安全加固 A 2 Web安全加固 Web A 3 流
  • linux2.4内核模块隐藏,Linux环境下的高级隐藏技术

    摘要 本文深入分析了Linux环境下文件 进程及模块的高级隐藏技术 其中包括 Linux可卸载模块编程技术 修改内存映象直接对系统调用进行修改技术 通过虚拟文件系统proc隐藏特定进程的技术 隐藏技术在计算机系统安全中应用十分广泛 尤其是在