[TOC]

样本分析常用工具

文件检测

file命令:linux下的一个命令,用来查看文件类型

PEID:一个强大的查壳脱壳工具

DIE:和PEID类似,也是一个查课脱壳工具

文件编辑

010edit:文本/十六进制编辑器

binwalk:固件分析工具

行为监控

ProcessMonitor:系统进程监视软件

火绒剑:强大的行为监视软件

wireshark:网络监视软件

静态分析

ApkTool:反编译APK文件的工具

Dex2jar:反编译java的工具

jd-gui:可用来查看java源代码

IDA:强大的反编译软件

Dnspy:针对与.NET的逆向工具

动态分析

OllyDbg:动态调试软件,支持多个插件,但是不支持64位程序的调试

x64/x32dbg:动态调试软件,支持32位和64位下的动态调试

windbg:支持windows内核调试

恶意样本常用API

文件类

Kernal32

CreateFile()        // 打开创建对象,返回句柄
CreateFileMapping()    // 创建一个新的文件映射内核对象
OpenFile()        // 打开文件
FindFirstFile()        // 到一个文件夹下搜索指定文件
FindNextFile()        // 遍历目录或文件,判断当前目录下是否有下一个目录或文件
GetModuleFileName()    // 获取当前进程已加载模块的完整路径,模块必须由当前进程加载
GetModeleHandle()    // 获取一个应用程序或动态链接库的模块句柄
GetProcAddress()    // 检索指定的动态链接库中的输出库函数的地址
GetStartupInfo()    // 取得进程在启动时被指定的 STARTUPINFO 结构
GetTempPathO()        // 获取为临时文件指定的路径
GetWindowsDirectory()        // 获取Windows目录的完整路径名
MapViewOfFile()        // 将一个文件映射对象映射到当前应用程序的地址空间
SetFileTime()    // 设置文件的创建、访问及上次修改时间
Wow64DisableWow64FsRedirection()        // 禁用文件系统重定向机制

NtosKrnl

NtQueryDirectoryFile()        // 返回多种指定的文件信息

网络类

ws2_32

socket()        // 用于根据指定的地址族、数据类型和协议来分配一个套接口的描述字及其所用的资源
accept()        // 用来监听入站网络连接
bind()            // 将一本地地址与一套接口捆绑
connect()        // 用来将参数sockfd 的socket 连至参数serv_addr 指定的网络地址
gethostbyname()    // 获取主机名,返回hostent结构指针
gethostname()    // 返回本地主机的标准主机名
inet_addr()        // 将一个点分十进制的IP转换成一个长整数型数
recv()        // 从已连接的socket中接收数据
send()        // 向一个已连接的socket中发送数据
WSAStartup()        // 初始化底层级别的网络函数

wininet

InternetOpenA()    // 初始化一个应用程序,以使用 WinINet 函数
InternetOpen()    // 初始化一个应用程序,以使用 WinINet 函数
InternetOpenUrl()    // 通过一个完整的FTP,Gopher或HTTP网址打开一个资源
InternetReadFile()    // 从一个由InternetOpenUrl,FtpOpenFile, 或HttpOpenRequest函数打开的句柄中读取数据
InternetWriteFile()    // 向服务器上传文件

ole32

CoCreateInstance()    // 用指定的类标识符创建一个Com对象,用指定的类标识符创建一个未初始化的对象
OleInitialize()        // 在当前单元(apartment)初始化组件对象模型(COM)库,将当前的并发模式标识为STA(single-thread apartment——单线程单元),并启用一些特别用于OLE技术的额外功能

wininet

FtpPutFile()    // 将本地文件上传到FTP服务器

Iphlpapi

GetAdaptersInfo()    // 获取网卡信息

Netapi32

NetShareEnum()        // 返回服务器上共享的资源的信息

urlmon

URLDownloadToFile()        // 从指定URL地址读取内容并将读取到的内容保存到特定的文件里

注册表与服务类

advapi32

