加载中,请稍等...

保护模式/2.段描述符

段描述符

20210325151734

  • S位:用于指定述符的类型(Descriptor Type)。当该位是“0”时,表示是一个系统段;为“1” 时,表示是一个代码段或者数据段(堆栈段也是特殊的数据段)
  • DPL:表示述符的特权级(Descriptor Privilege Level,DPL)。这两位用于指定段的特权级。共 有 4 种处理器支持的特权级别,分别是 0、1、2、3,其中 0 是最高特权级别,3 是最低特权级别。 刚进入保护模式时执行的代码具有最高特权级 0(可以看成是从处理器那里继承来的),这些代码通 常都是操作系统代码,因此它的特权级别最高。每当操作系统加载一个用户程序时,它通常都会指 定一个稍低的特权级,比如 3 特权级。不同特权级别的程序是互相隔离的,其互访是严格限制的, 而且有些处理器指令(特权指令)只能由 0 特权级的程序来执行,为的就是安全
  • G位是粒度(Granularity)位,用于解释段界限的含义。当 G 位是“0”时,段界限以字节为 单位。此时,段的扩展范围是从 1 字节到 1 兆字节(1B~1MB), 因 为 述 符 中 的 界 限 值 是 20 位 的。相反,如果该位是“1”, 那 么 , 段 界 限 是 以 4KB 为单位的。这样,段的扩展范围是从 4KB 到 4GB。
  • P位 段是否有效 1有效 0无效
  • D/B 位是“默认的操作数大小”(Default Operation Size)或者“默认的堆栈指针大小”(Default Stack Pointer Size),又或者“上部边界”(Upper Bound)标志,主要为了能够在32位处理器上兼容运行16位保护模式的程序
    • D:代码段 用于指示指令中默认的 偏移地址和操作数尺寸。D=0 表示指令中的偏移地址或者操作数是 16 位的;D=1,指示 32 位的 偏移地址或者操作数
    • B:堆栈段 用于在进行隐式的堆栈操作时,是使用 SP 寄存器还是 ESP 寄存器。隐式的堆栈操作指令包括 push、pop 和 call 等。如果该位是“0”,在访问那个段时, 使用 SP 寄存器,否则就是使用 ESP 寄存器。同时,B 位的值也决定了堆栈的上部边界。如果 B=0, 那么堆栈段的上部边界(也就是 SP 寄存器的最大值)为 0xFFFF;如果 B=1,那么堆栈段的上部 边界(也就是 ESP 寄存器的最大值)为 0xFFFFFFFF。
    • B=0 G=1 向上拓展 在普通数据段(ES,DS,FS,GS) B=0 是无效的
  • TYPE 字段共 4 位,用于指示述符的子类型,或者说是类别。

    • 对于数据段来 说,这 4 位分别是 X、E、W、A 位;

      X E W A 描述符类别 含义
      0 0 0 X 数据 只读
      0 0 1 X 数据 读,写
      0 1 0 X 数据 只读,向下扩展
      0 0 0 X 数据 读,写,向下扩展
    • 对于代码段来说,这 4 位则分别是 X、C、R、A 位;

      X C R A 描述符类别 含义
      1 0 0 X 代码 只执行
      1 0 1 X 代码 执行,读
      1 1 0 X 代码 只执行,依从的代码段
      1 1 1 X 代码 执行,读,依从的代码段
    • X 表示是否可以执行(eXecutable)。数据段总是不可执行的,X=0;代码段总是 可以执行的,因此,X=1

    • A 数据段和代码段的 A 位是已访问(Accessed)位,用于指示它所指向的段最近是否被访问过。 在述符创建的时候,应该清零。之后,每当该段被访问时,处理器自动将该位置“1”。对该位的 清零是由软件(操作系统)负责的,通过定期监视该位的状态,就可以统计出该段的使用频率。当 内存空间紧张时,可以把不经常使用的段退避到硬盘上,从而实现虚拟内存管理。

    • 对于数据段来说

      • E 位指示段的扩展方向。E=0 是向上扩展的,也就是向高地址方向扩展的,不包含limit, 是普通的数据段;E=1 是向下扩展的,也就是向低地址方向扩展的,包含limit,通常是堆栈段
      • W 位指示段 的读写属性,或者说段是否可写,W=0 的段是不允许写入的,否则会引发处理器异常中断;W=1 的段是可以正常写入的
    • 对于代码段来说

      • C 位指示段是否为特权级依从的(Conforming)。 C=0 表示非依从的代码段, 这样的代码段可以从与它特权级相同的代码段调用,或者通过门调用;C=1 表示允许从低特权级的 程序转移到该段执行。
      • R 位指示代码段是否允许 读出。代码段总是可以执行的,但是,为了防止程序被破坏,它是不能写入的。至于是否有读出的可 能,由 R 位指定。R=0 表示不能读出,如果企图去读一个 R=0 的代码段,会引发处理器异常中断; 如果 R=1,则代码段是可以读出的,即可以把这个段的内容当成 ROM 一样使用。
        • 码段是不可读的,那处理器怎么从里面取指令执行呢?事实上,这里的 R 属性并非用来限制处理器,而是用来限制程序和指令的行为。一个典型的例子是使用段超越前缀 “CS:”来访问代码段中的内容
  

保护模式/1.CPU尝试

CPU 架构

  1. Risc架构
    1. 手机 嵌入式
    2. 优点:少耗电,使用的时间更长
    3. 指令集:定长
    4. arm属于此架构
  2. Cisc架构
    1. U V I 低功耗省电
    2. 指令集:变长

