FlowDroid架构剖析

最近算是把FlowDroid源代码翻了一遍,并非通读,而是把整个系统的逻辑/设计整理了一下。这里稍微记录一下。由于FlowDroid能够分析Android程序,所以有一部分代码是对Android相关领域做适配,由于个人目前的工作对Android静态分析还不是很涉及,所以在分析FlowDroid源码时省略了Android相关的适配代码,主要是作通用Java相关的分析。

FlowDroid

几大组件:

  • EntryPointCreator:使用EntryPointCreator指定分析的入口
  • SourceSinkManager:给定一个Stmt, 确定Source和Sink(对应SourceInfo,SinkInfo)
  • NativeCallHandler:
    • 默认使用 DefaultNativeCallHandler
  • TaintPropagationWrapper:定义不应该被直接分析的类、方法。相反,分析结果取自外部模型中的方法摘要
    • 一般通过IInfoflow.setTaintWrapper(…) 来配置
  • Aliasing: 别名控制器
    • IAliasingStrategy为别名策略: FlowSensitive(默认), PtsBased(andersen式), Lazy
    • 以 BackwardsInfoflowProblem 为问题的求解器
  • IFDSSolver:IFDS求解器
    • 前向污点传播求解:InfoflowProblem
    • 后向别名分析: BackwardsInfoflowProblem
  • PathReconstructor:污点传播路径复现
  • IPC Manager 是安卓相关,不予考虑

Infoflow

配置ITaintPropagationWrapper的接口,Infoflow类会继承该接口。

interface ITaintWrapperDataFlowAnalysis {
    // 配置TaintPropagationWrapper
    void setTaintWrapper(ITaintPropagationWrapper taintWrapper);
    ITaintPropagationWrapper getTaintWrapper();
}

*IInfoflow

interface soot.jimple.infoflow.IInfoflow extends ITaintWrapperDataFlowAnalysis {
    // 配置InfoflowConfiguration的接口
    InfoflowConfiguration getConfig();
    void setConfig(InfoflowConfiguration config);
    
    // 用于配置NativeCallHandler
    void setNativeCallHandler(INativeCallHandler handler);
    
    // 用于信息流分析的前后分析行为植入
    void setPreProcessors(Collection<? extends PreAnalysisHandler> preprocessors);
    void setPostProcessors(Collection<? extends PostAnalysisHandler> postprocessors);
    
    // 计算信息流(信息流分析)的主入口接口
    void computeInfoflow(String appPath, 
                         String libPath, 
                         IEntryPointCreator entryPointCreator,
						 List<String> sources, 
                         List<String> sinks);
	
    void computeInfoflow(String appPath, 
                         String libPath, 
                         Collection<String> entryPoints,
						 Collection<String> sources, 
                         Collection<String> sinks);
    
    void computeInfoflow(String appPath, 
                         String libPath, 
                         String entryPoint, 
                         Collection<String> sources,
						 Collection<String> sinks);
	
    void computeInfoflow(String appPath, 
                         String libPath, 
                         IEntryPointCreator entryPointCreator,
						 ISourceSinkManager sourcesSinks);
    
    void computeInfoflow(String appPath, 
                         String libPath, 
                         String entryPoint, 
                         ISourceSinkManager sourcesSinks);
    
    // 获取分析结果
    InfoflowResults getResults();
    
    // 是否分析结果可用
    boolean isResultAvailable();
    
    // 配置 结果可用时的回调函数
    void addResultsAvailableHandler(ResultsAvailableHandler handler);
    
    // 用于配置底层Soot
    void setSootConfig(IInfoflowConfig config);
    
    // 用于配置 Path reconstructor 算法
    void setPathBuilderFactory(IPathBuilderFactory factory);
    
    // 获取已经收集的Source点
    Set<Stmt> getCollectedSources();
    
    // 获取已经收集的Sink点
    Set<Stmt> getCollectedSinks();
    
    // 主线程(如GUI)用于控制、中断分析
    void abortAnalysis();
    
    // 污点前向传播时调用
    void setTaintPropagationHandler(TaintPropagationHandler handler);
    
    // 别名后向传播时调用
    void setBackwardsPropagationHandler(TaintPropagationHandler handler);
    
    // 配置内存管理器
    void setMemoryManagerFactory(IMemoryManagerFactory factory);
    
    // 配置Executor
    void setExecutorFactory(IExecutorFactory executorFactory);
    
    // 配置污点传播规则管理器
    void setPropagationRuleManagerFactory(IPropagationRuleManagerFactory ruleManagerFactory);
    
    // Android IPC相关, 不需要关注
    void setIPCManager(IIPCManager ipcManager);
}
class soot.jimple.infoflow.Infoflow extends AbstractInfoflow {
    // 分析纯Java代码,无任何APKs或者Android SDK依赖
    public Infoflow() { ... }
    
    // 分析APK文件
    public Infoflow(String androidPath, boolean forceAndroidJar) { ... }
    
