Group of Software Security In Progress

GoSSIP @ LoCCS.Shanghai Jiao Tong University

DSCRETE: Automatic Rendering of Forensic Infomation From Memory Images via Application Logic Reuse

论文下载

Abstract && Introduction

  • 问题:在内存取证时,即使了解数据结构的语法、语义,也难以恢复数据域上的内容
  • 原因:加密,存在于图片、密码、特殊格式文件等
  • 作者提出DSCRETE(Data Structure Content Reverse Engineering via execuTable rEuse)工具,处理二进制
  • 基于观察:定义这些数据结构的应用都会包含翻译这些结构的逻辑(输出、保存)
  • 旨在重用这些逻辑,恢复内存镜像里的数据结构
  • (将重用、数据结构恢复应用于取证)
  • (类似动态分析天生免疫混淆一样,总归还是要给人看的,有加密逻辑,就肯定存在解密逻辑,重用就好)

Fig

System Overview

Key Idea: Executable Code Reuse

  • 重用原有程序中的解释逻辑
  • 以linux上gnome-paint(GP)为例
  • GP将输入图片拆分成许多内部数据结构,当用户编辑图片时,实质是在操作数据结构,保存图片时,再将数据结构重组
  • 当取证时,DSCRETE:

    1. 识别、抽取程序中相关的数据结构printing/rendering函数(简称P)
    2. 扫描镜像,识别可能的数据结构实例
  • P未必是一个函数,可能是多个函数组合成的功能模块

  • GP例子中,P是file_save函数,输入是GdkPixbuf数据结构
  • 这里有一个假设:如果P足够好,非法的数据输入会导致错误(暴力的开始)

Overview of DSCRETE Workflow

Fig

  • 输入是处理目标数据的二进制应用
  • 插桩粗粒度识别P范围(Dynamic Data Dependence Tracing)
  • 获得一些疑似函数(Identifying Functional Closure)
  • 检测每一个疑似函数(Finding the Scanner’s Entry Point),前提是有已知的数据结构实例测试用
  • 打包P,使其成为context-free memory scanner(Memory Image Scanning)
  • 这里并不是找源数据
  • 目标不是识别哪些数据是目标数据,这个是前提
  • 是已知某些数据是目标数据,将它们恢复成可读形式

Assumptions and Setup

  • 目标程序可执行,存在一个可执行的环境,关闭ASLR
  • 数据完好

System Design

Dynamic Data Dependence Tracing

  • 在目标二进制中,动态收集data dependence trace
  • 以GP为例
    1. 用GP处理一些图片,获得数据结构信息
    2. 保存图片,触发写操作
  • GP会调用GDK库函数gdk_pixbuf_save函数,图片作为参数
  • 同时记录数据依赖关系、函数调用关系,包括参数
  • DSCRETE在遇到使用输出相关的系统调用的函数调用时,会保留当时堆、栈的快照
  • 进行输出的函数简称F,F的参数记为B
  • 这一步的输出:data dependence graph
  • 以操作B的指令为源,加上所有与其有数据依赖关系的指令(切片)
  • (输入随机测试数据,动态trace,得到输出相关函数)

Identifying Functional Closure

  • closure point(CP):是一条指令,满足:直接操作目标数据(指针),与之后任何操作目标数据的指令都存在依赖关系
  • 所以CP有一个性质:只要改变CP的指针,就可以改变P的输出(类似全局变量)
  • 在GP中,CP是file_save中将GdkPixbuf指针mov给一个寄存器的指令
  • 实际情况中,可能存在多个CP,所以这里采用graph closure algorithm算法和启发式的方法进一步筛选CP

Fig

  • 对于和B中任何一个byte有关的指令,以此为起始节点,按照数据依赖关系,和相关指令一起组成图
  • 然后启发式:该起始节点需要操作可能的数据结构指针(位于可读可写的内存段中);dependence subgraph的size是最大的
  • intuition:CP操作的指针是被P使用的,所以是数据结构实例的指针,最大的subgraph的起始点应该是CP
  • GP的file_save函数dependence graph的所有subgraph中最大的起始于GdkPixbuf指针
  • 还有一个启发式策略:data dependence – graph包含从F到main的指令(逆序),而且P很接近F,并且明显小于其他功能的组件,用自定义百分比p表示 (个人理解F是P的子集,因为P是负责printing/rendering的component,是至少一个函数的组合,而F是负责写功能的外部库函数、系统调用,所以P和F应该是调用关系,而P will be close to F in the graph的表述似乎表明是平行关系)

Finding the Scanner’s Entry Point

  • 测试closure point
  • tester的输入:结束点(F,即F结束测试结束);执行F时的内存镜像;可能的CP;目标二进制
  • 将F的内存镜像作为“疑似”内存扫描,假设其中包含合法的数据结构实例
  • 内存镜像(memory image)被放到原本的地址上(ASLR关闭)
  • 作者注明:没有发现严重的内存overlap的问题
  • (测试用的数据是另外已知的合法数据结构实例)
  • 能够顺利执行而且最终结果正确的就是CP
  • 在GP中,file_save(P)中的CP将GdkPixbuf指针mov给寄存器,调用gdk_pixbuf_save(F)

Memory Image Scaning

  • 得到P后,遍历目标镜像中每个地址,恢复出文件

Evuluation

Fig