{"id":15040904,"url":"https://github.com/lukefalsina/grab-n-run","last_synced_at":"2025-04-07T06:11:13.240Z","repository":{"id":23587971,"uuid":"26956394","full_name":"lukeFalsina/Grab-n-Run","owner":"lukeFalsina","description":"Grab’n Run, a simple and effective Java Library for Android projects to secure dynamic code loading.","archived":false,"fork":false,"pushed_at":"2016-05-24T00:28:54.000Z","size":23121,"stargazers_count":413,"open_issues_count":2,"forks_count":56,"subscribers_count":32,"default_branch":"master","last_synced_at":"2025-03-31T05:04:51.304Z","etag":null,"topics":["android-application","android-development","application-security","dynamic","java","signature-verification"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lukeFalsina.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"docs/security.rst","support":null}},"created_at":"2014-11-21T10:48:21.000Z","updated_at":"2025-02-27T01:48:21.000Z","dependencies_parsed_at":"2022-08-22T03:10:18.986Z","dependency_job_id":null,"html_url":"https://github.com/lukeFalsina/Grab-n-Run","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lukeFalsina%2FGrab-n-Run","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lukeFalsina%2FGrab-n-Run/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lukeFalsina%2FGrab-n-Run/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lukeFalsina%2FGrab-n-Run/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lukeFalsina","download_url":"https://codeload.github.com/lukeFalsina/Grab-n-Run/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247601448,"owners_count":20964864,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android-application","android-development","application-security","dynamic","java","signature-verification"],"created_at":"2024-09-24T20:45:16.010Z","updated_at":"2025-04-07T06:11:13.210Z","avatar_url":"https://github.com/lukeFalsina.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ![Logo](https://github.com/lukeFalsina/Grab-n-Run/raw/master/gnr/app/src/main/res/drawable-mdpi/logo_with_name.png)\r\n\r\n## Research paper\r\n\r\nWe present the findings of this work in a research paper:\r\n\r\n**Grab'n Run: Secure and Practical Dynamic Code Loading for Android Applications**  \r\nLuca Falsina, Yanick Fratantonio, Stefano Zanero, Christopher Kruegel, Giovanni Vigna, Federico Maggi.  \r\n*In Proceedings of the Annual Computer Security Applications Conference (ACSAC). Los Angeles, CA December, 2015*\r\n[[PDF](http://cs.ucsb.edu/~yanick/publications/2015_acsac_grabandrun.pdf)]\r\n[[Bibtex](https://github.com/lukeFalsina/Grab-n-Run/raw/master/grabandrun.bib)]\r\n\r\nIf you use *Grab'n Run* in a scientific publication, we would appreciate citations to the previous paper.  \r\nPlease use this **Bibtex** entry:\r\n``` tex\r\n@InProceedings{falsina15:grabandrun,\r\n  author = {Luca Falsina and Yanick Fratantonio and Stefano Zanero and Christopher Kruegel and Giovanni Vigna and Federico Maggi},\r\n  title = {{Grab'n Run: Secure and Practical Dynamic Code Loading for Android Applications}},\r\n  booktitle = {Proceedings of the Annual Computer Security Applications Conference (ACSAC)},\r\n  month = {December},\r\n  year = {2015},\r\n  address = {Los Angeles, CA}\r\n}\r\n``` \r\n\r\n## News\r\n\r\n- *10/10/2015* - The **repackaging tool** is now **[online](http://grab-n-run.readthedocs.org/en/latest/repackaging.html)**. Use it to patch automatically your applications to use Grab'n Run APIs. \r\n- *01/17/2015* - **Grab'n Run** is now **available** on [JCenter](https://bintray.com/bintray/jcenter?filterByPkgName=grab-n-run)\r\n- *01/16/2015* - **Grab'n Run** project migrates to [Android Studio](http://developer.android.com/tools/studio/index.html), the official *IDE* for **Android application development**. However, you can still use the library also with your *ADT* projects! (*see below the \"Quick Setup\" section for further details*)\r\n- *11/26/2014* - **Grab'n Run is on line!**\r\n\r\n## Introduction\r\n\r\n*Grab’n Run* (aka **GNR**) is a **simple** and **effective** Java Library that you can easily add to your Android projects to perform *secure dynamic class loading* operations over standard [DexClassLoader](http://developer.android.com/reference/dalvik/system/DexClassLoader.html).\r\n\r\nPrevious research has shown that many applications often need to perform dynamic class loading to implement, for example, non-invasive self-update features. However, research has also shown that it is really challenging to *safely* implement these features. This is of particular importance as, in this context, **one single mistake** could open the application (and, therefore, the entire device) to **serious security vulnerabilities**, such as *remote code execution*.  \r\n\r\nThe main goal of *Grab's Run* is to offer an alternative to the native Android APIs, and its design enforces that even the most inexperienced developer cannot perform well-known, serious mistakes.\r\n\r\nFor a **brief presentation** of the library and some of its features you can give a look at these [slides](https://goo.gl/QrwWey), while if you prefer a more **structured and complete description** with *set up information, tutorials, examples, tips\u0026tricks, and a full presentation of the API* you should definitely check the [documentation](http://grab-n-run.readthedocs.org/en/latest/).\r\n\r\nIf you desire to suggest new *features, improvements, criticisms* or whatever, I would be more than glad to hear **any kind of constructive feedback** :D  \r\nYou can contact me either by dropping an email at [lfalsina@gmail.com](mailto:lfalsina@gmail.com) or by pinging me on Twitter [@lfalsina](https://twitter.com/lfalsina).\r\n\r\n## Main features\r\nSecurely load code dynamically into your Android application from **APK** containers or **JAR** libraries translated to be *executable by both the Dalvik Virtual Machine (DVM) and the Android Runtime (ART)* (don't worry a [section](http://grab-n-run.readthedocs.org/en/latest/complementary.html#on-library-developer-side-how-to-prepare-a-valid-library-container-compatible-with-gnr) of the docs explains step-by-step how to do it).\r\n\r\n- *JAR* and *APK* containers can be either already stored on the device or **automatically fetched from remote locations** by GNR.\r\n- Retrieved containers signatures are compared against a **valid developer certificate**. Only containers that are **correctly signed** are allowed to have their classes loaded dynamically. This ensures **integrity** and **developer authentication** on all the retrieved containers.\r\n- Developer certificates are retrieved from remote locations securely and cached on the mobile phone for future verifications.\r\n- *Cached classes, containers and certificates* used for the signature verification are stored into *application-private* folders. This **prevents** your application **from code injection attacks** at runtime.\r\n- GNR implements an **effective caching system** that speeds up its execution and at the same time enables it to *work in most cases also when no connectivity is available*.\r\n- Transition to GNR is **smooth** for the application developer since its **API** where thought to be *as close as possible to the standard API* provided by the Android framework.\r\n- When *many containers* are provided as sources for class loading, *Grab'n Run* performs a **concurrent multi-thread signature verification** in order to *limit the performance overhead*.\r\n- GNR helps the application developer to **implement silent updating** on *remote third-party libraries in a secure and concise way*. \r\n\r\n## Quick Setup\r\n\r\nThis section explains how to setup *Grab'n Run* as a library for your Android applications.\r\n\r\n#### 1. Include library\r\n\r\n###### a. Android Studio (AS)\r\n\r\n* Modify the *build.gradle* file in the *app* module of your Android project by adding the following *compile* line in the *dependencies* body:\r\n``` gradle\r\ndependencies {\r\n    // Grab'n Run will be imported from JCenter.\r\n    // Verify that the string \"jcenter()\" is included in your repositories block!\r\n    compile 'it.necst.grabnrun:grabnrun:1.0.4'\r\n}\r\n``` \r\n* Resync your project to apply changes.\r\n\r\n###### b. Android Development Tool (ADT)\r\n\r\n* [Download JAR](https://github.com/lukeFalsina/Grab-n-Run/raw/master/downloads/1.0.4/grabnrun-1.0.4.jar)\r\n* Put the JAR in the **libs** subfolder of your Android project\r\n\r\n#### 2. Android Manifest\r\n\r\nModify the *Android Manifest* of your application by adding a couple of **required permissions**:\r\n``` xml\r\n\u003cmanifest\u003e\r\n\t\u003c!-- \tInclude following permission to be able to download remote resources \r\n\t\t\tlike containers and certificates --\u003e\r\n\t\u003cuses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\" /\u003e\r\n\t\u003c!-- \tInclude following permission to be able to download remote resources \r\n\t\t\tlike containers and certificates --\u003e\r\n\t\u003cuses-permission android:name=\"android.permission.INTERNET\" /\u003e\r\n\t\u003c!-- \tInclude following permission to be able to import local containers \r\n\t\t\ton SD card --\u003e\r\n\t\u003cuses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\" /\u003e\r\n\t...\r\n\u003c/manifest\u003e\r\n```\r\n\r\n## Quick example of use\r\n\r\nThis quick use case gives you a taste on how to use GNR once you have added it to your project.\r\n\r\n#### 1. Create a key pair to sign your code and export your developer certificate\r\n\r\n* Open a terminal and type the following command to **generate a keystore** and a **keypair**:\r\n``` bash\r\n$ \tkeytool -genkey -v -keystore my-tests-key.keystore -alias test_dev_key \r\n\t-keyalg RSA -keysize 2048 -validity 10000\r\n```\r\n* Next **export** the public key **into a certificate** that will be *used to verify your library code* before dynamically loading it:\r\n``` bash\r\n$\tkeytool -exportcert -keystore my-tests-key.keystore -alias test_dev_key \r\n\t-file certificate.pem\r\n```\r\n* You should now see in the folder a **certificate file** called *certificate.pem*\r\n\r\n#### 2. Publish your developer certificate on line at a remote location which uses HTTPS protocol\r\n\r\nYou can publish the certificate wherever you like as long as **HTTPS** protocol is used and **everyone can access this location** from the web.\r\nAs a **test** example you could store the *certificate.pem* in your \"Public\" *Dropbox* folder and then retrieve the **associated public link**, which could be for example something like \"https://dl.dropboxusercontent.com/u/00000000/certificate.pem\". Note this URL down, you will need it soon.\r\n\r\n#### 3. Export an unsigned container and sign it with your developer key\r\n\r\nLet's say that in your IDE (i.e., the *Android Development Tools (ADT)*) you have an Android project called **\"LoaderApp\"** from which you want to load some of its classes dynamically in another project.\r\n\r\n* In the *ADT Package Explorer* **right** click on **\"LoaderApp\"** -\u003e Android Tools -\u003e Export Unsigned Application Package...\r\n![Screenshot](https://github.com/lukeFalsina/Grab-n-Run/raw/master/docs/images/ExportUnsignedContainer.png)\r\n* Next select the **same folder** where you have previously saved the keystore and the keypair as the *destination folder* and press OK.\r\n* Open a terminal which points to the destination folder and **sign the apk container** with the previously created key:\r\n``` bash\r\n$\tjarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 \r\n\t-keystore my-tests-key.keystore LoaderApp.apk test_dev_key\r\n```\r\n* Finally **align** the apk container to optimize access time to its resources:\r\n``` bash\r\n$\t\u003cpath_to_your_sdk\u003e/sdk/build-tools/\u003csdk_version_number\u003e/zipalign -v 4 \r\n\tLoaderApp.apk LoaderAppAligned.apk\r\n```\r\n\r\n**P.S.** *Step 3* can also be directly performed by means of your favorite *IDE*. In **ADT** you would have to select the option *\"Android Tools -\u003e Export Signed Application Package...\"* and, when it is required, navigate to the location of your keystore and inserting its password, the key id and the key password. On the other hand in **Android Studio** the signature process can be automatized by setting up a proper **signing configuration** as described [here](http://developer.android.com/tools/publishing/app-signing.html#release-mode).\r\n\r\n#### 4. Publish the signed and aligned version of the source container\r\n\r\nOnce you have obtained *LoaderAppAligned.apk*, you need to make also this resource **available on line**. Notice that, in this case, both remote locations that use **HTTP** or **HTTPS** protocols are fine as long as they are accessible from the web. Again, as an example, you can store the container in your \"Public\" *Dropbox* folder and get back a **public URL** like \"https://dl.dropboxusercontent.com/u/00000000/LoaderAppAligned.apk\".\r\n\r\n#### 5. Set up dynamic code loading with GNR in the application\r\n\r\nIn the end, it is time to set up a *SecureDexClassLoader* instance to **fetch your remote container and developer certificate**, **store it in a safe place** and **perform a signature verification** before dynamically loading your code.\r\n\r\n**Copy and paste** the code below in one of the Activity in your target Android project, where you have *already imported GNR*, to **dynamically and securely load** an instance of the class *\"com.example.MyClass\"*:\r\n``` java\r\n\r\nMyClass myClassInstance = null;\r\njarContainerPath = \"https://dl.dropboxusercontent.com/u/00000000/LoaderAppAligned.apk\";\r\n\r\ntry {\r\n\tMap\u003cString, URL\u003e packageNamesToCertMap = new HashMap\u003cString, URL\u003e();\r\n\tpackageNamesToCertMap.put(\"com.example\", new URL(\"https://dl.dropboxusercontent.com/u/00000000/certificate.pem\"));\r\n\r\n\tSecureLoaderFactory mSecureLoaderFactory = new SecureLoaderFactory(this);\r\n\tSecureDexClassLoader mSecureDexClassLoader = mSecureLoaderFactory.createDexClassLoader(\tjarContainerPath, \r\n\t\t\t\t\t\t\t\t\t\t\t\tnull, \r\n\t\t\t\t\t\t\t\t\t\t\t\tgetClass().getClassLoader(),\r\n\t\t\t\t\t\t\t\t\t\t\t\tpackageNamesToCertMap);\r\n\t\t\r\n\tClass\u003c?\u003e loadedClass = mSecureDexClassLoader.loadClass(\"com.example.MyClass\");\r\n\r\n\t// Check whether the signature verification process succeeded\r\n\tif (loadedClass != null) {\r\n\r\n\t\t// No security constraints were violated and so\r\n\t\t// class loading was successful.\r\n\t\tmyClassInstance = (MyClass) loadedClass.newInstance();\r\n\t\t\t\t\r\n\t\t// Do something with the loaded object myClassInstance\r\n\t\t// i.e. myClassInstance.doSomething();\r\n\t}\r\n\r\n} catch (ClassNotFoundException e) {\r\n\t// This exception will be raised when the container of the target class\r\n\t// is genuine but this class file is missing..\r\n\te.printStackTrace();\r\n} catch (InstantiationException e) {\r\n\te.printStackTrace();\r\n} catch (IllegalAccessException e) {\r\n\te.printStackTrace();\r\n} catch (MalformedURLException e) {\r\n\t// The previous URL used for the packageNamesToCertMap entry was a malformed one.\r\n\tLog.e(\"Error\", \"A malformed URL was provided for a remote certificate location\");\r\n}\r\n```\r\n\r\n*Et voilà..* now you have an instance of *\"MyClass\"* loaded in a **secure way** at **run time**!\r\n\r\n## Next steps :)\r\n\r\n* If you want to learn how to use *Grab'n Run* I suggest to start from the [tutorial](http://grab-n-run.readthedocs.org/en/latest/tutorial.html) and then moving on by analyzing the [example application](http://grab-n-run.readthedocs.org/en/latest/example.html).\r\n* If you are interested in understanding what are the **security threats** of *improper dynamic code loading* fixed by GNR check out the [security resume](http://grab-n-run.readthedocs.org/en/latest/security.html).\r\n* If you would like to implement cool features of GNR like **silent updates**, **handling more containers**, **concurrent code loading** or **dynamically loading JAR libraries in your applications** you should give a look at the [complementary topics](http://grab-n-run.readthedocs.org/en/latest/complementary.html).\r\n* You may also need to **consult** the *JavaDoc-like* [API documentation](https://rawgit.com/lukeFalsina/Grab-n-Run/master/docs/javaDoc/index.html).\r\n* Finally, you may want to convert automatically your applications to use Grab'n Run APIs for secure dynamic code loading. Give a try at the [repackaging tool](http://grab-n-run.readthedocs.org/en/latest/repackaging.html).\r\n\r\n## License\r\n\r\n*Grab'n Run* is released under the *Apache* license. Check the *COPYRIGHT* file for further details.\r\n\r\n[![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-Grab--n--Run-brightgreen.svg?style=flat)](https://android-arsenal.com/details/1/1185)\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flukefalsina%2Fgrab-n-run","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flukefalsina%2Fgrab-n-run","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flukefalsina%2Fgrab-n-run/lists"}