这个日常逆向工具就行,不限于IDA,xDBG等,主要是个测试用的虚拟机环境,这里就不细说了。
1、可以从恶意样本里获取最新技术
2、如果当这个样本过了杀软,那核心技术你就可以分析出来当作自己的了
3、核心取证,为了确定这个样本做了什么
4、分析样本通过样本知道系统还需要防护哪里
1、样本的威胁情报,什么家族?什么类型?
2、样本中有什么函数值得关注,是否有C2外联?是否存在创建文件?是否有注册表操作?等等。。。
3、样本是否存在加壳?
4、多实践发现
1、它使恶意代码“隐藏”在杀软中。当然,它并没有那么隐蔽,但它是一种软逃避技术,使分析师的工作变得更加困难,并最终给防御带来一些问题。(也算是免杀的一种)
2、由于需要规避许多反分析技术(反调试器和反虚拟机技巧),因此动态解密可能会很困难。
3、恶意软件通常使用定制进程将有价值的代码加密成多层
4、最终,整个恶意软件或者只有脱壳代码可能是多态的
1、 IAT(导入地址表)可能已被删除,或者最多只有一个导入函数
2、大多数字符都是加密的
3、从静态来看,内存完整性经过检查和保护,因此无法从内存中转储干净的可执行文件,因为原始指令未完全解码
4、混淆是基于堆栈的,因此使用静态方法处理虚拟化代码相当困难
5、 有数千行虚假的“推送”指令,当然,其中许多指令包含死代码和无用代码
6、这些保护器使用无条件跳转实现代码重新排序
7、所有这些现代打包器都使用代码扁平化、许多反调试和反虚拟机技术
8、大多数情况下,函数的序言和结尾不会被虚拟化
9、原始代码部分可能会被“分割”和/或分散在程序中
10、引用导入函数的指令可能会被清零,甚至被 NOP 替换,因此在这种情况下,这些“引用”将被动态恢复。有时这些相同的引用不会清零,但被使用 RVA 跳转到相同导入地址的指令所取代,即所谓的“IAT 混淆”
11、 与在 shellcode 和常见恶意软件中一样, API 名称经过哈希处理
12、使用混淆技术,例如常量展开、基于模式的混淆、控制间接、内联函数、代码复制和主要不透明谓词
1、该恶意软件真的被打包了吗?
2、代码打包的证据有哪些?
3、恶意软件是否执行自我注入或远程注入?
4、该恶意软件是否会执行自我覆盖?
5、有效载荷被写入哪里?
6、有效载荷将如何执行?
7、脱壳后有什么证据表明代码被脱壳了?
8、是否有额外的填充层?
1、 二进制样本导入的DLL和函数较少。
2、混淆的字符串较多
3、存在特定的系统调用
4、非标准的部分名称
5、非通用可执行二进制部分(只有 .text/.code 部分应该是可执行的)
6、意外的可写部分
7、高熵部分(通常高于7.0,但并非总是如此
8、某个部分的原始大小和虚拟大小之间存在很大差异
9、缺少与网络通信相关的 API
10、缺乏恶意软件功能所需的基本 API
11、不寻常的文件格式和标题
12、入口点指向 .text/.code 部分以外的其他部分。
13、代码中资源部分(.rsrc 部分)的大小很大,后面跟着LoadResource( )函数
14、在IDA Pro 上打开它并在彩色条上观察大量数据或未探索的代码
仅出现上述列表中的一个特征并不能确定恶意软件已加壳。因此,考虑两个或更多特征非常重要
1、大多数样本使用LoadLibrary()和GetProcAddress( )动态解析其 API
2、网络 API也可以动态解析。
3、格式错误的标头在第一次分析时可能有点难以检测
4、大资源部分可能不相关,因为它可能仅包含 GUI 工件和数字证书
5、加密/模糊字符串和纯文本字符串可能会混合在一起,因此更难判断二进制文件是否被打包。
1、反调试技术(时间检查、CPUID、堆检查、调试标志检查、NtSetInformationThread( )等),因此建议使用反调试器
2、针对 VMware、VirtualBox、Hyper‑V 和 Qemu 工件进行反虚拟机技巧检查
3、文件名、主机名和帐户检查(避免使用哈希作为文件名)
4、虚拟机上的可用磁盘大小(建议至少 100 GB)
5、测试虚拟机上的处理器数量(两个或更多是合适的)
6、正常运行时间(尝试保留正常运行时间超过 20 分钟的虚拟机快照)
7、许多无意义的调用(结果不再使用)和不存在的 API(假 API)。
8、异常处理程序被用作反调试技术。
9、软件断点被清除,寄存器(DR#)被操纵(反断点技术)
10、使用典型算法的哈希函数(例如,crc32、conti、add_ror13 等)
11、对知名工具(例如 Process Hacker、Process Explorer、Process Monitor等)进行恶意代码检查(建议在使用这些可执行二进制文件之前重命名它们)
12、反虚拟机技巧和反调试器技术并不总是可以通过插件来处理,我们必须设法使用调试器来绕过它们,在这种情况下,我们有一个有趣的可能性,那就是使用不同的调试器(如WinDbg)来管理一些需要 Ring 3 调试器的恶意软件威胁
13、仅限内核调试器而非内核调试器(最近的案例是 GuLoader 恶意软件)
1、DOS/PE 头可能在内存中被破坏或者被压缩库修改。
2、入口点(EP)可能已被清零或者错误
3、解密后的二进制文件的导入表可能由于已被转储而被破坏,并且其地址引用的是虚拟地址(映射版本而非未映射版本),因此会显示未对齐的部分或无部分
4、基地址错误
5、PE 格式的字段存在一些不一致
6、确定 OEP(原始入口点)可能很困难,它通常在使用间接调用(例如, call [eax]或jmp [eax] )从解包器代码转换后出现
此外,存在未解析的 API 可能是恶意代码尚未到达 OEP 的证据。准时: OEP 是可执行文件在被打包之前的入口点 (EP)。打包后,新的 EP 将与打包程序本身关联。
7、互斥锁被用作两个解包层之间的一种“解锁钥匙”。在这种情况下,如果第一阶段没有发生,第二阶段的解包就不会发生,如果发生了,那么互斥锁的存在就得到了确认
8、代码可能正在执行自我覆盖
9、脱壳代码的第一阶段不从任何目录运行,而只从特定目录运行
10、您可能已经提取了诱饵二进制文件。在许多实际情况下,恶意软件作者会将一个或多个无用的可执行文件打包为诱饵,以消耗分析师的时间。因此,最好不要相信您第一次尝试就从内存中解压了正确的二进制文件
1、从另一个可执行文件(或从自己的恶意软件样本)复制一个好的 PE 头,并根据解压后的二进制文件是未映射的(.text 部分通常从 0x400 开始)还是映射的(.text 部分通常从 0x1000 开始)来对齐部分。
2、通过修复各自的原始地址和原始大小来对齐解压二进制文件(映射寻址)的各个部分。此操作通常可以修复导入表,并可以毫无问题地可视化导入函数。注意可能的“陷阱”:某些解压二进制文件在对齐其部分之前不会显示其导入表。但是,其他恶意软件威胁即使在解压二进制文件后也不会在导入表中显示任何函数,因此这并不意味着您犯了任何错误,而意味着恶意软件会动态解析其所有 API。
3、重建IAT并强制OEP (原始入口点)。
4、如果您在查找 OEP 时遇到问题,请记住OEP 很可能是在 IAT 解析之后出现的。在这种情况下,一种可能的方法是检查 IAT 是否已解析(检查 x64dbg 或 OllyDbg 上的 Intermodular Calls)或在关键 API 上设置断点,该 API 将在恶意软件的关键操作期间执行(例如,勒索软件威胁中的 CryptoAcquireContext()),因为当执行到达这些关键 API 时,IAT 肯定会被解析。之后,建议寻找无条件跳转到特定内存地址甚至间接调用(例如,call [eax])。另一种有趣的方法是使用调试器的图形可视化(x64dbg 上的“g”)并在最后的“代码块”中检查这些转换点(间接调用或内存地址的无条件跳转)。最后,一个专门的工具可能会帮助您找出 OEP。正如您所注意到的,没有一种方法可以做到这一点
5、调整基地址以与从内存转储的段基地址匹配
6、为了检测恶意软件是否执行自我覆盖,我们可以尝试在.text/.code 部分。在这种情况下,我们可以选择在代码编写或执行期间触发此断点。
7、在两阶段脱壳的情况下,第一个脱壳的二进制文件可能是一个 DLL。因此,根据具体情况,将 DLL 二进制文件转换为可执行文件可能会很有用,并且有很多方法可以完成此任务,但我最喜欢的方法是编辑 PE 标头以更改 Characteristics 字段并将导出函数的条目作为入口点
脱壳只是恶意软件分析过程中的第一个障碍,许多其他艰难的挑战,例如字符串反混淆、API 解析、C2 配置提取、C2 模拟和其他主题会陆续讲到
代码注入是 Windows 系统支持的操作,当然,这是一种非常有用的规避方法,因为恶意软件能够将恶意代码注入(写入)进程本身(自我注入)或远程进程(远程注入)的内存区域(有些人使用术语“段”),并且此有效负载将在目标上下文中执行,就像它是其中的一部分一样,不会留下太多证据。此外,源进程(恶意软件)可以干净地终止自身
而恶意负载则继续在所谓的正常进程中运行(例如 explorer.exe 和 svchost.exe)。归根结底,这是一种逃避安全防御的隐秘方法
从 Windows 8.1(主要是 Windows 10 和 11)开始,就存在一系列缓解和保护措施,例如代码完整性保护、扩展点禁用策略、控制流保护、代码完整性保护、动态代码限制和任意代码保护(动态代码限制的一种更新),在这些 Windows 版本上执行代码注入并不那么容易不会被检测到和阻止
1、 DLL 注入:这种老技术用于强制进程加载 DLL。主要可能涉及的 API: OpenProcess( )、VirtualAllocEx( )、WriteProcessMemory和CreateRemoteThreat | NtCreateThread( ) | RtlCreateUserThread( )。
2、PE注入:该技术会写入恶意代码,然后强制在远程进程甚至自身进程中执行(自我注入)。主要相关 API:
OpenThread( )、SuspendThread( )、VirtualAllocEx( )、WriteProcessMemory( )、SetThreatContext( )和ResumeThreat( ) | NtResumeThread( )
3、反射注入:这种技术类似于 PE 注入,例如LoadLibrary() 和 CreateRemoteThread( )。此方法有许多有趣的派生,其中之一(也用于Cobalt Strike)由以下 API 完成:
CreateFileMapping()、Nt/MapViewOfFile()、OpenProcess()、memcpy()和Nt/MapViewOfSection( )。最后,可以通过调用来执行远程进程上的代码OpenProcess()、CreateThread()、NtQueueApcThread()、CreateRemoteThread()或RtlCreateUserThread()。值得注意的是,变体也可以使用VirtualQueryEx()和ReadProcessMemory()
4、 APC 注入:此代码注入技术允许程序通过附加到 APC 队列来在特定线程中执行代码。当线程退出可警告状态时(由SleepEx( )、SignalObjectAndWait( )、MsgWaitForMultipleObjectsEx( )、WaitForMultipleObjectsEx( ) 或WaitForSingleObjectEx ( ) 等调用发起),将执行注入的代码
因此,还经常可以看到CreateToolhelp32Snapshot()、Process32First()、Process32Next()、Thread32First()、Thread32Next()、QueueUserAPC()和KeInitializeAPC()等 API。参与到这个技术中
5、挖空或进程替换:简而言之,恶意软件使用这种技术“抽干”进程的全部内容,并将恶意内容插入其中。一些涉及的 API 包括CreateProcess( )、NtQueryProcessInformation( )、GetModuleHandle( )、Zw/NtUnmapViewOfSection( )、VirtualAllocEx( )、WriteProcessMemory( )、GetThreadContext( )、SetThreadContext ( )和ResumeThread( )。
6、 AtomBombing:此技术是前一种技术(APC 注入)的变体,其工作原理是将恶意负载拆分为单独的字符串,为每个给定的字符串创建一个 Atom,将它们复制到 RW 段(使用GlobalGetAtomName()和NtQueueApcThread( ))并使NtSetContextThread()设置上下文。因此,以下是进一步的 API 列表:
OpenThread()、GlobalAddAtom()、GlobalGetAtomName()和QueueUserAPC()
7、进程分身:这种技术可以视为进程的一种演化
Hollowing。这两种技术之间的关键区别在于,Process Hollowing 在进程恢复之前替换进程的内容(图像),而 Process Doppelgänging 能够在进程创建之前替换图像,方法是在加载之前用恶意图像覆盖目标图像。这里的关键概念是 NTFS 操作是在事务内执行的,因此事务内的所有这些操作要么一起提交,要么都不提交。同时,恶意图像仅存在,并且在事务内可见,对任何其他进程不可见。因此,恶意图像被加载到内存中,恶意软件会从文件系统中删除恶意负载(通过回滚事务),因为该文件以前从未存在过。此技术涉及一些 API:
CreateTransaction()、CreateFileTransaction()、NtCreateSection、NtCreateProcessEx()、NtQueryInformationProcess()、NtCreateThreadEx()和RollbackTransaction()
8、Process Herpaderping:此技术与 Process Doppelgänging 类似,但其过程略有不同。Process Herpaderping 基于以下事实:安全防御通常通过使用PsSetCreateProcessNotifyRoutineEx( )在内核端注册回调例程或在驱动程序的DispatchCleanup 例程 (IRP_MJ_CLEANUP) 期间监控进程创建,该例程在创建线程后调用。这是关键问题:如果对手创建并映射进程,之后该对手能够修改文件映像,然后创建线程,那么安全产品就能够检测到这种恶意负载
尽管如此,这个检查顺序可以决定攻击者是否能够在磁盘上创建恶意二进制文件、打开它的句柄、使用NtCreateSection将其映射为图像部分函数(包括SEC_IMAGE 标志),使用节句柄创建一个进程(NtCreateProcesEx()),修改文件内容使其听起来不像是恶意的,并使用此“好图像”创建线程(NtCreateThreadEx()) 。
重点是:创建线程时,会触发进程回调并检查磁盘上文件(好文件)的内容,因此安全防御认为一切都很好,因为磁盘上的图像没有危害,但真正的恶意是在内存中。换句话说,安全防御无法有效检测与内存上的图像不同的磁盘上的图像。此技术使用的一些 API: CreateFile()、NtCreateSection()、NtCreateProcessEx()和NtCreateThreadEx()。
9、挂钩注入:要使用此技术,我们将看到涉及挂钩活动的函数(例如SetWindowsHookEx()和PostThreadMessage())用于注入恶意 DLL
10、额外的 Windows 内存注入:恶意软件威胁利用这种技术将代码注入
通过使用额外 Windows 内存(即 EWM)来破坏进程,其大小最多为 40 字节,并在注册 Windows 类时附加类的实例。诀窍在于附加的空间足以存储可能将执行转发给恶意代码的指针。此技术涉及的一些可能 API 是FindWindowsA()、GetWindowThreadProcessId()、OpenProcess()、VirtualAllocEx()、WriteProcessMemory()、SetWindowLongPtrA()和SendNotify()。
11、传播注入:这种技术已被恶意软件威胁所使用,例如 RIG Exploit Kit Smoke Loader 将恶意代码注入 explorer.exe 进程(中等完整性级别)和其他持久进程,它基于枚举方法(EnumWindows() →EnumWindowsProc → EnumChildWindows() → EnumChildWindowsProc → EnumProps() → EnumPropsProc → GetProp)窗口实现SetWindowsSubclass() 一旦找到子类窗口(检查提供子类标头的UxSubclassInfo和/或CC32SubclassInfo ),就可以保留旧的 Windows 过程,但我们也可以通过更新 CallArray 字段为窗口分配一个新的过程。当向目标进程发送事件时,将调用新过程,之后还会调用旧过程保持,恶意软件会将恶意负载(shellcode)插入内存并使用SetPropA( ) 更新子类过程。当调用此新属性(通过 Windows 消息)时,执行将转发到负载。此技术涉及的一些 Windows API 包括FindWindow()、FindWindowEx()、GetProp()、GetWindowThreadProcessId()、OpenProcess()、ReadProcessMemory()、VirtualAllocEx()WriteProcessMemory()、SetProp()和PostMessage()
下面显示了恶意软件威胁的一个非常常见的代码注入序列示例(IDA Pro 的反编译输出):
在众所周知的 API 上设置软件断点,其中大多数与内存管理和操作有关,并寻找要从内存中提取的可执行文件和/或 shellcode
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2024-7-15 10:10
被PinkKey编辑
,原因:
上传的附件: