Coder Social home page Coder Social logo

fare9 / kunai-static-analyzer Goto Github PK

View Code? Open in Web Editor NEW
130.0 130.0 17.0 85.21 MB

Tool aimed to provide a binary analysis of different file formats through the use of an Intermmediate Representation.

Home Page: https://fare9.github.io/KUNAI-static-analyzer/

License: MIT License

C++ 94.42% Makefile 0.67% Java 1.90% Shell 0.43% CMake 1.72% C 0.87%

kunai-static-analyzer's Introduction

Hello, I'm Eduardo!

My name is Eduardo, but many people know me as Fare9 (Farenain), here you can find some things about me.

  • I work as compiler engineer at Quarkslab
  • I'm almost finishing a PhD in Computer Science at UC3M.
  • My PhD is focused on security and privacy analysis on Android Ecosystem.
  • I have written a book about fuzzing in IoT with QEMU and AFL.
  • I'm interested in compiler technologies, specially LLVM and Java stuff too!
  • I also write tools for binary analysis.
  • I have a N5 of Japanese (waiting for N4 results), and my dream is living in Japan.

kunai-static-analyzer's People

Contributors

artifactrepo avatar fare9 avatar jalopezg-git avatar javaernesto avatar lukhio avatar nyedr avatar sisco0 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

kunai-static-analyzer's Issues

BUG in "creating exceptions" with some samples

Bug arise after creating exception with a classes.dex from a malware sample.

  • MD5 of classes.dex of the file: 522930c6687964943c15e90458933315
  • MD5 of the sample: ab676e3aa25c4d16b5d148fd5702cd80

This looks like a possible bug in the parser, or in the MethodAnalysis createBlocks method.

The bug is raised with the next method:

Lcom/antume/Cantin;->buton(Landroid/content/Context;I)V

Once the method is going to be lifted, in the jump_target_analysis method, the program crashes with a segmentation_fault

C++ Improvement: Change argument type to reference types when appropiate

Whenever is possible change the type of some arguments for reference to the object, as if the type is not a reference, argument will be given as copy, and in case of copying std::string or std::vector and so on, this will make C++ create space in heap for a new object, and then a copy will be created, in that case if will be only used for reading just pass a reference.

Write a MLIR pass for dumping MLIR Function to .dot file

Currently MLIR implements a ViewOpGraph that writes a Module as a .dot graph, since it is generic for all the the MLIR dialects the representation is based on connecting statements by their parameters and result values, so those statements which are not using values from other instructions are disconnected on the graph, and the output is a little bit weird.

For example, for the next module:

module @"LSimple;" {
  func.func @my_add(%arg0: i32, %arg1: i32) -> i32 {
    %0 = arith.addi %arg0, %arg1 : i32
    %1 = arith.muli %arg0, %0 : i32
    %2 = arith.divsi %1, %arg1 : i32
    %3 = MjolnIR.loadfield @"LSimple;" -> @test_field(0) : i16
    MjolnIR.storefield %3 : i16, @"LSimple;" -> @test_field(0)
    MjolnIR.nop
    %4 = arith.cmpi ne, %0, %2 : i32
    cf.cond_br %4, ^bb2(%2 : i32), ^bb1(%0 : i32)
  ^bb1(%5: i32):  // pred: ^bb0
    %6 = "MjolnIR.move"(%5) : (i32) -> i32
    cf.br ^bb3(%6 : i32)
  ^bb2(%7: i32):  // pred: ^bb0
    MjolnIR.nop
    MjolnIR.fallthrough ^bb3(%7 : i32)
  ^bb3(%8: i32):  // 2 preds: ^bb1, ^bb2
    MjolnIR.nop
    return %8 : i32
  }
}

The next .dot is dumped:

digraph G {
  compound = true;
  subgraph cluster_1 {
    v2 [label = " ", shape = plain];
    label = "builtin.module : ())\n\nsym_name: \"LSimple;\"";
    subgraph cluster_3 {
      v4 [label = " ", shape = plain];
      label = "";
      subgraph cluster_5 {
        v6 [label = " ", shape = plain];
        label = "func.func : ())\n\nfunction_type: (i32, i32) -> i32\nsym_name: \"my_add\"";
        subgraph cluster_7 {
          v8 [label = " ", shape = plain];
          label = "";
          v9 [label = "arg0", shape = ellipse];
          v10 [label = "arg1", shape = ellipse];
          v11 [label = "arith.addi : (i32))\n", shape = ellipse];
          v12 [label = "arith.muli : (i32))\n", shape = ellipse];
          v13 [label = "arith.divsi : (i32))\n", shape = ellipse];
          v14 [label = "MjolnIR.loadfield : (i16))\n\nfieldClass: @\"LSimple;\"\nfieldName: @test_field\nfieldRef: 0 : ui32", shape = ellipse];
          v15 [label = "MjolnIR.storefield : ())\n\nfieldClass: @\"LSimple;\"\nfieldName: @test_field\nfieldRef: 0 : ui32", shape = ellipse];
          v16 [label = "MjolnIR.nop : ())\n", shape = ellipse];
          v17 [label = "arith.cmpi : (i1))\n\npredicate: 1 : i64", shape = ellipse];
          v18 [label = "cf.cond_br : ())\n\noperand_segment_sizes: array<i32: 1, 1, 1>", shape = ellipse];
        }
        subgraph cluster_19 {
          v20 [label = " ", shape = plain];
          label = "";
          v21 [label = "arg0", shape = ellipse];
          v22 [label = "MjolnIR.move : (i32))\n", shape = ellipse];
          v23 [label = "cf.br : ())\n", shape = ellipse];
        }
        subgraph cluster_24 {
          v25 [label = " ", shape = plain];
          label = "";
          v26 [label = "arg0", shape = ellipse];
          v27 [label = "MjolnIR.nop : ())\n", shape = ellipse];
          v28 [label = "MjolnIR.fallthrough : ())\n", shape = ellipse];
        }
        subgraph cluster_29 {
          v30 [label = " ", shape = plain];
          label = "";
          v31 [label = "arg0", shape = ellipse];
          v32 [label = "MjolnIR.nop : ())\n", shape = ellipse];
          v33 [label = "func.return : ())\n", shape = ellipse];
        }
      }
    }
  }
  v9 -> v11 [label = "0", style = solid];
  v10 -> v11 [label = "1", style = solid];
  v9 -> v12 [label = "0", style = solid];
  v11 -> v12 [label = "1", style = solid];
  v12 -> v13 [label = "0", style = solid];
  v10 -> v13 [label = "1", style = solid];
  v14 -> v15 [label = "", style = solid];
  v11 -> v17 [label = "0", style = solid];
  v13 -> v17 [label = "1", style = solid];
  v17 -> v18 [label = "0", style = solid];
  v13 -> v18 [label = "1", style = solid];
  v11 -> v18 [label = "2", style = solid];
  v21 -> v22 [label = "", style = solid];
  v22 -> v23 [label = "", style = solid];
  v26 -> v28 [label = "", style = solid];
  v31 -> v33 [label = "", style = solid];
}

I think it's psosible to write a MLIR pass that given a MjolnIR module, it dumps a .dot file for each function with the shape of a Control Flow Graph (CFG).

DEX Disassembler error

Check in DEX class after obtaining a class_def object, if class_data_item contains something, probably if it's an interface, it does not exist the class_data_item object.

Segmentation fault creating basic blocks

There's a segmentation fault creating the basic blocks for the method android.support.v4.os.ResultReceiver->writeToParcel(android.os.Parcel,int), probably some strange structure makes the program to crash. The next code represents the smali from the method:

void android.support.v4.os.ResultReceiver->writeToParcel(android.os.Parcel,int)
00000000  1d 00                   monitor-enter v0
00000002  54 02 df 00             iget-object v2, v0, Landroid/support/v4/os/ResultReceiver;->mReceiver Landroid/support/v4/os/IResultReceiver; (223)
00000006  39 02 09 00             if-nez v2, 9
0000000a  22 02 6c 01             new-instance v2, android.support.v4.os.ResultReceiver$MyResultReceiver (364)
0000000e  70 20 e1 07 02 00       invoke-direct {v2, v0}, void android.support.v4.os.ResultReceiver$MyResultReceiver-><init>(android.support.v4.os.ResultReceiver)
00000014  5b 02 df 00             iput-object v2, v0, Landroid/support/v4/os/ResultReceiver;->mReceiver Landroid/support/v4/os/IResultReceiver; (223)
00000018  54 02 df 00             iget-object v2, v0, Landroid/support/v4/os/ResultReceiver;->mReceiver Landroid/support/v4/os/IResultReceiver; (223)
0000001c  72 10 da 07 02 00       invoke-interface {v2}, android.os.IBinder android.support.v4.os.IResultReceiver->asBinder()
00000022  0c 02                   move-result-object v2
00000024  6e 20 40 07 21 00       invoke-virtual {v1, v2}, void android.os.Parcel->writeStrongBinder(android.os.IBinder)
0000002a  1e 00                   monitor-exit v0
0000002c  0e 00                   return-void
0000002e  0d 01                   move-exception v1
00000030  1e 00                   monitor-exit v0
00000032  27 01                   throw v1

Probably generation of basic blocks crashes due to the catch block that surrounds the whole function.

Implement EncodedAnnotation and AnnotationElement classes

In some applications which are compiled with all the Annotation information, it is necessary to implement these classes in order to avoiding a crash in the application, parsing fails because the pointer of the file doesn't advance with the parsing and it contains some missing data so it's necessary to implement both classes and add them to parser.

Here it's necessary to include the code:

It's possible to follow Androguard's code:
https://github.com/androguard/androguard/blob/8d091cbb309c0c50bf239f805cc1e0931b8dcddc/androguard/core/bytecodes/dvm.py#L1612
https://github.com/androguard/androguard/blob/8d091cbb309c0c50bf239f805cc1e0931b8dcddc/androguard/core/bytecodes/dvm.py#L1764
https://github.com/androguard/androguard/blob/8d091cbb309c0c50bf239f805cc1e0931b8dcddc/androguard/core/bytecodes/dvm.py#L1716

Create a log class

Create a very basic log class with static methods in order to print errors with a level of Warning, Error or just information. This could be printed to a log file too.

Update spdlog to newer version

Currently Kunai uses an old version of spdlog, it would be very useful installing and testing a newer version, and once the code is stable update the spdlog version used in the CMake.

Linking error

I run into this error when compiling with ./make.sh build on Ubuntu 22.04.1 LTS. This is using g++ version 11.2.0. The error message is very long, but basically I get the same kind of error all the time, some undefined references when linking:

/usr/bin/ld: objs/test_ir.o: in function `spdlog::details::aggregate_formatter::format(spdlog::details::log_msg const&, tm const&, fmt::v8::basic_memory_buffer<char, 250ul, std::allocator<char> >&)':
test_ir.cpp:(.text._ZN6spdlog7details19aggregate_formatter6formatERKNS0_7log_msgERK2tmRN3fmt2v819basic_memory_bufferIcLm250ESaIcEEE[_ZN6spdlog7details19aggregate_formatter6formatERKNS0_7log_msgERK2tmRN3fmt2v819basic_memory_bufferIcLm250ESaIcEEE]+0xc3): undefined reference to `fmt::v8::detail::assert_fail(char const*, int, char const*)'

From various StackOverflow posts it might be due to includes being in the wrong order thus creating undefined references, but I'm not familiar enough with KUNAI's code to check if that is the case here.

Here is the full error message for reference: https://pastebin.com/mK5pCX9r

Happy to do more tests if needed!

Fix SSA Graph from Kunai

The SSA algorithm is not correctly applied in those blocks that belongs to exception catcher blocks, check what error exists. Also in those cases where the IRPhi only receives one parameter, remove that IRPhi since it is not necessary.
image
image

Include a CONTRIBUTING file

Write a CONTRIBUTING file for helping developers to understand how they can contribute to the project. In this file there must be the branches where we commonly write the new features of the library, or those where we fix the errors instead of directly working on main branch, also the file should contain a short coding style guide to keep as much as possible the same style in the project.

