编程与调试 -- Windows 编程知识点(文档整理)2/2 逆向 & 驱动

浅析逆向分析

ELF(linux) 和 PE(windows)


PE 格式总览

PE 头

  • PE 结构相关头文件
    • Windows-sdk 下 \include\winnt.h
  • 关键结构
    • DosHeader
    • NtHeader
      • FileHeader
      • OptionalHeader
        • DataDirectory
    • SectionTable

DOS 头

  • 作用
    • 文件头,兼容 DOS 模式
    • DOS 下默认显示 This program must be run under win32
  • 重要字段
    • e_magic 标记 MZ(4D5A),MS-DOS 创建者 Mark Zbikowski
    • e_lfanew 指向真正的 PEHeader

DOS 头

FileHeader

  • 作用
    • 描述 PE 基础信息
  • 重要字段
    • Machine
    • NumberOfSections,节数量
    • SizeOfOptionalHeader,可选头大小
    • Characteristics,PE 属性

OptionalHeader

  • 作用
    • 描述 PE 详细信息
  • 重要字段
    • Magic
      • PE32/64
    • Subsystem
      • Console/win
    • DataDirectory
    • AddressOfEntryPoint(OEP)
      • 入口点,编译器特征
      • 劫持修改(感染型)
      • Main 和 OEP

main 和 OEP
  • main 是不是第一行执行的代码?
    • OEP(crt/src/cr0.c)
      • mainCRTStartup/WinMainCRTStartup
    • main
      • main/WinMain
  • 编译运行过程
    • 编译链接过程 ENTRY 选项指定入口函数,默认为 main
    • OEP 指定为 libc.lib 中的 mainCRTStartup(console)
    • mainCRTStartup 完成初始化后调用 main
  • 备注
    • 文件特征注意

DataDirectory

  • 作用
    • 导入、导出、资源等关键结构的总索引
  • 介绍
    • DataDirectory 位于 OptionalHeader 末尾
    • 共 16 组,每组指定一个重要数据结构
  • 重要字段
    • 导出表,导出函数
    • 导入表,引用外部 DLL 信息
    • 调试表,PDB 等调试信息
    • 资源表,图标,对话框,版本信息等
    • 安全表,数字签名

SectionTable

  • 作用
    • 除文件头外的代码、数据、资源分段存储索引
    • 便于系统安全性设置
  • 重要字段
    • VirtualAddress,节区在内存中的偏移
    • PointerToRawData,节区在文件偏移
    • Characteristics,描述该节的 rwx 属性

源码与 PE

PE 文件映射

  • PE-Section
    • .text,二进制代码,x 属性
    • .data,全局变量、字符串、预定义数据,rw 属性
    • .rsrc,资源图标、对话框资源、版本信息等,r 属性
  • TIPS
    • 对齐粒度
      • 0x200->0x1000
    • 节名无实质意义,不同的编译器喜好不同
      • .text(vc)
      • .CODE(delphi)
  • 节空隙
    • 恶意代码寄生

感染型病毒

ntcore CFF-Explorer

x86 指令编码

反汇编过程即二进制转汇编助记符,参考 intel 指令集手册 X86 为变长指令(灵活),arm 为定长指令(高效)[4G 寻址问题]


x86 指令编码

指令编码

  • 作用
    • 实现虚拟机(bochs) / 沙箱
      • 精准控制每个指令执行,OS 开发
    • 恶意代码仿真执行
      • 对抗混淆、加密
    • 反汇编,机读指令转人读指令
      • 安全必备
    • vulnerability/shellcode/inline-hook
      • 核心安全分析、防御
      • 漏洞(vulnerability)
        • 缓冲区溢出
        • 输入验证
        • 时间序列

汇编简介

  • 指令分类
    • 计算
      • Add/adc/inc/sub/mul/…
    • 读写
      • Mov/lea/push/pop/xchg/…
    • 控制
      • Jmp/jcc/loop/call/ret/…
    • 其他
      • clc/stc/cld/cupid/…
  • 备注
    • 仅寄存器可参与计算
    • 地址间不能直接操作

反汇编 — call stack

  • 寄存器
    • Ebp 指向当前函数栈基址
      • [ebp+xx] 参数 / [ebp-xx] 变量
    • Esp 指向当前函数栈顶
  • 进入 / 退出函数时构建和释放栈帧
    • 仅改变 ebp/esp 即可
    • 返回地址
  • 如何平衡堆栈
    • 根据调用类型