CreateService()        // 创建一个服务对象,并将其添加到指定的服务控制管理器数据库
ControlService()    // 向服务发送一个控制码
OpenSCManager()        // 建立了一个到服务控制管理器的连接,并打开指定的数据库
RegOpenKey()        // 打开给定键
StartServiceCtrlDispatcher()    // 将服务进程的主线程连接到服务控制管理器
RegCloseKey()        // 释放指定注册键的句柄
RegCreateKey()        // 创建或打开注册表项
RegCreateKeyEx()    // 创建指定的注册键
RegDeleteKey()        // 删除一个注册表键值
RegOpenKey()        // 打开给定键
RegOpenKeyEx()        // 打开一个指定的注册表键
RegDeleteValue()    // 删除一个键下的一个键值
RegQueryValue()        // 取得指定项或子项的默认(未命名)值
RegSetValue()        // 设置指定注册表项的默认值或未命名值的数据
RegSetValueEx()        // 设置指定值的数据和类型
RegQueryInfoKey()    // 获取与一个项有关的信息
RegEnumKey()        // 获取指定的子键值
RegEnumKeyEx()        // 枚举指定项下方的子项
RegEnumValue()        // 枚举指定项的值
RegLoadKey()        // 从以前用RegSaveKey函数创建的一个文件里装载注册表信息
RegReplaceKey()        // 用一个磁盘文件保存的信息替换注册表信息;并创建一个备份,在其中包含当前注册表信息
RegRestoreKey()        // 从一个磁盘文件恢复注册表信息
RegSaveKey()        // 将一个项以及它的所有子项都保存到一个磁盘文件
RegConnectRegistry()    // 访问远程系统的部分注册表
RegNotifyChangeKeyValue()    // 应用程序可以接收事件通知中指定的注册表项及其子项的更改
RegUnloadKey()        // 卸载指定的项以及它的所有子项

user32

RegisterHotKey()    // 定义一个系统范围的热键

进程线程类

user32

AttachThreadInput()    // 把一个线程的输入消息连接到另外的线程

kernel32

CheckRemoteDebuggerPresent() // 检查一个特定进程是否被调试。这个函数通常在一个反调试技术中被使用
ConnectNamedPipe()    // 指示一台服务器等待下去,直至客户机同一个命名管道连接
CreateProcess()        // 创建一个新的进程和它的主线程,这个新进程运行指定的可执行文件
CreateRemoteThread()    // 创建一个在其它进程地址空间中运行的线程(也称:创建远程线程)
CreateToolhelp32Snapshot()        // 通过获取进程信息为指定的进程、进程使用的堆[HEAP]、模块[MODULE]、线程建立一个快照
EnumProcesses()        // 检索进程标识符
EnumProcessModules()        // 枚举进程模块
IsWow64Process()        // 确定指定进程是否运行在64位操作系统的32环境(Wow64)下
OpenProcess()        // 打开一个已存在的进程对象,并返回进程的句柄
PeekNamedPipe()        // 预览一个管道中的数据,或取得与管道中的数据有关的信息
Process32First()    // 获取进程的句柄
Process32Next()        // 获取下一个进程的句柄
ReadProcessMemory()    // 根据进程句柄读入该进程的某个内存空间
ResumeThread()        // 恢复挂起的线程
SetThreadContext()    // 修改给定线程的上下文
SuspendThread()        // 暂停指定的线程
Thread32First()        // 返回进程中第一个线程的信息
Thread32Next()        // 返回进程中下一个线程的信息
WinExec()        // 运行指定的程序
WriteProcessMemory()    // 写入某一进程的内存区域

ntdll

ZwQueryInformationProcess()        // 返回特定进程的信息

shell32

ShellExecute()        // 运行一个外部程序,并有一定的控制

Rpccrt4

RpcServrRegisterIf()    // 注册与RPC运行时库的接口
RpcServerListen()        // 指示RPC运行时库来监听远程过程调用
RpcServerUseProtseqEp()        // 告诉RPC运行时库使用指定的协议序列与指定的端点组合来接收远程过程调用
RpcMgmtStopServerListening()        // 告诉服务端停止对RPC的监听
RpcServerUnregisterIf()        // 从RPC运行时库注册表中删除一个接口
RpcStringBindingCompose()    // 创建一个字符串绑定句柄
RpcBindingFromStringBinding()    // 从绑定句柄的字符串表示中返回绑定句柄
RpcStringFree()        // 释放由RPC运行库分配的字符串
RpcExceptionCode()        // 回一个code,标识异常出现的类型

注入类

kernel32

