免杀初探(三)

分享者才是最大的受益者

前言

使用编译后的二进制文件,绕过防病毒软件

有一些防病毒软件绕过技术可以使用已经编译的代码执行,这些代码可以运行,即使它被防病毒引擎检测为恶意软件

两个子技术:

调试项目

时间戳

x86汇编体系结构

汇编语言的发展是为了取代机器代码,让开发人员更容易地创建程序。

汇编被认为是一种低级语言,因此,它可以直接访问计算机的硬件,如CPU。

使用汇编,开发人员不需要理解和编写机器代码。多年来,开发了许多编程语言,使开发人员的编程更加简单

有事我们不能反编译程序以获得其源代码,我们需要使用一种称为反汇编器的工具来将其从机 器代码转换为汇编代码。

image-20210819220422465

堆栈

堆栈是系统进程用来存储变量和函数参数等值的一种内存类型

简单记住一点:堆栈内存布局基于后进先出(LIFO)原则

image-20210819220531005

与线性的堆栈内存不同,堆内存是自由样式的动态分配内存

堆内存可以随时分配,也可以随时释放。它主要用于在操作系统运行时执行程序

汇编x86寄存器

x86体系结构定义了几个通用寄存器,以及一些用于特定操作的寄存器

专用存储单元是CPU的一个组成部分,由CPU直接使用。在今天的计算机中,大多数寄存器用于它们最初打算用于的操作以外的操作

例如,32位ECX/64位RCX寄存器通常用作循环和比较等操作的计数器,但也可用于其他操作。

一般用途

EAX:通常用于算术运算;在实践中,用作存储返回值的内存区域,并用于其他目的

EBX:通常用于存储内存地址

ECX:主要用作循环操作和比较的计数器

EDX:主要用于需要更多内存来存储值的算术除法和乘法运算

另外,EDX 存储用于I/O(输入/输出)操作的地址

索引和指针

有一些寄存器用作指向特定位置的指针:

ESI:源索引,主要用于将数据从一个内存区域传输到另一个内存区域目的地(EDI)

EDI:目标索引,主要用作从源内存区域(ESI)传输的数据的目标。 

ESP:作为堆栈帧定义的一部分,与EBP寄存器一起使用。尤指指向堆栈的顶部 

EBP:还用于定义堆栈帧,以及ESP寄存器。EBP指向堆栈的底部

EIP:指向CPU要执行的下一条指令

汇编x86常用的指令

• MOV:将一个值从右操作数复制到左操作数,例如,MOV eax,1
这将把值1复制到EAX寄存器。

• Add:将一个值从右操作数添加到左操作数,例如,添加eax,1
这将把1的值 添加到EAX寄存器中。如果EAX寄存器先前存储了值2,则执行后的值将为3

• 从左操作数中减去一个值,例如SUB eax,1
这将把存储在EAX寄存器中的值减去1,如果EAX寄存器先前存储了值3,则执行后的值将为2

• CMP:比较两个操作数之间的值,例如,CMP eax,2
如果EAX寄存器存储的值等于2,通常下面的指令将包含一个跳转指令,它将程序执行转移到代码中的另一个位置

• XOR:使用左操作数上的右操作数执行逻辑XOR操作。XOR指令还用于使CPU寄存器如EAX寄存器归零,例如,XOR EAX,EAX
这使用EAX寄存器中存储的值对EAX寄存器执行逻辑XOR,因此,它将使EAX的值归零。 

• PUSH:将一个值推到堆栈上,例如,PUSH EAX
这将把存储在EAX寄存器中的值推送到堆栈上

• pop:Pops最近推送到堆栈的值,例如POP eax,这将把推送到堆栈的最新值弹出到EAX寄存器中

• ret:从最近的函数/子例程调用返回

• JMP:无条件跳转到指定位置,例如JMP EAX,这将无条件地跳转到其值存储在EAX寄存器中的位置。 

• JE/jz:如果该值等于比较值或该值为零(ZF=1),则有条件地跳转到指定位置

• JNE/jnz:如果值不等于比较值或值不为零(ZF=0),则有条件地跳转到指定位置

CPU有三种不同的模式:

实模式

实模式寄存器用作16位短寄存器,如AX、BX、DX

保护模式

保护模式则基于32位长寄存器 ,如EAX、EBX、EDX等

长模式

64位长模式为32位长寄存器(如RAX、RBX和RDX)注册扩展

简单程序集x86程序

global  _main
    extern  _printf
    section .text
_main:
    push    string
    call    _printf
    add     esp, 4
    ret
string:
    db  'Hello World!', 10, 0

使用NASM汇编程序:https://www.nasm.us/pub/nasm/releasebuilds/2.15.05/win64/nasm-2.15.05-installer-x64.exe

默认安装即可

环境变量配置

image-20210819223304801

image-20210819223331672

gcc:http://mingw-w64.org/doku.php/download

默认安装即可

一样 也是要进行环境变量的配置

image-20210819230715326

image-20210819231041912

编译程序->nasm & gcc

nasm -fwin32 HelloWorld.asm

image-20210819224429355

gcc HelloWorld.obj -o HelloWorld.exe

image-20210819230945921

简要分析

第一行声明代码的主函数

第二行导入 printf函数

接下来,section指令后面跟着,text声明,将定义程序的文本段,它将包括所有的汇编指令

text部分包含两个子例程:将执行所有汇编指令的主子例程,以及将保存Hello World的String内存区域!

