From ee0e91a8f52117e1dedd26e1c8ee786f50946643 Mon Sep 17 00:00:00 2001 From: Learner0x5a <21185907+Learner0x5a@users.noreply.github.com> Date: Tue, 17 May 2022 23:07:45 +0800 Subject: [PATCH] init commit --- IDAGenDFG.py | 49 ++++++ LICENSE | 339 +++++++++++++++++++++++++++++++++++++ README.md | 42 +++++ libdataflow.py | 276 ++++++++++++++++++++++++++++++ testcase/test | Bin 0 -> 87024 bytes testcase/test-idapython.py | 17 ++ testcase/test-miasm.py | 26 +++ testcase/test.cpp | 33 ++++ testcase/test.dump | 289 +++++++++++++++++++++++++++++++ utils.py | 220 ++++++++++++++++++++++++ 10 files changed, 1291 insertions(+) create mode 100644 IDAGenDFG.py create mode 100644 LICENSE create mode 100644 README.md create mode 100644 libdataflow.py create mode 100755 testcase/test create mode 100644 testcase/test-idapython.py create mode 100644 testcase/test-miasm.py create mode 100644 testcase/test.cpp create mode 100644 testcase/test.dump create mode 100644 utils.py diff --git a/IDAGenDFG.py b/IDAGenDFG.py new file mode 100644 index 0000000..2ead6d2 --- /dev/null +++ b/IDAGenDFG.py @@ -0,0 +1,49 @@ +import idaapi +import idautils +import idc +import ida_pro +import ida_auto +import os, sys +from libdataflow import ida_dataflow_analysis +from argparse import ArgumentParser + +def main(OUTPUT_DIR:str) -> None: + os.makedirs(OUTPUT_DIR, exist_ok=True) + + textStartEA = 0 + textEndEA = 0 + for seg in idautils.Segments(): + if (idc.get_segm_name(seg)==".text"): + textStartEA = idc.get_segm_start(seg) + textEndEA = idc.get_segm_end(seg) + break + + for func in idautils.Functions(textStartEA, textEndEA): + # Ignore Library Code + flags = idc.get_func_attr(func, idc.FUNCATTR_FLAGS) + if flags & idc.FUNC_LIB: + print(hex(func), "FUNC_LIB", idc.get_func_name(func)) + continue + try: + ida_dataflow_analysis(func, idc.get_func_name(func), OUTPUT_DIR, defuse_only=True) + except Exception as e: + print('Skip function {} due to dataflow analysis error: {}'.format(idc.get_func_name(func),e)) + +if __name__ == '__main__': + if len(idc.ARGV) < 2: + print('\n\nGenerating DFG & Def-Use Graph with IDA Pro and MIASM') + print('\tNeed to specify the output dir with -o option') + print('\tUsage: /path/to/ida -A -Lida.log -S"{} -o " /path/to/binary\n\n'.format(idc.ARGV[0])) + ida_pro.qexit(1) + + parser = ArgumentParser(description="IDAPython script for generating dataflow graph of each function in the given binary") + parser.add_argument("-o", "--output_dir", help="Output dir", default='./outputs', nargs='?') + # parser.add_argument("-s", "--symb", help="Symbolic execution mode", + # action="store_true") + args = parser.parse_args() + + ida_auto.auto_wait() + + main(args.output_dir) + + ida_pro.qexit(0) \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..3d64fce --- /dev/null +++ b/LICENSE @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + ida-dfg + Copyright (C) 2022 wenyu zhu + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/README.md b/README.md new file mode 100644 index 0000000..8387752 --- /dev/null +++ b/README.md @@ -0,0 +1,42 @@ +# ida-dfg + +IDA Pro data-flow graph generator + +Tested with IDA Pro 7.6 and miasm 7ee593d + +## libdataflow.py + +封装了两个核心接口给其他脚本用 + - `ida_dataflow_analysis`: 面向IDA + MIASM的场景 + - `miasm_dataflow_analysis`: 单独使用,不需要IDA Pro + +## IDAGenDFG.py + +IDAPython调用的脚本 + +`/path/to/ida -A -Lida.log -S"path/to/IDAGenDFG.py -o " /path/to/binary` + +## deprecated/graph_dataflow.py + +新版miasm支持的DFG/ReachinDefinition/DefUse分析 + +## deprecated/libdfg.py + +代码升级 & debug工作停止,因为新版miasm自身支持dfg生成。 + +但是这部分代码的价值在于学习如何将miasm用到IDAPython里,详见`dataflow_analysis`函数。 + + + +## miasm的一些核心概念: + - machine类: 定义架构、反汇编引擎、lifter + - LocationDB类:各类数据结构的loc_key(unique id),例如AsmBlock, IRBlock的loc_key;以及定义了offset和loc_key相互转换的函数 + - Instruction类:可以在miasm.core.cpu内查看其成员函数、变量 + - AsmCFG类、AsmBlock类:汇编控制流图、基本块 + - IRBlock类、AssignBlock类:AsmBlock经Lifter翻译得到IRBlock,每一个IRBlock有若干个AssignBlock + * 每个AssignBlock对应一条IR赋值语句(src -> dst),同时也可以对应回一条汇编指令(assignblk.instr) + +## miasm的局限性 + + - 反汇编较慢 + - 无法处理80bit浮点数 diff --git a/libdataflow.py b/libdataflow.py new file mode 100644 index 0000000..46c14b9 --- /dev/null +++ b/libdataflow.py @@ -0,0 +1,276 @@ +import os +from future.utils import viewitems, viewvalues +from utils import guess_machine + +from miasm.analysis.binary import Container +from miasm.analysis.machine import Machine +from miasm.expression.expression import get_expr_mem +from miasm.analysis.data_analysis import inter_block_flow #, intra_block_flow_raw +from miasm.core.graph import DiGraph +from miasm.ir.symbexec import SymbolicExecutionEngine +from miasm.analysis.data_flow import DeadRemoval, ReachingDefinitions, DiGraphDefUse +from miasm.core.locationdb import LocationDB +from miasm.core.bin_stream_ida import bin_stream_ida + +def intra_block_flow_symb(lifter, _, flow_graph, irblock, in_nodes, out_nodes): + symbols_init = lifter.arch.regs.regs_init.copy() + sb = SymbolicExecutionEngine(lifter, symbols_init) + sb.eval_updt_irblock(irblock) + print('*' * 40) + print(irblock) + + + out = sb.modified(mems=False) + current_nodes = {} + # Gen mem arg to mem node links + for dst, src in out: + src = sb.eval_expr(dst) + for n in [dst, src]: + + all_mems = set() + all_mems.update(get_expr_mem(n)) + + for n in all_mems: + node_n_w = (irblock.loc_key, 0, n) + if not n == src: + continue + o_r = n.ptr.get_r(mem_read=False, cst_read=True) + for i, n_r in enumerate(o_r): + if n_r in current_nodes: + node_n_r = current_nodes[n_r] + else: + node_n_r = (irblock.loc_key, i, n_r) + if not n_r in in_nodes: + in_nodes[n_r] = node_n_r + flow_graph.add_uniq_edge(node_n_r, node_n_w) + + # Gen data flow links + for dst in out: + src = sb.eval_expr(dst) + nodes_r = src.get_r(mem_read=False, cst_read=True) + nodes_w = set([dst]) + for n_r in nodes_r: + if n_r in current_nodes: + node_n_r = current_nodes[n_r] + else: + node_n_r = (irblock.loc_key, 0, n_r) + if not n_r in in_nodes: + in_nodes[n_r] = node_n_r + + flow_graph.add_node(node_n_r) + for n_w in nodes_w: + node_n_w = (irblock.loc_key, 1, n_w) + out_nodes[n_w] = node_n_w + + flow_graph.add_node(node_n_w) + flow_graph.add_uniq_edge(node_n_r, node_n_w) + + + +def intra_block_flow_raw(lifter, ircfg, flow_graph, irb, in_nodes, out_nodes): + """ + Create data flow for an irbloc using raw IR expressions + """ + current_nodes = {} + for i, assignblk in enumerate(irb): + dict_rw = assignblk.get_rw(cst_read=True) + current_nodes.update(out_nodes) + + # gen mem arg to mem node links + all_mems = set() + for node_w, nodes_r in viewitems(dict_rw): + for n in nodes_r.union([node_w]): + all_mems.update(get_expr_mem(n)) + if not all_mems: + continue + + for n in all_mems: + node_n_w = (hex(assignblk.instr.offset), i, n) + if not n in nodes_r: + continue + o_r = n.ptr.get_r(mem_read=False, cst_read=True) + for n_r in o_r: + if n_r in current_nodes: + node_n_r = current_nodes[n_r] + else: + node_n_r = (hex(assignblk.instr.offset), i, n_r) + current_nodes[n_r] = node_n_r + in_nodes[n_r] = node_n_r + flow_graph.add_uniq_edge(node_n_r, node_n_w) + + # gen data flow links + for node_w, nodes_r in viewitems(dict_rw): + for n_r in nodes_r: + if n_r in current_nodes: + node_n_r = current_nodes[n_r] + else: + node_n_r = (hex(assignblk.instr.offset), i, n_r) + current_nodes[n_r] = node_n_r + in_nodes[n_r] = node_n_r + + flow_graph.add_node(node_n_r) + + node_n_w = (hex(assignblk.instr.offset), i + 1, node_w) + out_nodes[node_w] = node_n_w + + flow_graph.add_node(node_n_w) + flow_graph.add_uniq_edge(node_n_r, node_n_w) + + + +def node2str(node): + out = "%s,%s\\l\\\n%s" % node + return out + + +def gen_function_data_flow_graph(lifter, ircfg, ad, block_flow_cb) -> DiGraph: + ''' + generate data flow graph for a given function + ''' + irblock_0 = None + for irblock in viewvalues(ircfg.blocks): + loc_key = irblock.loc_key + offset = ircfg.loc_db.get_location_offset(loc_key) + # print('{} -> {}'.format(hex(offset), irblock.loc_key)) + if offset == ad: + irblock_0 = irblock + break + assert irblock_0 is not None + flow_graph = DiGraph() + flow_graph.node2str = node2str + + + irb_in_nodes = {} + irb_out_nodes = {} + for label in ircfg.blocks: + irb_in_nodes[label] = {} + irb_out_nodes[label] = {} + + for label, irblock in viewitems(ircfg.blocks): + block_flow_cb(lifter, ircfg, flow_graph, irblock, irb_in_nodes[label], irb_out_nodes[label]) + + # for label in ircfg.blocks: + # print(label) + # print('IN', [str(x) for x in irb_in_nodes[label]]) + # print('OUT', [str(x) for x in irb_out_nodes[label]]) + + # print('*' * 20, 'interblock', '*' * 20) + inter_block_flow(lifter, ircfg, flow_graph, irblock_0.loc_key, irb_in_nodes, irb_out_nodes) + + return flow_graph + + +def ida_dataflow_analysis(function_addr:int, function_name:str, output_dir:str, defuse_only: bool = False) -> None: + + loc_db = LocationDB() + + ###################### IDA specific ####################### + machine = guess_machine() + bin_stream = bin_stream_ida() + + # Populate symbols with ida names + import idautils + for ad, name in idautils.Names(): + if name is None: + continue + loc_db.add_location(name, ad) + + + ###################### Reverse-tool-independent ###################### + + mdis = machine.dis_engine(bin_stream, loc_db=loc_db, dont_dis_nulstart_bloc=True) + mdis.follow_call = True + lifter = machine.lifter_model_call(loc_db=loc_db) + + print('disassembling function: {}:{}'.format(hex(function_addr), function_name)) + asmcfg = mdis.dis_multiblock(function_addr) + + print('generating IR...') + ircfg = lifter.new_ircfg_from_asmcfg(asmcfg) + deadrm = DeadRemoval(lifter) + # deadrm(ircfg) # TODO: 这里会删掉一部分IR,需要研究一下 + + with open(os.path.join(output_dir, '{}.asm2ir'.format(function_name)),'w') as f: + # print('\tOFFSET\t| ASM\t| SRC -> DST') + f.write('\tOFFSET\t| ASM\t| SRC -> DST\n') + for lbl, irblock in ircfg.blocks.items(): + insr = [] + for assignblk in irblock: + for dst, src in assignblk.iteritems(): + # print('\t{}\t| {}\t| {} -> {}'.format(hex(assignblk.instr.offset), assignblk.instr, src, dst)) + f.write('\t{}\t| {}\t| {} -> {}\n'.format(hex(assignblk.instr.offset), assignblk.instr, src, dst)) + + if not defuse_only: + block_flow_cb = intra_block_flow_raw # if args.symb else intra_block_flow_symb + + dfg = gen_function_data_flow_graph(lifter, ircfg, function_addr, block_flow_cb) + open(os.path.join(output_dir,'{}_dfg.dot'.format(function_name)), 'w').write(dfg.dot()) + + reaching_defs = ReachingDefinitions(ircfg) + defuse = DiGraphDefUse(reaching_defs) + open(os.path.join(output_dir,'{}_defuse.dot'.format(function_name)), 'w').write(defuse.dot()) + + ''' + 根据block_loc_key + assignblk_idx 可以推算出instr offset,所以这个def-use图也是可以对应回指令的 + ''' + LocKeyIdx2InstrOffset = {} + for block in viewvalues(reaching_defs.ircfg.blocks): + for index, assignblk in enumerate(block): + LocKeyIdx2InstrOffset['{}_{}'.format(block.loc_key, index)] = hex(assignblk.instr.offset) + + # print(['{}:{}'.format(key,LocKeyIdx2InstrOffset[key]) for key in LocKeyIdx2InstrOffset]) + open(os.path.join(output_dir,'{}_LocKeyIdx2InstrOffset.map'.format(function_name)), 'w').write( + '\n'.join(['{}:{}'.format(key,LocKeyIdx2InstrOffset[key]) for key in LocKeyIdx2InstrOffset])) + + +def miasm_dataflow_analysis(function_addr:int, function_name:str, output_dir:str, filepath:str, arch:str = "X86_64", defuse_only: bool = False) -> None: + + bin_stream = Container.from_stream(open(filepath, 'rb'), loc_db).bin_stream + machine = Machine(arch) + + loc_db = LocationDB() + mdis = machine.dis_engine(bin_stream, loc_db=loc_db, dont_dis_nulstart_bloc=True) + mdis.follow_call = True + lifter = machine.lifter_model_call(loc_db=loc_db) + + print('disassembling function: {}:{}'.format(hex(function_addr), function_name)) + asmcfg = mdis.dis_multiblock(function_addr) + + print('generating IR...') + ircfg = lifter.new_ircfg_from_asmcfg(asmcfg) + deadrm = DeadRemoval(lifter) + # deadrm(ircfg) # TODO: 这里会删掉一部分IR,需要研究一下 + + with open(os.path.join(output_dir, '{}.asm2ir'.format(function_name)),'w') as f: + # print('\tOFFSET\t| ASM\t| SRC -> DST') + f.write('\tOFFSET\t| ASM\t| SRC -> DST\n') + for lbl, irblock in ircfg.blocks.items(): + insr = [] + for assignblk in irblock: + for dst, src in assignblk.iteritems(): + # print('\t{}\t| {}\t| {} -> {}'.format(hex(assignblk.instr.offset), assignblk.instr, src, dst)) + f.write('\t{}\t| {}\t| {} -> {}\n'.format(hex(assignblk.instr.offset), assignblk.instr, src, dst)) + + if not defuse_only: + block_flow_cb = intra_block_flow_raw # if args.symb else intra_block_flow_symb + + dfg = gen_function_data_flow_graph(lifter, ircfg, function_addr, block_flow_cb) + open(os.path.join(output_dir,'{}_dfg.dot'.format(function_name)), 'w').write(dfg.dot()) + + reaching_defs = ReachingDefinitions(ircfg) + defuse = DiGraphDefUse(reaching_defs) + open(os.path.join(output_dir,'{}_defuse.dot'.format(function_name)), 'w').write(defuse.dot()) + + ''' + 根据block_loc_key + assignblk_idx 可以推算出instr offset,所以这个def-use图也是可以对应回指令的 + ''' + LocKeyIdx2InstrOffset = {} + for block in viewvalues(reaching_defs.ircfg.blocks): + for index, assignblk in enumerate(block): + LocKeyIdx2InstrOffset['{}_{}'.format(block.loc_key, index)] = hex(assignblk.instr.offset) + + # print(['{}:{}'.format(key,LocKeyIdx2InstrOffset[key]) for key in LocKeyIdx2InstrOffset]) + open(os.path.join(output_dir,'{}_LocKeyIdx2InstrOffset.map'.format(function_name)), 'w').write( + '\n'.join(['{}:{}'.format(key,LocKeyIdx2InstrOffset[key]) for key in LocKeyIdx2InstrOffset])) + + diff --git a/testcase/test b/testcase/test new file mode 100755 index 0000000000000000000000000000000000000000..bf45d6a4b35db494a7ea981ba9c44b67dd81c693 GIT binary patch literal 87024 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

