JSONルールを介してカスタマイズ可能なJava ByteCodeアナライザー。これは、1つ以上の瓶または戦争ファイルを含むパスを受信し、提供されたルールを使用してそれらを分析し、結果とともにHTMLレポートを生成するコマンドラインツールです。
usage: java -jar cba-cli.jar [OPTIONS] -a DIRECTORY_TO_ANALYZE
-a,--analyze <pathToAnalyze> Path of the directory to run the
analysis.
-c,--checks <checks...> Space separated list of custom checks
that are going to be run in the analysis.
-f,--custom-file <customFile> Specify a file in JSON format to run
custom rules. Read more in
https://github.com/fergarrui/custom-bytecode-analyzer.
-h,--help Print this message.
-i,--items-report <maxItems> Max number of items per report. If the
number of issues found exceeds this
value, the report will be split into
different files. Useful if expecting too
many issues in the report. Default: 50.
-o,--output <outputDir> Directory to save the report. Warning -
if there are already saved reports in
this directory they will be overwritten.
Default is "report".
-v,--verbose-debug Increase verbosity to debug mode.
-vv,--verbose-trace Increase verbosity to trace mode - makes it slower, use it only when you need.
ルールファイルは-f,--custom-file引数を使用して指定できます。ファイルはJSON形式で、次の構造があります。
final場合にのみサポートされています net.nandgr.cba.custom.model.Rules.javaを確認して、Javaコードの構造を確認することもできます。
ディレクトリの例にはすでにいくつかのルールがあります。とにかく、以下はすべてのルールのリストの例です。
カスタムの敏aserializationを備えたクラスを見つける必要がある場合は、非常に簡単に行うことができます。クラスはprivate void readObject(ObjectInputStream in)を実装することにより、カスタムの偏りを定義します。したがって、その方法が定義されているすべてのクラスを見つける必要があります。ルールを次のように定義するだけで十分でしょう。
{
"rules" : [{
"name" : " Custom deserialization " ,
"methods" : [{
"name" : " readObject " ,
"visibility" : " private " ,
"parameters" : [{
"type" : " java.io.ObjectInputStream "
}]
}]
}]
} private可視性、 readObjectが名前として、タイプjava.io.ObjectOutputStreamのパラメーターを備えたメソッドを報告します。パラメーターは配列であり、複数のパラメーターが指定されている場合、それらはすべて報告するために一致する必要があります。ルールが1つしかないため、名前付きレポート:Custom-Deserialization-0.htmlが作成されます。
この場合、2つの方法を持つ1つのルールを定義する必要があります。脱出の前の例と同じものと、 private void writeObject(ObjectOutputStream out)に一致する新しいもの。上記のJSON構造に示されているように、プロパティルール。rule.methodsは一連の方法であるため、次のようなルールを書くことができます。
{
"rules" : [{
"name" : " Custom serialization and deserialization " ,
"methods" : [{
"name" : " readObject " ,
"visibility" : " private " ,
"parameters" : [{
"type" : " java.io.ObjectInputStream "
}]
},{
"name" : " writeObject " ,
"report" : " false " ,
"visibility" : " private " ,
"parameters" : [{
"type" : " java.io.ObjectOutputStream "
}]
}]
}]
}プロパティreport 、同じルールについて2回報告することを避けるためにfalseに設定されました。 2番目の方法を条件として使用していますが、このルールの目的のためにreadObjectメソッドのみを報告するだけで十分なはずです。
プロパティが定義されていない場合、それは常に真実と一致します。たとえば、このルールはすべてのメソッド定義を返します。
{
"rules" : [{
"name" : " Method definitions " ,
"methods" : [{
}]
}]
}メソッドの呼び出しも見つけることができます。この場合のJSONは次のとおりです。
{
"rules" : [{
"name" : " String equals " ,
"invocations" : [{
"owner" : " java.lang.String " ,
"method" : {
"name" : " equals "
}
}]
}]
}プロパティowner 、メソッドを含むクラスを指定します。
別の方法の呼び出し例は、前の方法よりも少し便利です。
{
"rules" : [{
"name" : " Method invocation by reflection " ,
"invocations" : [{
"owner" : " java.lang.reflect.Method " ,
"method" : {
"name" : " invoke "
}
}]
}]
}それはどのメソッドの呼び出しと同じですが、この場合のメソッドの名前は<init>でなければなりません。
{
"rules" : [{
"name" : " String instantiation " ,
"invocations" : [{
"owner" : " java.lang.String " ,
"method" : {
"name" : " <init> "
}
}]
}]
}このルールは次のことを見つけます:
[...]
String s = new String ( "foo" );
[...]この例では、以前の例のようなシリアル化行動を定義するクラスではありません)を見つけたいと考えています。 DesarializationはObjectInputStream.readObject()が呼び出されたときに発生します。たとえば、このコードスニペットで:
ObjectInputStream in = new ObjectInputStream ( fileInputStream );
Object o = in . readObject ();したがって、 readObjectという名前のObjectInputStreamからメソッドの呼び出しを見つける必要があります。しかし、クラスがカスタムの偏りを定義すると、 private void readObject(ObjectInputStream in)メソッド内でこのメソッドへの呼び出しを行うと、レポートがあまりにも汚染されるため、研究のコンテキストでは多くの誤検知が見つかります。これらのケースを除外し、本物の脱登りのみを維持したい場合は、財産notFrom使用できます。
{
"rules" : [{
"name" : " Deserialization usage " ,
"invocations" : [{
"owner" : " java.io.ObjectInputStream " ,
"method" : {
"name" : " readObject "
},
"notFrom" : {
"name" : " readObject " ,
"visibility" : " private "
}
}]
}]
}このファイルはjava.io.ObjectInputStream.readObject() Invocationsがprivate void readObject(ObjectInputStream in)メソッド内で行われない場合に発見されます。
このコードにまとめられたクラスは報告されません。
private void readObject ( ObjectInputStream in ) throws IOException , ClassNotFoundException {
Object o = in . readObject ();
}しかし、これは報告されます:
public Object deserializeObject ( ObjectInputStream in ) throws IOException , ClassNotFoundException {
Object o = in . readObject ();
return o ;
}プロパティfromプロパティは、 notFromとまったく同じ方法で呼び出しに設定できますが、結果は逆になります。呼び出しが定義された方法から作成された場合にのみ一致します。
この場合、プロパティsuperClassを使用できます。 javax.servlet.http.HttpServletを拡張しているすべてのクラスを見つけたい場合、ルールは次のとおりです。
{
"rules" : [{
"name" : " Java servlets " ,
"superClass" : " javax.servlet.http.HttpServlet "
}]
}
ルールは、インターフェイスの配列を実装するクラスを見つけるために書くことができます。ルールで複数のインターフェイスが定義されている場合、クラスはそれらすべてを実装して報告する必要があります。 javax.net.ssl.X509TrustManagerを実装するクラスを見つけたい場合、ルールは次のとおりです。
{
"rules" : [{
"name" : " X509TrustManager implementations " ,
"interfaces" : [ " javax.net.ssl.X509TrustManager " ]
}]
} interfaces配列であることに注意してください。 ["interface1", "interface2", ...]正方形のブラケットの間に文字列を追加してください。
注釈もサポートされています。複数の注釈特性は、ルール(クラスの注釈を見つける)で、方法o変数(パラメーターまたはローカル変数)で定義できます。それらのすべてが分析されたクラスで見つかった場合、それは報告されます。たとえば、スプリングエンドポイントを見つけたい場合は、 org.springframework.web.bind.annotation.RequestMappingで注釈が付けられたクラスまたは方法を検索します。したがって、ルールは次のとおりです。
{
"rules" : [{
"name" : " Spring endpoint - class annotation " ,
"annotations" : [{
"type" : " org.springframework.web.bind.annotation.RequestMapping "
}]
},
{
"name" : " Spring endpoint - method annotation " ,
"methods" : [{
"annotations" : [{
"type" : " org.springframework.web.bind.annotation.RequestMapping "
}]
}]
}]
}プロパティrule.fieldsを使用して、クラスフィールドを見つけることができます。パスワード名を持つプライベート文字列フィールドを見つけたい場合は、次のようなルールを使用できます。
{
"rules" : [{
"name" : " Password fields " ,
"fields" : [
{
"visibility" : " private " ,
"type" : " java.lang.String " ,
"nameRegex" : " (password|pass|psswd|passwd) "
}
]
}]
}変数を見つけるには、 rule.variables使用できます。このプロパティは、ローカル変数とメソッド引数変数を報告します。タイプjavax.servlet.http.Partのすべての変数を見つけたい場合、ルールは次のとおりです。
{
"rules" : [{
"name" : " Servlet upload file " ,
"methods" : [{
"variables" : [{
"type" : " javax.servlet.http.Part "
}]
}]
}]
}同じJSONファイルで複数のルールを定義できます。それらは個別に処理および報告され、お互いに影響を与えません。以前の例ルールのいくつかを組み合わせることができます。
{
"rules" : [{
"name" : " Custom deserialization " ,
"methods" : [{
"name" : " readObject " ,
"visibility" : " private " ,
"parameters" : [{
"type" : " java.io.ObjectInputStream "
}]
}]
},{
"name" : " Method invocation by reflection " ,
"invocations" : [{
"owner" : " java.lang.reflect.Method " ,
"method" : {
"name" : " invoke "
}
}]
}]
}ここには、2つのルールがあります(「カスタムスターリア化」と「反射によるメソッドの呼び出し」)。それらは、2つの分離された実行でそれを行うかのように処理されます。ルールごとのレポートが生成されます。ルールに同じ名前がある場合、それらは同じファイルに報告されます。
このプロジェクトは、JSON形式でカバーされていないJavaコードに、より複雑なカスタムルールを追加するためにダウンロードおよび構築できます。パッケージnet.nandgr.cba.visitor.checksには、すでに3つの例があります。これらはCustomDeserializationCheck, DeserializationCheck and InvokeMethodCheckです。 net.nandgr.cba.custom.visitor.base.CustomAbstractClassVisitorを拡張して、独自のルールを作成できます。
上記のように、レポートはデフォルトでreportフォルダーの下に作成されます。すべてのルールには、同じ名前がない限り、別のファイルがあります。レポートが大きすぎる場合は、 -i,--items-report <maxItems>パラメーターを使用して分割できます。各パラメーターは、指定された引数を保持します(最後のものの場合)。報告されたすべてのアイテムは、見つかったjar、クラス名、およびメソッド名(関連する場合)を指定します。また、クイックビジュアルチェックを容易にするために、クラスの逆コンパイルバージョンを表示します。 java.io.Fileインスタンス化を見つけるためのルールのためにアイテムがどのように表示されるかの例:

