分享者才是最大的受益者
前言
使用编译后的二进制文件,绕过防病毒软件
有一些防病毒软件绕过技术可以使用已经编译的代码执行,这些代码可以运行,即使它被防病毒引擎检测为恶意软件
两个子技术:
调试项目
时间戳
x86汇编体系结构
汇编语言的发展是为了取代机器代码,让开发人员更容易地创建程序。
汇编被认为是一种低级语言,因此,它可以直接访问计算机的硬件,如CPU。
使用汇编,开发人员不需要理解和编写机器代码。多年来,开发了许多编程语言,使开发人员的编程更加简单
有事我们不能反编译程序以获得其源代码,我们需要使用一种称为反汇编器的工具来将其从机 器代码转换为汇编代码。
堆栈
堆栈是系统进程用来存储变量和函数参数等值的一种内存类型
简单记住一点:堆栈内存布局基于后进先出(LIFO)原则
堆
与线性的堆栈内存不同,堆内存是自由样式
的动态分配内存
堆内存可以随时分配,也可以随时释放。它主要用于在操作系统运行时执行程序
汇编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:
pushstring
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
默认安装即可
环境变量配置
gcc:http://mingw-w64.org/doku.php/download
默认安装即可
一样 也是要进行环境变量的配置
编译程序->nasm & gcc
nasm -fwin32 HelloWorld.asm
gcc HelloWorld.obj -o HelloWorld.exe
简要分析
第一行声明代码的主函数
第二行导入 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/
快捷键->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寄存器
我们的目标就是:不会把文件损坏掉
即,在进行更改后,文件仍然能够在操作系统中运行,我们对程序代码做了一个小的更改,改掉一些特征
然后对文件进行修补,这样它就可以作为原始可执行文件的一部分保存在计算机的硬盘上
当我们把18改成17
然后通过按Ctrl+P并单击patch File来修补可执行文件:
前后对比
不影响文件运行,但在VT上面少了10个爆毒。
时间戳
前言
简单来说,就是不编辑文件本 身,而是编辑它的创建时间
原理
许多防病毒引擎用来签名恶意软件的方法之一是文件创建的日期。他们这样做是为了执行静态签名,编辑时间即可降低被发现的可能
对比
我们使用一个绿色的小工具即可:BulkFileChanger
然后开始改动
垃圾代码
前言
防病毒软件有时会在代码的逻辑中搜索以对其进行检测,以便稍后将其归类为特 定类型的恶意软件
为了使杀毒软件很难通过代码的逻辑进行搜索,我们可以使用垃圾代码,这有助于使代码的逻辑变得更加复杂
常见的方法
条件跳转、无关变量名和空函数、影响硬盘驱动器的操作
小技巧
例如,如果我们希望使代码复杂化,那么最好创建四个函数,其中三个是空的(未使用的)函数
在恶意函数内,我们还可以添加一定数量的永远不会发生的条件,添加一些无意义的变量名
有几种方法可以实现影响硬盘驱动器的操作来混淆杀毒软件,包括加载不存在的DLL和创建合法的注册表值。
简单的伪代码,使用套接字打开到攻击者的命令和控制 服务器的连接
左侧是执行垃圾代码技术之前的代码
右侧是使用垃圾代码技术 后的相同功能
总结
免杀种汇编和调试是一定要会的!
x86汇编结构的学习、XOR对称加密、垃圾代码
免杀的关键是思路要骚
OK,这次就到这里!
- 本文作者: 略略略
- 本文来源: 奇安信攻防社区
- 原文链接: https://forum.butian.net/share/583
- 版权声明: 除特别声明外,本文各项权利归原文作者和发表平台所有。转载请注明出处!