Of_h-g#g*~ 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 Uzx!}R(ebS%J^pgk;pk`b{}kq`CIA2c literal 0 HcmV?d00001 diff --git a/testcase/test-idapython.py b/testcase/test-idapython.py new file mode 100644 index 0000000..923e23f --- /dev/null +++ b/testcase/test-idapython.py @@ -0,0 +1,17 @@ +import idc +import idautils +import idaapi +import ida_pro +import ida_auto +ida_auto.auto_wait() + + +for func in idautils.Functions(): + + func_name = idc.get_func_name(func) + print(hex(func),':',func_name) + + + + +ida_pro.qexit(0) diff --git a/testcase/test-miasm.py b/testcase/test-miasm.py new file mode 100644 index 0000000..8c7f874 --- /dev/null +++ b/testcase/test-miasm.py @@ -0,0 +1,26 @@ +import idc +import idautils +import idaapi +import ida_pro +import ida_auto +ida_auto.auto_wait() + + +from miasm.analysis.binary import Container +from miasm.core.asmblock import log_asmblock, AsmCFG +from miasm.core.interval import interval +from miasm.analysis.machine import Machine +from miasm.analysis.data_flow import \ + DiGraphDefUse, ReachingDefinitions, load_from_int +from miasm.expression.simplifications import expr_simp +from miasm.analysis.ssa import SSADiGraph +from miasm.ir.ir import AssignBlock, IRBlock +from miasm.analysis.simplifier import IRCFGSimplifierCommon, IRCFGSimplifierSSA +from miasm.core.locationdb import LocationDB + +print("[+] miasm loading success.") + +ida_pro.qexit(0) + + + diff --git a/testcase/test.cpp b/testcase/test.cpp new file mode 100644 index 0000000..f5933c3 --- /dev/null +++ b/testcase/test.cpp @@ -0,0 +1,33 @@ +// C++ program to demonstrate +// accessing of data members + +#include +using namespace std; +class Geeks +{ + // Access specifier + public: + + // Data Members + string geekname; + + // Member Functions() + void printname() + { + cout << "Geekname is: " << geekname; + } +}; + +int main() { + + // Declare an object of class geeks + Geeks obj1; + + // accessing data member + obj1.geekname = "Abhi"; + + // accessing member function + obj1.printname(); + return 0; +} + diff --git a/testcase/test.dump b/testcase/test.dump new file mode 100644 index 0000000..e86ef00 --- /dev/null +++ b/testcase/test.dump @@ -0,0 +1,289 @@ + +test: file format elf64-x86-64 + + +Disassembly of section .init: + +0000000000001000 <_init>: + 1000: 48 83 ec 08 sub $0x8,%rsp + 1004: 48 8b 05 dd 2f 00 00 mov 0x2fdd(%rip),%rax # 3fe8 <__gmon_start__> + 100b: 48 85 c0 test %rax,%rax + 100e: 74 02 je 1012 <_init+0x12> + 1010: ff d0 callq *%rax + 1012: 48 83 c4 08 add $0x8,%rsp + 1016: c3 retq + +Disassembly of section .plt: + +0000000000001020 <.plt>: + 1020: ff 35 e2 2f 00 00 pushq 0x2fe2(%rip) # 4008 <_GLOBAL_OFFSET_TABLE_+0x8> + 1026: ff 25 e4 2f 00 00 jmpq *0x2fe4(%rip) # 4010 <_GLOBAL_OFFSET_TABLE_+0x10> + 102c: 0f 1f 40 00 nopl 0x0(%rax) + +0000000000001030 <_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEED1Ev@plt>: + 1030: ff 25 e2 2f 00 00 jmpq *0x2fe2(%rip) # 4018 <_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEED1Ev@GLIBCXX_3.4.21> + 1036: 68 00 00 00 00 pushq $0x0 + 103b: e9 e0 ff ff ff jmpq 1020 <.plt> + +0000000000001040 <__cxa_atexit@plt>: + 1040: ff 25 da 2f 00 00 jmpq *0x2fda(%rip) # 4020 <__cxa_atexit@GLIBC_2.2.5> + 1046: 68 01 00 00 00 pushq $0x1 + 104b: e9 d0 ff ff ff jmpq 1020 <.plt> + +0000000000001050 <_ZStlsIcSt11char_traitsIcESaIcEERSt13basic_ostreamIT_T0_ES7_RKNSt7__cxx1112basic_stringIS4_S5_T1_EE@plt>: + 1050: ff 25 d2 2f 00 00 jmpq *0x2fd2(%rip) # 4028 <_ZStlsIcSt11char_traitsIcESaIcEERSt13basic_ostreamIT_T0_ES7_RKNSt7__cxx1112basic_stringIS4_S5_T1_EE@GLIBCXX_3.4.21> + 1056: 68 02 00 00 00 pushq $0x2 + 105b: e9 c0 ff ff ff jmpq 1020 <.plt> + +0000000000001060 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>: + 1060: ff 25 ca 2f 00 00 jmpq *0x2fca(%rip) # 4030 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@GLIBCXX_3.4> + 1066: 68 03 00 00 00 pushq $0x3 + 106b: e9 b0 ff ff ff jmpq 1020 <.plt> + +0000000000001070 <_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEaSEPKc@plt>: + 1070: ff 25 c2 2f 00 00 jmpq *0x2fc2(%rip) # 4038 <_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEaSEPKc@GLIBCXX_3.4.21> + 1076: 68 04 00 00 00 pushq $0x4 + 107b: e9 a0 ff ff ff jmpq 1020 <.plt> + +0000000000001080 <_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEC1Ev@plt>: + 1080: ff 25 ba 2f 00 00 jmpq *0x2fba(%rip) # 4040 <_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEC1Ev@GLIBCXX_3.4.21> + 1086: 68 05 00 00 00 pushq $0x5 + 108b: e9 90 ff ff ff jmpq 1020 <.plt> + +0000000000001090 <_ZNSt8ios_base4InitC1Ev@plt>: + 1090: ff 25 b2 2f 00 00 jmpq *0x2fb2(%rip) # 4048 <_ZNSt8ios_base4InitC1Ev@GLIBCXX_3.4> + 1096: 68 06 00 00 00 pushq $0x6 + 109b: e9 80 ff ff ff jmpq 1020 <.plt> + +00000000000010a0 <_Unwind_Resume@plt>: + 10a0: ff 25 aa 2f 00 00 jmpq *0x2faa(%rip) # 4050 <_Unwind_Resume@GCC_3.0> + 10a6: 68 07 00 00 00 pushq $0x7 + 10ab: e9 70 ff ff ff jmpq 1020 <.plt> + +Disassembly of section .plt.got: + +00000000000010b0 <__cxa_finalize@plt>: + 10b0: ff 25 1a 2f 00 00 jmpq *0x2f1a(%rip) # 3fd0 <__cxa_finalize@GLIBC_2.2.5> + 10b6: 66 90 xchg %ax,%ax + +Disassembly of section .text: + +00000000000010c0 <_start>: + 10c0: 31 ed xor %ebp,%ebp + 10c2: 49 89 d1 mov %rdx,%r9 + 10c5: 5e pop %rsi + 10c6: 48 89 e2 mov %rsp,%rdx + 10c9: 48 83 e4 f0 and $0xfffffffffffffff0,%rsp + 10cd: 50 push %rax + 10ce: 54 push %rsp + 10cf: 4c 8d 05 6a 02 00 00 lea 0x26a(%rip),%r8 # 1340 <__libc_csu_fini> + 10d6: 48 8d 0d 03 02 00 00 lea 0x203(%rip),%rcx # 12e0 <__libc_csu_init> + 10dd: 48 8d 3d c1 00 00 00 lea 0xc1(%rip),%rdi # 11a5
+ 10e4: ff 15 f6 2e 00 00 callq *0x2ef6(%rip) # 3fe0 <__libc_start_main@GLIBC_2.2.5> + 10ea: f4 hlt + 10eb: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1) + +00000000000010f0 : + 10f0: 48 8d 3d 79 2f 00 00 lea 0x2f79(%rip),%rdi # 4070 <__TMC_END__> + 10f7: 48 8d 05 72 2f 00 00 lea 0x2f72(%rip),%rax # 4070 <__TMC_END__> + 10fe: 48 39 f8 cmp %rdi,%rax + 1101: 74 15 je 1118 + 1103: 48 8b 05 ce 2e 00 00 mov 0x2ece(%rip),%rax # 3fd8 <_ITM_deregisterTMCloneTable> + 110a: 48 85 c0 test %rax,%rax + 110d: 74 09 je 1118 + 110f: ff e0 jmpq *%rax + 1111: 0f 1f 80 00 00 00 00 nopl 0x0(%rax) + 1118: c3 retq + 1119: 0f 1f 80 00 00 00 00 nopl 0x0(%rax) + +0000000000001120 : + 1120: 48 8d 3d 49 2f 00 00 lea 0x2f49(%rip),%rdi # 4070 <__TMC_END__> + 1127: 48 8d 35 42 2f 00 00 lea 0x2f42(%rip),%rsi # 4070 <__TMC_END__> + 112e: 48 29 fe sub %rdi,%rsi + 1131: 48 c1 fe 03 sar $0x3,%rsi + 1135: 48 89 f0 mov %rsi,%rax + 1138: 48 c1 e8 3f shr $0x3f,%rax + 113c: 48 01 c6 add %rax,%rsi + 113f: 48 d1 fe sar %rsi + 1142: 74 14 je 1158 + 1144: 48 8b 05 a5 2e 00 00 mov 0x2ea5(%rip),%rax # 3ff0 <_ITM_registerTMCloneTable> + 114b: 48 85 c0 test %rax,%rax + 114e: 74 08 je 1158 + 1150: ff e0 jmpq *%rax + 1152: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1) + 1158: c3 retq + 1159: 0f 1f 80 00 00 00 00 nopl 0x0(%rax) + +0000000000001160 <__do_global_dtors_aux>: + 1160: 80 3d 29 30 00 00 00 cmpb $0x0,0x3029(%rip) # 4190 + 1167: 75 2f jne 1198 <__do_global_dtors_aux+0x38> + 1169: 55 push %rbp + 116a: 48 83 3d 5e 2e 00 00 cmpq $0x0,0x2e5e(%rip) # 3fd0 <__cxa_finalize@GLIBC_2.2.5> + 1171: 00 + 1172: 48 89 e5 mov %rsp,%rbp + 1175: 74 0c je 1183 <__do_global_dtors_aux+0x23> + 1177: 48 8b 3d e2 2e 00 00 mov 0x2ee2(%rip),%rdi # 4060 <__dso_handle> + 117e: e8 2d ff ff ff callq 10b0 <__cxa_finalize@plt> + 1183: e8 68 ff ff ff callq 10f0 + 1188: c6 05 01 30 00 00 01 movb $0x1,0x3001(%rip) # 4190 + 118f: 5d pop %rbp + 1190: c3 retq + 1191: 0f 1f 80 00 00 00 00 nopl 0x0(%rax) + 1198: c3 retq + 1199: 0f 1f 80 00 00 00 00 nopl 0x0(%rax) + +00000000000011a0 : + 11a0: e9 7b ff ff ff jmpq 1120 + +00000000000011a5
: + 11a5: 55 push %rbp + 11a6: 48 89 e5 mov %rsp,%rbp + 11a9: 53 push %rbx + 11aa: 48 83 ec 28 sub $0x28,%rsp + 11ae: 48 8d 45 d0 lea -0x30(%rbp),%rax + 11b2: 48 89 c7 mov %rax,%rdi + 11b5: e8 e8 00 00 00 callq 12a2 <_ZN5GeeksC1Ev> + 11ba: 48 8d 45 d0 lea -0x30(%rbp),%rax + 11be: 48 8d 35 f9 0e 00 00 lea 0xef9(%rip),%rsi # 20be <_ZNSt8__detailL19_S_invalid_state_idE+0x16> + 11c5: 48 89 c7 mov %rax,%rdi + 11c8: e8 a3 fe ff ff callq 1070 <_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEaSEPKc@plt> + 11cd: 48 8d 45 d0 lea -0x30(%rbp),%rax + 11d1: 48 89 c7 mov %rax,%rdi + 11d4: e8 95 00 00 00 callq 126e <_ZN5Geeks9printnameEv> + 11d9: bb 00 00 00 00 mov $0x0,%ebx + 11de: 48 8d 45 d0 lea -0x30(%rbp),%rax + 11e2: 48 89 c7 mov %rax,%rdi + 11e5: e8 d4 00 00 00 callq 12be <_ZN5GeeksD1Ev> + 11ea: 89 d8 mov %ebx,%eax + 11ec: eb 1a jmp 1208 + 11ee: 48 89 c3 mov %rax,%rbx + 11f1: 48 8d 45 d0 lea -0x30(%rbp),%rax + 11f5: 48 89 c7 mov %rax,%rdi + 11f8: e8 c1 00 00 00 callq 12be <_ZN5GeeksD1Ev> + 11fd: 48 89 d8 mov %rbx,%rax + 1200: 48 89 c7 mov %rax,%rdi + 1203: e8 98 fe ff ff callq 10a0 <_Unwind_Resume@plt> + 1208: 48 83 c4 28 add $0x28,%rsp + 120c: 5b pop %rbx + 120d: 5d pop %rbp + 120e: c3 retq + +000000000000120f <_Z41__static_initialization_and_destruction_0ii>: + 120f: 55 push %rbp + 1210: 48 89 e5 mov %rsp,%rbp + 1213: 48 83 ec 10 sub $0x10,%rsp + 1217: 89 7d fc mov %edi,-0x4(%rbp) + 121a: 89 75 f8 mov %esi,-0x8(%rbp) + 121d: 83 7d fc 01 cmpl $0x1,-0x4(%rbp) + 1221: 75 32 jne 1255 <_Z41__static_initialization_and_destruction_0ii+0x46> + 1223: 81 7d f8 ff ff 00 00 cmpl $0xffff,-0x8(%rbp) + 122a: 75 29 jne 1255 <_Z41__static_initialization_and_destruction_0ii+0x46> + 122c: 48 8d 3d 5e 2f 00 00 lea 0x2f5e(%rip),%rdi # 4191 <_ZStL8__ioinit> + 1233: e8 58 fe ff ff callq 1090 <_ZNSt8ios_base4InitC1Ev@plt> + 1238: 48 8d 15 21 2e 00 00 lea 0x2e21(%rip),%rdx # 4060 <__dso_handle> + 123f: 48 8d 35 4b 2f 00 00 lea 0x2f4b(%rip),%rsi # 4191 <_ZStL8__ioinit> + 1246: 48 8b 05 ab 2d 00 00 mov 0x2dab(%rip),%rax # 3ff8 <_ZNSt8ios_base4InitD1Ev@GLIBCXX_3.4> + 124d: 48 89 c7 mov %rax,%rdi + 1250: e8 eb fd ff ff callq 1040 <__cxa_atexit@plt> + 1255: 90 nop + 1256: c9 leaveq + 1257: c3 retq + +0000000000001258 <_GLOBAL__sub_I_main>: + 1258: 55 push %rbp + 1259: 48 89 e5 mov %rsp,%rbp + 125c: be ff ff 00 00 mov $0xffff,%esi + 1261: bf 01 00 00 00 mov $0x1,%edi + 1266: e8 a4 ff ff ff callq 120f <_Z41__static_initialization_and_destruction_0ii> + 126b: 5d pop %rbp + 126c: c3 retq + 126d: 90 nop + +000000000000126e <_ZN5Geeks9printnameEv>: + 126e: 55 push %rbp + 126f: 48 89 e5 mov %rsp,%rbp + 1272: 48 83 ec 10 sub $0x10,%rsp + 1276: 48 89 7d f8 mov %rdi,-0x8(%rbp) + 127a: 48 8d 35 2f 0e 00 00 lea 0xe2f(%rip),%rsi # 20b0 <_ZNSt8__detailL19_S_invalid_state_idE+0x8> + 1281: 48 8d 3d f8 2d 00 00 lea 0x2df8(%rip),%rdi # 4080 <_ZSt4cout@@GLIBCXX_3.4> + 1288: e8 d3 fd ff ff callq 1060 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt> + 128d: 48 89 c2 mov %rax,%rdx + 1290: 48 8b 45 f8 mov -0x8(%rbp),%rax + 1294: 48 89 c6 mov %rax,%rsi + 1297: 48 89 d7 mov %rdx,%rdi + 129a: e8 b1 fd ff ff callq 1050 <_ZStlsIcSt11char_traitsIcESaIcEERSt13basic_ostreamIT_T0_ES7_RKNSt7__cxx1112basic_stringIS4_S5_T1_EE@plt> + 129f: 90 nop + 12a0: c9 leaveq + 12a1: c3 retq + +00000000000012a2 <_ZN5GeeksC1Ev>: + 12a2: 55 push %rbp + 12a3: 48 89 e5 mov %rsp,%rbp + 12a6: 48 83 ec 10 sub $0x10,%rsp + 12aa: 48 89 7d f8 mov %rdi,-0x8(%rbp) + 12ae: 48 8b 45 f8 mov -0x8(%rbp),%rax + 12b2: 48 89 c7 mov %rax,%rdi + 12b5: e8 c6 fd ff ff callq 1080 <_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEC1Ev@plt> + 12ba: 90 nop + 12bb: c9 leaveq + 12bc: c3 retq + 12bd: 90 nop + +00000000000012be <_ZN5GeeksD1Ev>: + 12be: 55 push %rbp + 12bf: 48 89 e5 mov %rsp,%rbp + 12c2: 48 83 ec 10 sub $0x10,%rsp + 12c6: 48 89 7d f8 mov %rdi,-0x8(%rbp) + 12ca: 48 8b 45 f8 mov -0x8(%rbp),%rax + 12ce: 48 89 c7 mov %rax,%rdi + 12d1: e8 5a fd ff ff callq 1030 <_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEED1Ev@plt> + 12d6: 90 nop + 12d7: c9 leaveq + 12d8: c3 retq + 12d9: 0f 1f 80 00 00 00 00 nopl 0x0(%rax) + +00000000000012e0 <__libc_csu_init>: + 12e0: 41 57 push %r15 + 12e2: 49 89 d7 mov %rdx,%r15 + 12e5: 41 56 push %r14 + 12e7: 49 89 f6 mov %rsi,%r14 + 12ea: 41 55 push %r13 + 12ec: 41 89 fd mov %edi,%r13d + 12ef: 41 54 push %r12 + 12f1: 4c 8d 25 b0 2a 00 00 lea 0x2ab0(%rip),%r12 # 3da8 <__frame_dummy_init_array_entry> + 12f8: 55 push %rbp + 12f9: 48 8d 2d b8 2a 00 00 lea 0x2ab8(%rip),%rbp # 3db8 <__init_array_end> + 1300: 53 push %rbx + 1301: 4c 29 e5 sub %r12,%rbp + 1304: 48 83 ec 08 sub $0x8,%rsp + 1308: e8 f3 fc ff ff callq 1000 <_init> + 130d: 48 c1 fd 03 sar $0x3,%rbp + 1311: 74 1b je 132e <__libc_csu_init+0x4e> + 1313: 31 db xor %ebx,%ebx + 1315: 0f 1f 00 nopl (%rax) + 1318: 4c 89 fa mov %r15,%rdx + 131b: 4c 89 f6 mov %r14,%rsi + 131e: 44 89 ef mov %r13d,%edi + 1321: 41 ff 14 dc callq *(%r12,%rbx,8) + 1325: 48 83 c3 01 add $0x1,%rbx + 1329: 48 39 dd cmp %rbx,%rbp + 132c: 75 ea jne 1318 <__libc_csu_init+0x38> + 132e: 48 83 c4 08 add $0x8,%rsp + 1332: 5b pop %rbx + 1333: 5d pop %rbp + 1334: 41 5c pop %r12 + 1336: 41 5d pop %r13 + 1338: 41 5e pop %r14 + 133a: 41 5f pop %r15 + 133c: c3 retq + 133d: 0f 1f 00 nopl (%rax) + +0000000000001340 <__libc_csu_fini>: + 1340: c3 retq + +Disassembly of section .fini: + +0000000000001344 <_fini>: + 1344: 48 83 ec 08 sub $0x8,%rsp + 1348: 48 83 c4 08 add $0x8,%rsp + 134c: c3 retq diff --git a/utils.py b/utils.py new file mode 100644 index 0000000..f55fe9a --- /dev/null +++ b/utils.py @@ -0,0 +1,220 @@ +''' +This file comes from the official miasm repo + miasm/example/ida/utils.py +''' +from __future__ import print_function +from builtins import map +import idaapi +from idc import * + +from miasm.analysis.machine import Machine +from miasm.ir.translators import Translator +import miasm.expression.expression as m2_expr + +def guess_machine(addr=None): + "Return an instance of Machine corresponding to the IDA guessed processor" + + processor_name = get_inf_attr(INF_PROCNAME) + info = idaapi.get_inf_structure() + + if info.is_64bit(): + size = 64 + elif info.is_32bit(): + size = 32 + else: + size = None + + if processor_name == "metapc": + size2machine = { + 64: "x86_64", + 32: "x86_32", + None: "x86_16", + } + + machine = Machine(size2machine[size]) + + elif processor_name == "ARM": + # TODO ARM/thumb + # hack for thumb: set armt = True in globals :/ + # set bigendiant = True is bigendian + # Thumb, size, endian + info2machine = {(True, 32, True): "armtb", + (True, 32, False): "armtl", + (False, 32, True): "armb", + (False, 32, False): "arml", + (False, 64, True): "aarch64b", + (False, 64, False): "aarch64l", + } + + # Get T reg to detect arm/thumb function + # Default is arm + is_armt = False + if addr is not None: + t_reg = get_sreg(addr, "T") + is_armt = t_reg == 1 + + is_bigendian = info.is_be() + infos = (is_armt, size, is_bigendian) + if not infos in info2machine: + raise NotImplementedError('not fully functional') + machine = Machine(info2machine[infos]) + + from miasm.analysis.disasm_cb import guess_funcs, guess_multi_cb + from miasm.analysis.disasm_cb import arm_guess_subcall, arm_guess_jump_table + guess_funcs.append(arm_guess_subcall) + guess_funcs.append(arm_guess_jump_table) + + elif processor_name == "msp430": + machine = Machine("msp430") + elif processor_name == "mipsl": + machine = Machine("mips32l") + elif processor_name == "mipsb": + machine = Machine("mips32b") + elif processor_name == "PPC": + machine = Machine("ppc32b") + else: + print(repr(processor_name)) + raise NotImplementedError('not fully functional') + + return machine + + +class TranslatorIDA(Translator): + """Translate a Miasm expression to a IDA colored string""" + + # Implemented language + __LANG__ = "ida_w_color" + + def __init__(self, loc_db=None, **kwargs): + super(TranslatorIDA, self).__init__(**kwargs) + self.loc_db = loc_db + + def str_protected_child(self, child, parent): + return ("(%s)" % ( + self.from_expr(child)) if m2_expr.should_parenthesize_child(child, parent) + else self.from_expr(child) + ) + + def from_ExprInt(self, expr): + return idaapi.COLSTR(str(expr), idaapi.SCOLOR_NUMBER) + + def from_ExprId(self, expr): + out = idaapi.COLSTR(str(expr), idaapi.SCOLOR_REG) + return out + + def from_ExprLoc(self, expr): + if self.loc_db is not None: + out = self.loc_db.pretty_str(expr.loc_key) + else: + out = str(expr) + out = idaapi.COLSTR(out, idaapi.SCOLOR_REG) + return out + + def from_ExprMem(self, expr): + ptr = self.from_expr(expr.ptr) + size = idaapi.COLSTR('@' + str(expr.size), idaapi.SCOLOR_RPTCMT) + out = '%s[%s]' % (size, ptr) + return out + + def from_ExprSlice(self, expr): + base = self.from_expr(expr.arg) + start = idaapi.COLSTR(str(expr.start), idaapi.SCOLOR_RPTCMT) + stop = idaapi.COLSTR(str(expr.stop), idaapi.SCOLOR_RPTCMT) + out = "(%s)[%s:%s]" % (base, start, stop) + return out + + def from_ExprCompose(self, expr): + out = "{" + out += ", ".join(["%s, %s, %s" % (self.from_expr(subexpr), + idaapi.COLSTR(str(idx), idaapi.SCOLOR_RPTCMT), + idaapi.COLSTR(str(idx + subexpr.size), idaapi.SCOLOR_RPTCMT)) + for idx, subexpr in expr.iter_args()]) + out += "}" + return out + + def from_ExprCond(self, expr): + cond = self.str_protected_child(expr.cond, expr) + src1 = self.from_expr(expr.src1) + src2 = self.from_expr(expr.src2) + out = "%s?(%s,%s)" % (cond, src1, src2) + return out + + def from_ExprOp(self, expr): + if expr._op == '-': # Unary minus + return '-' + self.str_protected_child(expr._args[0], expr) + if expr.is_associative() or expr.is_infix(): + return (' ' + expr._op + ' ').join([self.str_protected_child(arg, expr) + for arg in expr._args]) + return (expr._op + '(' + + ', '.join( + self.from_expr(arg) + for arg in expr._args + ) + ')') + + def from_ExprAssign(self, expr): + return "%s = %s" % tuple(map(expr.from_expr, (expr.dst, expr.src))) + + + +def expr2colorstr(expr, loc_db): + """Colorize an Expr instance for IDA + @expr: Expr instance to colorize + @loc_db: LocationDB instance + """ + + translator = TranslatorIDA(loc_db=loc_db) + return translator.from_expr(expr) + + +class translatorForm(idaapi.Form): + """Translator Form. + Offer a ComboBox with available languages (ie. IR translators) and the + corresponding translation.""" + + flags = (idaapi.Form.MultiLineTextControl.TXTF_FIXEDFONT | \ + idaapi.Form.MultiLineTextControl.TXTF_READONLY) + + def __init__(self, expr): + "@expr: Expr instance" + + # Init + self.languages = list(Translator.available_languages()) + self.expr = expr + + # Initial translation + text = Translator.to_language(self.languages[0]).from_expr(self.expr) + + # Create the Form + idaapi.Form.__init__(self, r"""STARTITEM 0 +Python Expression +{FormChangeCb} + + +""", { + 'result': idaapi.Form.MultiLineTextControl(text=text, + flags=translatorForm.flags), + 'cbLanguage': idaapi.Form.DropdownListControl( + items=self.languages, + readonly=True, + selval=0), + 'FormChangeCb': idaapi.Form.FormChangeCb(self.OnFormChange), + }) + + def OnFormChange(self, fid): + if fid == self.cbLanguage.id: + # Display the Field (may be hide) + self.ShowField(self.result, True) + + # Translate the expression + dest_lang = self.languages[self.GetControlValue(self.cbLanguage)] + try: + text = Translator.to_language(dest_lang).from_expr(self.expr) + except Exception as error: + self.ShowField(self.result, False) + return -1 + + # Update the form + self.SetControlValue(self.result, + idaapi.textctrl_info_t(text=str(text), + flags=translatorForm.flags)) + return 1 \ No newline at end of file