由db程序集指令声明的消息。 在_main子例程下,第一行用于推送Hello World!消息作为_printf函数的参数,该函数将在下一行调用。

下面的行call _printf将调用_printf函数并将执行传递给它。在_printf函数执行后, 我们的消息被打印到屏幕上,程序将返回到下一行,添加esp,4,这将依次清除堆栈。最后,ret的最后一行将返回,程序的执行终止

XOR对称加密

前言

它进行接受二进制101的二进制字节输入,并使用二进制密钥110对其进行加密。然后,程序用相同的密钥对XOR加密的数据进行解密

代码如下

IDEAL
MODEL SMALL
STACK 100h
DATASEG

    data db 101B
    key db  110B

CODESEG
encrypt:

        xor dl, key
        mov bl, dl
        ret

decrypt:

        xor bl, key
        mov dl, bl
        ret

start:
        mov ax, @data
        mov ds, ax
        mov bl, data
        mov dl, bl
        call encrypt
        call decrypt
exit:
    mov ah, 4ch
    int 21h
END start

运行代码->TASM

建议使用Turbo汇编程序(TASM)

https://sourceforge.net/projects/guitasm8086/

image-20210820085728886

快捷键->F9运行代码

简要分析

在DATASEG段中,有两个变量声明:要加密的数据和用作加密密钥的第二个变量

在CODESEG段中,我们有我们程序的实际代码或指令

这个段包括许多子例程, 每个子例程都有一个独特的目的:

encrypt子例程用于加密我们的数据

decrypt子例程用于在加密发生后进行解密数据

我们的程序从start子程序开始执行,并通过调用exit子程序结束,而exit子程序又使用两行代码来处理程序的退出过程

start函数的前两行初始化在DATASEG段内定义的变量,而第三行将输入变量分配 给bl,即16位BX寄存器的8位较低部分。

然后,通过调用encrypt指令调用加密子例程。 一旦执行被转移到encrypt子例程,我们的输入将被加密如下:

1. XOR指令加密DX下部的初始化数据 使用密钥变量注册(DL),该变量是用加密密钥初始化的。 
2. XOR加密的数据现在从DX寄存器(DL)的下部复制到BX寄存器(BL)的下部 。 
3. 最后,使用ret指令从函数返回。 程序从加密子例程返回后,将调用decrypt 子程序使用调用解密指令。 

一旦执行传递到decrypt子例程,输入将被解密如下:

1. XOR指令使用先前用加密密钥初始化的密钥操作数解密BX寄存器(BL)下 部的初始化数据,就像在加密阶段所做的那样。 
2. XOR加密的数据现在从BX寄存器(BL)的下部复制到DX寄存器(DL)的下部 。 
3. 最后,使用ret指令从函数返回。 

最后,程序到达exit子程序,程序结束

netcat->patch

前言

netcat,瑞士军刀,它已经被大多数防病毒引擎签名并检测为恶意文件

https://eternallybored.org/misc/netcat/

简要分析

使用x32dbg打开nc.exe

并到达文件的入口点时

首先看到的是第一个函数

并且使用命令sub esp,18 - >subtract 18 from esp寄存器

我们的目标就是:不会把文件损坏掉

即,在进行更改后,文件仍然能够在操作系统中运行,我们对程序代码做了一个小的更改,改掉一些特征

然后对文件进行修补,这样它就可以作为原始可执行文件的一部分保存在计算机的硬盘上

image-20210820093732127

image-20210820094219702

当我们把18改成17

然后通过按Ctrl+P并单击patch File来修补可执行文件:

image-20210820094811562

前后对比

不影响文件运行,但在VT上面少了10个爆毒。

时间戳

前言

简单来说,就是不编辑文件本 身,而是编辑它的创建时间

原理

许多防病毒引擎用来签名恶意软件的方法之一是文件创建的日期。他们这样做是为了执行静态签名,编辑时间即可降低被发现的可能

对比

我们使用一个绿色的小工具即可:BulkFileChanger

image-20210820103353663

然后开始改动

image-20210820103528784

image-20210820103817190

image-20210820103735148

垃圾代码

前言

防病毒软件有时会在代码的逻辑中搜索以对其进行检测,以便稍后将其归类为特 定类型的恶意软件

为了使杀毒软件很难通过代码的逻辑进行搜索,我们可以使用垃圾代码,这有助于使代码的逻辑变得更加复杂

常见的方法

条件跳转、无关变量名和空函数、影响硬盘驱动器的操作

小技巧

例如,如果我们希望使代码复杂化,那么最好创建四个函数,其中三个是空的(未使用的)函数

在恶意函数内,我们还可以添加一定数量的永远不会发生的条件,添加一些无意义的变量名

image-20210820104931458

有几种方法可以实现影响硬盘驱动器的操作来混淆杀毒软件,包括加载不存在的DLL和创建合法的注册表值。

image-20210820105050902

简单的伪代码,使用套接字打开到攻击者的命令和控制 服务器的连接

左侧是执行垃圾代码技术之前的代码

右侧是使用垃圾代码技术 后的相同功能

总结

免杀种汇编和调试是一定要会的!
x86汇编结构的学习、XOR对称加密、垃圾代码
免杀的关键是思路要骚
OK,这次就到这里!

  • 发表于 2021-08-31 19:05:20
  • 阅读 ( 6090 )
  • 分类:漏洞分析

0 条评论

请先 登录 后评论
略略略
略略略

36 篇文章

站长统计