GetThreadContext()        // 获取目标线程的上下文
QueueUserAPC()        // 把一个APC对象加入到指定线程的APC队列中
VirtualAllocEx()    // 在指定进程的虚拟空间保留或提交内存区域,除非指定MEM_RESET参数,否则将该内存区域置0
VirtualProtectEx()        // 改变在特定进程中内存区域的保护属性

驱动类

kernel32

DeviceIoControl()    // 直接发送控制代码到指定的设备驱动程序,使相应的移动设备以执行相应的操作

secur32

LsaEnumerateLogonSessions()        // 枚举当前系统上的登录会话

ntoskrnl

MmGetSystemRoutineAddress()        // 返回特定函数的地址

加密与解密

Advapi32

// csp是微软提供的加密服务应用接口
CryptAcquireContext()        // 获取有某个容器的CSP模块的指针
CryptReleaseContext()        // 释放CSP句柄
CryptEnumProviders()        // 此函数得到第一个或下一个可用的CSP。如果使用循环,就可以得到计算机上所有可用的CSP
CryptCreateHash()        // 此函数初始化哈希数据流
CryptGetHashParam()        // 得到指定哈希对象的数据
CryptDestroyHash()        // 此函数销毁由hHash指定的哈希对象
CryptHashData()        // 添加数据到hash对象
CryptDeriveKey()        // 此函数从一基本数据值中派生会话密钥
CryptGetProvParam()        // 此函数获得CSP的各种参数
CryptSetKeyParam()        // 自定义会话密钥各方面的操作
CryptEncrypt()        // 此函数用于加密数据
CryptDecrypt()        // 此函数对由CryptEncrypt加密过的数据进行解密
CryptDestroyKey()        // 此函数释放密钥句柄
CryptGenKey()        // 生成一个密钥
CryptGetUserKey()    // 获取用户的公钥/私钥对其中一个的句柄
CryptContextAddRef()        // 增加CSP的引用计数器的数值
CryptReleaseContext()        // 释放CSP句柄
CryptExportKey()        // 

消息传递

User32

SendMessage()        // 将指定的消息发送到一个或多个窗口
SendMessageCallback()        // 将指定的消息发送到一个或多个窗口,此函数为指定的窗口调用窗口程序,并立即返回
SendNotifyMessage()        // 将指定的消息发送到一个窗口
SendMessageTimeout()    // 将指定的消息发送到一个或多个窗口
PostMessage()        // 将一条消息放入到消息队列中
PostThreadMessage()        // 将一个消息放入(寄送)到指定线程的消息队列里,不等待线程处理消息就返回
PostQuitMessage()        // 向系统表明有个线程有终止请求
BroadcastSystemMessage()    // 该函数发送消息给指定的接受者
GetMessage()        // 从调用线程的消息队列里取得一个消息并将其放于指定的结构
PeekMessage()        // 为一个消息检查线程消息队列,并将该消息(如果存在)放于指定的结构
WaitMessage()        // 当一个线程的消息队列中无其它消息时,该函数就将控制权交给另外的线程,同时将该线程挂起,直到一个新的消息被放入线程的消息队列之中才返回
DispatchMessage()        // 该函数分发一个消息给窗口程序

溯源

了解攻击链

恶意攻击活动大概有以下七步:

侦查 -> 定向的攻击工具制作 -> 将攻击工具输送到目标主机上 -> 攻击代码在目标主机上触发 -> 远控程序的安装 -> 攻击工具与远控程序(C2)交互 -> 窃取信息(横向扩大战果)

追踪溯源的方法

主要要理清楚:发动攻击的人是谁,有啥背景,攻击的意图是什么,此次攻击使用了什么技术、使用了那些工具,整个攻击的路径是咋样的

恶意样本追踪溯源可采取以下五种方式

  • 域名/IP分析
  • 入侵日志分析
  • 全流量分析
  • 同源分析
  • 攻击模型分析

域名/IP分析

最常用的方法,通过挖掘攻击者的域名/IP来定位攻击者

可以使用微步等网站,分析恶意域名/IP,通过whois查询等一系列社工的方法找到攻击者的社交账号等信息

入侵日志分析

通过分析相关主机日志、web日志来提取相关攻击者的信息

linux下