セキュリティバグを検索する場合、コールグラフを使用することは非常に便利です。現時点では、 reportディレクトリの下に単純なDOT互換ファイルが作成されています。グラフには、発見された問題が呼び出される可能性のあるすべてのフローが含まれています。たとえば、脱介入を見つけるためのルールが使用される場合、脱介入を呼び出す方法につながるすべての可能なパスを含むグラフが生成されます。
ファイルはcall-graph.dotであり、このようになります(これは非常に簡単な例です):
graph callGraph {
"demo.callgraph.Class1:method1" -- "demo.callgraph.Class2:method2"
"demo.callgraph.Class3:method3" -- "demo.callgraph.Class2:method2"
}
視覚的に表示するには、 DOT使用することができます(または互換性のあるソフトウェア)。たとえば、ファイルをsvgに変換するには:
dot -Tsvg call-graph.dot -o call-graph.svg
これは、システムパスにDOTが見つかった場合、デフォルトで自動的に実行されます。そうでない場合は、 sudo apt-get install graphvizを使用してDebianベースのシステムにDOTをインストールできます。
inkscapeやJust firefoxなどのプログラムを使用してPNGに変換したり、視覚化できるcall-graph.svgという名前のSVGファイルを作成します。
上記のファイルの非常に簡単な例は、次のことです。

