CodeQL具有用于标识调用其他代码,以及可以被任意位置调用的代码的类。通过这个类你可以找到从未使用过的方法。

调用图类

CodeQL的Java库提供了两个抽象类来表示程序的调用图:CallableCall前者是MethodConstructor的公共超类,后者是MethodAccessClassInstanceExpressionThisConstructorInvocationStmtSuperConstructorInvocationStmt的通用超类简而言之,Callable是被调用的函数,而Call则是调用Callable

在下面的示例中,所有Callable和Call都带有注释注解:

class Super {
    int x;

    // callable
    public Super() {
        this(23);       // call
    }

    // callable
    public Super(int x) {
        this.x = x;
    }

    // callable
    public int getX() {
        return x;
    }
}

    class Sub extends Super {
    // callable
    public Sub(int x) {
        super(x+19);    // call
    }

    // callable
    public int getX() {
        return x-19;
    }
}

class Client {
    // callable
    public static void main(String[] args) {
        Super s = new Sub(42);  // call
        s.getX();               // call
    }
}

 

Call类提供了两个调用图导航谓词:

  • getCallee返回此调用(静态)解析的Callable请注意,对于实例方法(即非静态方法)的调用,在运行时调用的实际方法可能是覆写该方法的其他方法。
  • getCaller返回此调用在语法上的一部分Callable

例如,在我们Client.main第二个call的getCallee 示例中,将返回Super.getX不过,在运行时,此call实际上会调用Sub.getX

Callable类定义了大量的成员谓词;就我们的目的而言,两个最重要的是:

  • calls(Callable target),如果这个callable包含callee作为target的调用
  • polyCalls(Callable target),如果这个callable在运行时调用target如果它包含调用,该调用的callee为targettarget覆写的方法,则为这种情况

在我们的示例中,Client.main calls构造函数Sub(int)Super.getX方法另外,它polyCalls Sub.getX方法

示例:查找未使用的方法

我们可以使用Callable类来编写查询,以查找未被任何其他方法调用的方法:

import java

from Callable callee
where not exists(Callable caller | caller.polyCalls(callee))
select callee

在LGTM.com上的查询控制台中查看此内容这个简单的查询通常返回大量结果。

笔记

这里我们必须使用polyCalls而不是calls:我们想要合理地确保callee不会被直接或通过覆写方法调用。

在典型的Java项目上运行此查询会导致Java标准库中出现很多匹配项。这是有道理的,因为没有单个客户端程序会去使用标准库的每一个方法。更一般而言,我们可能要从编译的库中排除方法和构造函数。我们可以使用谓词fromSource来检查编译单元是否为源文件,并优化查询:

import java

from Callable callee
where not exists(Callable caller | caller.polyCalls(callee)) and
    callee.getCompilationUnit().fromSource()
select callee, "Not called."

在LGTM.com上的查询控制台中查看此内容此更改减少了大多数项目返回的结果数。

我们可能还会注意到一些名称有些陌生的未使用的方法<clinit>:这些是类初始化器;尽管在代码中的任何地方都没有显式调用它们,但是在加载周围的类时会隐式调用它们。因此,将它们从我们的查询中排除是有意义的。

在此过程中,我们还可以排除finalize,finalize也会被隐式调用:

import java

from Callable callee
where not exists(Callable caller | caller.polyCalls(callee)) and
    callee.getCompilationUnit().fromSource() and
    not callee.hasName("<clinit>") and not callee.hasName("finalize")
select callee, "Not called."

在LGTM.com上的查询控制台中查看此内容这也减少了大多数项目返回的结果数量。

我们可能还希望从查询中排除public方法,因为它们可能是外部API入口点:

import java

from Callable callee
where not exists(Callable caller | caller.polyCalls(callee)) and
    callee.getCompilationUnit().fromSource() and
    not callee.hasName("<clinit>") and not callee.hasName("finalize") and
    not callee.isPublic()
select callee, "Not called."

在LGTM.com上的查询控制台中查看此内容这应该对返回的结果数量产生更明显的影响。

另一个特殊情况是非public默认构造函数:例如,在单例模式中,为类提供了私有的空默认构造函数,以防止被实例化。由于此类构造函数的真正目的是不被调用,因此不应对其进行标记:

import java

from Callable callee
where not exists(Callable caller | caller.polyCalls(callee)) and
    callee.getCompilationUnit().fromSource() and
    not callee.hasName("<clinit>") and not callee.hasName("finalize") and
    not callee.isPublic() and
    not callee.(Constructor).getNumberOfParameters() = 0
select callee, "Not called."

在LGTM.com上的查询控制台中查看此内容此更改对某些项目的结果影响很大,而对其他项目的结果影响很小。在不同项目之间,此模式的使用差异很大。