反汇编案例

动态调试 & 静态分析

TIPS

  • 资源 DLLFindResourceA/W
    • LoadStringA/W(user32.dll)
  • 调用栈结构
  • Ctrl+F9 执行到返回
  • 关注前置跳转
  • 分析建立在开发 / 系统的理解之上

多层封装 异步调用 动态加载 加密解密 自定义接口 壳 反调试

代码防护

  • 关键函数 / 文件采用无意义名字
  • 避免明文存储,配置文件 hash 化
  • 尽量减少无用提示
  • 无关代码注释删除

防御基本原理

防御 & 系统简述

防御(内核)同步 & 异步 拦截的区别及应用场景

  • 同步:触发(命中)关键行为时,发起行为的线程被阻塞,内核将行为的相关信息传递至应用层;
  • 异步:触发(命中)关键行为时,获取行为的相关信息后,不影响行为的继续执行,内核将行为的相关信息传递至应用层;
  • 行为的相关信息:
    • 行为发起者(进程文件路径)
    • 行为标识(防御标记的行为种类)
    • 行为目标(根据标识有所不同,如:进程创建类的,这里的目标会是被调用的进程文件路径)
    • ………………
  • 场景:
    • 同步拦截用于威胁性较高的行为,如:进程创建、创建服务、启动服务、修改注册表项启动项……
    • 异步拦截用于信息通知、文件写完成……,如:进程退出
  • 内核层
    • 进程防御
      • 进程执行
      • 模块加载
      • 防进程倍结束
      • 内存防御
    • 文件防御
      • 文件操作(创建、读写、删除)
      • 文件自保护
    • 注册表防御
      • 注册表操作(创建、修改、删除)
    • 全局防御
      • 创建、启动、修改 服务
      • 安装全局钩子
    • 网络防御
      • 防黑墙(远程木马)
      • 访问恶意链接
      • 流量监控
  • 应用层
    • 下载保护(文件下载完成时对文件的安全检测)
    • 网址安全(通过浏览器访问链接时对网址的安全检测)
    • 自保护

Windows 关键进程

  • system - 驱动的载体,通过 Process Explorer 查看该进程,可查看到系统已加载的驱动
  • winlogon.exe - 管理用户的登录和注销
  • csrss.exe - Client/Server Runtime Server Subsystem,Win32 子系统的用户模式部分;在 Win7 结束该进程,系统直接 BSOD(Blue Screen Of Death)
  • lsass.exe - 本地安全和登陆策略 smss.exe - 会话管理子系统,负责启动用户会话
  • services.exe - 系统服务控制管理
  • svchost.exe - 从动态链接库(DLL)中运行的服务的通用主机进程名称;以服务的形式将 DLL 加载执行;
  • explorer.exe - 资源管理器(桌面)
  • mov eax,42h 对应内核里 SSDT 表所在的 index
  • mov edx,7FFE0300h 0x7ffe0000 存储 _KUSER_SHARED_DATA 结构体,用于应用层和内核层共享数据

防御原理

驱动使用的监控技术

Hook 技术

  • “注入”,通过修改目标进程,将代码指令写入至目标进程的内存并执行;
  • “钩子”,可对程序内关键函数或任意有效内存地址进行“安装”;大部分的“安装”对指定程序内的内存进行修改,与注入组合使用;

Detour 微软提供的可用于多平台的“hook”库,提供:进程创建时的注入(模块)、指定函数 hook……

DetourCreateProcessWithDlls - 创建指定进程,并将指定模块注入至目标进程(加载时机早)

在修改导入表完成后,目前进程还处于“挂起”状态,后续调用“ResumeThread”后,系统按照标准的进程创建流程,遍历导入表将对应的模块进行加载(将模块映射至当前进程内存,并获取 AddressOfEntryPoint 调用入口点 DllEntry);

进程的首个线程(进程初始化)ntdll!_LdrpInitialize –> ntdll!LdrpInitializeProcess –> ntdll!LdrpRunInitializeRoutines –> ntdll!LdrpCallInitRoutine TLS 回调比模块的 dllmain 执行时机更早


LdrpRunInitializeRoutines 代码片段

SSDT(System Services Descriptor Table)