たとえば、検索されたアイテムがjava.lang.Runnable.run()または同様の方法にある場合、いくつかの制限があります。スレッドの実行場所は見つかりません。また、グラフはStackOverflowError Sを避けるためにサイクルをクリーニングしています。これは、大規模なディレクトリの分析中にシステムのメモリが排出されないため、少し保守的な方法で作られています。
将来のバージョンにはその他のオプションが追加されます。
java -jar cba-cli-<version>.jar -a /path/with/jars -f /path/with/json/file/rules.json
カスタムJavaルールを使用するには、クラス名を-cの引数として指定する必要があります。
java -jar cba-cli-<version>.jar -a /path/with/jars -c DeserializationCheck
スペース分離リストを受け入れるため、複数のカスタムルールを定義できます(各ルールが個別のレポートを作成します):
java -jar cba-cli-<version>.jar -a /path/with/jars -c DeserializationCheck InvokeMethodCheck CustomDeserializationCheck YourCustomRule
java -jar cba-cli-<version>.jar -a /path/with/jars -f /path/with/json/file/rules.json -c YourCustomRule1 YourCustomRule2
エラーを見つけるために、冗長性を高めることができます。デバッグレベル:
java -jar cba-cli-<version>.jar -a /path/with/jars -c YourCustomRule1 -v
トレースレベル:
java -jar cba-cli-<version>.jar -a /path/with/jars -c YourCustomRule1 -vv
現時点では、APKを最初にJARに変換する必要があります。
d2j-dex2jar.sh -f -o app_to_analyze.jar app_to_analyze.apk-aパラメーター変換されたJARファイルを含むディレクトリ。 https://github.com/fergarrui/custom-bytecode-analyzer/blob/master/bin/cba-cli-0.1-snapshot.jarに、 bin Directoryにはすでに実行可能なJARファイルがあります。変更を行うか、カスタムルールを追加したい場合は、プロジェクトを構築できます。
git clone https://github.com/fergarrui/custom-bytecode-analyzer.git
cd custom-bytecode-analyzer
mvn clean package
targetフォルダーの下に2つの瓶が生成されます。 cba-cli-<version>.jarにはすべての依存関係が含まれており、実行可能です。 java -jar cba-cli-<version>.jarを使用して実行できます