├── COPYING ├── README.md ├── docs └── images │ ├── exfiltration_cat.png │ ├── graphviz_dot.png │ ├── recording.png │ └── taint_graph.png ├── panda-patch.patch └── spaniel ├── Makefile ├── spaniel.cpp ├── spaniel_helper.h ├── spaniel_syscalls.h ├── spaniel_tools.cpp └── spaniel_tools.h /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PANDA plugin: spaniel 2 | 3 | Summary 4 | ------- 5 | Spaniel is a plugin for [PANDA](https://github.com/panda-re/panda). 6 | 7 | By specifying the filenames that are compromised by an attacker, spaniel can trace every instruction which is (potentially) handled by a malware. These automated analyses are based on taint analysis. 8 | 9 | I used `taint2`, `osi_linux`, `osi` that are plugins for taint analysis and introspection functions that are default-installed in PANDA. 10 | 11 | 12 | Set up 13 | ------- 14 | 15 | First, build PANDA I used. 16 | I added little modification to the original code of PANDA. I inserted rr callback functions that handle received and/or sent packets in e1000 virtual network device. 17 | 18 | 19 | Please apply the patch `panda-patch.patch` as follows. 20 | After applied the patch, [build PANDA](https://github.com/panda-re/panda). 21 | (The platform I used is ubuntu14.04.) 22 | 23 | % git clone https://github.com/panda-re/panda.git 24 | % cd panda 25 | % git checkout -b 4e639ff4d867db6c485647773732bd38a316b9d6 26 | % patch -p1 < ../panda-patch.patch 27 | % cd .. 28 | % mkdir build-panda 29 | % cd build-panda/ 30 | % ../panda/build.sh 31 | 32 | 33 | Next, put the folder `spaniel` into the directory `panda/plugins`. And then, edit the `config.llvm.panda` to append the name of a plugin to build, namely spaniel. 34 | 35 | % cd ../panda/panda/plugins/ 36 | % mv spaniel panda/plugins 37 | % cd panda/plugins/ 38 | % echo "spaniel" >> config.llvm.panda 39 | 40 | Finally, build Spaniel. 41 | 42 | % cd ../../../build-panda/ 43 | % make -j 2 44 | 45 | 46 | 47 | Arguments 48 | --------- 49 | The arguments names are derived from `file_taint` a default-installed plugin of [PANDA](https://github.com/panda-re/panda). 50 | 51 | * `filename`: string, filename we want to monitor and analyze by using taint analysis. 52 | * `file_taint`: boolean, Enable taint analysis on data. 53 | * `last_tainted_rr`: uint64, The timing (the count of rr instruction) at which taint tracking will stop. 54 | 55 | Dependencies 56 | ------------ 57 | I modified the source code of [PANDA](https://github.com/panda-re/panda) by inserting rr callback functions that handle received and/or sent packets in e1000 virtual network device. 58 | 59 | Use case 60 | ------- 61 | 62 | This demo can be seen in this [video link](https://youtu.be/HibJrxdUUvg). 63 | 64 | Data exfiltration analysis: on the left we have the attacker (Kali Linux), on the right, the victim (Debian on QEMU). 65 | 66 | ![Record file exfiltration by attacker](docs/images/exfiltration_cat.png) 67 | 68 | 69 | I want to analyze malcious processing applied to 'passwd'. 70 | 71 | $PANDA_PATH/i386-softmmu/qemu-system-i386 -m 128 -replay meterbind_cat_1211_4 -os linux-32 -panda osi\ 72 | -panda osi_linux:kconf_group=debian-3.2.81-686-pae:32 -panda syscalls2:profile=linux_x86 \ 73 | -panda spaniel:filename=passwd,file_taint,last_tainted_rr=3194324 74 | 75 | And you will see this dot script in spaniel's output: 76 | 77 | digraph taintgraph { 78 | "/etc/passwd"[shape=note]; 79 | "Tainted Buffer"[shape=doubleoctagon]; 80 | "[fd]1"[shape=folder]; 81 | "[fd]4"[shape=folder]; 82 | "[tcp]192.168.124.131:44261"[shape=folder][style=filled]; 83 | "cat"[style=filled]; 84 | "cmd:cat"; 85 | "cmd:meterbind2.elf"; 86 | "cmd:sh"; 87 | "ld-2.13.so"[style=filled]; 88 | "libc-2.13.so"[style=filled]; 89 | "sys_read"; 90 | "sys_sendto"; 91 | "sys_write"; 92 | "Tainted Buffer" -> "cat"; 93 | "Tainted Buffer" -> "cmd:cat"; 94 | "Tainted Buffer" -> "cmd:meterbind2.elf"; 95 | "Tainted Buffer" -> "ld-2.13.so"; 96 | "Tainted Buffer" -> "libc-2.13.so"; 97 | "cmd:cat" -> "sys_read"; 98 | "cmd:cat" -> "sys_write"; 99 | "cmd:meterbind2.elf" -> "cmd:cat"; 100 | "cmd:meterbind2.elf" -> "sys_sendto"; 101 | "cmd:sh" -> "cmd:cat"; 102 | "sys_read" -> "/etc/passwd"; 103 | "sys_read" -> "Tainted Buffer"; 104 | "sys_sendto" -> "[fd]4"; 105 | "sys_sendto" -> "[tcp]192.168.124.131:44261"; 106 | "sys_write" -> "[fd]1"; 107 | } 108 | 109 | You can give the dot script an arbitrary name, I named it "exfiltration.dot." The corresponding graph can be generated with the following command: 110 | 111 | > dot -T pdf exfiltration.dot -o exfiltration.pdf 112 | 113 | You can visualize the graph as follows: 114 | 115 | > open exfiltration.pdf 116 | 117 | ![Graph Visualization](docs/images/taint_graph.png) 118 | 119 | 120 | License 121 | ------- 122 | GPLv2. 123 | 124 | 125 | Publications 126 | ------- 127 | 128 | * Shun Yonamine, Youki Kadobayashi, Daisuke Miyamoto, Yuzo Taenaka, "Towards Automated Characterization of Malware's High-level Mechanism Using Virtual Machine Introspection." 5th International Conference on Information Systems Security and Privacy (ICISSP 2019), Plague, Czech, Feb 2019. [pdf](http://www.insticc.org/Primoris/Resources/PaperPdf.ashx?idPaper=74055) 129 | 130 | 131 | 132 | References 133 | ------- 134 | Above graph was inspired from this paper. 135 | 136 | * Yin, Heng, et al. "Panorama: capturing system-wide information flow for malware detection and analysis." Proceedings of the 14th ACM conference on Computer and communications security. ACM, 2007. 137 | 138 | -------------------------------------------------------------------------------- /docs/images/exfiltration_cat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shun-yo/Spaniel/546b326cd422314769de12af9e4082f61871589f/docs/images/exfiltration_cat.png -------------------------------------------------------------------------------- /docs/images/graphviz_dot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shun-yo/Spaniel/546b326cd422314769de12af9e4082f61871589f/docs/images/graphviz_dot.png -------------------------------------------------------------------------------- /docs/images/recording.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shun-yo/Spaniel/546b326cd422314769de12af9e4082f61871589f/docs/images/recording.png -------------------------------------------------------------------------------- /docs/images/taint_graph.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shun-yo/Spaniel/546b326cd422314769de12af9e4082f61871589f/docs/images/taint_graph.png -------------------------------------------------------------------------------- /panda-patch.patch: -------------------------------------------------------------------------------- 1 | diff -rupN panda/hw/net/e1000.c panda_patched/hw/net/e1000.c 2 | --- panda/hw/net/e1000.c 2019-03-25 21:07:30.375966172 +0900 3 | +++ panda_patched/hw/net/e1000.c 2019-03-25 21:08:58.659989105 +0900 4 | @@ -38,6 +38,9 @@ 5 | 6 | #include "e1000x_common.h" 7 | 8 | +#include "panda/rr/rr_log_all.h" 9 | + 10 | + 11 | static const uint8_t bcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 12 | 13 | #define E1000_DEBUG 14 | @@ -520,6 +523,21 @@ inc_tx_bcast_or_mcast_count(E1000State * 15 | static void 16 | e1000_send_packet(E1000State *s, const uint8_t *buf, int size) 17 | { 18 | + //printf("e1000_send_pack %d\n", RR_CALL_HANDLE_PACKET); 19 | + if (rr_in_record()){ 20 | + //rr_record_handle_packet_call(RR_CALLSITE_E1000_XMIT_SEG_1, tp->vlan, 21 | + // tp->size + 4, PANDA_NET_TX); 22 | + //printf("in_record now...\n"); 23 | + 24 | + //printf("args %d\n", (int)size); 25 | + 26 | + rr_record_handle_packet_call(RR_CALLSITE_NIC_SEND_PACKET, (uint8_t *)buf, size, PANDA_NET_TX); 27 | +// rr_record_handle_packet_call(RR_CALLSITE_NIC_RECEIVE_PACKET, (uint8_t *)(iov->iov_base+iov_ofs), iov_copy, PANDA_NET_RX, (uint64_t)(iov->iov_base+iov_ofs)); 28 | + 29 | + } 30 | + 31 | + 32 | + 33 | static const int PTCregs[6] = { PTC64, PTC127, PTC255, PTC511, 34 | PTC1023, PTC1522 }; 35 | 36 | @@ -577,10 +595,12 @@ xmit_seg(E1000State *s) 37 | } 38 | 39 | if (tp->props.sum_needed & E1000_TXD_POPTS_TXSM) { 40 | +// printf("tcp_checksum\n"); 41 | putsum(tp->data, tp->size, tp->props.tucso, 42 | tp->props.tucss, tp->props.tucse); 43 | } 44 | if (tp->props.sum_needed & E1000_TXD_POPTS_IXSM) { 45 | +// printf("ip_checksum\n"); 46 | putsum(tp->data, tp->size, tp->props.ipcso, 47 | tp->props.ipcss, tp->props.ipcse); 48 | } 49 | @@ -588,8 +608,10 @@ xmit_seg(E1000State *s) 50 | memmove(tp->vlan, tp->data, 4); 51 | memmove(tp->data, tp->data + 4, 8); 52 | memcpy(tp->data + 8, tp->vlan_header, 4); 53 | +// printf("sendpacket_tp_vlan\n"); 54 | e1000_send_packet(s, tp->vlan, tp->size + 4); 55 | } else { 56 | +// printf("sendpacket_tp_data\n"); 57 | e1000_send_packet(s, tp->data, tp->size); 58 | } 59 | 60 | @@ -932,6 +954,14 @@ e1000_receive_iov(NetClientState *nc, co 61 | do { 62 | iov_copy = MIN(copy_size, iov->iov_len - iov_ofs); 63 | pci_dma_write(d, ba, iov->iov_base + iov_ofs, iov_copy); 64 | + 65 | +//////////////// 66 | + if (rr_in_record()){ 67 | + rr_record_handle_packet_call(RR_CALLSITE_NIC_RECEIVE_PACKET, (uint8_t *)(iov->iov_base+iov_ofs), iov_copy, PANDA_NET_RX); 68 | + } 69 | +//////////////// 70 | + 71 | + 72 | copy_size -= iov_copy; 73 | ba += iov_copy; 74 | iov_ofs += iov_copy; 75 | diff -rupN panda/panda/include/panda/rr/rr_log_all.h panda_patched/panda/include/panda/rr/rr_log_all.h 76 | --- panda/panda/include/panda/rr/rr_log_all.h 2019-03-25 21:07:30.419966180 +0900 77 | +++ panda_patched/panda/include/panda/rr/rr_log_all.h 2019-03-25 21:09:53.048003547 +0900 78 | @@ -37,6 +37,11 @@ 79 | #include "qemu/log.h" 80 | #include "qom/cpu.h" 81 | 82 | + 83 | + 84 | +#define PANDA_NET_RX 0 85 | +#define PANDA_NET_TX 1 86 | + 87 | // Used later for enum to string macros 88 | #define GENERATE_ENUM(ENUM) ENUM 89 | #define GENERATE_STRING(STRING) #STRING 90 | @@ -188,7 +193,11 @@ static inline const char* get_log_entry_ 91 | ACTION(RR_CALLSITE_WRITE_4), \ 92 | ACTION(RR_CALLSITE_WRITE_2), \ 93 | ACTION(RR_CALLSITE_WRITE_1), \ 94 | - ACTION(RR_CALLSITE_LAST), 95 | + ACTION(RR_CALLSITE_LAST), \ 96 | + ACTION(RR_CALLSITE_NIC_SEND_PACKET), \ 97 | + ACTION(RR_CALLSITE_NIC_RECEIVE_PACKET),\ 98 | + ACTION(RR_CALLSITE_NIC_NET_TRANSFER_TX), \ 99 | + ACTION(RR_CALLSITE_NIC_NET_TRANSFER_RX), 100 | 101 | typedef enum { 102 | FOREACH_CALLSITE(GENERATE_ENUM) 103 | @@ -543,10 +552,13 @@ typedef struct { 104 | uint8_t* buf; 105 | uint32_t size; 106 | uint8_t direction; 107 | +// uint64_t old_buf_addr; 108 | } RR_handle_packet_args; 109 | 110 | void rr_record_handle_packet_call(RR_callsite_id call_site, uint8_t* buf, 111 | int size, uint8_t direction); 112 | +//void rr_record_handle_packet_call(RR_callsite_id call_site, uint8_t* buf, 113 | +// int size, uint8_t direction, uint64_t old_buf_addr); 114 | 115 | void rr_record_net_transfer(RR_callsite_id call_site, 116 | Net_transfer_type transfer_type, uint64_t src_addr, 117 | diff -rupN panda/panda/src/rr/rr_log.c panda_patched/panda/src/rr/rr_log.c 118 | --- panda/panda/src/rr/rr_log.c 2019-03-25 21:07:30.435966184 +0900 119 | +++ panda_patched/panda/src/rr/rr_log.c 2019-03-25 21:09:28.983995284 +0900 120 | @@ -50,6 +50,9 @@ 121 | #include "migration/qemu-file.h" 122 | #include "io/channel-file.h" 123 | #include "sysemu/sysemu.h" 124 | + 125 | +#include "panda/plugin.h" 126 | + 127 | /******************************************************************************************/ 128 | /* GLOBALS */ 129 | /******************************************************************************************/ 130 | @@ -305,26 +308,32 @@ static inline void rr_write_item(void) 131 | RR_skipped_call_args* args = &item.variant.call_args; 132 | // mz write kind first! 133 | RR_WRITE_ITEM(args->kind); 134 | +//printf("debug args->kind %d\n", args->kind); 135 | switch (args->kind) { 136 | case RR_CALL_CPU_MEM_RW: 137 | +//printf("rr_write_item cpu_mem_rw\n"); 138 | RR_WRITE_ITEM(args->variant.cpu_mem_rw_args); 139 | rr_fwrite(args->variant.cpu_mem_rw_args.buf, 1, 140 | args->variant.cpu_mem_rw_args.len); 141 | break; 142 | case RR_CALL_CPU_MEM_UNMAP: 143 | +//printf("rr_write_item cpu_mem_unmap\n"); 144 | RR_WRITE_ITEM(args->variant.cpu_mem_unmap); 145 | rr_fwrite(args->variant.cpu_mem_unmap.buf, 1, 146 | args->variant.cpu_mem_unmap.len); 147 | break; 148 | case RR_CALL_MEM_REGION_CHANGE: 149 | +//printf("rr_write_item mem_region_change\n"); 150 | RR_WRITE_ITEM(args->variant.mem_region_change_args); 151 | rr_fwrite(args->variant.mem_region_change_args.name, 1, 152 | args->variant.mem_region_change_args.len); 153 | break; 154 | case RR_CALL_HD_TRANSFER: 155 | +//printf("rr_write_item hd_transfer\n"); 156 | RR_WRITE_ITEM(args->variant.hd_transfer_args); 157 | break; 158 | case RR_CALL_NET_TRANSFER: 159 | +//printf("rr_write_item net_transfer\n"); 160 | RR_WRITE_ITEM(args->variant.net_transfer_args); 161 | break; 162 | case RR_CALL_HANDLE_PACKET: 163 | @@ -333,14 +342,17 @@ static inline void rr_write_item(void) 164 | args->variant.handle_packet_args.size, 1); 165 | break; 166 | default: 167 | +//printf("rr_write_item Unimmplemented skippedcall\n"); 168 | // mz unimplemented 169 | rr_assert(0 && "Unimplemented skipped call!"); 170 | } 171 | } break; 172 | case RR_LAST: 173 | +//printf("rr_write_item rr_last\n"); 174 | // mz nothing to read 175 | break; 176 | default: 177 | +//printf("rr_write_item unimplemented_replay_log_entry\n"); 178 | // mz unimplemented 179 | rr_assert(0 && "Unimplemented replay log entry!"); 180 | } 181 | @@ -589,6 +601,7 @@ void rr_record_net_transfer(RR_callsite_ 182 | void rr_record_handle_packet_call(RR_callsite_id call_site, uint8_t* buf, 183 | int size, uint8_t direction) 184 | { 185 | +// printf("in rr_handle_packet_call enter\n"); 186 | RR_log_entry* item = &(rr_nondet_log->current_item); 187 | // mz just in case 188 | memset(item, 0, sizeof(RR_log_entry)); 189 | @@ -602,7 +615,10 @@ void rr_record_handle_packet_call(RR_cal 190 | item->variant.call_args.variant.handle_packet_args.buf = buf; 191 | item->variant.call_args.variant.handle_packet_args.size = size; 192 | item->variant.call_args.variant.handle_packet_args.direction = direction; 193 | + //item->variant.call_args.variant.handle_packet_args.old_buf_addr = (uint64_t)buf; 194 | + //item->variant.call_args.variant.handle_packet_args.old_buf_addr = old_buf_addr; 195 | 196 | +// printf("in rr_handle_packet_call return\n"); 197 | rr_write_item(); 198 | } 199 | 200 | @@ -725,27 +741,35 @@ static RR_log_entry *rr_read_item(void) 201 | RR_READ_ITEM(item->header.kind); 202 | RR_READ_ITEM(item->header.callsite_loc); 203 | 204 | + 205 | // mz read the rest of the item 206 | switch (item->header.kind) { 207 | case RR_INPUT_1: 208 | +// printf("rr_input1 %d\n", (int)item->header.kind); 209 | RR_READ_ITEM(item->variant.input_1); 210 | break; 211 | case RR_INPUT_2: 212 | +// printf("rr_input2 %d\n", (int)item->header.kind); 213 | RR_READ_ITEM(item->variant.input_2); 214 | break; 215 | case RR_INPUT_4: 216 | +// printf("rr_input4 %d\n", (int)item->header.kind); 217 | RR_READ_ITEM(item->variant.input_4); 218 | break; 219 | case RR_INPUT_8: 220 | +// printf("rr_input8 %d\n", (int)item->header.kind); 221 | RR_READ_ITEM(item->variant.input_8); 222 | break; 223 | case RR_INTERRUPT_REQUEST: 224 | +// printf("rr_interrupt %d\n", (int)item->header.kind); 225 | RR_READ_ITEM(item->variant.interrupt_request); 226 | break; 227 | case RR_EXIT_REQUEST: 228 | +// printf("rr_exit %d\n", (int)item->header.kind); 229 | RR_READ_ITEM(item->variant.exit_request); 230 | break; 231 | case RR_SKIPPED_CALL: { 232 | +//printf("rr_skipped %d\n", (int)item->header.kind); 233 | RR_skipped_call_args* args = &item->variant.call_args; 234 | // mz read kind first! 235 | RR_READ_ITEM(args->kind); 236 | @@ -782,9 +806,11 @@ static RR_log_entry *rr_read_item(void) 237 | break; 238 | 239 | case RR_CALL_HANDLE_PACKET: 240 | +//printf("rr_handle %d\n", (int)item->header.kind); 241 | RR_READ_ITEM(args->variant.handle_packet_args); 242 | // mz XXX HACK 243 | args->old_buf_addr = (uint64_t)args->variant.handle_packet_args.buf; 244 | + //args->old_buf_addr = (uint64_t)args->variant.handle_packet_args.old_buf_addr; 245 | // mz buffer length in args->variant.cpu_mem_rw_args.len 246 | // mz always allocate a new one. we free it when the item is added 247 | // to the recycle list 248 | @@ -1052,6 +1078,37 @@ void rr_replay_skipped_calls_internal(RR 249 | /*is_write=*/1, 250 | args.variant.cpu_mem_unmap.len); 251 | } break; 252 | + case RR_CALL_HANDLE_PACKET: { 253 | + // run all callbacks registered for packet handling 254 | + RR_handle_packet_args hp = args.variant.handle_packet_args; 255 | + panda_cb_list *plist; 256 | + for (plist = panda_cbs[PANDA_CB_REPLAY_HANDLE_PACKET]; plist != NULL; plist = panda_cb_list_next(plist)) { 257 | + plist->entry.replay_handle_packet 258 | + (first_cpu, 259 | + hp.buf, 260 | + hp.size, 261 | + hp.direction, 262 | + args.old_buf_addr); 263 | + } 264 | + } break; 265 | + 266 | + case RR_CALL_NET_TRANSFER: { 267 | + // run all callbacks registered for transfers within network 268 | + // card (E1000) 269 | + RR_net_transfer_args nta = 270 | + args.variant.net_transfer_args; 271 | + panda_cb_list *plist; 272 | + for (plist = panda_cbs[PANDA_CB_REPLAY_NET_TRANSFER]; 273 | + plist != NULL; plist = panda_cb_list_next(plist)) { 274 | + plist->entry.replay_net_transfer 275 | + (first_cpu, 276 | + nta.type, 277 | + nta.src_addr, 278 | + nta.dest_addr, 279 | + nta.num_bytes); 280 | + } 281 | + } break; 282 | + 283 | default: 284 | // mz sanity check 285 | rr_assert(0); 286 | @@ -1389,7 +1446,7 @@ void rr_do_end_record(void) 287 | #endif 288 | } 289 | 290 | -extern void panda_cleanup(void); 291 | +//extern void panda_cleanup(void); 292 | 293 | // file_name_full should be full path to the record/replay log 294 | int rr_do_begin_replay(const char* file_name_full, CPUState* cpu_state) 295 | -------------------------------------------------------------------------------- /spaniel/Makefile: -------------------------------------------------------------------------------- 1 | # Don't forget to add your plugin to config.panda! 2 | 3 | # If you need custom CFLAGS or LIBS, set them up here 4 | # CFLAGS+= 5 | # LIBS+= 6 | LIBS+=-lcapstone 7 | 8 | # The main rule for your plugin. List all object-file dependencies. 9 | $(PLUGIN_TARGET_DIR)/panda_$(PLUGIN_NAME).so: \ 10 | $(PLUGIN_OBJ_DIR)/$(PLUGIN_NAME).o \ 11 | $(PLUGIN_OBJ_DIR)/spaniel_tools.o \ 12 | 13 | -------------------------------------------------------------------------------- /spaniel/spaniel.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2019 Shun Yonamine */ 2 | /* 3 | * This work is licensed under the terms of the GNU GPL, version 2. 4 | * See the COPYING file in the top-level directory. */ 5 | 6 | // This needs to be defined before anything is included in order to get 7 | // the PRIx64 macro 8 | #define __STDC_FORMAT_MACROS 9 | 10 | #include "panda/plugin.h" 11 | #include "panda/plugin_plugin.h" 12 | 13 | #include "osi/osi_types.h" 14 | #include "osi/osi_ext.h" 15 | #include "osi_linux/osi_linux_ext.h" 16 | #include "syscalls2/gen_syscalls_ext_typedefs.h" 17 | #include "taint2/taint2.h" 18 | #include "taint2/taint2_ext.h" 19 | #include "panda/plugin.h" 20 | 21 | #include "spaniel_helper.h" 22 | #include "spaniel_syscalls.h" 23 | #include "spaniel_tools.h" 24 | //#include "entro.h" 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #define MAX_FILENAME 256 40 | 41 | // These need to be extern "C" so that the ABI is compatible with 42 | // QEMU/PANDA, which is written in C 43 | extern "C" { 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | 52 | bool init_plugin(void *); 53 | void uninit_plugin(void *); 54 | } 55 | 56 | //Plugin parameter's argument 57 | panda_arg_list *args; 58 | bool file_taint = false; 59 | bool all_file_taint = false; 60 | bool no_taint=false; 61 | bool all_read_taint = false; 62 | bool rx_taint = false; 63 | bool no_positional_labels=false; 64 | bool no_char = false; 65 | bool debug = false; 66 | const char *taint_filename = 0; 67 | uint32_t watched_fd_num; 68 | const char *watched_cmd = 0; 69 | uint64_t last_tainted_rr = 0; 70 | bool check_funcall = false; 71 | uint64_t check_funcall_rr = 0; 72 | ////////// 73 | 74 | std::vector< std::pair > fd_watched; 75 | std::map running_procs; 76 | 77 | // file-descriptor-name such as "SYSTEMCALL" or filename. 78 | typedef std::map FDMP; 79 | std::map procs_fdmap; 80 | 81 | //instruction's addr to module-name. 82 | typedef std::map MODMP; 83 | std::map procs_mapped_modules; 84 | 85 | 86 | typedef std::map> MOD_PC_MP; 87 | std::map procs_pc_module_mp; 88 | 89 | 90 | //procs to its referenced module-name. 91 | typedef std::set MODS; 92 | std::map procs_refered_module; 93 | 94 | typedef struct Info_taint_source Info_t; 95 | std::map taint_label_info; 96 | 97 | typedef struct Info_taint_output Info_out; 98 | std::vector< Info_out > taint_outs; 99 | 100 | //rr count to name of destination 101 | std::map transfered_data_info; 102 | 103 | //packet data, expressed in std-string-format 104 | std::string tx_packet_payload; 105 | std::string rx_packet_payload; 106 | std::map label_network_rx_mp; 107 | 108 | void cb_sys_tapped(CPUState* cpu, std::string tapped_syscall, int fd, uint32_t buf, uint32_t len, uint32_t cb_state); 109 | void cb_taint(CPUState* cpu, std::string tapped_syscall, int fd, uint32_t buf, uint32_t count, uint32_t cb_state); 110 | 111 | uint16_t cur_tb_size; 112 | target_ulong cur_tb_pc; 113 | 114 | target_ulong last_user_pc; 115 | target_ulong rx_last_user_pc; 116 | target_ulong tx_last_user_pc; 117 | 118 | 119 | 120 | std::set rx_remote_hosts; 121 | std::set tx_remote_hosts; 122 | 123 | 124 | //asid,command-name to set(resource) 125 | std::map, std::set> cmd_resource_mp; 126 | 127 | 128 | 129 | // I used running_procs map for saving OsiProc, 130 | // but in before-exec-cb, that osiproc hold a not-enough 131 | // length of name or information, so I hold osiproc 132 | // in vmi_pgd_changed callback. this is for tainted-cmd-names 133 | OsiProc *proc_at_pgd; 134 | 135 | bool asid_just_changed = false; 136 | 137 | uint32_t asid_at_pgd; 138 | 139 | bool pid_ok(int pid){ 140 | if(pid < 4){ 141 | return false; 142 | }else{ 143 | return true; 144 | } 145 | } 146 | 147 | bool check_proc_ok(OsiProc* proc){ 148 | return (proc && pid_ok(proc->pid)); 149 | } 150 | 151 | 152 | std::string hex2str(int dec){ 153 | std::ostringstream oss; 154 | oss << std::setfill('0') << std::setw(2) << std::hex << dec; 155 | return std::string(oss.str()); 156 | } 157 | 158 | 159 | //uint32_t little_endian_vec(uint8_t *vec, int size){ 160 | uint32_t endian_vec(uint8_t *vec, int size, int big){ 161 | uint32_t endianed_val = 0; 162 | if(big == 1){ 163 | for(int i = size-1; i>=0; i--) 164 | endianed_val |= vec[i] << ((i-1) * 8); 165 | }else{ 166 | for(int i = 0; i bool contain(const std::string& s, const T& v){ 173 | return s.find(v) != std::string::npos; 174 | } 175 | 176 | 177 | void str_add(std::string& s, const std::string& v) 178 | { 179 | if(!contain(s, v)){ 180 | s += v; 181 | } 182 | } 183 | 184 | void update_procs_fdmap(CPUState *cpu, uint32_t fd){ 185 | std::string filename = get_filename_from_fd(cpu, fd); 186 | uint32_t asid = panda_current_asid(cpu); 187 | procs_fdmap[asid][fd] = filename; 188 | } 189 | 190 | std::string get_procs_fdmap(CPUState* cpu, uint32_t fd){ 191 | uint32_t asid = panda_current_asid(cpu); 192 | return procs_fdmap[asid][fd]; 193 | } 194 | 195 | 196 | #ifdef TARGET_I386 197 | 198 | void hex_dump(const uint8_t *buf, int size) 199 | { 200 | int len, i, j, c; 201 | for(i=0;i 16) 204 | len = 16; 205 | fprintf(stdout, "%08x ", i); 206 | for(j=0;j<16;j++) { 207 | if (j < len) 208 | fprintf(stdout, " %02x", buf[i+j]); 209 | else 210 | fprintf(stdout, " "); 211 | } 212 | fprintf(stdout, " "); 213 | for(j=0;j '~') 216 | c = '.'; 217 | fprintf(stdout, "%c", c); 218 | } 219 | fprintf(stdout, "\n"); 220 | } 221 | } 222 | 223 | 224 | uint32_t get_syscall_retval(CPUState* cpu){ 225 | CPUArchState *env = (CPUArchState*)cpu->env_ptr; 226 | return env->regs[R_EAX]; 227 | } 228 | 229 | 230 | std::string get_filename_from_fd(CPUState* cpu, uint32_t fd){ 231 | std::string the_filename; 232 | uint32_t asid = panda_current_asid(cpu); 233 | OsiProc& proc = running_procs[asid]; 234 | char *filename = osi_linux_fd_to_filename(cpu, &proc, fd); 235 | 236 | if(filename != NULL){ 237 | the_filename = std::string(filename); 238 | }else{ 239 | the_filename = "(" ISNULL " fd:" + std::to_string(fd) + ")"; 240 | } 241 | return the_filename; 242 | }; 243 | 244 | uint64_t get_pos_from_fd(CPUState* cpu, uint32_t fd){ 245 | uint32_t asid = panda_current_asid(cpu); 246 | OsiProc& proc = running_procs[asid]; 247 | uint64_t pos = osi_linux_fd_to_pos(cpu, &proc, fd); 248 | return pos; 249 | }; 250 | 251 | 252 | std::string get_current_command(CPUState* cpu){ 253 | uint32_t asid = panda_current_asid(cpu); 254 | char *comm = running_procs[asid].name; 255 | return (comm ? std::string(comm) : ISNULL); 256 | } 257 | 258 | 259 | std::set get_commands_from_pid(uint32_t pid){ 260 | std::set cmds; 261 | for(auto x : running_procs){ 262 | if(x.second.pid == pid){ 263 | if(x.second.name){ 264 | cmds.insert(std::string(x.second.name)); 265 | } 266 | } 267 | } 268 | return cmds; 269 | } 270 | 271 | //get command-name of current's parent-process. 272 | std::set get_current_parent_command(CPUState* cpu){ 273 | std::set parent_cmds; 274 | uint32_t asid = panda_current_asid(cpu); 275 | OsiProc& current = running_procs[asid]; 276 | parent_cmds = get_commands_from_pid(current.ppid); 277 | return parent_cmds; 278 | } 279 | 280 | 281 | void get_current_mod(CPUState* cpu, target_ulong pc_addr){ 282 | uint32_t asid = panda_current_asid(cpu); 283 | uint32_t pc; 284 | if(pc_addr == 0){ 285 | pc = panda_current_pc(cpu); 286 | }else{ 287 | pc = pc_addr; 288 | } 289 | 290 | OsiProc *current = get_current_process(cpu); 291 | OsiModules *ms = get_libraries(cpu, current); 292 | OsiModule m; 293 | 294 | //Set blank string in current pc's if not defined yet. 295 | if(procs_mapped_modules[asid].count(pc) == 0){ 296 | procs_mapped_modules[asid][pc] = ISNULL; 297 | } 298 | 299 | if(ms==NULL) return; 300 | 301 | for(int i=0; i < ms->num; i++){ 302 | m = ms->module[i]; 303 | for(auto x : procs_mapped_modules[asid]){ 304 | if(x.second == ISNULL){ 305 | if(x.first > m.base && x.first<(m.base+m.size)){ 306 | procs_mapped_modules[asid][x.first] = m.name; 307 | //if m.file is NULL, name will be "[???]" 308 | 309 | if(m.file){ 310 | procs_pc_module_mp[asid][x.first] = std::make_pair(get_current_command(cpu), m.name); 311 | procs_refered_module[asid].insert(m.name); 312 | } 313 | } 314 | } 315 | } 316 | } 317 | return; 318 | } 319 | 320 | 321 | 322 | bool is_in_watched_cmd(CPUState* cpu){ 323 | if(contain(get_current_command(cpu), watched_cmd)) 324 | return true; 325 | else 326 | return false; 327 | } 328 | 329 | 330 | void monitor_resource_access(CPUState* cpu, std::string call_name, int fd,uint32_t size){ 331 | std::string filename = get_filename_from_fd(cpu, fd); 332 | Info_resource touched; 333 | touched.resource_name = filename; 334 | touched.cmd = get_current_command(cpu); 335 | touched.parent_cmds = get_current_parent_command(cpu); 336 | touched.size = size; 337 | touched.rr_count = rr_get_guest_instr_count(); 338 | //resource_touched[call_name].insert(touched); 339 | resource_touched[call_name].push_back(touched); 340 | } 341 | 342 | 343 | int app_getlabels(uint32_t el, void *stuff1){ 344 | if(el){ 345 | ((std::set *)stuff1)->insert(el); 346 | return 0; 347 | }else{ 348 | return 1; 349 | } 350 | } 351 | 352 | void check_virtaddr_labeled(CPUState* cpu, target_ulong virt_addr, std::set &ls){ 353 | hwaddr pa = panda_virt_to_phys(cpu, virt_addr); 354 | //for checking taint labels, id or something. 355 | if (pa != (hwaddr) -1) { 356 | taint2_labelset_ram_iter(pa, app_getlabels, &ls); 357 | } 358 | } 359 | 360 | 361 | bool is_tapped_buf_labeled(CPUState* cpu, uint32_t addr, uint32_t len, int fd, std::string tapped_call){ 362 | if(!taint2_enabled()){return false;}; 363 | 364 | Info_out t; 365 | t.cmd = get_current_command(cpu); 366 | t.parent_cmds = get_current_parent_command(cpu); 367 | t.resource = get_filename_from_fd(cpu,fd); 368 | t.syscall = tapped_call; 369 | t.buf = get_buf_dump(cpu, addr, len); 370 | t.rr_count = rr_get_guest_instr_count(); 371 | t.fd = fd; 372 | 373 | for(int i=0; i 0){ 378 | taint_outs.push_back(t); 379 | return true; 380 | }else{ 381 | return false; 382 | } 383 | 384 | } 385 | 386 | 387 | // label this virtual address. might fail, so 388 | // returns true if byte was labeled 389 | bool label_byte(CPUState *cpu, target_ulong virt_addr, uint32_t label_num) { 390 | if(!taint2_enabled()) return false; 391 | 392 | hwaddr pa = panda_virt_to_phys(cpu, virt_addr); 393 | if (pa == (hwaddr) -1) { 394 | printf ("label_byte: virtual addr " TARGET_FMT_lx " not available\n", virt_addr); 395 | return false; 396 | } 397 | 398 | taint2_label_ram(pa, label_num); 399 | 400 | return true; 401 | } 402 | 403 | 404 | void ranged_label_byte(CPUState *cpu, target_ulong pc, target_ulong virt_addr, uint32_t len, int fd, std::string tap_call) { 405 | if(!taint2_enabled()) return; 406 | 407 | if(len>0){ 408 | static uint32_t label_num = 0; 409 | std::string buf_data = get_buf_printable(cpu, virt_addr, len, true); 410 | Info_t tap; 411 | tap.asid = panda_current_asid(cpu); 412 | tap.pc = pc; 413 | tap.syscall = tap_call; 414 | tap.resource = get_filename_from_fd(cpu,fd); 415 | tap.cmd = get_current_command(cpu); 416 | tap.parent_cmds = get_current_parent_command(cpu); 417 | tap.range_size = len; 418 | tap.rr_count = rr_get_guest_instr_count(); 419 | tap.fd = fd; 420 | 421 | if(!no_positional_labels){ 422 | label_num += 1; 423 | }else{ 424 | label_num = 1; 425 | } 426 | 427 | for(int i = 0; i < len; i++){ 428 | label_byte(cpu, virt_addr+i, label_num); 429 | } 430 | 431 | // In the case of taint in, payload is possibly be splitted because of transported in TCP, 432 | // and these data is concatenated before read to buffer by sys_readv() 433 | // So check whether buf_data(bigger one) contains packet payload or not. 434 | // Constraint: resource's filename is null. 435 | if(contain(tap.resource, ISNULL)){ 436 | if((buf_data.size()/2 <= 1460 and buf_data==rx_packet_payload) or \ 437 | (buf_data.size()/2 > 1460 and contain(buf_data, rx_packet_payload))){ 438 | tap.resource += " (Matched-net-incoming " + rx_last_tcp_conn + ")"; 439 | tap.candidate_src_host = rx_last_tcp_conn; 440 | label_network_rx_mp[label_num] = rx_last_tcp_conn; 441 | } 442 | } 443 | taint_label_info[ label_num ] = tap; 444 | } 445 | } 446 | 447 | uint32_t buf_virtaddr_little_endianed(CPUState *cpu, uint32_t addr, uint64_t len){ 448 | uint32_t little_endianed=0; 449 | uint8_t tmp = -1; 450 | for(int i = 0; i < len; i++){ 451 | panda_virtual_memory_rw(cpu, addr+i, (uint8_t *)&tmp, sizeof(tmp), 0); 452 | little_endianed |= (uint32_t)tmp << (i*8); 453 | } 454 | return little_endianed; 455 | }; 456 | 457 | 458 | std::vector get_buf_dump(CPUState *cpu, uint32_t addr, uint32_t len){ 459 | std::vector dumped_buf; 460 | uint8_t cell = -1; 461 | for(int i = 0; i < len; i++){ 462 | panda_virtual_memory_rw(cpu, addr+i, (uint8_t *)&cell, sizeof(cell), 0); 463 | dumped_buf.push_back(cell); 464 | } 465 | return dumped_buf; 466 | } 467 | 468 | 469 | std::string get_buf_printable(CPUState *cpu, uint32_t addr, uint32_t len, bool in_hex){ 470 | std::string printable_str; 471 | std::vector dumped_buf; 472 | dumped_buf = get_buf_dump(cpu, addr, len); 473 | for(uint8_t c : dumped_buf){ 474 | if(in_hex){ 475 | printable_str += hex2str(c); 476 | }else if(isprint(c)){ 477 | printable_str += c; 478 | }else{ 479 | printable_str += "."; 480 | } 481 | } 482 | return printable_str; 483 | } 484 | 485 | 486 | std::string get_strncpy_buf(CPUState *cpu, target_ulong guest_addr, size_t max_len){ 487 | std::string str; 488 | char *buf = new char[max_len]; 489 | int i; 490 | uint8_t c; 491 | for(i=0; i sysenter_pc_mp; 559 | 560 | if(cb_state == ENTER){ 561 | if(cb_satisfy_read_taint(cpu, fd, buf, count)){ 562 | if(!taint2_enabled()){ 563 | sysenter_pc_mp[read_call] = panda_current_pc(cpu); 564 | taint2_enable_taint(); 565 | } 566 | } 567 | }else if(cb_state == RETURN){ 568 | if(count>0 && cb_satisfy_read_taint(cpu, fd, buf, count)){ 569 | if(taint2_enabled()){ 570 | 571 | get_current_mod(cpu, sysenter_pc_mp[read_call]); 572 | 573 | target_ulong pc = sysenter_pc_mp[read_call]; 574 | 575 | ranged_label_byte(cpu, pc, buf, count, fd, read_call); 576 | } 577 | } 578 | } 579 | } 580 | 581 | 582 | void linux_sys_read(CPUState *cpu, target_ulong pc, uint32_t fd, uint32_t buf, uint32_t count, uint32_t cb_state){ 583 | if(cb_state == ENTER){ 584 | 585 | //std::cout << "get_current_pc en: 0x" << std::hex << panda_current_pc(cpu) << std::endl; 586 | 587 | cb_taint(cpu, "sys_read", fd, buf, count, cb_state); 588 | }else if(cb_state == RETURN){ 589 | 590 | //std::cout << "get_current_pc re: 0x" << std::hex << panda_current_pc(cpu) << std::endl; 591 | 592 | //update_procs_fdmap(cpu, fd); 593 | int read_byte = get_syscall_retval(cpu); 594 | if(read_byte>0){ 595 | cb_taint(cpu, "sys_read", fd, buf, read_byte, cb_state); 596 | } 597 | monitor_resource_access(cpu, "sys_read", fd, read_byte); 598 | } 599 | } 600 | 601 | 602 | void linux_read_enter(CPUState *cpu, target_ulong pc, uint32_t fd, uint32_t buf, uint32_t count) { 603 | linux_sys_read(cpu, pc, fd, buf, count, ENTER); 604 | return; 605 | } 606 | 607 | void linux_read_return(CPUState *cpu, target_ulong pc, uint32_t fd, uint32_t buf, uint32_t count) { 608 | linux_sys_read(cpu, pc, fd, buf, count, RETURN); 609 | return; 610 | } 611 | 612 | void linux_open_enter(CPUState *cpu, target_ulong pc, uint32_t filename, int32_t flags, int32_t mode) { 613 | return; 614 | } 615 | 616 | void linux_open_return(CPUState* cpu,target_ulong pc,uint32_t filename,int32_t flags,int32_t mode){ 617 | std::string the_filename = get_strncpy_buf(cpu, filename, MAX_FILENAME); 618 | std::cout << "Fileopen : " << the_filename << std::endl; 619 | 620 | int the_fd = get_syscall_retval(cpu); 621 | target_ulong the_asid = panda_current_asid(cpu); 622 | std::string opened_filename = the_filename; 623 | 624 | if(contain(opened_filename, taint_filename)){ 625 | fd_watched.push_back( {the_fd, the_asid} ); 626 | } 627 | 628 | return; 629 | } 630 | 631 | void linux_sys_readv(CPUState* cpu,target_ulong pc,uint32_t fd,uint32_t vec,uint32_t vlen, uint32_t cb_state){ 632 | 633 | if(cb_state == ENTER){ 634 | cb_taint(cpu, "sys_readv", fd, 0, 0, cb_state); 635 | }else if(cb_state == RETURN){ 636 | //update_procs_fdmap(cpu, fd); 637 | 638 | //this retval uses for range of taint. 639 | int readv_byte = get_syscall_retval(cpu); 640 | std::vector readv_buf = get_buf_dump(cpu, vec, vlen*(sizeof(struct iovec32))); 641 | 642 | struct iovec32 *iovec_info = new struct iovec32[vlen]; 643 | cast_to_struct(*iovec_info, readv_buf); 644 | 645 | uint32_t addr; 646 | uint32_t len; 647 | for(int i = 0; i0 && readv_byte>0){ 652 | cb_taint(cpu, "sys_readv", fd, addr, readv_byte, cb_state); 653 | } 654 | } 655 | monitor_resource_access(cpu, "sys_read", fd, readv_byte); 656 | } 657 | } 658 | 659 | void linux_readv_enter(CPUState* cpu,target_ulong pc,uint32_t fd,uint32_t vec,uint32_t vlen){ 660 | linux_sys_readv(cpu, pc, fd, vec, vlen, ENTER); 661 | return; 662 | } 663 | 664 | void linux_readv_return(CPUState* cpu,target_ulong pc,uint32_t fd,uint32_t vec,uint32_t vlen){ 665 | linux_sys_readv(cpu, pc, fd, vec, vlen, RETURN); 666 | return; 667 | } 668 | 669 | 670 | void linux_sys_write(CPUState* cpu,target_ulong pc,uint32_t fd,uint32_t buf,uint32_t count, uint32_t cb_state){ 671 | if(cb_state == ENTER){ 672 | monitor_resource_access(cpu, "sys_write", fd, 0); 673 | cb_sys_tapped(cpu, "sys_write", fd, buf, count, cb_state); 674 | return; 675 | }else if(cb_state == RETURN){ 676 | cb_sys_tapped(cpu, "sys_write", -1, 0, 0, cb_state); 677 | return; 678 | } 679 | } 680 | 681 | void linux_write_enter(CPUState* cpu,target_ulong pc,uint32_t fd,uint32_t buf,uint32_t count){ 682 | linux_sys_write(cpu, pc, fd, buf, count, ENTER); 683 | return; 684 | } 685 | 686 | void linux_write_return(CPUState* cpu,target_ulong pc,uint32_t fd,uint32_t buf,uint32_t count){ 687 | linux_sys_write(cpu, pc, fd, buf, count, RETURN); 688 | return; 689 | } 690 | 691 | 692 | void linux_sys_writev(CPUState* cpu,target_ulong pc,uint32_t fd,uint32_t vec,uint32_t vlen, uint32_t cb_state){ 693 | struct iovec32 *iovec_info; 694 | uint32_t addr; 695 | uint32_t len; 696 | if(cb_state == ENTER){ 697 | monitor_resource_access(cpu, "sys_writev", fd, 0); 698 | std::vector writev_buf = get_buf_dump(cpu, vec, vlen*(sizeof(struct iovec32))); 699 | iovec_info = new struct iovec32[vlen]; 700 | cast_to_struct(*iovec_info, writev_buf); 701 | for(int i = 0; i sock_vec; 762 | struct sockaddr_in32 *sin_info; 763 | // uint32_t port; 764 | uint32_t ipaddr; 765 | struct in_addr inaddr; 766 | std::string ipaddr_str; 767 | 768 | sys_buf = buf_virtaddr_little_endianed(cpu, args+4, 4); 769 | sock_vec = get_buf_dump(cpu, sys_buf, sizeof(struct sockaddr_in32)); 770 | 771 | sin_info = new struct sockaddr_in32; 772 | cast_to_struct(*sin_info, sock_vec); 773 | // port = sin_info->sin_port.val; 774 | ipaddr = sin_info->sin_addr.val; 775 | inaddr.s_addr = ipaddr; 776 | ipaddr_str = std::string(inet_ntoa(inaddr)); 777 | // std::cout << "sys_conn ip: " << std::string(inet_ntoa(inaddr)) << std::endl; 778 | // std::cout << "sys_conn port: " << ntohs(port) << std::endl; 779 | } 780 | } 781 | 782 | void sys_send(CPUState* cpu, int32_t call, uint32_t args, uint32_t cb_state){ 783 | // std::cout << "sys_send " << std::endl; 784 | uint32_t sys_buf; 785 | sys_buf = buf_virtaddr_little_endianed(cpu, args+4, 4); 786 | // std::cout << std::hex << sys_buf << std::endl; 787 | // std::cout << "sys_buf: "; 788 | buf_dump_panda_virtaddr(cpu, sys_buf, 30, false); 789 | // std::cout << std::endl; 790 | } 791 | 792 | 793 | void cb_sys_tapped(CPUState* cpu, std::string tapped_syscall, int fd, uint32_t buf, uint32_t len, uint32_t cb_state){ 794 | 795 | static std::map tapped_rr_count_mp; 796 | static std::map> tapped_bufvec_mp; 797 | 798 | if(cb_state == ENTER){ 799 | bool labeled = is_tapped_buf_labeled(cpu, buf, len, fd, tapped_syscall); 800 | if(labeled){ 801 | tapped_rr_count_mp[tapped_syscall] = rr_get_guest_instr_count(); 802 | std::string buf_data = get_buf_printable(cpu, buf, len, true); 803 | tapped_bufvec_mp[tapped_syscall].push_back(buf_data); 804 | } 805 | }else if(cb_state == RETURN){ 806 | uint64_t rr_count_at_tapped = tapped_rr_count_mp[tapped_syscall]; 807 | for(std::string data : tapped_bufvec_mp[tapped_syscall]){ 808 | //writevなどで複数に分けてパケットに書き込まれることもあると想定 809 | //checking if data matched or not. 810 | //mss is 1460 811 | if(((data.size())/2<=1460 and tx_packet_payload==data) or \ 812 | ((data.size())/2 > 1460 and contain(data, tx_packet_payload))){ 813 | // std::cout << "Matched data with new_cb exfiltration " << tapped_syscall << std::endl; 814 | transfered_data_info[rr_count_at_tapped] = tx_last_tcp_conn; 815 | } 816 | } 817 | //re-initialization 818 | rr_count_at_tapped = 0; 819 | tapped_bufvec_mp[tapped_syscall].clear(); 820 | tapped_bufvec_mp[tapped_syscall].shrink_to_fit(); 821 | } 822 | return; 823 | } 824 | 825 | 826 | void sys_sendto(CPUState* cpu, int32_t call, uint32_t args, uint32_t cb_state){ 827 | uint32_t sys_buf; 828 | uint32_t sys_len; 829 | uint32_t sys_fd; 830 | 831 | sys_fd = buf_virtaddr_little_endianed(cpu, args, 4); 832 | sys_buf = buf_virtaddr_little_endianed(cpu, args+4, 4); 833 | sys_len = buf_virtaddr_little_endianed(cpu, args+8, 4); 834 | //update_procs_fdmap(cpu, sys_fd); 835 | 836 | if(cb_state == ENTER){ 837 | 838 | monitor_resource_access(cpu, "sys_sendto", sys_fd, sys_len); 839 | 840 | cb_sys_tapped(cpu, "sys_sendto", sys_fd, sys_buf, sys_len, cb_state); 841 | return; 842 | }else if(cb_state == RETURN){ 843 | cb_sys_tapped(cpu, "sys_sendto", -1, 0, 0, cb_state); 844 | return; 845 | } 846 | } 847 | 848 | 849 | void sys_recv(CPUState* cpu, int32_t call, uint32_t args, uint32_t cb_state){ 850 | uint32_t sys_buf; 851 | uint32_t sys_len; 852 | if(cb_state == ENTER){ 853 | sys_buf = buf_virtaddr_little_endianed(cpu, args+4, 4); 854 | sys_len = buf_virtaddr_little_endianed(cpu, args+8, 4); 855 | // std::cout << "recv_buf: "; 856 | buf_dump_panda_virtaddr(cpu, sys_buf, sys_len, false); 857 | return; 858 | }else if(cb_state == RETURN){ 859 | return; 860 | } 861 | } 862 | 863 | void sys_recvmsg(CPUState* cpu, int32_t call, uint32_t args, uint32_t cb_state){ 864 | } 865 | 866 | void linux_socketcall_enter(CPUState* cpu,target_ulong pc,int32_t call,uint32_t args){ 867 | //std::cout << "socketcall_func_enter: " << sys_sockcall_name[call] << std::endl; 868 | if(sockcalls[call] != NULL) 869 | sockcalls[call](cpu, call, args, ENTER); 870 | } 871 | 872 | void linux_socketcall_return(CPUState* cpu,target_ulong pc,int32_t call,uint32_t args){ 873 | //std::cout << "socketcall_func_return: " << sys_sockcall_name[call] << std::endl; 874 | if(sockcalls[call] != NULL) 875 | sockcalls[call](cpu, call, args, RETURN); 876 | } 877 | 878 | 879 | void linux_fork_enter(CPUState* cpu,target_ulong pc){ 880 | // std::cout << "linux_fork_enter" << std::endl; 881 | } 882 | 883 | void linux_fork_return(CPUState* cpu,target_ulong pc){ 884 | // uint32_t newpid = get_syscall_retval(cpu); 885 | // std::cout << "linux_fork pid: " << std::dec << newpid << " current-cmd:" << get_current_command(cpu) << std::endl; 886 | } 887 | 888 | void taint_change(Addr addr, uint64_t size){ 889 | 890 | CPUState* cpu = first_cpu; 891 | if(panda_in_kernel(cpu)) return; 892 | Tainted_cmd command; 893 | command.cmd = get_current_command(cpu); 894 | command.parent_cmds = get_current_parent_command(cpu); 895 | command.asid = panda_current_asid(cpu); 896 | command.rr_count = rr_get_guest_instr_count(); 897 | 898 | get_current_mod(cpu, 0); 899 | std::set taint_changed_labels; 900 | taint2_labelset_addr_iter(addr, app_getlabels, &taint_changed_labels); 901 | 902 | tainted_commands.insert(command); 903 | 904 | Tainted_instr ti; 905 | ti.pc = panda_current_pc(cpu); 906 | ti.asid = panda_current_asid(cpu); 907 | ti.rr_count = rr_get_guest_instr_count(); 908 | ti.labels = taint_changed_labels; 909 | tainted_instrs.push_back(ti); 910 | 911 | for(uint32_t x : taint_changed_labels){ 912 | taint_label_info[x].propagate_count += 1; 913 | } 914 | 915 | /////////// 916 | //function call checking!! 917 | uint64_t cur_rr_count = rr_get_guest_instr_count(); 918 | if(check_funcall){ 919 | // only if in 'userland' and in 'watched_cmd' 920 | //if(is_in_watched_cmd(cpu) and !panda_in_kernel(cpu)){ 921 | // 922 | //but, std::set is not duplicable, and call_stack is userland-only stacked container, so, i think need not to care about ring0 or ring3... 923 | //if(is_in_watched_cmd(cpu)){ 924 | if(is_in_watched_cmd(cpu) and !panda_in_kernel(cpu)){ 925 | if(!call_stack.empty()){ 926 | taint_funcs.insert( call_stack.top() ); 927 | 928 | if(cur_rr_count > 0 and cur_rr_count <= check_funcall_rr){ 929 | taint_funcs_rr_limited.insert( call_stack.top() ); 930 | } 931 | 932 | }else{ 933 | taint_funcs.insert( "" ); 934 | } 935 | } 936 | } 937 | /////////// 938 | 939 | 940 | return; 941 | } 942 | 943 | void linux_fchmodat_enter(CPUState* cpu,target_ulong pc,int32_t dfd,uint32_t filename,uint32_t mode){ 944 | return; 945 | } 946 | 947 | void linux_fchmodat_return(CPUState* cpu,target_ulong pc,int32_t dfd,uint32_t filename,uint32_t mode){ 948 | std::string the_filename = get_strncpy_buf(cpu, filename, MAX_FILENAME); 949 | // std::cout << "fchmodat_return: " << the_filename << " mode: " << std::oct << mode << " cmd:"; 950 | // std::cout << std::dec; 951 | for(auto x : get_current_parent_command(cpu)) 952 | // std::cout << x << " "; 953 | // std::cout << std::endl; 954 | return; 955 | } 956 | 957 | void linux_unlinkat_enter(CPUState* cpu,target_ulong pc,int32_t dfd,uint32_t pathname,int32_t flag){ 958 | std::string the_filename = get_strncpy_buf(cpu, pathname, MAX_FILENAME); 959 | // std::cout << "unlinkat_enter: " << the_filename << " : flag: " << std::dec << flag << " cmd:" ; 960 | for(auto x : get_current_parent_command(cpu)){ 961 | // std::cout << x << " "; 962 | } 963 | // std::cout << std::endl; 964 | } 965 | 966 | 967 | 968 | 969 | void linux_mkdir_enter(CPUState* cpu,target_ulong pc,uint32_t pathname,int32_t mode){ 970 | std::string dirname = get_strncpy_buf(cpu, pathname, MAX_FILENAME); 971 | // std::cout << "mkdir_enter: " << dirname << std::endl; 972 | 973 | std::pair< target_ulong, std::string > os_cmd = std::make_pair( panda_current_asid(cpu), get_current_command(cpu) ); 974 | 975 | cmd_resource_mp[os_cmd].insert(dirname); 976 | 977 | } 978 | 979 | 980 | 981 | 982 | int osi_process_introspection(CPUState *cpu, TranslationBlock *tb) { 983 | if(tb){ 984 | cur_tb_size = tb->size; 985 | cur_tb_pc = tb->pc; 986 | } 987 | 988 | // std::string hoge = get_disas_pc(cpu, cur_tb_pc, cur_tb_pc, cur_tb_size); 989 | // std::cout << hoge << std::endl; 990 | // if(!panda_in_kernel(cpu)){ 991 | // last_user_pc = panda_current_pc(cpu); 992 | // } 993 | 994 | if(panda_in_kernel(cpu)){ 995 | OsiProc *p = get_current_process(cpu); 996 | target_ulong asid = panda_current_asid(cpu); 997 | //sanity check on what we think the current process is 998 | if(p->offset==0) return 0; 999 | //or the name 1000 | if(p->name==0) return 0; 1001 | if(((int) p->pid) == -1) return 0; 1002 | uint32_t n = strnlen(p->name, 32); 1003 | if(n<2) return 0; 1004 | uint32_t np = 0; 1005 | for(uint32_t i=0; iname[i]) != 0); 1007 | } 1008 | if(np != n) return 0; 1009 | ///////// 1010 | if(asid_just_changed && check_proc_ok(p)){ 1011 | running_procs[asid] = *p; 1012 | } 1013 | if(asid_just_changed && check_proc_ok(proc_at_pgd)){ 1014 | p = proc_at_pgd; 1015 | asid = asid_at_pgd; 1016 | asid_just_changed = false; 1017 | running_procs[asid] = *p; 1018 | }else if( check_proc_ok(p) ){ 1019 | running_procs[asid] = *p; 1020 | }else{ 1021 | //if not check_proc_ok(p) 1022 | return 0; 1023 | } 1024 | asid_just_changed = false; 1025 | ///////// 1026 | } 1027 | return 0; 1028 | } 1029 | 1030 | 1031 | int vmi_pgd_changed(CPUState *cpu, target_ulong old_pgd, target_ulong new_pgd) { 1032 | proc_at_pgd = get_current_process(cpu); 1033 | if(proc_at_pgd->asid == 0){ 1034 | return 0; 1035 | } 1036 | asid_just_changed = true; 1037 | // old_pgd is same with panda_current_asid(cpu), 1038 | // and new_pgd is asid just now changed. 1039 | // so, old_pgd is same with panda_current_process's asid. 1040 | //この時のold_pgd(つまりpanda_current_asid)は、まさにそのOsiProcを指している 1041 | asid_at_pgd = old_pgd; 1042 | return osi_process_introspection(cpu, NULL); 1043 | } 1044 | 1045 | 1046 | int handle_packet(CPUState *cpu, uint8_t *buf, int size, uint8_t direction, uint64_t old_buf_addr){ 1047 | 1048 | struct iphdr* pkt_iphdr; 1049 | struct tcphdr* pkt_tcphdr; 1050 | struct in_addr inaddr; 1051 | std::string src_addr; 1052 | std::string dst_addr; 1053 | std::string src_port; 1054 | std::string dst_port; 1055 | 1056 | pkt_iphdr = (struct iphdr*)(buf+sizeof(struct ether_header)); 1057 | inaddr.s_addr = pkt_iphdr->saddr; 1058 | src_addr = std::string(inet_ntoa(inaddr)); 1059 | inaddr.s_addr = pkt_iphdr->daddr; 1060 | dst_addr = std::string(inet_ntoa(inaddr)); 1061 | 1062 | pkt_tcphdr = (struct tcphdr*)(buf+sizeof(struct ether_header)+sizeof(struct iphdr)); 1063 | src_port = std::to_string(ntohs(pkt_tcphdr->source)); 1064 | dst_port = std::to_string(ntohs(pkt_tcphdr->dest)); 1065 | 1066 | uint8_t *data = buf+sizeof(struct ether_header)+sizeof(struct iphdr) + (pkt_tcphdr->doff)*4; 1067 | int data_size = size-(sizeof(struct ether_header)+sizeof(struct iphdr)+(pkt_tcphdr->doff)*4); 1068 | 1069 | std::string payload; 1070 | for(int i = 0; isize; 1095 | //// cur_tb_pc = tb->pc; 1096 | // return 1; 1097 | //} 1098 | 1099 | 1100 | enum instr_type { 1101 | INSTR_UNKNOWN = 0, 1102 | INSTR_CALL, 1103 | INSTR_RET, 1104 | INSTR_SYSCALL, 1105 | INSTR_SYSRET, 1106 | INSTR_SYSENTER, 1107 | INSTR_SYSEXIT, 1108 | INSTR_INT, 1109 | INSTR_IRET, 1110 | }; 1111 | 1112 | struct instr_detail{ 1113 | instr_type type; 1114 | std::string opcode; 1115 | }; 1116 | 1117 | //std::map call_cache; 1118 | std::map call_cache; 1119 | csh cs_handle_32_2; 1120 | csh cs_handle_64_2; 1121 | //procname and stacks 1122 | //instr_type disas_after_block_translate(CPUArchState* env, target_ulong pc, int size) { 1123 | instr_detail disas_after_block_translate(CPUArchState* env, target_ulong pc, int size) { 1124 | unsigned char *buf = (unsigned char *) malloc(size); 1125 | int err = panda_virtual_memory_rw(ENV_GET_CPU(env), pc, buf, size, 0); 1126 | if (err == -1) printf("Couldn't read TB memory!\n"); 1127 | //instr_type res = INSTR_UNKNOWN; 1128 | instr_detail res = {INSTR_UNKNOWN, ISNULL}; 1129 | #if defined(TARGET_I386) 1130 | csh handle = (env->hflags & HF_LMA_MASK) ? cs_handle_64_2 : cs_handle_32_2; 1131 | #elif defined(TARGET_ARM) 1132 | csh handle = cs_handle_32_2; 1133 | if (env->thumb){ 1134 | cs_option(handle, CS_OPT_MODE, CS_MODE_THUMB); 1135 | } 1136 | else { 1137 | cs_option(handle, CS_OPT_MODE, CS_MODE_ARM); 1138 | } 1139 | //#elif defined(TARGET_PPC) 1140 | // csh handle = cs_handle_32_2; 1141 | #endif 1142 | cs_insn *insn; 1143 | cs_insn *end; 1144 | size_t count = cs_disasm(handle, buf, size, pc, 0, &insn); 1145 | if (count <= 0) goto done2; 1146 | for (end = insn + count - 1; end >= insn; end--) { 1147 | if (!cs_insn_group(handle, end, CS_GRP_INVALID)) { 1148 | break; 1149 | } 1150 | } 1151 | if (end < insn) goto done; 1152 | if (cs_insn_group(handle, end, CS_GRP_CALL)) { 1153 | std::string mnem = end->mnemonic; 1154 | std::string op = end->op_str; 1155 | std::string space = " "; 1156 | std::string disas_instr = mnem + space + op; 1157 | //res = INSTR_CALL; 1158 | res = instr_detail{ INSTR_CALL, disas_instr}; 1159 | } else if (cs_insn_group(handle, end, CS_GRP_RET)) { 1160 | std::string mnem = end->mnemonic; 1161 | std::string op = end->op_str; 1162 | std::string space = " "; 1163 | std::string disas_instr = mnem + space + op; 1164 | // res = INSTR_RET; 1165 | res = instr_detail{ INSTR_RET, disas_instr}; 1166 | } else { 1167 | // res = INSTR_UNKNOWN; 1168 | res = instr_detail{ INSTR_UNKNOWN, ISNULL}; 1169 | } 1170 | done: 1171 | cs_free(insn, count); 1172 | done2: 1173 | free(buf); 1174 | return res; 1175 | } 1176 | 1177 | //std::map< std::string , std::stack > call_stack; 1178 | //defined in "my_helper.h" 1179 | //std::stack call_stack; 1180 | bool just_called_func = false; 1181 | int after_block_translate(CPUState *cpu, TranslationBlock *tb) { 1182 | 1183 | 1184 | if(check_funcall){ 1185 | 1186 | if(just_called_func and (is_in_watched_cmd(cpu) and !panda_in_kernel(cpu) )){ 1187 | //if(just_called_func and is_in_watched_cmd(cpu)){ 1188 | func_addrs.insert( tb->pc ); 1189 | just_called_func = false; 1190 | } 1191 | 1192 | 1193 | CPUArchState* env = (CPUArchState*)cpu->env_ptr; 1194 | instr_detail insd = disas_after_block_translate(env, tb->pc, tb->size); 1195 | std::string command = get_current_command(cpu); 1196 | //if(is_in_watched_cmd(cpu)){ 1197 | // only if in 'userland' and in 'watched_cmd' 1198 | if(is_in_watched_cmd(cpu) and !panda_in_kernel(cpu)){ 1199 | if(insd.type == INSTR_CALL){ 1200 | call_stack.push( insd.opcode ); 1201 | watched_cmd_funcs.insert( insd.opcode ); 1202 | 1203 | // for getting address. 1204 | just_called_func = true; 1205 | 1206 | }else if(insd.type == INSTR_RET){ 1207 | 1208 | // for getting address. 1209 | just_called_func = false; 1210 | 1211 | 1212 | if(!call_stack.empty()){ 1213 | call_stack.pop(); 1214 | } 1215 | } 1216 | } 1217 | } 1218 | 1219 | 1220 | 1221 | 1222 | return 1; 1223 | } 1224 | 1225 | /* 1226 | int after_block_exec(CPUState *env, TranslationBlock *tb){ 1227 | cur_tb_size = tb->size; 1228 | cur_tb_pc = tb->pc; 1229 | return 0; 1230 | } 1231 | */ 1232 | 1233 | 1234 | int cb_virt_mem_after_read(CPUState *cpu, target_ulong pc, target_ulong addr, target_ulong size, void *buf) 1235 | { 1236 | // if(is_in_watched_cmd(cpu)){ 1237 | //// std::cout << "cb_virtmem_read: "; 1238 | //// buf_dump_panda_virtaddr(cpu, addr, 32, true); 1239 | //// //std::cout << size << std::endl; 1240 | //// std::cout << "0x" << std::hex << buf << " 0x" << std::hex << addr << std::endl; 1241 | // } 1242 | return 0; 1243 | } 1244 | 1245 | 1246 | int cb_virt_mem_after_write(CPUState *cpu, target_ulong pc, target_ulong addr, target_ulong size, void *buf) 1247 | { 1248 | // if(is_in_watched_cmd(cpu)){ 1249 | //// std::cout << "cb_virtmem_write: "; 1250 | //// buf_dump_panda_virtaddr(cpu, addr, 32, true); 1251 | //// std::cout << "0x" << std::hex << buf << " 0x" << std::hex << addr << std::endl; 1252 | // } 1253 | return 0; 1254 | } 1255 | 1256 | 1257 | //std::set< std::pair > recorded_stacks; 1258 | //// Check if the instruction is sysenter (0F 34) 1259 | //bool insn_translate(CPUState *cpu, target_ulong pc) { 1260 | //// std::cout << "insn_cur_func: " << get_current_command(cpu) << std::endl;; 1261 | // std::string command = get_current_command(cpu) ; 1262 | // CPUArchState *env = (CPUArchState*)cpu->env_ptr; 1263 | // target_ulong ebp = env->regs[R_EBP]; 1264 | // if(!panda_in_kernel(cpu)){ 1265 | //// std::cout << "insn_cur: " << command << " " << std::hex << "ebp: 0x" << ebp << " :asid: " << panda_current_asid(cpu) << std::endl; 1266 | // } 1267 | // 1268 | // recorded_stacks.insert( std::make_pair(command, ebp) ); 1269 | // 1270 | // return true; 1271 | //} 1272 | 1273 | #endif 1274 | 1275 | bool init_plugin(void *self) { 1276 | 1277 | #ifdef TARGET_I386 1278 | 1279 | panda_cb pcb; 1280 | pcb.before_block_exec = osi_process_introspection; 1281 | panda_register_callback(self, PANDA_CB_BEFORE_BLOCK_EXEC, pcb); 1282 | 1283 | //pcb.after_block_exec = after_block_exec; 1284 | //panda_register_callback(self, PANDA_CB_AFTER_BLOCK_EXEC, pcb); 1285 | 1286 | // pcb.virt_mem_after_read = cb_virt_mem_after_read; 1287 | // panda_register_callback(self, PANDA_CB_VIRT_MEM_AFTER_READ, pcb); 1288 | // pcb.virt_mem_after_write = cb_virt_mem_after_write; 1289 | // panda_register_callback(self, PANDA_CB_VIRT_MEM_AFTER_WRITE, pcb); 1290 | // /// 1291 | 1292 | pcb.asid_changed = vmi_pgd_changed; 1293 | panda_register_callback(self, PANDA_CB_ASID_CHANGED, pcb); 1294 | 1295 | pcb.replay_handle_packet = handle_packet; 1296 | panda_register_callback(self, PANDA_CB_REPLAY_HANDLE_PACKET, pcb); 1297 | 1298 | ///////// 1299 | #if defined(TARGET_I386) 1300 | if (cs_open(CS_ARCH_X86, CS_MODE_32, &cs_handle_32_2) != CS_ERR_OK) 1301 | #if defined(TARGET_X86_64) 1302 | if (cs_open(CS_ARCH_X86, CS_MODE_64, &cs_handle_64_2) != CS_ERR_OK) 1303 | #endif 1304 | #elif defined(TARGET_ARM) 1305 | if (cs_open(CS_ARCH_ARM, CS_MODE_ARM, &cs_handle_32_2) != CS_ERR_OK) 1306 | #elif defined(TARGET_PPC) 1307 | if (cs_open(CS_ARCH_PPC, CS_MODE_32, &cs_handle_32_2) != CS_ERR_OK) 1308 | #endif 1309 | return false; 1310 | 1311 | // Need details in capstone to have instruction groupings 1312 | cs_option(cs_handle_32_2, CS_OPT_DETAIL, CS_OPT_ON); 1313 | #if defined(TARGET_X86_64) 1314 | cs_option(cs_handle_64_2, CS_OPT_DETAIL, CS_OPT_ON); 1315 | #endif 1316 | 1317 | // pcb.insn_translate = insn_translate; 1318 | // panda_register_callback(self, PANDA_CB_INSN_TRANSLATE, pcb); 1319 | pcb.after_block_translate = after_block_translate; 1320 | panda_register_callback(self, PANDA_CB_AFTER_BLOCK_TRANSLATE, pcb); 1321 | ///////// 1322 | 1323 | 1324 | //args = panda_get_args("my_network_exploit"); 1325 | args = panda_get_args("spaniel"); 1326 | debug = panda_parse_bool_opt(args, "debug", "Print debug message"); 1327 | no_taint = panda_parse_bool_opt(args, "notaint", "don't actually taint anything"); 1328 | file_taint = panda_parse_bool_opt(args, "file_taint", "Let's taint opened file."); 1329 | all_file_taint = panda_parse_bool_opt(args, "all_file_taint", "taint every opened file"); 1330 | all_read_taint = panda_parse_bool_opt(args, "all_taint", "Taint every read data, buffer."); 1331 | 1332 | rx_taint = panda_parse_bool_opt(args, "rx_taint", "Taint watched_process's incoming traffic"); 1333 | 1334 | no_positional_labels = panda_parse_bool_opt(args, "nonpos", "use positional labels"); 1335 | no_char = panda_parse_bool_opt(args, "nonchar", "don't use printable character for output, but use hex format"); 1336 | 1337 | taint_filename = panda_parse_string_opt(args, "filename", "abc123", "filename to taint"); 1338 | watched_fd_num = panda_parse_ulong(args, "watched_fd", -1 ); 1339 | 1340 | watched_cmd = panda_parse_string_opt(args, "watched_cmd", "abc123", "command name to inspect"); 1341 | 1342 | 1343 | //last_tainted_rr = panda_parse_uint64_opt(args, "last_tainted_rr", 0, "check tainted instructions until this instruction, just for debugging"); 1344 | last_tainted_rr = panda_parse_uint64_opt(args, "last_tainted_rr", 10000000, "check tainted instructions until this instruction, just for debugging"); 1345 | 1346 | 1347 | check_funcall = panda_parse_bool_opt(args, "check_funcall", "check and recorrd current Function-name."); 1348 | //check_funcall_rr = panda_parse_bool_opt(args, "check_funcall_rr", "check_funcall based on last rr."); 1349 | check_funcall_rr = panda_parse_uint64_opt(args, "check_funcall_rr", 0, "For check_funcall, rr_instr count."); 1350 | 1351 | 1352 | init_syscall_mp(); 1353 | 1354 | panda_require("taint2"); 1355 | assert(init_taint2_api()); 1356 | 1357 | //before_block_exec requires precise_pc for panda_current_asid(note in: taint2.cpp 1358 | panda_enable_precise_pc(); 1359 | 1360 | if(!init_osi_api()) return false; 1361 | if (panda_os_type == OST_LINUX) { 1362 | panda_require("osi_linux"); 1363 | assert(init_osi_linux_api()); 1364 | 1365 | PPP_REG_CB("syscalls2", on_sys_open_enter, linux_open_enter); 1366 | PPP_REG_CB("syscalls2", on_sys_open_return, linux_open_return); 1367 | 1368 | PPP_REG_CB("syscalls2", on_sys_read_enter, linux_read_enter); 1369 | PPP_REG_CB("syscalls2", on_sys_read_return, linux_read_return); 1370 | 1371 | PPP_REG_CB("syscalls2", on_sys_readv_enter, linux_readv_enter); 1372 | PPP_REG_CB("syscalls2", on_sys_readv_return, linux_readv_return); 1373 | 1374 | PPP_REG_CB("syscalls2", on_sys_write_enter, linux_write_enter); 1375 | PPP_REG_CB("syscalls2", on_sys_write_return, linux_write_return); 1376 | 1377 | PPP_REG_CB("syscalls2", on_sys_writev_enter, linux_writev_enter); 1378 | PPP_REG_CB("syscalls2", on_sys_writev_return, linux_writev_return); 1379 | 1380 | PPP_REG_CB("syscalls2", on_all_sys_enter, linux_all_sys_enter); 1381 | PPP_REG_CB("syscalls2", on_all_sys_return, linux_all_sys_return); 1382 | 1383 | PPP_REG_CB("syscalls2", on_sys_stat64_enter, linux_stat64_enter); 1384 | PPP_REG_CB("syscalls2", on_sys_stat64_return, linux_stat64_return); 1385 | 1386 | PPP_REG_CB("syscalls2", on_sys_execve_enter, linux_execve_enter); 1387 | PPP_REG_CB("syscalls2", on_sys_execve_return, linux_execve_return); 1388 | 1389 | PPP_REG_CB("syscalls2", on_sys_socketcall_enter, linux_socketcall_enter); 1390 | PPP_REG_CB("syscalls2", on_sys_socketcall_return, linux_socketcall_return); 1391 | 1392 | PPP_REG_CB("syscalls2", on_sys_fork_enter, linux_fork_enter); 1393 | PPP_REG_CB("syscalls2", on_sys_fork_return, linux_fork_return); 1394 | 1395 | PPP_REG_CB("syscalls2", on_sys_fchmodat_enter, linux_fchmodat_enter); 1396 | PPP_REG_CB("syscalls2", on_sys_fchmodat_return, linux_fchmodat_return); 1397 | 1398 | //for detecting rm command 1399 | PPP_REG_CB("syscalls2", on_sys_unlinkat_enter, linux_unlinkat_enter); 1400 | 1401 | //for detecting mkdir command 1402 | PPP_REG_CB("syscalls2", on_sys_mkdir_enter, linux_mkdir_enter); 1403 | 1404 | std::memset(sockcalls, 0, sizeof(sockcalls)); 1405 | sockcalls[SYS_CONNECT] = sys_connect; 1406 | sockcalls[SYS_SEND] = sys_send; 1407 | sockcalls[SYS_SENDTO] = sys_sendto; 1408 | sockcalls[SYS_RECV] = sys_recv; 1409 | sockcalls[SYS_RECVMSG] = sys_recvmsg; 1410 | 1411 | //setting for taint analysis 1412 | PPP_REG_CB("taint2", on_taint_change, taint_change); 1413 | taint2_track_taint_state(); 1414 | } 1415 | #endif 1416 | return true; 1417 | } 1418 | 1419 | void uninit_plugin(void *self) { 1420 | 1421 | std::vector graph_edges; 1422 | 1423 | std::cout << "=============" << std::endl; 1424 | std::cout << "taint_in:" << std::endl; 1425 | for(auto x : taint_label_info){ 1426 | 1427 | ////TaingGraph 1428 | //nodes when tainting are started: src syscall, src resource, src command 1429 | graph_edges.push_back(Edge(Node(SYSCALL, x.second.syscall), Node(BUF, "Tainted Buffer"))); 1430 | graph_edges.push_back(Edge(Node(SYSCALL, x.second.syscall), Node(TAINT_SRC, x.second.resource))); 1431 | graph_edges.push_back(Edge(Node(PROC, "cmd:"+x.second.cmd), Node(SYSCALL, x.second.syscall))); 1432 | 1433 | std::cout << "\tlabel-" << std::dec << x.first << std::endl; 1434 | std::cout << "\t\ttainted_resource: " << x.second.resource << std::endl; 1435 | std::cout << "\t\tsyscall: " << x.second.syscall << std::endl; 1436 | std::cout << "\t\t\trr_instr: " << std::dec << x.second.rr_count << std::endl; 1437 | std::cout << "\t\t\tsize: " << std::dec << x.second.range_size << std::endl; 1438 | std::cout << "\t\tcmd: " << x.second.cmd << std::endl; 1439 | for(auto y : x.second.parent_cmds){ 1440 | std::cout << "\t\t\tparent_cmd: " << y << std::endl; 1441 | 1442 | ////TaingGraph 1443 | //parent's 1444 | graph_edges.push_back(Edge(Node(PROC, "cmd:"+y), Node(PROC, "cmd:"+x.second.cmd))); 1445 | 1446 | } 1447 | 1448 | // std::cout << std::endl; 1449 | } 1450 | 1451 | std::cout << "=============" << std::endl; 1452 | for(auto x : taint_outs){ 1453 | std::cout << "taint_out: " << std::endl; 1454 | std::cout << "\tcmd: " << x.cmd << std::endl; 1455 | for(auto y : x.parent_cmds) 1456 | std::cout << "\t\t\tparent_cmd: " << y << std::endl; 1457 | 1458 | std::cout << "\tsyscall: " << x.syscall << std::endl; 1459 | std::cout << "\t\trr_instr: " << std::dec << x.rr_count << std::endl; 1460 | std::cout << "\t\tresource: " << x.resource << std::endl; 1461 | if(transfered_data_info.count(x.rr_count) > 0){ 1462 | std::cout << "\t\t\tcandidate_dst_host: " << transfered_data_info[x.rr_count] << std::endl; 1463 | } 1464 | if(debug){ 1465 | std::cout << "\t\tbuf: size:" << x.buf.size() << " "; 1466 | for(int data : x.buf){ 1467 | if(no_char){ 1468 | printf("%02x ", data); 1469 | }else{ 1470 | if(isprint(data)) 1471 | printf("%c", (char)data); 1472 | else 1473 | printf("."); 1474 | } 1475 | } 1476 | std::cout << std::endl; 1477 | } 1478 | 1479 | ////TaingGraph 1480 | //nodes when tainted data are out: dst command, dst syscall, dst resource(file,ipaddress) are checked 1481 | graph_edges.push_back(Edge(Node(BUF, "Tainted Buffer"), Node(PROC, "cmd:"+x.cmd))); 1482 | graph_edges.push_back(Edge(Node(PROC, "cmd:"+x.cmd), Node(SYSCALL, x.syscall))); 1483 | if(contain(x.resource, ISNULL)){ 1484 | graph_edges.push_back(Edge(Node(SYSCALL, x.syscall), Node(TAINT_DST, "[fd]"+std::to_string(x.fd)))); 1485 | }else{ 1486 | graph_edges.push_back(Edge(Node(SYSCALL, x.syscall), Node(TAINT_DST, x.resource))); 1487 | } 1488 | if(transfered_data_info[x.rr_count].size()>0){ 1489 | graph_edges.push_back(Edge(Node(SYSCALL, x.syscall), Node(NET_TX, "[tcp]"+transfered_data_info[x.rr_count]))); 1490 | } 1491 | //////////// 1492 | 1493 | for(uint32_t y : x.ls){ 1494 | std::cout << "\t\t\tlabel-" << y << ", " << taint_label_info[y].resource << " "; 1495 | std::cout << "compute:" << std::dec << taint_label_info[y].propagate_count << std::endl; 1496 | } 1497 | } 1498 | 1499 | 1500 | ///////////////////// 1501 | std::set tainted_mods; 1502 | for(auto p : tainted_instrs){ 1503 | if(p.rr_count <= last_tainted_rr){ 1504 | std::string modname = procs_pc_module_mp[p.asid][p.pc].second; 1505 | if(modname.size()>0){ 1506 | tainted_mods.insert(modname); 1507 | } 1508 | } 1509 | } 1510 | if(tainted_mods.size()>0){ 1511 | // std::cout << "\tmodule: " << std::endl; 1512 | for(auto modname : tainted_mods){ 1513 | // std::cout << "\t\t" << modname << std::endl; 1514 | } 1515 | } 1516 | ///////////////////// 1517 | 1518 | // std::cout << "===Resource Access===" << std::endl; 1519 | // for(auto x : resource_touched){ 1520 | // std::cout << x.first << std::endl; 1521 | // for(auto info : x.second){ 1522 | // std::cout << "\t" << info.resource_name << " size:" << info.size << " " << std::dec << info.rr_count << " ,"; 1523 | // std::cout << "\tcmd:" << info.cmd << " "; 1524 | // std::cout << std::endl; 1525 | // } 1526 | // } 1527 | 1528 | 1529 | // std::cout << "===Network outgoing host list===" << std::endl; 1530 | for(auto x : tx_remote_hosts){ 1531 | // std::cout << x << std::endl; 1532 | } 1533 | 1534 | 1535 | // std::cout << "=====================" << std::endl; 1536 | for(auto x : tainted_commands){ 1537 | if(x.rr_count <= last_tainted_rr){ 1538 | 1539 | std::set cmd_resource = cmd_resource_mp[ std::make_pair(x.asid, x.cmd)]; 1540 | if(cmd_resource.size() > 0){ 1541 | graph_edges.push_back(Edge(Node(BUF, "Tainted Buffer"), Node(PROC, x.cmd))); 1542 | for(auto y : cmd_resource){ 1543 | graph_edges.push_back(Edge(Node(PROC, x.cmd), Node(OS_OBJECT, y))); 1544 | } 1545 | } 1546 | 1547 | 1548 | // std::cout << "cmds: " << x.cmd << std::endl; 1549 | for(auto parent : x.parent_cmds){ 1550 | // std::cout << "\tparent:" << parent << std::endl; 1551 | } 1552 | } 1553 | } 1554 | 1555 | std::cout << "====" << std::endl; 1556 | 1557 | std::cout << "++++++++++++++++++++++" << std::endl; 1558 | 1559 | ////TaingGraph 1560 | for(auto p : tainted_instrs){ 1561 | if(p.rr_count <= last_tainted_rr){ 1562 | std::string modname = procs_pc_module_mp[p.asid][p.pc].second; 1563 | if(modname.size()>0){ 1564 | graph_edges.push_back(Edge(Node(BUF, "Tainted Buffer"), Node(MODULE, modname))); 1565 | } 1566 | } 1567 | } 1568 | gen_graph_dot(graph_edges); 1569 | //////////// 1570 | 1571 | 1572 | // std::cout << "===============" << std::endl; 1573 | // std::cout << "===============" << std::endl; 1574 | // for(auto x : taint_funcs) 1575 | // std::cout << "t:call: " << x << std::endl; 1576 | // for(auto x : watched_cmd_funcs) 1577 | // std::cout << "w:call: " << x << std::endl; 1578 | // std::cout << "===============" << std::endl; 1579 | // std::cout << "taint: " << taint_funcs.size() << std::endl;; 1580 | // std::cout << "watched: " << watched_cmd_funcs.size() << std::endl;; 1581 | // 1582 | // 1583 | // std::cout << "===============" << std::endl; 1584 | // for(auto x : taint_funcs_rr_limited) 1585 | // std::cout << "tl:call: " << x << std::endl; 1586 | // std::cout << "taint: " << taint_funcs_rr_limited.size() << std::endl;; 1587 | // 1588 | // 1589 | // 1590 | // std::cout << "===============" << std::endl; 1591 | // std::cout << "===============" << std::endl; 1592 | // for(auto x : func_addrs) 1593 | // std::cout << "addr: 0x" << std::hex << x << std::endl; 1594 | // std::cout << "cnt_addrs: " << std::dec << func_addrs.size() << std::endl;; 1595 | 1596 | } 1597 | -------------------------------------------------------------------------------- /spaniel/spaniel_helper.h: -------------------------------------------------------------------------------- 1 | #define __STDC_FORMAT_MACROS 2 | 3 | #include "panda/plugin.h" 4 | #include "panda/plugin_plugin.h" 5 | #include "osi/osi_types.h" 6 | #include "osi/osi_ext.h" 7 | #include "osi_linux/osi_linux_ext.h" 8 | #include "syscalls2/gen_syscalls_ext_typedefs.h" 9 | #include "taint2/taint2.h" 10 | #include "taint2/taint2_ext.h" 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #define PANDA_NET_RX 0 20 | #define PANDA_NET_TX 1 21 | 22 | 23 | #define ISNULL "Isnull" 24 | 25 | enum Sockcall{ 26 | PADDING = 0, 27 | SYS_SOCKET = 1, 28 | SYS_BIND = 2, 29 | SYS_CONNECT = 3, 30 | SYS_LISTEN = 4, 31 | SYS_ACCEPT = 5, 32 | SYS_GETSOCKNAME = 6, 33 | SYS_GETPEERNAME = 7, 34 | SYS_SOCKETPAIR = 8, 35 | SYS_SEND = 9, 36 | SYS_RECV = 10, 37 | SYS_SENDTO = 11, 38 | SYS_RECVFROM = 12, 39 | SYS_SHUTDOWN = 13, 40 | SYS_SETSOCKOPT = 14, 41 | SYS_GETSOCKOPT = 15, 42 | SYS_SENDMSG = 16, 43 | SYS_RECVMSG = 17, 44 | SYS_ACCEPT4 = 18, 45 | SYS_RECVMMSG = 19, 46 | SYS_SENDMMSG = 20, 47 | FUNC_TOTAL = 21, 48 | }; 49 | 50 | std::string sys_sockcall_name[]{ 51 | "padding", 52 | "sys_socket", 53 | "sys_bind", 54 | "sys_connect" , 55 | "sys_listen" , 56 | "sys_accept" , 57 | "sys_getsockname" , 58 | "sys_getpeername" , 59 | "sys_socketpair " , 60 | "sys_send" , 61 | "sys_recv" , 62 | "sys_sendto" , 63 | "sys_recvfrom" , 64 | "sys_shutdown" , 65 | "sys_setsockopt" , 66 | "sys_getsockopt " , 67 | "sys_sendmsg" , 68 | "sys_recvmsg" , 69 | "sys_accept4" , 70 | "sys_recvmmsg" , 71 | "sys_sendmmsg" , 72 | }; 73 | 74 | enum cb_state{ 75 | ENTER, 76 | RETURN, 77 | }; 78 | 79 | 80 | 81 | bool current_tap_labeled = false; 82 | std::string tx_last_tcp_conn; 83 | std::string rx_last_tcp_conn; 84 | 85 | 86 | /* 87 | #define GEN_ENUM(ENUM) ENUM 88 | #define GEN_FALSE(ENUM) false 89 | #define FOREACH_TAP_ENUM(ACTION) \ 90 | ACTION(TAP_SENDTO), \ 91 | ACTION(TAP_WRITE), \ 92 | ACTION(TAP_WRITEV) 93 | enum tap_point{ 94 | FOREACH_TAP_ENUM(GEN_ENUM) 95 | }; 96 | bool is_tap_labeled[] = { 97 | FOREACH_TAP_ENUM(GEN_FALSE) 98 | }; 99 | */ 100 | 101 | //(CPUState* cpu, int32_t call, uint32_t args, int32_t state) 102 | typedef void sockcall_func_t(CPUState* cpu, int32_t call, uint32_t args, uint32_t cb_state); 103 | 104 | sockcall_func_t* sockcalls[FUNC_TOTAL]; 105 | 106 | void sys_connect(CPUState* cpu, int32_t call, uint32_t args, uint32_t cb_state); 107 | void sys_send(CPUState* cpu, int32_t call, uint32_t args, uint32_t cb_state); 108 | void sys_sendto(CPUState* cpu, int32_t call, uint32_t args, uint32_t cb_state); 109 | void sys_recv(CPUState* cpu, int32_t call, uint32_t args, uint32_t cb_state); 110 | void sys_recvmsg(CPUState* cpu, int32_t call, uint32_t args, uint32_t cb_state); 111 | 112 | //For using string, include-maching 113 | template bool contain(const std::string& s, const T& v); 114 | 115 | void str_add(std::string& s, const std::string& v); 116 | void update_procs_fdmap(CPUState *cpu, uint32_t fd); 117 | std::string get_procs_fdmap(CPUState* cpu, uint32_t fd); 118 | 119 | ///for Structured data// 120 | struct iovec32{ 121 | union {uint8_t ar[4]; uint32_t val;}iov_base; 122 | union {uint8_t ar[4]; uint32_t val;}iov_len; 123 | }; 124 | 125 | struct sockaddr_in32{ 126 | uint8_t sin_len; 127 | uint8_t sin_family; 128 | union {uint8_t ar[2]; uint16_t val;}sin_port; 129 | union {uint8_t ar[4]; uint32_t val;}sin_addr; 130 | }; 131 | 132 | template 133 | void cast_to_struct(T& result, std::vector vec){ 134 | std::copy(vec.begin(), vec.end(), reinterpret_cast(&result)); 135 | } 136 | 137 | /// 138 | //#ifdef TARGET_I386 139 | 140 | ///For Introspection/// 141 | bool pid_ok(int pid); 142 | bool check_proc_ok(OsiProc* proc); 143 | uint32_t get_syscall_retval(CPUState* cpu); 144 | std::string get_filename_from_fd(CPUState* cpu, uint32_t fd); 145 | std::set get_commands_from_pid(uint32_t pid); 146 | std::string get_current_command(CPUState* cpu); 147 | std::set get_current_parent_command(CPUState* cpu); 148 | 149 | //void get_current_mod(CPUState* cpu); 150 | void get_current_mod(CPUState* cpu, target_ulong pc_addr); 151 | bool is_in_watched_cmd(CPUState* cpu); 152 | /// 153 | 154 | //For using strcpy and memcpy in C 155 | std::string get_strncpy_buf(CPUState *cpu, target_ulong guest_addr, size_t max_len); 156 | 157 | 158 | //Functions for doing little endian 159 | uint32_t little_endian_vec(uint8_t *vec, int size); 160 | uint32_t buf_virtaddr_little_endianed(CPUState *cpu, uint32_t addr, uint64_t len); 161 | 162 | //for print debugging or something, use little-endian-function above 163 | std::vector get_buf_dump(CPUState *cpu, uint32_t addr, uint32_t len); 164 | std::string hex2str(int dec); 165 | std::string get_buf_printable(CPUState *cpu, uint32_t addr, uint32_t len, bool in_hex); 166 | 167 | void buf_dump_panda_virtaddr(CPUState *cpu, uint32_t addr, uint64_t len, bool fmt_char); 168 | 169 | 170 | typedef struct Info_resource{ 171 | std::string resource_name; 172 | std::string cmd; 173 | std::set parent_cmds; 174 | uint32_t size; 175 | uint64_t rr_count; 176 | }Info_resource; 177 | 178 | bool operator<(const Info_resource &lhs, const Info_resource &rhs){ 179 | return lhs.resource_name < rhs.resource_name; 180 | } 181 | 182 | //syscall, and filename(read or written,etc. 183 | //typedef std::map> RESOURCE_MP; 184 | typedef std::map> RESOURCE_MP; 185 | RESOURCE_MP resource_touched; 186 | 187 | //For debugging 188 | //void monitor_resource_access(CPUState* cpu, std::string call_name, int fd); 189 | 190 | 191 | ///Taint Analysis/// 192 | typedef struct Info_taint_source{ 193 | uint64_t rr_count; 194 | target_ulong pc; 195 | target_ulong asid; 196 | std::string resource; //file or file descriptor 197 | std::string cmd; 198 | std::set parent_cmds; //in some cases, several commands share the same pid. 199 | std::string syscall; 200 | uint32_t propagate_count; 201 | Info_taint_source() : propagate_count(0){}; 202 | uint32_t range_size; 203 | std::string candidate_src_host = "(no_tagged_host)"; 204 | int fd; 205 | }Info_t; 206 | 207 | typedef struct Info_taint_output{ 208 | std::set ls; 209 | std::string cmd; 210 | std::string syscall; 211 | std::string resource; 212 | std::set parent_cmds; //in some cases, several commands share the same pid. 213 | std::vector buf; 214 | uint64_t rr_count; 215 | int fd; 216 | }Info_out; 217 | 218 | int app_getlabels(uint32_t el, void *stuff1); 219 | //uint32_t is_virtaddr_labeled(CPUState* cpu, target_ulong virt_addr, std::set &ls); 220 | void check_virtaddr_labeled(CPUState* cpu, target_ulong virt_addr, std::set &ls); 221 | bool is_tapped_buf_labeled(CPUState* cpu, uint32_t addr, uint32_t len, int fd, std::string tapped_call); 222 | 223 | 224 | 225 | struct Tainted_cmd{ 226 | uint64_t rr_count; 227 | std::string cmd; 228 | std::set parent_cmds; 229 | uint32_t asid; 230 | std::string disas_code; 231 | //std::set labels; 232 | //target_ulong pc; 233 | }; 234 | 235 | bool operator<(const Tainted_cmd &lhs, const Tainted_cmd &rhs){ 236 | return (lhs.cmd < rhs.cmd); 237 | } 238 | 239 | std::set tainted_commands; 240 | 241 | 242 | 243 | 244 | struct Tainted_instr{ 245 | uint64_t rr_count; 246 | uint32_t asid; 247 | std::set labels; 248 | target_ulong pc; 249 | }; 250 | std::vector tainted_instrs; 251 | 252 | 253 | 254 | // label this virtual address. might fail, so 255 | // returns true if byte was labeled 256 | bool label_byte(CPUState *cpu, target_ulong virt_addr, uint32_t label_num); 257 | //void ranged_label_byte(CPUState *cpu, target_ulong virt_addr, uint32_t size, int fd, std::string tap_call); 258 | //bool satisfy_read_taint(CPUState* cpu, uint32_t fd, uint32_t buf, uint32_t len); 259 | //////////////////// 260 | 261 | std::stack call_stack; 262 | 263 | std::set taint_funcs; 264 | std::set watched_cmd_funcs; 265 | 266 | std::set taint_funcs_rr_limited; 267 | 268 | 269 | std::set< target_ulong > func_addrs; 270 | 271 | 272 | 273 | -------------------------------------------------------------------------------- /spaniel/spaniel_syscalls.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | std::map syscall_name; 5 | 6 | void init_syscall_mp(){ 7 | syscall_name[0] = "sys_restart_syscall"; 8 | syscall_name[1] = "sys_exit"; 9 | syscall_name[2] = "sys_fork"; 10 | syscall_name[3] = "sys_read"; 11 | syscall_name[4] = "sys_write"; 12 | syscall_name[5] = "sys_open"; 13 | syscall_name[6] = "sys_close"; 14 | syscall_name[7] = "sys_waitpid"; 15 | syscall_name[8] = "sys_creat"; 16 | syscall_name[9] = "sys_link"; 17 | syscall_name[10] = "sys_unlink"; 18 | syscall_name[11] = "sys_execve"; 19 | syscall_name[12] = "sys_chdir"; 20 | syscall_name[13] = "sys_time"; 21 | syscall_name[14] = "sys_mknod"; 22 | syscall_name[15] = "sys_chmod"; 23 | syscall_name[16] = "sys_lchown16"; 24 | syscall_name[18] = "sys_stat"; 25 | syscall_name[19] = "sys_lseek"; 26 | syscall_name[20] = "sys_getpid"; 27 | syscall_name[21] = "sys_mount"; 28 | syscall_name[22] = "sys_oldumount"; 29 | syscall_name[23] = "sys_setuid16"; 30 | syscall_name[24] = "sys_getuid16"; 31 | syscall_name[25] = "sys_stime"; 32 | syscall_name[26] = "sys_ptrace"; 33 | syscall_name[27] = "sys_alarm"; 34 | syscall_name[28] = "sys_fstat"; 35 | syscall_name[29] = "sys_pause"; 36 | syscall_name[30] = "sys_utime"; 37 | syscall_name[33] = "sys_access"; 38 | syscall_name[34] = "sys_nice"; 39 | syscall_name[36] = "sys_sync"; 40 | syscall_name[37] = "sys_kill"; 41 | syscall_name[38] = "sys_rename"; 42 | syscall_name[39] = "sys_mkdir"; 43 | syscall_name[40] = "sys_rmdir"; 44 | syscall_name[41] = "sys_dup"; 45 | syscall_name[42] = "sys_pipe"; 46 | syscall_name[43] = "sys_times"; 47 | syscall_name[45] = "sys_brk"; 48 | syscall_name[46] = "sys_setgid16"; 49 | syscall_name[47] = "sys_getgid16"; 50 | syscall_name[48] = "sys_signal"; 51 | syscall_name[49] = "sys_geteuid16"; 52 | syscall_name[50] = "sys_getegid16"; 53 | syscall_name[51] = "sys_acct"; 54 | syscall_name[52] = "sys_umount"; 55 | syscall_name[54] = "sys_ioctl"; 56 | syscall_name[55] = "sys_fcntl"; 57 | syscall_name[57] = "sys_setpgid"; 58 | syscall_name[59] = "sys_olduname"; 59 | syscall_name[60] = "sys_umask"; 60 | syscall_name[61] = "sys_chroot"; 61 | syscall_name[62] = "sys_ustat"; 62 | syscall_name[63] = "sys_dup2"; 63 | syscall_name[64] = "sys_getppid"; 64 | syscall_name[65] = "sys_getpgrp"; 65 | syscall_name[66] = "sys_setsid"; 66 | syscall_name[67] = "sigaction"; 67 | syscall_name[68] = "sys_sgetmask"; 68 | syscall_name[69] = "sys_ssetmask"; 69 | syscall_name[70] = "sys_setreuid16"; 70 | syscall_name[71] = "sys_setregid16"; 71 | syscall_name[72] = "sigsuspend"; 72 | syscall_name[73] = "sys_sigpending"; 73 | syscall_name[74] = "sys_sethostname"; 74 | syscall_name[75] = "sys_setrlimit"; 75 | syscall_name[76] = "sys_old_getrlimit"; 76 | syscall_name[77] = "sys_getrusage"; 77 | syscall_name[78] = "sys_gettimeofday"; 78 | syscall_name[79] = "sys_settimeofday"; 79 | syscall_name[80] = "sys_getgroups16"; 80 | syscall_name[81] = "sys_setgroups16"; 81 | syscall_name[82] = "sys_old_select"; 82 | syscall_name[83] = "sys_symlink"; 83 | syscall_name[84] = "sys_lstat"; 84 | syscall_name[85] = "sys_readlink"; 85 | syscall_name[86] = "sys_uselib"; 86 | syscall_name[87] = "sys_swapon"; 87 | syscall_name[88] = "sys_reboot"; 88 | syscall_name[89] = "sys_old_readdir"; 89 | syscall_name[90] = "sys_old_mmap"; 90 | syscall_name[91] = "sys_munmap"; 91 | syscall_name[92] = "sys_truncate"; 92 | syscall_name[93] = "sys_ftruncate"; 93 | syscall_name[94] = "sys_fchmod"; 94 | syscall_name[95] = "sys_fchown16"; 95 | syscall_name[96] = "sys_getpriority"; 96 | syscall_name[97] = "sys_setpriority"; 97 | syscall_name[99] = "sys_statfs"; 98 | syscall_name[100] = "sys_fstatfs"; 99 | syscall_name[101] = "sys_ioperm"; 100 | syscall_name[102] = "sys_socketcall"; 101 | syscall_name[103] = "sys_syslog"; 102 | syscall_name[104] = "sys_setitimer"; 103 | syscall_name[105] = "sys_getitimer"; 104 | syscall_name[106] = "sys_newstat"; 105 | syscall_name[107] = "sys_newlstat"; 106 | syscall_name[108] = "sys_newfstat"; 107 | syscall_name[109] = "sys_uname"; 108 | syscall_name[110] = "sys_iopl"; 109 | syscall_name[111] = "sys_vhangup"; 110 | syscall_name[113] = "sys_vm86old"; 111 | syscall_name[114] = "sys_wait4"; 112 | syscall_name[115] = "sys_swapoff"; 113 | syscall_name[116] = "sys_sysinfo"; 114 | syscall_name[117] = "sys_ipc"; 115 | syscall_name[118] = "sys_fsync"; 116 | syscall_name[119] = "sys_sigreturn"; 117 | syscall_name[120] = "sys_clone"; 118 | syscall_name[121] = "sys_setdomainname"; 119 | syscall_name[122] = "sys_newuname"; 120 | syscall_name[123] = "sys_modify_ldt"; 121 | syscall_name[124] = "sys_adjtimex"; 122 | syscall_name[125] = "sys_mprotect"; 123 | syscall_name[126] = "sys_sigprocmask"; 124 | syscall_name[128] = "sys_init_module"; 125 | syscall_name[129] = "sys_delete_module"; 126 | syscall_name[131] = "sys_quotactl"; 127 | syscall_name[132] = "sys_getpgid"; 128 | syscall_name[133] = "sys_fchdir"; 129 | syscall_name[134] = "sys_bdflush"; 130 | syscall_name[135] = "sys_sysfs"; 131 | syscall_name[136] = "sys_personality"; 132 | syscall_name[138] = "sys_setfsuid16"; 133 | syscall_name[139] = "sys_setfsgid16"; 134 | syscall_name[140] = "sys_llseek"; 135 | syscall_name[141] = "sys_getdents"; 136 | syscall_name[142] = "sys_select"; 137 | syscall_name[143] = "sys_flock"; 138 | syscall_name[144] = "sys_msync"; 139 | syscall_name[145] = "sys_readv"; 140 | syscall_name[146] = "sys_writev"; 141 | syscall_name[147] = "sys_getsid"; 142 | syscall_name[148] = "sys_fdatasync"; 143 | syscall_name[149] = "sys_sysctl"; 144 | syscall_name[150] = "sys_mlock"; 145 | syscall_name[151] = "sys_munlock"; 146 | syscall_name[152] = "sys_mlockall"; 147 | syscall_name[153] = "sys_munlockall"; 148 | syscall_name[154] = "sys_sched_setparam"; 149 | syscall_name[155] = "sys_sched_getparam"; 150 | syscall_name[156] = "sys_sched_setscheduler"; 151 | syscall_name[157] = "sys_sched_getscheduler"; 152 | syscall_name[158] = "sys_sched_yield"; 153 | syscall_name[159] = "sys_sched_get_priority_max"; 154 | syscall_name[160] = "sys_sched_get_priority_min"; 155 | syscall_name[161] = "sys_sched_rr_get_interval"; 156 | syscall_name[162] = "sys_nanosleep"; 157 | syscall_name[163] = "sys_mremap"; 158 | syscall_name[164] = "sys_setresuid16"; 159 | syscall_name[165] = "sys_getresuid16"; 160 | syscall_name[166] = "sys_vm86"; 161 | syscall_name[168] = "sys_poll"; 162 | syscall_name[170] = "sys_setresgid16"; 163 | syscall_name[171] = "sys_getresgid16"; 164 | syscall_name[172] = "sys_prctl"; 165 | syscall_name[173] = "sys_rt_sigreturn"; 166 | syscall_name[174] = "rt_sigaction"; 167 | syscall_name[175] = "sys_rt_sigprocmask"; 168 | syscall_name[176] = "sys_rt_sigpending"; 169 | syscall_name[177] = "sys_rt_sigtimedwait"; 170 | syscall_name[178] = "sys_rt_sigqueueinfo"; 171 | syscall_name[179] = "sys_rt_sigsuspend"; 172 | syscall_name[180] = "sys_pread64"; 173 | syscall_name[181] = "sys_pwrite64"; 174 | syscall_name[182] = "sys_chown16"; 175 | syscall_name[183] = "sys_getcwd"; 176 | syscall_name[184] = "sys_capget"; 177 | syscall_name[185] = "sys_capset"; 178 | syscall_name[186] = "sys_sigaltstack"; 179 | syscall_name[187] = "sys_sendfile"; 180 | syscall_name[190] = "sys_vfork"; 181 | syscall_name[191] = "sys_getrlimit"; 182 | syscall_name[192] = "sys_mmap_pgoff"; 183 | syscall_name[193] = "sys_truncate64"; 184 | syscall_name[194] = "sys_ftruncate64"; 185 | syscall_name[195] = "sys_stat64"; 186 | syscall_name[196] = "sys_lstat64"; 187 | syscall_name[197] = "sys_fstat64"; 188 | syscall_name[198] = "sys_lchown"; 189 | syscall_name[199] = "sys_getuid"; 190 | syscall_name[200] = "sys_getgid"; 191 | syscall_name[201] = "sys_geteuid"; 192 | syscall_name[202] = "sys_getegid"; 193 | syscall_name[203] = "sys_setreuid"; 194 | syscall_name[204] = "sys_setregid"; 195 | syscall_name[205] = "sys_getgroups"; 196 | syscall_name[206] = "sys_setgroups"; 197 | syscall_name[207] = "sys_fchown"; 198 | syscall_name[208] = "sys_setresuid"; 199 | syscall_name[209] = "sys_getresuid"; 200 | syscall_name[210] = "sys_setresgid"; 201 | syscall_name[211] = "sys_getresgid"; 202 | syscall_name[212] = "sys_chown"; 203 | syscall_name[213] = "sys_setuid"; 204 | syscall_name[214] = "sys_setgid"; 205 | syscall_name[215] = "sys_setfsuid"; 206 | syscall_name[216] = "sys_setfsgid"; 207 | syscall_name[217] = "sys_pivot_root"; 208 | syscall_name[218] = "sys_mincore"; 209 | syscall_name[219] = "sys_madvise"; 210 | syscall_name[220] = "sys_getdents64"; 211 | syscall_name[221] = "sys_fcntl64"; 212 | syscall_name[224] = "sys_gettid"; 213 | syscall_name[225] = "sys_readahead"; 214 | syscall_name[226] = "sys_setxattr"; 215 | syscall_name[227] = "sys_lsetxattr"; 216 | syscall_name[228] = "sys_fsetxattr"; 217 | syscall_name[229] = "sys_getxattr"; 218 | syscall_name[230] = "sys_lgetxattr"; 219 | syscall_name[231] = "sys_fgetxattr"; 220 | syscall_name[232] = "sys_listxattr"; 221 | syscall_name[233] = "sys_llistxattr"; 222 | syscall_name[234] = "sys_flistxattr"; 223 | syscall_name[235] = "sys_removexattr"; 224 | syscall_name[236] = "sys_lremovexattr"; 225 | syscall_name[237] = "sys_fremovexattr"; 226 | syscall_name[238] = "sys_tkill"; 227 | syscall_name[239] = "sys_sendfile64"; 228 | syscall_name[240] = "sys_futex"; 229 | syscall_name[241] = "sys_sched_setaffinity"; 230 | syscall_name[242] = "sys_sched_getaffinity"; 231 | syscall_name[243] = "set_thread_area"; 232 | syscall_name[244] = "get_thread_area"; 233 | syscall_name[245] = "sys_io_setup"; 234 | syscall_name[246] = "sys_io_destroy"; 235 | syscall_name[247] = "sys_io_getevents"; 236 | syscall_name[248] = "sys_io_submit"; 237 | syscall_name[249] = "sys_io_cancel"; 238 | syscall_name[250] = "sys_fadvise64"; 239 | syscall_name[252] = "sys_exit_group"; 240 | syscall_name[253] = "sys_lookup_dcookie"; 241 | syscall_name[254] = "sys_epoll_create"; 242 | syscall_name[255] = "sys_epoll_ctl"; 243 | syscall_name[256] = "sys_epoll_wait"; 244 | syscall_name[257] = "sys_remap_file_pages"; 245 | syscall_name[258] = "sys_set_tid_address"; 246 | syscall_name[259] = "sys_timer_create"; 247 | syscall_name[260] = "sys_timer_settime"; 248 | syscall_name[261] = "sys_timer_gettime"; 249 | syscall_name[262] = "sys_timer_getoverrun"; 250 | syscall_name[263] = "sys_timer_delete"; 251 | syscall_name[264] = "sys_clock_settime"; 252 | syscall_name[265] = "sys_clock_gettime"; 253 | syscall_name[266] = "sys_clock_getres"; 254 | syscall_name[267] = "sys_clock_nanosleep"; 255 | syscall_name[268] = "sys_statfs64"; 256 | syscall_name[269] = "sys_fstatfs64"; 257 | syscall_name[270] = "sys_tgkill"; 258 | syscall_name[271] = "sys_utimes"; 259 | syscall_name[272] = "sys_fadvise64_64"; 260 | syscall_name[274] = "sys_mbind"; 261 | syscall_name[275] = "sys_get_mempolicy"; 262 | syscall_name[276] = "sys_set_mempolicy"; 263 | syscall_name[277] = "sys_mq_open"; 264 | syscall_name[278] = "sys_mq_unlink"; 265 | syscall_name[279] = "sys_mq_timedsend"; 266 | syscall_name[280] = "sys_mq_timedreceive"; 267 | syscall_name[281] = "sys_mq_notify"; 268 | syscall_name[282] = "sys_mq_getsetattr"; 269 | syscall_name[283] = "sys_kexec_load"; 270 | syscall_name[284] = "sys_waitid"; 271 | syscall_name[286] = "sys_add_key"; 272 | syscall_name[287] = "sys_request_key"; 273 | syscall_name[288] = "sys_keyctl"; 274 | syscall_name[289] = "sys_ioprio_set"; 275 | syscall_name[290] = "sys_ioprio_get"; 276 | syscall_name[291] = "sys_inotify_init"; 277 | syscall_name[292] = "sys_inotify_add_watch"; 278 | syscall_name[293] = "sys_inotify_rm_watch"; 279 | syscall_name[294] = "sys_migrate_pages"; 280 | syscall_name[295] = "sys_openat"; 281 | syscall_name[296] = "sys_mkdirat"; 282 | syscall_name[297] = "sys_mknodat"; 283 | syscall_name[298] = "sys_fchownat"; 284 | syscall_name[299] = "sys_futimesat"; 285 | syscall_name[300] = "sys_fstatat64"; 286 | syscall_name[301] = "sys_unlinkat"; 287 | syscall_name[302] = "sys_renameat"; 288 | syscall_name[303] = "sys_linkat"; 289 | syscall_name[304] = "sys_symlinkat"; 290 | syscall_name[305] = "sys_readlinkat"; 291 | syscall_name[306] = "sys_fchmodat"; 292 | syscall_name[307] = "sys_faccessat"; 293 | syscall_name[308] = "sys_pselect6"; 294 | syscall_name[309] = "sys_ppoll"; 295 | syscall_name[310] = "sys_unshare"; 296 | syscall_name[311] = "sys_set_robust_list"; 297 | syscall_name[312] = "sys_get_robust_list"; 298 | syscall_name[313] = "sys_splice"; 299 | syscall_name[314] = "sys_sync_file_range"; 300 | syscall_name[315] = "sys_tee"; 301 | syscall_name[316] = "sys_vmsplice"; 302 | syscall_name[317] = "sys_move_pages"; 303 | syscall_name[318] = "sys_getcpu"; 304 | syscall_name[319] = "sys_epoll_pwait"; 305 | syscall_name[320] = "sys_utimensat"; 306 | syscall_name[321] = "sys_signalfd"; 307 | syscall_name[322] = "sys_timerfd_create"; 308 | syscall_name[323] = "sys_eventfd"; 309 | syscall_name[324] = "sys_fallocate"; 310 | syscall_name[325] = "sys_timerfd_settime"; 311 | syscall_name[326] = "sys_timerfd_gettime"; 312 | syscall_name[327] = "sys_signalfd4"; 313 | syscall_name[328] = "sys_eventfd2"; 314 | syscall_name[329] = "sys_epoll_create1"; 315 | syscall_name[330] = "sys_dup3"; 316 | syscall_name[331] = "sys_pipe2"; 317 | syscall_name[332] = "sys_inotify_init1"; 318 | syscall_name[333] = "sys_preadv"; 319 | syscall_name[334] = "sys_pwritev"; 320 | syscall_name[335] = "sys_rt_tgsigqueueinfo"; 321 | syscall_name[336] = "sys_perf_event_open"; 322 | syscall_name[337] = "sys_recvmmsg"; 323 | syscall_name[338] = "sys_fanotify_init"; 324 | syscall_name[339] = "sys_fanotify_mark"; 325 | syscall_name[340] = "sys_prlimit64"; 326 | syscall_name[341] = "sys_name_to_handle_at"; 327 | syscall_name[342] = "sys_open_by_handle_at"; 328 | syscall_name[343] = "sys_clock_adjtime"; 329 | syscall_name[344] = "sys_syncfs"; 330 | syscall_name[345] = "sys_sendmmsg"; 331 | syscall_name[346] = "sys_setns"; 332 | syscall_name[347] = "sys_process_vm_readv"; 333 | syscall_name[348] = "sys_process_vm_writev"; 334 | } 335 | 336 | -------------------------------------------------------------------------------- /spaniel/spaniel_tools.cpp: -------------------------------------------------------------------------------- 1 | #define __STDC_FORMAT_MACROS 2 | #include"spaniel_tools.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | csh cs_handle_32; 11 | csh cs_handle_64; 12 | 13 | std::string get_disas_pc(CPUState* cpu, target_ulong pc, target_ulong tb_pc, uint16_t tb_size) { 14 | #if defined(TARGET_I386) 15 | if (cs_open(CS_ARCH_X86, CS_MODE_32, &cs_handle_32) != CS_ERR_OK) return std::string("No disas"); 16 | cs_option(cs_handle_32, CS_OPT_DETAIL, CS_OPT_ON); 17 | unsigned char *buf = (unsigned char *) malloc(tb_size); 18 | int err = panda_virtual_memory_rw(cpu, tb_pc, buf, tb_size, 0); 19 | if (err == -1){free(buf); return std::string("No disas"); } 20 | CPUArchState* env = (CPUArchState*)cpu->env_ptr; 21 | csh handle = (env->hflags & HF_LMA_MASK) ? cs_handle_64 : cs_handle_32; 22 | cs_insn *insn; 23 | std::string disas_pc; 24 | size_t count = cs_disasm(handle, buf, tb_size, tb_pc, 0, &insn); 25 | if(count <= 0) goto done2; 26 | if(count>0){ 27 | size_t j; 28 | for(j=0; j edges){ 51 | std::string in_taint_icon_fmt = "\"%s\"[shape=note];"; 52 | //std::string out_taint_icon_fmt = "\"%s\"[shape=folder];"; 53 | std::string out_taint_icon_fmt = "\"%s\"[shape=cylinder];"; 54 | std::string tainted_icon = "\"Tainted Buffer\"[shape=doubleoctagon];"; 55 | 56 | std::string default_fmt = "\"%s\";"; 57 | 58 | std::string mod_icon_fmt = "\"%s\"[style=filled];"; 59 | //std::string mod_icon_fmt = "\"%s\"[shape=box;style=filled];"; 60 | //std::string proc_icon_fmt = "\"%s\";"; 61 | std::string proc_icon_fmt = "\"%s\"[shape=box][style=rounded];"; 62 | std::string syscall_icon_fmt = "\"%s\";"; 63 | std::string concat_fmt = "\"%s\" -> \"%s\";"; 64 | std::string buf_icon_fmt = "\"%s\"[shape=doubleoctagon];"; 65 | //std::string net_tx_icon_fmt = "\"%s\"[shape=folder][style=filled];"; 66 | std::string net_tx_icon_fmt = "\"%s\"[shape=cylinder][style=filled];"; 67 | 68 | 69 | std::map fmt_dict; 70 | fmt_dict[TAINT_SRC] = in_taint_icon_fmt; 71 | fmt_dict[TAINT_DST] = out_taint_icon_fmt; 72 | fmt_dict[MODULE] = mod_icon_fmt; 73 | fmt_dict[PROC] = proc_icon_fmt; 74 | fmt_dict[SYSCALL] = syscall_icon_fmt; 75 | fmt_dict[BUF] = buf_icon_fmt; 76 | fmt_dict[CONCAT] = concat_fmt; 77 | fmt_dict[NET_TX] = net_tx_icon_fmt; 78 | 79 | fmt_dict[OS_OBJECT] = default_fmt; 80 | 81 | std::set defined_nodes; 82 | std::set concated_nodes; 83 | for(auto p : edges){ 84 | char *s1 = new char[256]; 85 | char *s2 = new char[256]; 86 | char *concated = new char[256]; 87 | snprintf(s1, 256, fmt_dict[p.first.first].c_str(), p.first.second.c_str()); 88 | snprintf(s2, 256, fmt_dict[p.second.first].c_str(), p.second.second.c_str()); 89 | defined_nodes.insert(s1); 90 | defined_nodes.insert(s2); 91 | snprintf(concated, 256, fmt_dict[CONCAT].c_str(), p.first.second.c_str(), p.second.second.c_str()); 92 | concated_nodes.insert(concated); 93 | } 94 | // std::cout << std::endl; 95 | std::cout << "digraph taintgraph {" << std::endl; 96 | for(auto s : defined_nodes){ 97 | std::cout << "\t"; 98 | std::cout << s << std::endl; 99 | } 100 | for(auto s : concated_nodes){ 101 | std::cout << "\t"; 102 | std::cout << s << std::endl; 103 | } 104 | std::cout << "}" << std::endl; 105 | } 106 | -------------------------------------------------------------------------------- /spaniel/spaniel_tools.h: -------------------------------------------------------------------------------- 1 | #include "panda/plugin.h" 2 | #include 3 | #if defined(TARGET_I386) 4 | #include 5 | #elif defined(TARGET_ARM) 6 | #include 7 | #elif defined(TARGET_PPC) 8 | #include 9 | #endif 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | std::string get_disas_pc(CPUState* cpu, target_ulong pc, target_ulong tb_pc, uint16_t tb_size); 17 | 18 | 19 | /////// 20 | enum node_type{ 21 | BUF, 22 | TAINT_SRC, 23 | TAINT_DST, 24 | MODULE, 25 | PROC, 26 | SYSCALL, 27 | OS_OBJECT, 28 | // 29 | CONCAT, 30 | NET_TX, 31 | }; 32 | typedef std::pair Node; 33 | //typedef std::pair dir_tg_node; 34 | typedef std::pair Edge; 35 | 36 | //void gen_graph_dot(std::vector node_pair); 37 | void gen_graph_dot(std::vector edges); 38 | /////// 39 | 40 | --------------------------------------------------------------------------------