typedef struct {
    PVOID *pTable; // Service Table Pointer
    PULONG pulTableCounter; // Table Item Counter. This table is only updated in checked builds.
    ULONG ulServiceCounter; // Number of services contained in this table.
    PUCHAR rguchParamTable; // Table containing the number of bytes of parameters the handler function takes.
} SERVICE_TABLE;

SSSDT(System Shadow Services Descriptor Table)

typedef struct {
    PVOID *pTable; // Service Table Pointer
    PULONG pulTableCounter; // Table Item Counter. This table is only updated in checked builds.
    ULONG ulServiceCounter; // Number of services contained in this table.
    PUCHAR rguchParamTable; // Table containing the number of bytes of parameters the handler function takes.
} SERVICE_TABLE;

x86 \ x64 系统的区别

防御基于 x86 架构上的监控实现,基本是以 hook(inline hook) + 注册系统回调实现的;但在 x64 构架上,微软引入 Driver Signature Enforcement + Kernel Patch Protection(PatchGuard,简称 PG) 安全机制,杜绝第三方驱动在系统关键“驱动”中进行的内存修改。因为 PG 的存在,无法继续使用 x86 的 hook 方式实现更多行为的监控,只能使用系统提供的标准回调;x86 hook 的方式可将 SSDT + SSSDT 里涉及到的各函数调用都进行监控,基本上涵盖了系统上所有的行为,而系统提供的标准回调,只有进程创建 / 退出、模块加载、注册表相关、文件、对象回调,所以,导致了一些在 x86 上可进行防御的行为,在 x64 上无效(或实现方法与 x86 不同);

监控点的实现

监控点实现(应用层)

  • 文件监控 ReadDirectoryChangesW
    • 应用层实现文件监控效果的函数(非回调),可对文件夹里的文件名变动、目录名变动、文件属性变动……进行监控
    • 缺点:
      • 1、有针对性的(传入的目录句柄),不是全局监控
      • 2、无法获取操作者,即无法知道是哪个进程发起对文件的修改行为
  • 注册表监控 RegNotifyChangeKeyValue
    • 应用层实现注册表监控效果的函数(非回调),完成调用后指定位置如发生变化会返回
    • 缺点:
      • 1、有针对性的(传入的指定项),不是全局监控
      • 2、无法获取操作者,即无法知道哪个进程发起的修改行为
      • 3、无法获取更多的信息,即无法知道哪个键、哪些键值发生变化
  • x64 自保护
    • 通过 TLS 回调的更早执行时机,Hook 自身 PEB 内 KernelCallbackTable 表的 __ClientLoadLibrary,实现对全局钩子的拦截

例子 / 参考资料

Code

ntfs

Through the looking glass: webcam interception and protection in kernel mode


Figure 1: After driver installation.

Figure 2: The desirable order.

Tool

文件重启删除

文件重启删除 读取注册表 smss.exe 删除的。

  • svchost.exe HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Svchost\
    • %SystemRoot%\system32\svchost.exe -k RPCSS
    • File: %SystemRoot%\System32\RpcEpMap.dll
    • Registry key: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\RpcEptMapper
void KInstallFile::DeleteFile()
{
    if ( m_bFolder && ::PathFileExists(m_strInstallPath))
        KFunction::DeleteFolder(m_strInstallPath);
    else
    {
        TCHAR szFileFullPath[MAX_PATH];
        ::GetModuleFileName(NULL, szFileFullPath, MAX_PATH);

        if ( m_strInstallPath.Compare( szFileFullPath ) != 0 )
        {
            KProcessManager::KillProcessByPath( m_strInstallPath );
            Sleep( 100 );
        }
        if (::PathFileExists(m_strInstallPath) && !::DeleteFile( m_strInstallPath ))
        {
            CString strTempFileName;
            strTempFileName.Format(_T("%s_%d_del"), m_strInstallPath, int(::GetTickCount()));

            if (::MoveFileEx(m_strInstallPath, strTempFileName, MOVEFILE_REPLACE_EXISTING))
            {
                ::MoveFileEx(strTempFileName, NULL, MOVEFILE_DELAY_UNTIL_REBOOT);
            }
        }
    }
}

逆向分析

  • IDA
  • windbg
  • CFF-Explorer

反汇编过程即二进制转汇编助记符,参考 intel 指令集手册。 X86 为变长指令(灵活),arm 为定长指令(高效)[ 4G 寻址问题 ]


参考资料快照
Windows 编程知识点 系列文章
参考资料快照

本文短链接:
If you have any questions or feedback, please reach out .