10#ifndef KUNAI_DEX_ANALYSIS_ANALYSIS_HPP
11#define KUNAI_DEX_ANALYSIS_ANALYSIS_HPP
13#include "Kunai/DEX/parser/parser.hpp"
14#include "Kunai/DEX/DVM/disassembler.hpp"
15#include "Kunai/DEX/analysis/external_class.hpp"
16#include "Kunai/DEX/DVM/dalvik_instructions.hpp"
17#include "Kunai/Exceptions/analysis_exception.hpp"
37 std::vector<Instruction *> instructions;
40 bool try_block =
false;
42 bool catch_block =
false;
44 bool start_block =
false;
46 bool end_block =
false;
60 return instructions.size();
67 instructions.push_back(instr);
88 if (instructions.size() > 0 && instructions.back()->is_terminator())
89 return instructions.back();
97 if (instructions.size() > 0)
98 return instructions[0]->get_address();
106 if (instructions.size() > 0)
107 return instructions.back()->get_address();
111 std::string& get_name()
119 name =
"BB.(start block)";
121 name =
"BB.(end block)";
143 this->try_block = try_block;
157 this->catch_block = catch_block;
171 handler_type = handler;
185 this->start_block = start_block;
199 this->end_block = end_block;
209 std::set<DVMBasicBlock *>>;
211 using edges_t = std::vector<std::pair<DVMBasicBlock *, DVMBasicBlock *>>;
223 std::vector<DVMBasicBlock *> nodes;
274 predecessors[node].insert(pred);
296 sucessors[node].insert(suc);
304 if (std::find(nodes.begin(), nodes.end(), node) == nodes.end())
305 nodes.push_back(node);
316 auto edge_pair = std::make_pair(src, dst);
317 if (std::find(edges.begin(), edges.end(), edge_pair) == edges.end())
318 edges.push_back(edge_pair);
343 if (predecessors[node].size() > 1)
345 else if (sucessors[node].size() > 1)
385 std::vector<std::tuple<ClassAnalysis *, MethodAnalysis *, std::uint64_t>> xrefread;
387 std::vector<std::tuple<ClassAnalysis *, MethodAnalysis *, std::uint64_t>> xrefwrite;
400 std::string &get_name()
405 const std::vector<std::tuple<ClassAnalysis *, MethodAnalysis *, std::uint64_t>> &
411 std::vector<std::tuple<ClassAnalysis *, MethodAnalysis *, std::uint64_t>> &
417 const std::vector<std::tuple<ClassAnalysis *, MethodAnalysis *, std::uint64_t>> &
418 get_xrefwrite()
const
423 std::vector<std::tuple<ClassAnalysis *, MethodAnalysis *, std::uint64_t>> &
435 xrefread.push_back(std::make_tuple(c, m, offset));
444 xrefwrite.push_back(std::make_tuple(c, m, offset));
454 std::vector<std::tuple<ClassAnalysis *, MethodAnalysis *, std::uint64_t>> xreffrom;
461 const std::string &get_value()
const
466 const std::vector<std::tuple<ClassAnalysis *, MethodAnalysis *, std::uint64_t>> &
472 std::vector<std::tuple<ClassAnalysis *, MethodAnalysis *, std::uint64_t>> &
484 xreffrom.push_back(std::make_tuple(c, m, offset));
495 "Landroid/",
"Lcom/android/internal/util",
"Ldalvik/",
"Ljava/",
"Ljavax/",
"Lorg/apache/",
496 "Lorg/json/",
"Lorg/w3c/dom/",
"Lorg/xml/sax",
"Lorg/xmlpull/v1/",
"Ljunit/",
"Landroidx/"};
500 bool is_external =
false;
510 mutable std::string name;
513 mutable std::string descriptor;
517 mutable std::string access_flag;
520 mutable std::string class_name;
523 mutable std::string full_name;
526 std::uint16_t regs_from_method;
529 std::uint16_t num_of_params;
532 std::vector<std::unique_ptr<Instruction>> instructions;
538 std::vector<Disassembler::exceptions_data> exceptions;
541 std::vector<std::tuple<ClassAnalysis *, FieldAnalysis *, std::uint64_t>> xrefread;
543 std::vector<std::tuple<ClassAnalysis *, FieldAnalysis *, std::uint64_t>> xrefwrite;
546 std::vector<std::tuple<ClassAnalysis *, MethodAnalysis *, std::uint64_t>> xrefto;
548 std::vector<std::tuple<ClassAnalysis *, MethodAnalysis *, std::uint64_t>> xreffrom;
551 std::vector<std::pair<ClassAnalysis *, std::uint64_t>> xrefnewinstance;
553 std::vector<std::pair<ClassAnalysis *, std::uint64_t>> xrefconstclass;
558 void dump_instruction_dot(std::ofstream& dot_file,
Instruction* instr);
563 void dump_block_dot(std::ofstream& dot_file,
DVMBasicBlock* bb);
568 void dump_method_dot(std::ofstream& dot_file);
573 void create_basic_blocks();
577 std::variant<EncodedMethod *, ExternalMethod *> method_encoded,
578 std::vector<std::unique_ptr<Instruction>> &instructions) : method_encoded(method_encoded), instructions(std::move(instructions))
580 is_external = method_encoded.index() == 0 ? false :
true;
584 auto em = std::get<EncodedMethod*>(method_encoded);
586 regs_from_method = em->get_code_item().get_registers_size();
588 num_of_params = em->getMethodID()->get_proto()->get_parameters().size();
591 if (this->instructions.size() > 0)
592 create_basic_blocks();
601 std::ofstream dot_file;
603 dot_file.open(file_path);
605 dump_method_dot(dot_file);
620 BasicBlocks& get_basic_blocks()
625 std::uint32_t get_number_of_registers()
const
627 return regs_from_method;
630 std::uint32_t get_number_of_parameters()
const
632 return num_of_params;
639 const std::string &get_name()
const;
641 const std::string &get_descriptor()
const;
643 const std::string &get_access_flags()
const;
645 const std::string &get_class_name()
const;
647 const std::string &get_full_name()
const;
649 std::vector<std::unique_ptr<Instruction>>& get_instructions()
654 std::variant<EncodedMethod *, ExternalMethod *> get_encoded_method()
const
656 return method_encoded;
659 const std::vector<std::tuple<ClassAnalysis *, FieldAnalysis *, std::uint64_t>> &
665 std::vector<std::tuple<ClassAnalysis *, FieldAnalysis *, std::uint64_t>> &
671 const std::vector<std::tuple<ClassAnalysis *, FieldAnalysis *, std::uint64_t>> &
672 get_xrefwrite()
const
677 std::vector<std::tuple<ClassAnalysis *, FieldAnalysis *, std::uint64_t>> &
683 const std::vector<std::tuple<ClassAnalysis *, MethodAnalysis *, std::uint64_t>> &
689 std::vector<std::tuple<ClassAnalysis *, MethodAnalysis *, std::uint64_t>> &
695 const std::vector<std::tuple<ClassAnalysis *, MethodAnalysis *, std::uint64_t>> &
701 std::vector<std::tuple<ClassAnalysis *, MethodAnalysis *, std::uint64_t>> &
707 const std::vector<std::pair<ClassAnalysis *, std::uint64_t>> &
708 get_xrefnewinstance()
const
710 return xrefnewinstance;
713 std::vector<std::pair<ClassAnalysis *, std::uint64_t>> &
714 get_xrefnewinstance()
716 return xrefnewinstance;
719 const std::vector<std::pair<ClassAnalysis *, std::uint64_t>> &
720 get_xrefconstclass()
const
722 return xrefconstclass;
725 std::vector<std::pair<ClassAnalysis *, std::uint64_t>> &
728 return xrefconstclass;
731 void add_xrefread(ClassAnalysis *c, FieldAnalysis *f, std::uint64_t offset)
733 xrefread.push_back(std::make_tuple(c, f, offset));
736 void add_xrefwrite(ClassAnalysis *c, FieldAnalysis *f, std::uint64_t offset)
738 xrefwrite.push_back(std::make_tuple(c, f, offset));
741 void add_xrefto(ClassAnalysis *c, MethodAnalysis *m, std::uint64_t offset)
743 xrefto.push_back(std::make_tuple(c, m, offset));
746 void add_xreffrom(ClassAnalysis *c, MethodAnalysis *m, std::uint64_t offset)
748 xreffrom.push_back(std::make_tuple(c, m, offset));
751 void add_xrefnewinstance(ClassAnalysis *c, std::uint64_t offset)
753 xrefnewinstance.push_back(std::make_pair(c, offset));
756 void add_xrefconstclass(ClassAnalysis *c, std::uint64_t offset)
758 xrefconstclass.push_back(std::make_pair(c, offset));
768 std::set<std::tuple<TYPES::REF_TYPE, MethodAnalysis *, std::uint64_t>>>;
773 std::variant<ClassDef *, ExternalClass *> class_def;
779 mutable std::string extends_;
782 mutable std::string name_;
785 std::unordered_map<std::string, MethodAnalysis *> methods;
787 std::unordered_map<EncodedField *, std::unique_ptr<FieldAnalysis>> fields;
795 std::vector<std::pair<MethodAnalysis *, std::uint64_t>> xrefnewinstance;
798 std::vector<std::pair<MethodAnalysis *, std::uint64_t>> xrefconstclass;
801 ClassAnalysis(std::variant<ClassDef *, ExternalClass *> class_def) : class_def(class_def)
803 is_external = class_def.index() == 0 ? false :
true;
810 size_t get_nb_methods()
const
812 return methods.size();
815 size_t get_nb_fields()
const
817 return fields.size();
834 std::string& extends()
const;
836 std::string& name()
const;
845 const std::unordered_map<std::string, MethodAnalysis *> &
853 std::unordered_map<std::string, MethodAnalysis *> &
859 const std::unordered_map<EncodedField *, std::unique_ptr<FieldAnalysis>> &
865 std::unordered_map<EncodedField *, std::unique_ptr<FieldAnalysis>> &
886 if (fields.find(field) == fields.end())
887 fields[field] = std::make_unique<FieldAnalysis>(field);
888 fields[field]->add_xrefread(classobj, method, off);
896 if (fields.find(field) == fields.end())
897 fields[field] = std::make_unique<FieldAnalysis>(field);
898 fields[field]->add_xrefwrite(classobj, method, off);
901 void add_method_xref_to(MethodAnalysis *method1,
902 ClassAnalysis *classobj,
903 MethodAnalysis *method2,
906 auto method_key = method1->get_full_name();
908 if (methods.find(method_key) == methods.end())
910 methods[method_key]->add_xrefto(classobj, method2, off);
913 void add_method_xref_from(MethodAnalysis *method1,
914 ClassAnalysis *classobj,
915 MethodAnalysis *method2,
918 auto method_key = method1->get_full_name();
920 if (methods.find(method_key) == methods.end())
922 methods[method_key]->add_xreffrom(classobj, method2, off);
925 void add_xref_to(TYPES::REF_TYPE ref_kind,
926 ClassAnalysis *classobj,
927 MethodAnalysis *methodobj,
928 std::uint64_t offset)
930 xrefto[classobj].insert(std::make_tuple(ref_kind, methodobj, offset));
933 void add_xref_from(TYPES::REF_TYPE ref_kind,
934 ClassAnalysis *classobj,
935 MethodAnalysis *methodobj,
936 std::uint64_t offset)
938 xreffrom[classobj].insert(std::make_tuple(ref_kind, methodobj, offset));
941 void add_xref_new_instance(MethodAnalysis *methodobj, std::uint64_t offset)
943 xrefnewinstance.push_back(std::make_pair(methodobj, offset));
946 void add_xref_const_class(MethodAnalysis *methodobj, std::uint64_t offset)
948 xrefconstclass.push_back(std::make_pair(methodobj, offset));
975 const std::vector<std::pair<MethodAnalysis *, std::uint64_t>>
976 get_xrefnewinstance()
const
978 return xrefnewinstance;
981 std::vector<std::pair<MethodAnalysis *, std::uint64_t>>
982 get_xrefnewinstance()
984 return xrefnewinstance;
987 const std::vector<std::pair<MethodAnalysis *, std::uint64_t>>
988 get_xrefconstclass()
const
990 return xrefconstclass;
993 std::vector<std::pair<MethodAnalysis *, std::uint64_t>>
996 return xrefconstclass;
Class to keep all the Dalvik Basic Blocks from a method.
Definition analysis.hpp:205
node_type_t get_node_type(DVMBasicBlock *node)
Get the node type between JOIN_NODE, BRANCH_NODE or REGULAR_NODE.
Definition analysis.hpp:341
void remove_node(DVMBasicBlock *node)
Remove a node from the graph, this operation can be expensive on time.
std::unordered_map< DVMBasicBlock *, std::set< DVMBasicBlock * > > connected_blocks_t
blocks that are connected with others
Definition analysis.hpp:209
std::vector< DVMBasicBlock * > & get_nodes()
Get a reference to the nodes of the graph.
Definition analysis.hpp:371
~BasicBlocks()
Destructor of the BasicBlocks, we need to free the memory.
Definition analysis.hpp:239
void add_sucessor(DVMBasicBlock *node, DVMBasicBlock *suc)
Add a node to the list of sucessors of another.
Definition analysis.hpp:294
void add_node(DVMBasicBlock *node)
Add a node to the vector of nodes, we will transfer the ownership.
Definition analysis.hpp:302
std::vector< std::pair< DVMBasicBlock *, DVMBasicBlock * > > edges_t
edges between nodes
Definition analysis.hpp:211
void add_predecessor(DVMBasicBlock *node, DVMBasicBlock *pred)
Add a node to the list of predecessors of another.
Definition analysis.hpp:272
connected_blocks_t & get_predecessors()
Get all predecessors from all the blocks.
Definition analysis.hpp:264
size_t get_number_of_basic_blocks() const
Return the number of basic blocks in the graph.
Definition analysis.hpp:250
node_type_t
Type of a node.
Definition analysis.hpp:215
const connected_blocks_t & get_predecessors() const
Get all predecessors from all the blocks.
Definition analysis.hpp:257
DVMBasicBlock * get_basic_block_by_idx(std::uint64_t idx)
Get a basic block given an idx, the idx can be one address from the first to the last address of the ...
const edges_t & get_edges() const
Get a constant reference to the edges of the graph.
Definition analysis.hpp:326
void add_edge(DVMBasicBlock *src, DVMBasicBlock *dst)
Add an edge to the basic blocks.
Definition analysis.hpp:311
const connected_blocks_t & get_sucessors() const
Get all sucessors from all the blocks.
Definition analysis.hpp:279
connected_blocks_t & get_sucessors()
Get all sucessors from all the blocks.
Definition analysis.hpp:286
const std::vector< DVMBasicBlock * > & get_nodes() const
Get a constant reference to the nodes of the graph.
Definition analysis.hpp:364
edges_t & get_edges()
Get a reference to the edges of the graph.
Definition analysis.hpp:333
Specification of the class analysis, this class contains fields, strings, methods....
Definition analysis.hpp:765
std::variant< ClassDef *, ExternalClass * > get_class_definition() const
Get the class definition object.
Definition analysis.hpp:822
std::unordered_map< std::string, MethodAnalysis * > & get_methods()
get a reference to the methods
Definition analysis.hpp:854
FieldAnalysis * get_field_analysis(EncodedField *field)
Given an encoded field return a FieldAnalysis pointer.
std::vector< DVMClass * > & implements()
Return a vector of implemented interfaces, in the case of external class raise exception.
bool is_class_external() const
Is the current class an external class?
Definition analysis.hpp:829
const std::unordered_map< std::string, MethodAnalysis * > & get_methods() const
get a constant reference to the methods
Definition analysis.hpp:846
void add_method(MethodAnalysis *method_analysis)
add a method to the current class
MethodAnalysis * get_method_analysis(std::variant< EncodedMethod *, ExternalMethod * > method)
Given an Encoded or ExternalMethod returns a MethodAnalysis pointer.
Class that contain the instructions of basic block different DVMBasicBlock exists.
Definition analysis.hpp:35
void set_try_block(bool try_block)
Set the block is a try block.
Definition analysis.hpp:141
std::uint64_t get_first_address()
Get the first address of the basic block in case there are instructions.
Definition analysis.hpp:95
void set_end_block(bool end_block)
Set the block as an end block.
Definition analysis.hpp:197
bool is_start_block() const
Get if current block is a starting block.
Definition analysis.hpp:176
bool is_end_block() const
Get if current block is an end block.
Definition analysis.hpp:190
DVMType * get_handler_type()
Get the type of handler in case is a catch block.
Definition analysis.hpp:162
size_t get_nb_instructions() const
Obtain the number of instructions from the instructions vector.
Definition analysis.hpp:58
std::uint64_t get_last_address()
Get the last address of the basic block in case there are instructions.
Definition analysis.hpp:104
Instruction * get_terminator()
Return the last instruction in case this is a terminator instruction.
Definition analysis.hpp:86
std::vector< Instruction * > & get_instructions()
Get a reference to the vector of instructions.
Definition analysis.hpp:79
void set_catch_block(bool catch_block)
Set the block is a catch block.
Definition analysis.hpp:155
const std::vector< Instruction * > & get_instructions() const
Get a constant reference to the vector of instructions.
Definition analysis.hpp:72
void add_instruction(Instruction *instr)
Add an instruction to the basic block.
Definition analysis.hpp:65
bool is_try_block() const
Is the current block a try-block?
Definition analysis.hpp:134
void set_handler_type(DVMType *handler)
Set a handler type.
Definition analysis.hpp:169
void set_start_block(bool start_block)
Set the block as a start block.
Definition analysis.hpp:183
bool is_catch_block() const
Is the current block a catch-block?
Definition analysis.hpp:148
Represents the base class of a Type in the DVM we have different types.
Definition types.hpp:26
Class that represent field information it contains a FieldID and also the access flags.
Definition encoded.hpp:266
const FieldID * get_field() const
Get a constant pointer to the FieldID.
Definition encoded.hpp:288
Class that represent the information from a Method.
Definition encoded.hpp:635
Definition external_method.hpp:23
specification of a field analysis
Definition analysis.hpp:379
void add_xrefwrite(ClassAnalysis *c, MethodAnalysis *m, std::uint64_t offset)
Add a cross reference where the field is written in code.
Definition analysis.hpp:442
void add_xrefread(ClassAnalysis *c, MethodAnalysis *m, std::uint64_t offset)
Add a cross reference where the field is read in code.
Definition analysis.hpp:433
const std::string & get_name() const
Get a constant reference to the name of the field.
Definition fields.hpp:93
Base class for the Instructions of the Dalvik Bytecode.
Definition dalvik_instructions.hpp:69
Specification of the method analysis, a method contains instructions, exceptions data,...
Definition analysis.hpp:491
void dump_dot_file(std::string &file_path)
Dump the method as a dot file into the current path.
Definition analysis.hpp:599
bool external() const
Check if the method is external.
Definition analysis.hpp:610
bool is_android_api() const
Check if current method is an android api.
const std::vector< std::string > known_apis
vector of known apis of Android
Definition analysis.hpp:494
specification of a string analysis
Definition analysis.hpp:450
void add_xreffrom(ClassAnalysis *c, MethodAnalysis *m, std::uint64_t offset)
Add a cross reference where the string is read.
Definition analysis.hpp:482
Exception raised in the analysis of dalvik.
Definition analysis_exception.hpp:16
utilities
Definition analysis.hpp:23