~/.bash_history #历史命令记录文件的路径
命令: cat ~/.bash_history   查看历史命令
        history -a      将当前shell会话的历史命令追加到命令历史文件中,命令历史文件是保存历史命令的配置文件。
       history -c     清空当前历史命令列表。
        history -d     删除历史命令列表中指定序号的命令。
        history -n    从命令历史文件中读取本次Shell会话开始时没有读取的历史命令。
        history -s    将指定的命令作为单独的条目加入命令历史内存缓冲区。在执行添加之前先删除命令历史内存缓冲区中最后一条命令。
        history -w    把当前的shell历史命令内存缓冲区的内容写入命令历史文件。

/var/log查看日志
/var/log/boot.log:录了系统在引导过程中发生的事件,就是Linux系统开机自检过程显示的信息
/var/log/lastlog :记录最后一次用户成功登陆的时间、登陆IP等信息
/var/log/messages :记录Linux操作系统常见的系统和服务错误信息
/var/log/secure :Linux系统安全日志,记录用户和工作组变坏情况、用户登陆认证情况
/var/log/btmp :记录Linux登陆失败的用户、时间以及远程IP地址
/var/log/syslog:只记录警告信息,常常是系统出问题的信息,使用lastlog查看
/var/log/wtmp:该日志文件永久记录每个用户登录、注销及系统的启动、停机的事件,使用last命令查看 /var/run/utmp:该日志文件记录有关当前登录的每个用户的信息。如 who、w、users、finger等就需要访问这个文件 /var/log/syslog 或 /var/log/messages 存储所有的全局系统活动数据,包括开机信息。基于 Debian 的系统如 Ubuntu 在
/var/log/syslog 中存储它们,而基于 RedHat 的系统如 RHEL 或 CentOS 则在t
/var/log/messages 中存储它们。
/var/log/auth.log 或 /var/log/secure 存储来自可插拔认证模块(PAM)的日志,包括成功的登录,失败的登录尝试和认证方式。Ubuntu 和 Debian 在
/var/log/auth.log 中存储认证信息,而 RedHat 和 CentOS 则在 /var/log/secure 中存储该信息。

windows下

日志路径:C:\Windows\System32\winevt\Logs
应用程序日志,系统日志,安全日志
审核策略与事件查看器(审核策略默认不开启,若日志系统出现故障、安全事故则可以查看系统的日志文件,排除故障,追查入侵者的信息等)
路径:开始——管理工具——本地安全策略——本地策略——审核策略
设置合理的日志属性,日志最大覆盖阈值
分析日志:事件ID
4624   登录成功
4625   登录失败
4634   注销成功
4647   用户启动的注销
4672   使用超级用户进行登录
4720   创建用户
            登录类型
2  交互式登录
3  网络
4  批处理
5  服务
7   解锁
8   网络明文

全流量分析

通过全流量分析,还原整个入侵过程,结合入侵日志进一步对恶意样本攻击进行追踪溯源

同源分析

获取到恶意样本后,可以通过和历史恶意代码相似度比较,获取历史攻击时间,关联到响应的组织

攻击模型分析

分析攻击的模型,查找相应会使用该攻击模型的组织

溯源常用步骤

攻击源捕获

  • 安全设备报警,如IP扫描、口令爆破、病毒木马等
  • 日志与流量分析,异常的流量,攻击流量
  • 服务器资源异常,异常的文件、账号、进程、端口、服务等
  • 邮件钓鱼,恶意样本,恶意的URL
  • 蜜罐系统捕获,获取攻击者行为,意图

溯源反制

  • IP定位技术:根据IP定位物理位置
  • ID追踪技术:通过搜索引擎、社交账号、社工库匹配ID
  • 网站URL:通过whois查询,查询URL注册人的相应信息
  • 恶意样本:分析恶意样本、提取相关信息,比如用户名、IP、域名、C2信息
  • 社交账号:通过JSONP跨域,获取攻击者的主机信息、浏览器信息等

攻击者画像

  • 分析攻击路劲,分析攻击目的,是否拿到权限,是否窃取信息,分析网络代理,是否使用国外或匿名代理,分析攻击手法,是否使用鱼叉攻击或web渗透
  • 攻击者画像,分析出攻击者的虚拟身份,ID/网名等,查询真实信息,姓名/物理地址等,查询联系方式等信息

参考:

恶意样本分析手册

http://blog.nsfocus.net/malware-sample-analysis-summary/