    // 分析APK文件
    public Infoflow(String androidPath, 
                    boolean forceAndroidJar, 
                    BiDirICFGFactory icfgFactory) { ... }
}

EntryPointCreator (√)

interface IEntryPointCreator {

	// 生成dummy Main方法,它会调用给定列表中的所有方法
	SootMethod createDummyMain();

	void setSubstituteCallParams(boolean b);
    
	void setSubstituteClasses(List<String> l);

	Collection<String> getRequiredClasses();

	Collection<SootMethod> getAdditionalMethods();
    
	Collection<SootField> getAdditionalFields();

	SootMethod getGeneratedMainMethod();
}
  • BaseEntryPointCreator: 创建一个空的dummyMainClass, dummyMainMethod
    • DefaultEntryPointCreator 任意顺序处理entry point method
      • 通过传入的函数签名,往dummyMainMethod中添加对这些函数签名的调用
      • 调用顺序任意
    • SequentialEntryPointCreator
      • 调用顺序就是一个列表
    • 其它的EntryPointCreator都是android相关的

IInfoflowConfig

soot.jimple.infoflow.config.IInfoflowConfig 用于配置FlowDroid的InfoflowConfiguration和Soot的Options

public interface IInfoflowConfig {
    void setSootOptions(Options options, InfoflowConfiguration config);
}
// 比如
// 配置污染路径:能够得到比较详细的污染路径
config.getPathConfiguration().setPathReconstructionMode(InfoflowConfiguration.PathReconstructionMode.Precise);

InfoflowManager

最重要的两次实例化:

  • 一次是forward 前向污点分析时实例化
  • 一次是backward 后向别名分析时实例化
class InfoflowManager {
    // 配置Infoflow
    InfoflowConfiguration config;
    // IFDS/IDE求解器 (forward: source -> sink)
    IInfoflowSolver forwardSolver;
    // ICFG, 流程间控制流图
    IInfoflowCFG icfg;
    // SourceSinkManager
    ISourceSinkManager sourceSinkManager;
    // 污点传播Wrapper
    ITaintPropagationWrapper taintWrapper;
    // 类型工具
    TypeUtils typeUtils;
    // 快速Hierarchy
    FastHierarchy hierarchy;
    // AccessPath 工厂类
    AccessPathFactory accessPathFactory;
    // 全局污点管理
    GlobalTaintManager globalTaintManager;
    // 别名
    Aliasing aliasing;
}

污染传播相关

IInfoflowSolver
public interface soot.jimple.infoflow.solver.IInfoflowSolver {
    // 当求解时,调度给定的边。如果边早已经被处理过,返回false
    boolean processEdge(PathEdge<Unit, Abstraction> edge);
    
    // 通过incoming抽象,给出方法的summary   
    Set<Pair<Unit, Abstraction>> endSummary(SootMethod m, Abstraction d3);
    
    void injectContext(IInfoflowSolver otherSolver, 
                       SootMethod callee, 
                       Abstraction d3, 
                       Unit callSite,
                       Abstraction d2, 
                       Abstraction d1);
    void cleanup();
    void setFollowReturnsPastSeedsHandler(IFollowReturnsPastSeedsHandler handler);
    void setMemoryManager(IMemoryManager<Abstraction, Unit> memoryManager);
    IMemoryManager<Abstraction, Unit> getMemoryManager();
    void setPredecessorShorteningMode(PredecessorShorteningMode mode);
    long getPropagationCount();
    void solve();
    void setSolverId(boolean solverId);
    // 求解器对应的IFDS Problem
    AbstractInfoflowProblem getTabulationProblem();
    void setMaxJoinPointAbstractions(int maxJoinPointAbstractions);
    void setMaxCalleesPerCallSite(int maxCalleesPerCallSite);
    void setMaxAbstractionPathLength(int maxAbstractionPathLength);
    void setPeerGroup(SolverPeerGroup solverPeerGroup);
    void terminate();
}
ISourceSinkManager
// SourceSinkManager用于告诉是否一条语句包含Source或者Sink
interface soot.jimple.infoflow.sourcesSinks.manager.ISourceSinkManager {
    // 初始化
    void initialize();
    // 看是否一个Stmt包含一个Source
    SourceInfo getSourceInfo(Stmt sCallSite, InfoflowManager manager);
    // 看是否一个Stmt包含一个Sink
    SinkInfo getSinkInfo(Stmt sCallSite, InfoflowManager manager, AccessPath ap);
}