mov eax,dword ptr ds:[0x12345678]

执行流程:

I5 :

  1. 预取 :取指针
  2. 译码1 :获取原操作数 (指令)
  3. 译码2 :计算地址或者寄存器
  4. 执行 :发送CPU执行
  5. 回写 :执行完回写

I7+ :

  1. 预取 :取指针
  2. 译码1 :获取原操作数 (指令)
  3. 取目标数
  4. 译码2 :计算地址或者寄存器
  5. 执行 :发送CPU执行
  6. 回写 :执行完回写

支持多级流水线 这种CPU内部协同工作 叫做超级线程

CPU:预计算 不影响结果的前提 去执行,如下 VS并行执行

1
2
xor eax,eax
xor ecx,ecx

逻辑地址+gtd.ds.base = 线性地址

线性地址拆成物理地址

  

linux下编译yara

bash: ./build.sh: /bin/sh^M: bad interpreter: No such file or directory

q:执行.sh脚本时,报错 “start.sh /bin/bash^M: 坏的解释器:没有那个文件或目录”,因为 .sh文件是从windows拷贝过来的,所以多了\r,执行命令,把文件中的\r 替换成空白

sed -i 's/\r$//' build.sh

参考链接

error: AC_CONFIG_MACRO_DIRS([m4]) conflicts with ACLOCAL_AMFLAGS=-. m4

1
2
3
4
apt-get install dos2unix 

dos2unix *.sh
dos2unix *.am

冲突原因,在windows下载,在linux上使用,行结尾标志不一样,需要使用dos2unix转换一下即可

  

hips主动防御

HIPS

1.进程、线程,过滤+保护

  • PsSetCreateProcessNotifyRoutineEx 进程创建和退出时通知
  • PsCreateThreadNotifyRoutineEx 线程创建和退出时通知
  • ObRegisterCallbacks 对操作进程和线程句柄的回调

2.注册表过滤+保护

  • cmregistercallback

3.模块加载过滤

  • PsSetLoadImageNotifyRoutine 可执行模板加载时通知

4.文件过滤+保护

  • minifilter

5.网络过滤

  • wfp
  

一个藏在正常程序下的C#木马样本分析

前言

本文章只分析了木马加载的过程,不分析木马功能

背景

护网期间一个朋友发给我的样本让我帮忙分析一下

分析过程

  1. ExeinfoPe查了一下是一个C#的程序,然后加了个混淆直接de4dot处理一下拉入dnspy

    20210415111921
    反编译之后看没发现什么http请求,启动函数运行了一个frmMain窗体,看了看代码什么的发现是一个正常的窗体程序,什么也没发现

  2. 动态调试

    20210415112425
    程序肯定是有问题的,于是就动态调试发现,这个程序是一个加载程序,他找了一套正常程序的源码重写了一个属性的set函数 在set函数中,从资源文件拿到dll然后加载dll

  3. 利用反射加载dll之后 反射调用函数

    1. Type type = assembly.GetTypes()[0];

    2. MethodInfo method = type.GetMethod(“Click”);

    3. method.Invoke(0, parameters);

      20210415112756

      20210415112805

      反射获取到第一个类,然后获取该类的Client函数,参数分别是 “OVAGp”,”bAJs”,”Finast”

  4. 直接dnspy动态调试 dump出来dll文件

  5. dll也是C#的 然后加了混淆直接de4dot处理 然后拖入dnspy

  6. dnspy dll反编译

    20210415113101

    看着这样一个正常的程序,我们直接找一个Client的函数

    20210415113204

    一眼就是反射调用,不过他是通过vb.net的

    dll是报错在图片中的 这个不用关注 我们直接把处理之后的的rawAssembly 给dump出来就好了

  7. dump出来的dll还是一个C#的 是有复杂的混淆的 de4dot处理不了,我直接找画眉师傅给处理了一下然后拉到dnspy里面看了看 就是真实的木马样本。

总结

此样本是一个加载器 首先从资源文件中拿到dll通过C#的反射加载起来,然后该dll再次从资源文件中拿到一个图片,从图片中提取出来功能dll,通过Microsoft.VisualBasic库的反射加载起来功能dll,

加载器和dll都是伪装成了正常的程序,如果不仔细看的时候 就可能以为是一个正常程序放过去了

linux-docker

docker常用命令

  1. docker run
    20201123144905
    20201123144928

  2. 删除docker容器

    1. docker rm $(docker ps -a -q)一次删除所有停止的容器
    2. docker rm <CONTAINER ID|NAME> <CONTAINER ID|NAME> 删除单个或多个容器。
  3. 启动/停止/连接容器

    1. docker start <CONTAINER ID|NAME> 启动容器
    2. docker stop <CONTAINER ID|NAME> 停止容器
    3. docker attach <CONTAINER ID|NAME> 附加到当前正在运行的容器

docker .net core生成影像

  1. docker build -t radarserver . 生成影像
  2. docker run -itd -p 5000:5000 imageid arg 生成容器
  3. docker commit -m="has update" -a="zpt" 5a76c9bb0d02 zpt/ubuntu:v2 容器更新镜像
    1. -m:提交的描述信息
    2. -a:指定镜像作者
    3. 5a76c9bb0d02:容器ID
    4. runoob/ubuntu:v2:指定要创建的目标镜像名

参考文章:
参考链接

  

:D 一言句子获取中...