{"id":13462756,"url":"https://github.com/pfalcon/awesome-linux-android-hacking","last_synced_at":"2025-10-25T04:30:22.159Z","repository":{"id":22188246,"uuid":"25520370","full_name":"pfalcon/awesome-linux-android-hacking","owner":"pfalcon","description":"List of hints and Q\u0026As to get most of your Linux/Android device","archived":false,"fork":false,"pushed_at":"2021-05-07T20:37:14.000Z","size":19,"stargazers_count":124,"open_issues_count":0,"forks_count":25,"subscribers_count":12,"default_branch":"master","last_synced_at":"2024-05-23T06:11:20.177Z","etag":null,"topics":["awesome","awesome-list"],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pfalcon.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":null,"support":null}},"created_at":"2014-10-21T12:15:25.000Z","updated_at":"2024-04-07T15:17:03.000Z","dependencies_parsed_at":"2022-08-20T23:50:47.561Z","dependency_job_id":null,"html_url":"https://github.com/pfalcon/awesome-linux-android-hacking","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pfalcon%2Fawesome-linux-android-hacking","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pfalcon%2Fawesome-linux-android-hacking/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pfalcon%2Fawesome-linux-android-hacking/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pfalcon%2Fawesome-linux-android-hacking/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pfalcon","download_url":"https://codeload.github.com/pfalcon/awesome-linux-android-hacking/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238075349,"owners_count":19412315,"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":["awesome","awesome-list"],"created_at":"2024-07-31T13:00:29.702Z","updated_at":"2025-10-25T04:30:16.858Z","avatar_url":"https://github.com/pfalcon.png","language":null,"funding_links":[],"categories":["\u003ca id=\"8c5a692b5d26527ef346687e047c5c21\"\u003e\u003c/a\u003e收集","Mobile security resources","Education Best Practices"],"sub_categories":["ColdFusion","Secure OSes"],"readme":"*(c) 2014-2018 Paul Sokolovsky. Portions of content (c) by their respective authors.*\n\n## Linux\n\n### How to find out version of kernel running\n\nIf that kernel is booted and you have access to console:\n```\nuname -a\n```\n\nAlternatively:\n\n```\ncat /proc/version\n```\n\n\nIf you have only kernel image file ... (tba).\n\n### How to see what devices/partitions are mounted and their filesystem, types\n```\nmount\n```\n\nAlternatively:\n\n```\ncat /proc/mounts\n```\n\n### How to read kernel message log (including boot log)\n\n```\ndmesg\n```\n\nKernel log contains all messages from the beginning of kernel boot,\nbut it is implemented as a circular buffer (of configurable size), so\nnewer messages may replace older.\n\n### Is it possible to read kernel log if dmesg is not available?\n\n`cat /proc/kmsg` will block and dump ''new'' kernel messages. This\nwill work reliably only if there are no other consumer(s) of\n`/proc/kmsg` (note: on typical fully booted Linux system there's -\nsyslogd, etc.), otherwise the output may be garbled.\n\n\n### How to read system log\n\nOn a full-fledged Linux system, system log is usually accessible as\n`/var/log/messages`. Recently, some particular distributions started\nto play original, for example, in Ubuntu 12.04 `/var/log/messages` is\nempty and instead `/var/log/syslog` may contain some, or all, of\nsystem log messages.\n\nOn an embedded system, a busybox syslogs may be used, providing\ncircular buffer without file backing storage. It can be accessed using\n`logread` command.\n\n### How to write to system log\n`logger` command does that.\n\n### How to find out config of a kernel?\n\nWith a running kernel, if it was built with CONFIG_IKCONFIG_PROC, the\nconfig can be read as `/proc/config.gz`. For a zImage file,\n`scripts/extract-ikconfig` can be used to extract it (just\nCONFIG_IKCONFIG is required for this).\n\n### How to list loaded kernel modules?\n```\nlsmod\n```\n\nAlternatively:\n```\ncat /proc/modules\n```\n\n### How to load kernel modules?\nLow-level command to load a specific filename is:\n```\ninsmod /path/\u003cmodule\u003e.ko\n```\n\nHigher level command is:\n```\nmodprobe \u003cmodule\u003e\n```\n\nThis will look for modules located in `/lib/modules/\u003ckernel_version\u003e`\nand requires support files generated by `depmod`.\n\n### How to force loading of kernel module?\nModule loading is subject to many checks (see below), so and kernel\nmay refuse to load improper one. If CONFIG_MODULE_FORCE_LOAD is\ndefined, it is possible to force-load module nonetheless.\nUnfortunately, it's not possible to force load with (recent) `insmod`.\nIt can be done with `modprobe -f` (`modprobe ---help` for other force\noptions).\n\n### How to unload kernel modules?\n```\nrmmod \u003cmodule\u003e\n```\n\nModule unloading usually available, but still depends on\nCONFIG_MODULE_UNLOAD. Module may refuse to unload if other modules\ndepend on it, or if it's in particular state (which also includes\nstates like \"hanged\" and \"gone awry\"), in which case it's possible to\nforce unload (`rmmod -f`), if CONFIG_MODULE_FORCE_UNLOAD was defined.\n\n### Can kernel modules built for one version be used with another kernel version?\nIn general, this is not possible. With Linux kernel's \"stable API is\nnonsense\" attitude, anything in the kernel can be changed at any time\n- this includes APIs which can be called by a module, module format\nand layout itself, etc. Not only that, same kernel version built with\ndifferent configuration options may have differences in these aspects\n(it's possible to #ifdef some fields in structures and even parameters\nto function calls).\n\nThat said, for close kernel versions and small differences in\nconfiguration, chances of fatal incompatibilities of modules are low.\nHowever, kernel itself has \"helpful guards\" to preclude usage of\nmodules with different kernel version. By default (CONFIG_MODVERSIONS\nis not defined), kernel's and module's vermagic strings are compared,\nwhich are of the form: \"3.2.0-32-generic SMP mod_unload modversions\n686\", i.e. include kernel version, extraversion, then tags for most\nimportant configuration params. If vermagics don't match, module\nloading fails.\n\nEven more annoying \"protection\" is employed if CONFIG_MODVERSIONS is\ndefined. In this case, each kernel exported symbol gets hash (CRC)\nsignature based on the parameter signature on the underlying C\nfunction, stored both in kernel and module. These signatures are\ncompared, and on any mismatch, loading fails. The only easing with\nthis is that when vermagics comparison is done, kernel versions are\nignored, i.e. if different kernel versions don't have param signature\nchanges and have same core config params, a module will work across\nsuch versions.\n\nThere's also support for forced module load, but that will work only\nif enabled in kernel config (CONFIG_MODULE_FORCE_LOAD).\n\n### How to get detailed information about a kernel module\n```\nmodinfo \u003cmodule\u003e\n```\n\nThis will dump main module properties and vermagic string. As a\nparameter, both a filename and system module name (as available in\n/lib/modules) can be given.\n\nTo dump modversions hashes:\n```\nmodprobe --dump-modversions \u003cmodule\u003e.ko\n```\n\n### How to build out of tree kernel module\n\nFrom official kernel docs:\n[Documentation/kbuild/modules.txt](http://www.kernel.org/doc/Documentation/kbuild/modules.txt),\nfor a module source in current dir:\n\n```\nmake -C \u003cpath_to_kernel_src\u003e M=$PWD\n```\n\nBuild against currently running kernel (requires linux-headers package\ninstalled):\n\n```\nmake -C /lib/modules/$(uname -r)/build M=$PWD\n```\n\n### How to install built kernel modules to a specific location\nUseful when cross-compiling, etc.\n```\nmake modules_install INSTALL_MOD_PATH=/path/where\n```\n\nMore details:\n[Documentation/kbuild/modules.txt](http://www.kernel.org/doc/Documentation/kbuild/modules.txt).\n\n\n### How to setup NAT (masquerading)\n\nIf you have another host/embedded device/QEMU connected to a local host interface,\nand you would like to let that device connect to the Internet, masquerading should\nbe set up for device's IP address:\n\n```\niptables -t nat -A POSTROUTING -j MASQUERADE -s 192.168.2.2\n```\n\n(This assumes that the host has Internet connection and has IP forwarding enabled).\n\n\n### How to connect to WiFi network from bare command-line (using wpa_supplicant \u0026 wpa_cli)\nIf you're not on bare command-line, make sure you killed already running\nwpa_supplicant as well as other daemons which may respawn it (e.g.\nNetworkManager on Ubuntu).\n\nMake sure that WiFi interface is up. It otherwise doesn't need to have any\nspecial configuration:\n```\nifconfig wlan0 up\n```\n\nRun:\n```\nwpa_supplicant -i wlan0 -g /tmp/wpa -C /tmp\n```\n\n`-g` specifies \"global control socket\". The caveat about is that many\ncommands are not supported via it, issuing them via it leads to obfuscated\n\"UNKNOWN COMMAND\" reply. So, it's important to specify `-C` switch, which\ntakes *directory* path under which individual control sockets for each\nWiFi interface will be stored.\n\nIn another window, run:\n```\nwpa_cli -p /tmp\n```\n\n`-p` option gives path to per-WiFi-interface control socket dir (`-C` of\nwpa_supplicant). Issue following commands in wpa_cli interactive session\n(ignore # lines):\n\n```\n# Scan for available APs\n\u003e scan\nOK\n# Wait a bit, then view results\n\u003c3\u003eCTRL-EVENT-SCAN-STARTED \n\u003c3\u003eCTRL-EVENT-SCAN-RESULTS \n\u003e scan_results \n...\n# Create new AP entry, returned is ID of new entry\n\u003e add_network\n0\n# Start setting AP parameters\n\u003e set_network 0 ssid \"MY_AP\"\nOK\n\u003e set_network 0 psk \"password\"\nOK\n# These should be all params requires for WPA\n# Activate network\n\u003e select_network 0\nOK\n# Trigger connection\n\u003e reconnect\nOK\n\u003c3\u003eSME: Trying to authenticate with xx:xx:xx:xx:xx:xx (SSID='MY_AP' freq=2462 MHz)\n\u003c3\u003eTrying to associate with xx:xx:xx:xx:xx:xx (SSID='MY_AP' freq=2462 MHz)\n\u003c3\u003eAssociated with xx:xx:xx:xx:xx:xx\n```\n\nThis will have wlan0 connected to AP. Then get IP address via DHCP:\n```\ndhclient wlan0\n```\n\nAnd configure /etc/resolv.conf to suitable DNS address (e.g. 8.8.8.8 to\nbe monitored by Google):\n```\nnameserver 8.8.8.8\n```\n\nThe instructions above show how to run wpa_supplicant without any stored\nconfiguration, and instead configure it dynamically (e.g., programmatically).\nAlternatively, using config:\n```\n# Create simple config file\nwpa_passphrase MY_AP \u003ewpa.conf\n# Enter password\n...\nwpa_supplicant -i wlan0 -c wpa.conf\n\n```\n\n### How to test network multicasting\nMulticasting is basis of many usability protocols and services (e.g. mDNS,\nUPNP, DLNA, etc.), and yet means to query/test/diagnose it are not widely\nknown, if not to say obfuscated. At the same time, multicasting has known\nandregular issues, when used on network interfaces differing from Ethernet,\nfor which it was initially conceived (these other networking types include\nWiFi/other wireless, loopback, etc.)\n\nMulticast is similar to broadcast, except individual hosts don't receive\ndatagrams unconditionally, but need to join \"multicast group\" (other way\nto think about it is a PubSub pattern). Multicast groups are represented\nby special IP addresses, e.g. for IPv4 it's 224.0.0.0 to 239.255.255.255.\nSome multicast IPs have predefined (STD/RFC) meaning, other are supposedly\ncan be (dynamically) allocated per purpose.\n\n224.0.0.1 is a \"local network\" predefined address. All hosts on current\nsubnetwork are supposed to (auto)join it. In this regard, that address is\nsimilar to local network broadcast, 255.255.255.255. The basic means to\ntest multicasting is ping this address:\n```\nping 224.0.0.1\n```\n\nThe expected outcome is that each host which is member of multicast group\nwill respond (ping thus will receive duplicate responses and will report so).\n\nHowever:\n* A firewall will likely interfere. Note that broadcast/multicast pings are\nespecially not firewall friendly, as replies are not received from\ndestination of packet (ping packets are sent to 224.0.0.1, but received from\nindividual host IPs). The easiest way to deal with this is usually to disable\nfirewall during testing.\n* Besides firewall, modern Linux kernels ignore broadcast/multicast pings\nby default. To enable responses to such pings use:\n```\necho \"0\" \u003e/proc/sys/net/ipv4/icmp_echo_ignore_broadcasts\n```\n(needs to be done on each machine from which you want to receive responses\nof course).\n* The network interface used should have multicast support enabled, and\ne.g. loopback (lo) is notoriously known to not have it enabled by distros\nby default.\n\nIf you have a normal Ethernet/WiFi interface, following first 2 suggestions\nshould lead to `ping 224.0.0.1` to get responses at least from the host\nyou run it on.\n\nFor other multicast groups, they should be pingable as long as a socket\nbound to that group is active on a host.\n\nTo further diagnose multicast settings, refer to following /proc files:\n* `/proc/net/igmp` (IP-level multicast)\n* `/proc/net/dev_mcast` (Physical-level multicast)\n\nFew other points:\n* It's not required to be a member of multicast group to send a datagram\nto it.\n* To send a datagram to multicast address, sendto() call should be used,\nif reply is expected to be received on the same socket. connect() +\nsend() won't work, because reply won't come from a multicast address, but\nreather from a real host address.\n\n## Android\n\n### How to enable ADB connection on device\n\nThis is called \"USB debugging\" and is available in Settings -\u003e Developer\noptions. Developer options themselves are concealed by default in\nAndroid 4.2 and higher. From https://developer.android.com/studio/debug/dev-options:\n\n\u003e On Android 4.1 and lower, the Developer options screen is available by\n\u003e default. On Android 4.2 and higher, you must enable this screen. To\n\u003e enable developer options, tap the Build Number option 7 times. You\n\u003e can find this option in one of the following locations, depending on\n\u003e your Android version:\n\u003e\n\u003e * Android 9 (API level 28) and higher: Settings \u003e About Phone \u003e Build Number\n\u003e * Android 8.0.0 (API level 26) and Android 8.1.0 (API level 26): Settings \u003e System \u003e About Phone \u003e Build Number\n\u003e * Android 7.1 (API level 25) and lower: Settings \u003e About Phone \u003e Build Number\n\n### How to configure udev rules for using adb over USB\n\nCreate `/etc/udev/rules.d/99-android.rules` with content:\n```\nSUBSYSTEM==\"usb\", ATTR{idVendor}==\"0bb4\", MODE=\"0660\", GROUP=\"plugdev\"\n```\n\nHere, ``0bb4`` is a USB vendor ID, you may need to adjust it for your device;\n``plugdev`` - is typical pluggable device access group on most modern Linux\ndistros.\n\nBased on: http://developer.android.com/tools/device.html\n\n### How to connect adb over WiFi (or TCP/IP in general)\nOn Android command line:\n```\nsu\nstop adbd\nsetprop service.adb.tcp.port 6565\nstart adbd\n```\n\nUse `netcfg` to check device IP. (In newer Android versions, standard\n`ifconfig` or `ip addr` may work.)\n\nPer above (`su`), this requires a rooted device. An alternative is to\nconnect device using USB first, and run `adb tcpip 6565`, after which\nUSB cable can be disconnected.\n\nAfter that, on host:\n```\nadb connect \u003cIP\u003e:6565\nadb shell\n```\n\n### How secure is ADB connection?\n\nADB protocol does not seem to support encryption (protocol description:\nhttps://android.googlesource.com/platform/system/core/+/master/adb/protocol.txt).\nThis means that using it over broadcasting non-encrypted physical medium (like\nEthernet or public WiFi) is insecure.\n\nUntil Android 4.2.2, protocol did not support authentication, which made it\nhighly insecure. There are known exploits of trojan \"charging stations\" used\nto break into devices.\n\nIn Android 4.2.1_r1, public key authentication was added to adb protocol:\nhttps://github.com/android/platform_system_core/commit/d5fcafaf41f8ec90986c813f75ec78402096af2d\nThis requires ADB version 1.0.31 (available in SDK Platform-tools r16.0.1 or\nhigher). User is required to confirm connection to a new ADB host on a device\nitself, for one time connection or to remember the approval. In the latter\ncase, host key(s) are saved in `/data/misc/adb/adb_keys`. There can be\npre-installed keys in `/adb_keys`.\n\n\n### How to verify ADB host fingerprint\n\nWhen connecting to a new ADB host, an Android device shows an RSA fingerprint,\nhowever, it takes some effort to check that this fingerprint actually belongs\nto a host.\n\nOn a host, ADB public key is in $HOME/.android/adb_key.pub. To get its\nfingerprint:\n\nawk '{print $1}' \u003c adbkey.pub|openssl base64 -A -d -a | openssl md5 -c\n\n\nBased on: http://nelenkov.blogspot.de/2013/02/secure-usb-debugging-in-android-422.html\n\n\n### How to read Android logs\nOn Android command line:\n```\nlogcat\n```\nSee `logcat --help`\n\nFrom host:\n```\nadb logcat\n```\n\n### How to list installed Android packages?\nOn device:\n```\npm list packages\n```\n\n### How to install Android package (.apk)?\nOn device:\n```\npm install app.apk\n```\n\n### How to install .apk using adb (from host command line)\nFrom host:\n```\nadb install app.apk\n```\n\nTo force install even if already exists:\n```\nadb install -r app.apk\n```\n\n`adb --help` for more.\n\n### How to remove installed Android package?\nOn device:\n```\npm uninstall \u003cpackage.name\u003e\n```\n\nThis won't work for system packages located in `/system/app`, see\nquestion below on how to remove them.\n\n### How to get around lack of `cp` in default Android `toolbox`\n\nTry:\n```\ncat /path/from \u003e/path/to\n```\n\n### Is there a writable location on the main filesystems on non-rooted device?\n\nFirst of all, there's `/mnt/sdcard`, which is accessible to default\n`adb` user. However, that filesystem is mounted `noexec`, so it's not\npossible to run any executables from there. However, there's\n`/data/local` which is both writable and executable. On newer Android\nversions (checked with Android 7), only `/data/local/tmp` is such.\n\n### How to get temporary root access on ro.secure=1 devices\n\nAn exploit executable is needed. For Android 2.x,\n[zergRush](https://github.com/revolutionary/zergRush) is a well-known\napp.\nOn host:\n```\nunzip zergRush.zip\nadb push zergRush /data/local\nadb shell\ncd /data/local\nchmod 770 zergRush\n./zergRush\n```\n\nIf you get error like `[-] Cannot copy boomsh.: Permission denied`,\nit's likely zergRush was already run previously and left some cruft,\nremove it and retry (on device):\n```\nrm tmp/sh\nrm tmp/boomsh\n./zergRush\n```\n\n### How to install Android su with frontend (permanent root)\n\nGet root shell as described above. Then (you [can get newer\nversions](http://androidsu.com/superuser/) than 3.0.7, but they're\nkinda bloat):\n```\nhttp://downloads.noshufou.netdna-cdn.com/superuser/Superuser-3.0.7-efghi-signed.zip\nunzip Superuser-3.0.7-efghi-signed.zip\nadb push system/bin/su /system/bin/\nadb push system/app/Superuser.apk /system/app/\nadb shell chmod 06755 /system/bin/su\n```\n\n### Where vendor-provided software is located in filesystem?\nPreinstalled application are in `/system/app`, unlike user-installed\napplications, which are in `/data/app` .\n\n### How to remove bloatware from /system/app\nThis requires root.\n\nOn host:\n```\nadb remount\nadb shell\n```\nThen on device:\n```\ncd /system/app\nrm bloatware.apk\nsync\n```\n\nYou may want to reboot to clear app cache, though apps should be gone\nimmediately.\n\n### What are user and group ids used by Android?\n\nThese are defined in\n[system/core/include/private/android_filesystem_config.h](http://code.metager.de/source/xref/android/2.3.7/system/core/include/private/android_filesystem_config.h)\n\n### Is it possible to use stdout/stderr/printf/System.out.println/etc. in Android?\n\nReference: http://developer.android.com/tools/debugging/debugging-log.html#viewingStd\n\nBy default, Android redirects stdout, etc. to /dev/null. However,\n`log.redirect-stdio` system property can be set to `true` to redirect\nto system log (logcat) instead. This takes effect after system restart\n(and has effect during current system session), so the complete command\nsequence to enable stdout logging is:\n\n```\nstop\nsetprop log.redirect-stdio true\nstart\n```\n\n### How to list Android services?\n```\nservice list\n```\n\n### How to call Android services from command line?\n\nBased on http://www.slideshare.net/jserv/android-ipc-mechanism\n\nGetting Java class implementing service:\n```\nservice call activity 1598968902\n```\n\n1598968902 (0x5f4e5446) is [INTERFACE_TRANSACTION](http://developer.android.com/reference/android/os/IBinder.html#INTERFACE_TRANSACTION).\n\nPrepare to dial number \"123\":\n```\nservice call phone 1 s16 123\n```\n\n\"1\" is a method #1 per\n[ITelephony.aidl](https://github.com/android/platform_frameworks_base/blob/master/telephony/java/com/android/internal/telephony/ITelephony.aidl),\ni.e. `dial()`.\n\n### How to start/stop Android daemons\n`start` \u0026 `stop` commands do that. E.g.:\n```\nstop vold\n```\n\nAlternatively, this can be done by setting system properties:\n```\nsetprop ctl.stop vold\nsetprop ctl.start vold\n```\n\n### How to start/stop complete Android environment\nFor this, `zygote` daemon should be stopped:\n```\nstop zygote\n```\n\nzygote is also a default argument for `start`/`stop`, so following\nwill work too:\n```\nstop\n```\n\n### How to dump detailed service state?\n`dumpsys \u003cservice\u003e` dumps loadsome of information about internal\nservice state. Omit service name to dump state of all services.\n\n### How to Allow Apps To Write Files to USB Mass Storage Devices in Android\n\n[Based\non](http://www.cnx-software.com/2012/08/26/how-to-allow-apps-to-write-files-to-usb-mass-storage-devices-in-android/):\n\nEdit `/system/etc/permissions/platform.xml` to add `\u003cgroup\ngid=\"media_rw\" /\u003e` to WRITE_EXTERNALS_STORAGE permission:\n\n```\n\u003cpermission name=\"android.permission.WRITE_EXTERNAL_STORAGE\"\u003e\n\u003cgroup gid=\"sdcard_rw\" /\u003e\n\u003cgroup gid=\"media_rw\" /\u003e\n\u003c/permission\u003e\n```\n\nReboot required. Tested with Android 4.\n\n### How to list all modules available in Android platform source tree?\n```\nmake modules\n```\n\n### Is it possible to write console Dalvik apps?\nYes, actually \"am\", \"pm\" and few other standard Android tools are actually\nsuch, and are run via shell wrapper:\nhttps://android.googlesource.com/platform/frameworks/base/+/gingerbread/cmds/am/\n\n[hello-world.html](https://android.googlesource.com/platform/dalvik/+/gingerbread/docs/hello-world.html)\nfrom platform/dalvik/docs/ explains how:\n\n```\n# Create file Foo.java\nclass Foo {\n    public static void main(String[] args) {\n        System.out.println(\"Hello, world\");\n    }\n}\n```\n\n```\njavac Foo.java\ndx --dex --output=foo.jar Foo.class\nadb push foo.jar /sdcard\nadb shell dalvikvm -cp /sdcard/foo.jar Foo\n```\n\n### I tried to flash a custom image to recovery partition (Android 4.x), however it doesn't boot and instead \"red triangle of doom\" is shown\nAssuming the image is correct for your type of device and flashed into\nright place for it, known \"feature\" which causes this behavior is\nAndroid 4.x \"recovery from boot\". The idea is following: Recovery\nallows you to restore main Android install if something goes wrong.\nBut what if recovery itself gets corrupted? Then if main image gets\ncorrupted too, the device is bricked. So, main image and recovery were\nmade to \"watch after another\". In particular, during boot of main\nimage, recovery partition is checked, and if it doesn't contain \"know\ngood\" image, it gets silently reflashed with copy of such image kept\nin main partition.\n\nThe backup of recovery image is commonly held in\n/system/recovery-from-boot.p . Actual boot-time checking and\nreflashing is handled by /system/etc/install-recovery.sh . Thus, to\ndisable this behavior which gets into way of advanced Android usage,\ndo following:\n```\nmv /system/recovery-from-boot.p /system/recovery-from-boot.p.old\n```\nor:\n```\nchmod 644 /system/etc/install-recovery.sh\n```\n\nAlso, \"red triangle of doom\" is actually how a stock recovery of\nAndroid 4.x looks - while previous versions offered interactive means\nto investigate and fix your device, that's what to it was reduced in\nAndroid 4.x.\n\nBased on:\nhttp://android.stackexchange.com/questions/18932/why-isnt-clockworkmod-recovery-sticking\n, http://androtab.info/clockworkmod/rockchip/install/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpfalcon%2Fawesome-linux-android-hacking","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpfalcon%2Fawesome-linux-android-hacking","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpfalcon%2Fawesome-linux-android-hacking/lists"}