ISourceSinkManager的具体实现:

  • BaseSourceSinkManager
  BaseSourceSinkManager implements ISourceSinkManager, IOneSourceAtATimeManager {
  • DefaultSourceSinkManager
    默认 SourceSinkManager,调用computeInfoflow时通过传入sources, sinks集合会默认创建一个DefaultSourceSinkManager

    也可提供一个ISourceSinkDefinitionProvider实例作为SourceSink的定义源
  DefaultSourceSinkManager implements ISourceSinkManager {
  • MethodBasedSourceSinkManager 基于方法的SourceSinkManager, 用于用户扩展的类,给定一个callSite, 我们只需要决定它的targetMethod的sourceSink相关信息
  MethodBasedSourceSinkManager implements ISourceSinkManager {
    • EmptySourceSinkManager 空SourceSinkManager
    EmptySourceSinkManager extends MethodBasedSourceSinkManager {
  • SummarySourceSinkManager: 可使用它来生成方法的Summaries。
    SummaryGenerator就使用它来生成方法的污点摘要
  SummarySourceSinkManager implements ISourceSinkManager {
ISourceSinkDefinitionProvider

可用于给ISourceSinkManager类提供source,sink的定义

public interface soot.jimple.infoflow.sourcesSinks.definitions.ISourceSinkDefinitionProvider {
    Set<? extends ISourceSinkDefinition> getSources();
    Set<? extends ISourceSinkDefinition> getSinks();
    Set<? extends ISourceSinkDefinition> getAllMethods();
}
  • XMLSourceSinkParser: 测试类XmlParserTest查看使用
  • FilteringSourceSinkDefinitionProvider
  • NullSourceSinkDefinitionProvider
PropagationRuleManager

IPropagationRuleManagerFactory(只有一个子类DefaultPropagationRuleManagerFactory) 用于创建 PropagationRuleManager

InfoflowProblem实例化时需要传入IPropagationRuleManagerFactory

// 用于管理传播规则
soot.jimple.infoflow.problems.rules.PropagationRuleManager

ITaintPropagationWrapper

定义不应该被直接分析的类、方法。相反,分析结果取自外部模型中的方法摘要(which improves performance and helps if the sources are not available)

interface soot.jimple.infoflow.taintWrappers.ITaintPropagationWrapper {
    void initialize(InfoflowManager manager);
    // 检查调用语句用于黑盒污点传播, 这能让我们手动在方法调用间传播污点, 而不要求分析深入到方法内
    Set<Abstraction> getTaintsForMethod(Stmt stmt, Abstraction d1, Abstraction taintedPath);
    // 告诉分析器不要在callee内部传播
    boolean isExclusive(Stmt stmt, Abstraction taintedPath);
    // 被摘要的方法通过给定抽象生成的可能的别名
    Set<Abstraction> getAliasesForMethod(Stmt stmt, Abstraction d1, Abstraction taintedPath);
    boolean supportsCallee(SootMethod method);
    boolean supportsCallee(Stmt callSite);
    int getWrapperHits();
    int getWrapperMisses();
}

soot.jimple.infoflow.cmd.MainClass#initializeTaintWrapper方法中有ITaintPropagationWrapper的各种实例化方式,可供参考

  • IReversibleTaintWrapper
    • SummaryTaintWrapper: 通过IMethodSummaryProvider提供Summary, 使用StubDroid创建的方法摘要
      • ReportMissingSummaryWrapper
    • TaintWrapperList: 遍历ITaintPropagationWrapper列表list,如果list中有一个返回非空污点集合,此集合就被使用
    • TaintWrapperSet: 遍历ITaintPropagationWrapper集合Set, 将所有返回的非空污点集合作并集
  • AbstractTaintWrapper
    • *EasyTaintWrapper
    • IdentityTaintWrapper: 如果receiver object或者函数调用的入参有污点,那么返回值也被污染
    • RecordingTaintWrapper: 用于记录统计数据, 从不会返回任何污点信息
  • SummaryGenerationTaintWrapper: 在summary构造的时候使用

IMethodSummaryProvider

// 能提供方法摘要的公共类接口
interface IMethodSummaryProvider {
    Set<String> getLoadableClasses();
    
    // 支持直接返回方法summary的类
    Set<String> getSupportedClasses();
    // 是否支持提供该类的方法summary
    boolean supportsClass(String clazz);
    // 
    default ClassMethodSummaries getMethodFlows(SootClass sootClass, String methodSubSignature) {
        return getMethodFlows(sootClass.getName(), methodSubSignature);
    }
    ClassMethodSummaries getMethodFlows(String className, String methodSignature);
    ClassSummaries getMethodFlows(Set<String> classes, String methodSignature);
    ClassMethodSummaries getClassFlows(String clazz);
    boolean mayHaveSummaryForMethod(String subsig);
    ClassSummaries getSummaries();
    boolean isMethodExcluded(String className, String subSignature);
}
  • XMLSummaryProvider: 从外部xml文件中加载Summary
    • LazySummaryProvider: 懒加载summary
    • EagerSummaryProvider: 实例化时立即load summary
  • MemorySummaryProvider: 从内存数据结构中加载Summary
  • MergingSummaryProvider: IMethodSummaryProvider的组合

工具类

SootMethodRepresentationParser

  • 解析方法签名
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值