最后,在许多Java项目中,有一些方法是通过反射间接调用的。因此,尽管没有calls调用这些方法,但实际上它们是被使用的。通常很难识别这种方法。但是,一个非常常见的特殊情况是JUnit测试方法,由测试运行器反射地调用。Java的CodeQL库支持识别JUnit和其他测试框架的测试类,我们可以使用它们来过滤掉在此类中定义的方法:

import java

from Callable callee
where not exists(Callable caller | caller.polyCalls(callee)) and
    callee.getCompilationUnit().fromSource() and
    not callee.hasName("<clinit>") and not callee.hasName("finalize") and
    not callee.isPublic() and
    not callee.(Constructor).getNumberOfParameters() = 0 and
    not callee.getDeclaringType() instanceof TestClass
select callee, "Not called."

在LGTM.com上的查询控制台中查看此内容这样可以进一步减少返回结果的数量。

posted @ 2021-05-10 19:01 bamb00 阅读(962) 评论(0) 推荐(0) 编辑
摘要: 声明类 下述表格列出了所有Stmt的子类: Statement syntaxCodeQL classSuperclassesRemarks ; EmptyStmt Expr ; ExprStmt { Stmt ... } BlockStmt if ( Expr ) Stmt else Stmt If 阅读全文
posted @ 2021-05-08 21:07 bamb00 阅读(873) 评论(0) 推荐(0) 编辑
摘要: 1.命令替换 实现方法 替换系统中常见的进程查看工具(比如ps、top、lsof)的二进制程序 对抗方法 使用stat命令查看文件状态并且使用md5sum命令查看文件hash,从干净的系统上拷贝这些工具的备份至当前系统,对比hash是否一致,不一致,则说明被替换了。 注:需要在bin目录下执行。 2 阅读全文
posted @ 2021-03-05 20:19 bamb00 阅读(1436) 评论(0) 推荐(0) 编辑
摘要: OAuth 2.0 有 4 种认证流程: 授权码模式(authorization code) 简化模式(implicit) 密码模式(resource owner password credentials) 客户端模式(client credentials) 下面以微信为例介绍最常见的也是最安全的 阅读全文
posted @ 2021-02-27 20:03 bamb00 阅读(1713) 评论(0) 推荐(2) 编辑
摘要: 数据流程图 CodeQL数据流库通过对程序或功能的数据流图进行建模来实现对程序或功能的数据流分析。与抽象语法树不同,数据流图不反映程序的语法结构,而是在运行时对数据流过程序的方式进行建模。抽象语法树中的节点代表语法元素,例如语句或表达式。另一方面,数据流图中的节点表示在运行时带有值的语义元素。 一些 阅读全文
posted @ 2020-08-31 23:18 bamb00 阅读(3805) 评论(0) 推荐(0) 编辑
摘要: 该库被实现为一个QL模块,是一个后缀为.qll的文件,即java.qll,该模块导入了所有核心Java库模块,因此,我们可以在查询的开始位置通过以下方式来引入完整的java库: import java 库类总结标准Java库中重要的类可以分为5种: 表示编程元素的类(例如类和方法) 表示AST节点的 阅读全文
posted @ 2020-08-31 23:13 bamb00 阅读(1491) 评论(0) 推荐(0) 编辑
摘要: 在CodeQL CLI中使用自定义查询 为了使用CodeQL进行定制分析,我们可以通过自己编写查询来实现查找漏洞或错误。CodeQL的查询类型有: 告警查询:突出显示代码中特定位置的问题的查询。 路径查询:代码中source和sink之间信息流的查询。 基本查询结构 用CodeQL编写的查询文件扩展 阅读全文
posted @ 2020-08-31 23:12 bamb00 阅读(1800) 评论(0) 推荐(0) 编辑
摘要: 一、CodeQL 工作流程 CodeQL 的整体工作流程如下图所示:(图片来源:https://blog.semmle.com/introduction-to-variant-analysis-part-2/) CodeQL 的整体思路是把源代码转化成一个可查询的数据库,通过 Extractor 模 阅读全文
posted @ 2020-08-22 16:17 bamb00 阅读(5452) 评论(0) 推荐(0) 编辑
只有注册用户登录后才能阅读该文。 阅读全文
posted @ 2020-01-20 00:09 bamb00 阅读(57) 评论(0) 推荐(0) 编辑
摘要: 网页加载js步骤1、浏览器一边下载html网页,一边开始解析(不等下载完就解析)2、遇到<script>标签,暂停解析,网页渲染的控制权交给javascript引擎3、如果<script>标签引用了外部脚本,先下载在执行,否则直接执行4、执行完毕,控制权交还渲染引擎,继续往下解析html网页注意:有 阅读全文
posted @ 2019-08-06 11:19 bamb00 阅读(867) 评论(0) 推荐(0) 编辑
点击右上角即可分享
微信分享提示