This should have been written long ago... (I'm a disaster... :D)

Missing <optional> header in mjolnIR

I ran into this issue while compiling with ./make.sh build on Ubuntu 22.04.1 LTS. This is using g++ version 11.2.0.

[+] Compiling KUNAI with 4 jobs
Compiling src/main.cpp -> objs/main.o
Compiling src/Utils/utils.cpp -> objs/utils.o
Compiling src/DEX/parser/dex_header.cpp -> objs/dex_header.o
Compiling src/DEX/parser/dex_strings.cpp -> objs/dex_strings.o
Compiling src/DEX/parser/dex_types.cpp -> objs/dex_types.o
Compiling src/DEX/parser/dex_protos.cpp -> objs/dex_protos.o
Compiling src/DEX/parser/dex_fields.cpp -> objs/dex_fields.o
Compiling src/DEX/parser/dex_methods.cpp -> objs/dex_methods.o
Compiling src/DEX/parser/dex_classes.cpp -> objs/dex_classes.o
Compiling src/DEX/parser/dex_encoded.cpp -> objs/dex_encoded.o
Compiling src/DEX/parser/dex_annotations.cpp -> objs/dex_annotations.o
Compiling src/DEX/parser/dex_parser.cpp -> objs/dex_parser.o
Compiling src/DEX/DVM/dex_dalvik_opcodes.cpp -> objs/dex_dalvik_opcodes.o
Compiling src/DEX/DVM/dex_instructions.cpp -> objs/dex_instructions.o
Compiling src/DEX/DVM/dex_linear_sweep_disassembly.cpp -> objs/dex_linear_sweep_disassembly.o
Compiling src/DEX/DVM/dex_recursive_traversal_disassembly.cpp -> objs/dex_recursive_traversal_disassembly.o
Compiling src/DEX/DVM/dex_disassembler.cpp -> objs/dex_disassembler.o
Compiling src/DEX/DVM/dex_external_methods.cpp -> objs/dex_external_methods.o
Compiling src/DEX/DVM/dex_external_classes.cpp -> objs/dex_external_classes.o
Compiling src/DEX/Analysis/dex_string_analysis.cpp -> objs/dex_string_analysis.o
Compiling src/DEX/Analysis/dex_dvm_basic_block.cpp -> objs/dex_dvm_basic_block.o
Compiling src/DEX/Analysis/dex_exception_analysis.cpp -> objs/dex_exception_analysis.o
Compiling src/DEX/Analysis/dex_method_analysis.cpp -> objs/dex_method_analysis.o
Compiling src/DEX/Analysis/dex_field_analysis.cpp -> objs/dex_field_analysis.o
Compiling src/DEX/Analysis/dex_class_analysis.cpp -> objs/dex_class_analysis.o
Compiling src/DEX/Analysis/dex_analysis.cpp -> objs/dex_analysis.o
Compiling src/DEX/dex.cpp -> objs/dex.o
Compiling src/APK/apk.cpp -> objs/apk.o
Compiling src/mjolnIR/ir_type.cpp -> objs/ir_type.o
In file included from src/mjolnIR/ir_type.cpp:1:
src/include/KUNAI/mjolnIR/ir_grammar.hpp:550:18: error: ‘optional’ in namespace ‘std’ does not name a template type
  550 |             std::optional<std::vector<irstmnt_t> *> get_def_use_chain_by_value(irexpr_t value)
      |                  ^~~~~~~~
src/include/KUNAI/mjolnIR/ir_grammar.hpp:27:1: note: ‘std::optional’ is defined in header ‘<optional>’; did you forget to ‘#include <optional>’?
   26 | #include "KUNAI/mjolnIR/arch/ir_dalvik.hpp"
  +++ |+#include <optional>
   27 | 
make: *** [Makefile:219: objs/ir_type.o] Error 1
make: *** Waiting for unfinished jobs....
[-] An error ocurred, check output...

Following the suggestion from the compiler seems to fix the issue, I will open a pull request too.

Apply code cleanup and fix issues

For next release, it would be nice to do some code cleanup in order to make the code more readable. With this fixes to the code could be done as well as more error handling. Probably in this issue, the next issue: #25, should be fixed too. Efficiency of the code could be checked, for example: check if it's possible to apply disassembly without re-reading the buffer all the times an instruction is disassembled. Look for possible access to variables that can take long time, etc.

Create test code for parts of the parser.

Create test code for all the parts of the parser, this code must contain the asserts to do the checks of the header values in order to know if parsing was correct.

Visualization of parameters in the disassembler.

In Smali the parameters are represented by the last numbers of the registers. So for example, a method with 5 registers {0-4} and 2 parameters will have the registers {v0, v1, v2} and the parameters {p0, p1}. Right now the disassembler would show {v0,v1,v2,v3,v4} but it's necessary to check the number of parameters and the number of registers, to use 'v' or 'p' and the correct number.

linker error ostream operator << to print DEX header

When trying to print a DEX header through std::cout and the overloaded operator << that is implemented in kunai-lib/lib/DEX/parser/header.cpp, it gives an error while compiling. Error message is the following:

undefined reference to `KUNAI::DEX::operator<<(std::ostream&, KUNAI::DEX::Header const&)'
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Work in MjolnIR Lifter

For some of the passes to work correctly, it's needed to have in some of the instructions the same type both for operands and for result values. MjolnIR Lifter right now has some problems creating new instructions like cast instructions, since they generate new values that are not taking into account for the already created basic blocks. It's needed to create some triggers or some way for re-generating instructions if a new instruction that change values is included. Lifter's code should be cleaned and improved.

For example, in case we need to add the different types of cast instructions, it would be useful the next:

  1. Have a function that check for the proper type for values being casted to.
  2. Generate cast instruction.
  3. Look for uses of the resulted value, re-generate those instructions in order to retrieve the last generated value.

Other utilities could be included at Lifter's code, example, for including instructions at the end of a block, for obtaining addresses of blocks, etc.

Modify type of disassembly applied

In order to improve the disassembly and make it resilient to possible obfuscation we should change the Linear Sweep Disassembly for a Speculative Disassembly. In this way we would apply first recursive disassembly through the control flows from the methods, and then we would apply linear sweep disassembly to fill the gaps and correct the previous output.

Paper to check: https://dl.acm.org/doi/10.1145/2968455.2968505

Add ARM support

Possibly recycle some code for instruction translation
Different ABI
Start with iOS

Check the generation of while loop with IR

There's a problem lifting loops with MjolnIR, probably due to the backward arrow. A very simple dalvik bytecode like the next one:

void Main->test()
BB-Start Block
BB-0
00000000  12 00                   const/4 v0, 0
BB-2
00000002  13 01 0a 00             const/16 v1, 10
00000006  35 10 0a 00             if-ge v0, v1, 10
BB-a
0000000a  62 01 00 00             sget-object v1, Ljava/lang/System;->out Ljava/io/PrintStream; (0)
0000000e  6e 20 03 00 01 00       invoke-virtual {v1, v0}, void java.io.PrintStream->println(int)
00000014  d8 00 00 01             add-int/lit8 v0, v0, 1
00000018  28 f5                   goto 2
BB-1a
0000001a  0e 00                   return-void

It's generated as something like the next one:

"builtin.module"() ({
  "func.func"() <{function_type = () -> (), sym_name = "test"}> ({
    %0 = "MjolnIR.load-value"() {value = 0 : si64} : () -> i8
    "cf.br"(%0)[^bb1] : (i8) -> ()
  ^bb1(%1: i8):  // 3 preds: ^bb0, ^bb1, ^bb2
    %2 = "arith.constant"() <{value = 10 : i32}> : () -> i32
    %3 = "MjolnIR.loadfield"() {fieldClass = @"Ljava/lang/System;", fieldName = @out, fieldRef = 0 : ui32} : () -> !MjolnIR.object<"Ljava/io/PrintStream;">
    "MjolnIR.invoke"(%3, %1) {callee = @println, isStatic = 0 : ui32, methodRef = 3 : ui32} : (!MjolnIR.object<"Ljava/io/PrintStream;">, i8) -> ()
    %4 = "arith.constant"() <{value = 1 : i8}> : () -> i8
    %5 = "arith.addi"(%1, %4) : (i8, i8) -> i32
    "cf.br"()[^bb1] : () -> ()
    %6 = "arith.cmpi"(%1, %3) <{predicate = 5 : i64}> : (i8, !MjolnIR.object<"Ljava/io/PrintStream;">) -> i1
    "cf.cond_br"(%6)[^bb3, ^bb2] {operand_segment_sizes = array<i32: 1, 0, 0>} : (i1) -> ()
  ^bb2:  // pred: ^bb1
    %7 = "MjolnIR.loadfield"() {fieldClass = @"Ljava/lang/System;", fieldName = @out, fieldRef = 0 : ui32} : () -> !MjolnIR.object<"Ljava/io/PrintStream;">
    "MjolnIR.invoke"(%7, %5) {callee = @println, isStatic = 0 : ui32, methodRef = 3 : ui32} : (!MjolnIR.object<"Ljava/io/PrintStream;">, i32) -> ()
    %8 = "arith.constant"() <{value = 1 : i8}> : () -> i8
    %9 = "arith.addi"(%5, %8) : (i32, i8) -> i32
    "cf.br"(%5)[^bb1] : (i32) -> ()
  ^bb3:  // pred: ^bb1
    "func.return"() : () -> ()
  }) : () -> ()
}) {sym_name = "LMain;"} : () -> ()

Check why some block is being generated twice, and fix it in the Lifter!

Modify the use of normal pointers for smart pointers

Take time for changing the use of common pointers to use smart pointers and avoid possible data leakages, dangling pointers, use after free, and all those kind of things.
Think carefully where to use std::unique_ptr and where to use std::shared_ptr, former should be used for those variables that will not be returned by a method, used internally in a class and so on, latter should be used in all those types that are returned and used by other classes.

Create common OP_TYPE for IR

IRStmnt should contain a global OP_TYPE that each one of the classes the derives from it must follow, this will allow to have just one get_op_type that we can globally check to know the type of instruction we are working on, this will avoid using RTTI on the utilities. We will have to check the to_string, and the equal functions already created, so from IRStmnt it will be possible to do all the necessary checks. Or it's possible to implement that OP_TYPE in IRStmnt for those checks and user checks, no need to care about the internal hierarchy from the IR.

Rewrite DEX classes avoiding over use of std::shared_ptr

In order to improve performance avoid overuse of std::shared_ptr, keeping it only in very connected components (for example IRGraph and Graphs of basic blocks). In other cases, it is better to keep ownership in just one object (use of std::unique_ptr), there's no need to share ownership of many objects. A raw pointer can be returned in some cases when read access is needed.

Another interesting utility, whenever we use a vector of objects, we can do the next:

  using object_t = std::vector<Object*>;

And from these we could try to return iterators in order to go over them in case a user wants to go over all the data structure.

All these improvements will also be helpful for creating the bindings for other languages, since it does not use many shared_ptr, and there's no need to keep counter for number of references, etc.

A new branch will be created for doing all these changes, so we will avoid having issues.

Add Python binding

Since Python is a language easy to work with, it would be nice to include a binding that allow user to work with Python. Since Kunai uses C++17 it will be necessary to know if some features like std::optional or std::variant are supported. Each class maybe would be changed in order to include the binding, this probably would need its own branch to work with.

C++ improvement: use of std::optional whenever a reference is returned

In C++ 17 we have std::optional type for returning a std::nullopt whenever an asked object does not exists, there's a problem with methods that return a reference to an object because these cannot return a nullptr, for that reason it would be good to use the std::optional wrapper and the user can check if the object they asked for exists or not.

Create optimizations to improve IR code, or apply common deobfuscation

Create different templates for optimizations, optimizations can be applied at instruction level, block level and also at Graph level.

As optimizations can delete instructions, or can group instructions, or can delete blocks, find a safe way to delete this information and keep traversing them in order to apply more optimizations. Implement helper functions for deleting statements from blocks, and delete blocks from graphs.

Rewrite new parser for MethodID

Write a new parser for the DEX Methods and the MethodID, this has to follow the convention from the other parsers (strings, types, protos, fields...), once the class is created, it must be included to Parser class, and also a function like parse_methods must be included in the Method class and must be called from the Parser function parse_file. Use the branch https://github.com/Fare9/KUNAI-static-analyzer/tree/refactoring for it, and once it is everything included, the code must compile properly, and also the unit-test from the parser must run without crashing.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.