10px^2 spacer

shell scripts

this is a collection of miscellaneous shell scripting projects i've worked on (and may have finished), am working on (and may never finish), or may work on.

downloadable project files are contained within compressed archives (zip) to be more "security software/hardware friendly" as these archives are often less scrutinized (which is hilarious) while executable binaries are most scrutinized, often blocked outright by software/application firewalls for example.

thumbnails are cropped, scaled-down versions of the original image.  to see the un-cropped, full-size original image, which will open in a new window, click its respective thumbnail.


android_scripts_huawei_ascend

android scripts (huawei ascend)

i used to own a huawei ascend (m860) from cricket and had written some shell scripts for it.  here are all of those scripts which had come in handy for various system modifications, system troubleshooting, system diagnostics, and app backups.

cp.sh (windows command processor)

cp.sh new window internal link (windows command processor)

pong.sh (better terminal emulator magic)

pong.sh new window internal link (better terminal emulator magic)

rmount.sh (windows command processor)

rmount.sh new window internal link (windows command processor)

wifi_config.sh (better terminal emulator magic)

wifi_config.sh new window internal link (better terminal emulator magic)

these scripts are independent of each other and have no dependencies that aren't already available on any version of android.

expand/collapse cp.sh
the shell environment is sans an "easy" 1:1 file copy command.  while dd is present, cp isn't.  cp.sh solves this problem by using dd to do 1:1 file copying.  equivalent to dd if=SOURCE of=DESTINATION bs=4096.

#!/system/bin/sh
#
# cp.sh
#
# Simple (very) 1:1 file copy script.  Utilizes dd.
#
# The shell on my Huawei M860 running Android 2.1 (Update 1) is sans cp.
#
# (C)MMX Ickis <ickis84@hotmail.com>.  All rights reserved.

src="$1" # SOURCE
dst="$2" # DESTINATION

dd_copy()
{
  dd if=$src of=$dst bs=4096
}

case "$1" in
  '') echo "Usage: $0 SOURCE DESTINATION";;
  *)
    case "$2" in
      '') echo "Usage: $0 SOURCE DESTINATION";;
      *) dd_copy;;
    esac
  ;;
esac
expand/collapse pong.sh
this pings a host 10 times.  equivalent to ping -U -n -c 10 HOST.

#!/system/bin/sh
#
# pong.sh
#
# Script to ping a host.
#
# Script pings a specified host 10 times.
#
# (C)MMX Ickis <ickis84@hotmail.com>.  All rights reserved.

case "$1" in
  '') echo "Usage: $0 HOST";;
  *) ping -U -n -c 10 $1;;
esac
expand/collapse rmount.sh
this, which requires root, remounts the / or /system directories as read-only or read/write.

#!/system/bin/sh
#
# rmount.sh
#
# Specific partition remount script.
#
# Script to remount the '/' and '/system' partitions as read-only or
# read/write on my Huawei M860 running Android 2.1 (Update 1).
#
# (C)MMX Ickis <ickis84@hotmail.com>.  All rights reserved.

# mount result excerpt
#
#   rootfs / rootfs ro 0 0
#   /dev/block/mtdblock4 /system yaffs2 ro 0 0

case "$1" in
  'system') # /system
    case "$2" in
      'ro') mount -o ro,remount -t yaffs2 /dev/block/mtdblock4 /system;; # read-only
      'rw') mount -o rw,remount -t yaffs2 /dev/block/mtdblock4 /system;; # read/write
      *) echo "Unknown filesystem mode.";;                               # unknown
    esac
  ;;
  'root') # /
    case "$2" in
      'ro') mount -o ro,remount -t rootfs rootfs /;; # read-only
      'rw') mount -o rw,remount -t rootfs rootfs /;; # read/write
      *) echo "Unknown filesystem mode.";;           # unknown
    esac
  ;;
  *) echo "Usage: $0 root|system ro|rw";;
esac
expand/collapse wifi_config.sh
system environment dump of wi-fi settings.

#!/system/bin/sh
#
# wifi_config.sh
#
# Script to dump current Wi-Fi configuration properties to screen.
#
# (C)MMX Ickis <ickis84@hotmail.com>.  All rights reserved.

# getprop result excerpt
#
# [wifi.interface]: [eth0]
# [dhcp.eth0.result]: [ok]
# [dhcp.eth0.pid]: [5519]
# [dhcp.eth0.reason]: [BOUND]
# [dhcp.eth0.dns1]: [10.10.220.1]
# [dhcp.eth0.dns2]: []
# [dhcp.eth0.dns3]: []
# [dhcp.eth0.dns4]: []
# [dhcp.eth0.ipaddress]: [10.11.12.3]
# [dhcp.eth0.gateway]: [10.11.12.13]
# [dhcp.eth0.mask]: [255.255.255.224]
# [dhcp.eth0.leasetime]: [86400]
# [dhcp.eth0.server]: [10.11.12.13]

wifi_interface=`getprop wifi.interface`
dhcp_result=`getprop dhcp.$wifi_interface.result`
dhcp_reason=`getprop dhcp.$wifi_interface.reason`
dhcp_pid=`getprop dhcp.$wifi_interface.pid`
dhcp_server=`getprop dhcp.$wifi_interface.server`
dhcp_leastime=`getprop dhcp.$wifi_interface.leasetime`
dhcp_ipaddress=`getprop dhcp.$wifi_interface.ipaddress`
dhcp_gateway=`getprop dhcp.$wifi_interface.gateway`
dhcp_mask=`getprop dhcp.$wifi_interface.mask`
dhcp_dns1=`getprop dhcp.$wifi_interface.dns1`
dhcp_dns2=`getprop dhcp.$wifi_interface.dns2`
dhcp_dns3=`getprop dhcp.$wifi_interface.dns3`
dhcp_dns4=`getprop dhcp.$wifi_interface.dns4`

echo "Wi-Fi interface: $wifi_interface"
echo "$wifi_interface result: $dhcp_result"
echo "$wifi_interface reason: $dhcp_reason"
echo "$wifi_interface PID: $dhcp_pid"
echo "$wifi_interface server: $dhcp_server"
echo "$wifi_interface lease time: $dhcp_leastime"
echo "$wifi_interface IP address: $dhcp_ipaddress"
echo "$wifi_interface gateway: $dhcp_gateway"
echo "$wifi_interface subnet mask: $dhcp_mask"
echo "$wifi_interface DNS server 1: $dhcp_dns1"
echo "$wifi_interface DNS server 2: $dhcp_dns2"
echo "$wifi_interface DNS server 3: $dhcp_dns3"
echo "$wifi_interface DNS server 4: $dhcp_dns4"
expand/collapse apps_backup.sh
this backs up installed apps to external memory "sd card".

#!/system/bin/sh
#
# apps_backup.sh
#
# Script to backup installed apps to external memory (e.g. "SD card").
#
# (C)MMX Ickis <ickis84@hotmail.com>.  All rights reserved.

apps_dir="/data/app/"                      # path must end with '/'
backup_dir="/sdcard/apps/installed/"       # path must end with '/'
txt_file="/sdcard/apps/installed/apps.txt"
log_file="/sdcard/apps_backup.log"
date=`date`

ls $apps_dir > $txt_file
echo -e "apps_backup.sh Log - $date\n" > $log_file

while read app
  do
    echo $app >> $log_file
    dd if=$apps_dir$app of=$backup_dir$app bs=4096 2>> $log_file
    echo >> $log_file
done <$txt_file

rm $txt_file

"apps to csv"

this exports specified app data to a csv file for export.  this specified data can be:

  • permissions
  • owner
  • group
  • date
  • time
  • file

these scripts are dependent of each other and have no other dependencies that aren't already available on any version of android.

expand/collapse appstocsv
exports specified app data to a csv file for export.  it's implied that vars.cfg, apps_to_csv, and parse_ls_output.sh reside in /system/bin/apps_to_csv/.

#!/system/bin/sh

OLD_PATH=$PATH

export PATH=$PATH:/system/bin/apps_to_csv
cd /system/bin/apps_to_csv
apps_to_csv.sh
cd -
PATH=$OLD_PATH
expand/collapse vars.cfg
file with global variables for apps_to_csv.sh and parse_ls_output.sh.  should reside in /system/bin/apps_to_csv/.

# vars.cfg
#
# File with global variables for 'apps_to_csv.sh' and 'parse_ls_output.sh'.
#
# (C)MMX Ickis <ickis84@hotmail.com>.  All rights reserved.

APPS_DIR="/data/data/"         # directory with app data
CSV_FILE="apps.csv"            # result of apps_to_csv.sh
TXT_FILE="apps.txt"            # result of 'ls -l' on $APPS_DIR
SEPARATOR=" "                  # separator to use with $IFS to tokenize lines in $APPS_TXT
HEADER="\"OWNER\",\"PACKAGE\"" # headers to use in $CSV_FILE

# line from $APPS_TXT
#
#   drwxr-xr-x app_46   app_46            2010-11-10 10:51 com.android.mms

# tokens created by parse_ls_output.sh on the above $APPS_TXT line
#
# $1 = permissions
# $2 = owner
# $3 = group
# $4 = date
# $5 = time
# $6 = file

TOKENS="\\\"\$2\\\",\\\"\$6\\\"" # tokenized fields from $APPS_TXT to populate $CSV_FILE with
expand/collapse apps_to_csv.sh
script to export specific fields from ls -l of $APPS_DIR as $APPS_CSV.  should reside in /system/bin/apps_to_csv/.

#!/system/bin/sh
#
# apps_to_csv.sh
#
# Script to export specific fields from 'ls -l' of $APPS_DIR as $APPS_CSV.
#
# (C)MMX Ickis <ickis84@hotmail.com>.  All rights reserved.

. vars.cfg

ls -l $APPS_DIR > $TXT_FILE
echo $HEADER > $CSV_FILE

while read fields
  do
    ./parse_ls_output.sh $fields >> $CSV_FILE
done <$TXT_FILE

rm $TXT_FILE
expand/collapse parse_ls_output.sh
script to tokenize lines in $APPS_TXT (see vars.cfg).  should reside in /system/bin/apps_to_csv/.

#!/system/bin/sh
#
# parse_ls_output.sh
#
# Script to tokenize lines in $APPS_TXT (see 'vars.cfg').
#
# (C)MMX Ickis <ickis84@hotmail.com>.  All rights reserved.

. vars.cfg

fields=$@
IFS=$SEPARATOR

set -- $fields

eval echo $TOKENS

unset IFS

the whole enchilada

for ease/convenience i've placed all of my android scripts into an archive with a setup/install script.  said setup/install script will create all the necessary folders on both the device and the external memory (sd card), do all the necessary file copying, set all the necessary file permissions, and even create all the necessary symbolic links which will allow said scripts to be executed from within anywhere in the shell (without the .sh extension).

save link android.scripts.zip (4.11 kilobytes)
my android scripts.  extract to the device's root directory.  speaking of root, you'll need to be root to setup/install.  to setup/install, after becoming root of course, execute the following commands:

chmod 755 setup.sh
./setup.sh

md5 checksum: ca20df5541bb7198d38a73209c1c0e36

android_scripts_samsung_galaxy_tab_2_7_0

android scripts (samsung galaxy tab 2 (7.0))

i currently own a samsung galaxy tab 2 (7.0) (gt-p3113) and have written a couple shell scripts for it.  here are those couple shell scripts which come in handy for various information security "tasks".

these scripts are independent of each other and have no dependencies that aren't already available on any version of android.

expand/collapse randomac.sh
this script, which requires root, will change the device's mac address from its default one to a random one (and back again if so desired), with the option to reboot afterwards.

#!/system/bin/sh
#
# randomac.sh
#
# Script to randomize/reset the MAC address (after reboot).
#
# (C)MMXIII Ickis <ickis@nerpter77.com>.  Permission to use, copy, modify, and
# distribute this software and its documentation for non-commercial purposes and
# without fee is hereby granted.

case "$1" in
  'random') # random
    if [ ! -e "/efs/wifi/.mac.cob.old" ]; then
      dd if=/efs/wifi/.mac.cob of=/efs/wifi/.mac.cob.old bs=4096
      chmod 600 /efs/wifi/.mac.cob.old
    fi

    echo "00:00:00:00:00:00" > /efs/wifi/.mac.cob

    if [ ! -e "/efs/wifi/.mac.info.old" ]; then
      dd if=/efs/wifi/.mac.info of=/efs/wifi/.mac.info.old bs=4096
      chmod 664 /efs/wifi/.mac.info.old
    fi

    echo "00:00:00:00:00:00" > /efs/wifi/.mac.info

    case "$2" in
      'reboot') reboot;;
      '');;
      *) echo "Usage: $0 random|reset [reboot]";;
    esac
  ;;
  'reset') # reset
    if [ -e "/efs/wifi/.mac.cob.old" ]; then
      if [ "`md5sum /efs/wifi/.mac.cob.old | grep -o \"[a-f0-9]\{32\}\"`" != "`md5sum /efs/wifi/.mac.cob | grep -o \"[a-f0-9]\{32\}\"`" ]; then
        dd if=/efs/wifi/.mac.cob.old of=/efs/wifi/.mac.cob bs=4096
      fi
    fi

    if [ -e "/efs/wifi/.mac.info.old" ]; then
      if [ "`md5sum /efs/wifi/.mac.info.old | grep -o \"[a-f0-9]\{32\}\"`" != "`md5sum /efs/wifi/.mac.info | grep -o \"[a-f0-9]\{32\}\"`" ]; then
        dd if=/efs/wifi/.mac.info.old of=/efs/wifi/.mac.info bs=4096
      fi
    fi

    case "$2" in
      'reboot') reboot;;
      '');;
      *) echo "Usage: $0 random|reset [reboot]";;
    esac
  ;;
  *) echo "Usage: $0 random|reset [reboot]";;
esac
expand/collapse change_hostname.sh
this script, which requires root, will change the device's hostname (temporarily) to a user-defined one, with the option to bring down and bring up wlan0 (effectively reconnecting to the current network).

#!/system/bin/sh
#
# change_hostname.sh
#
# Script to change the (network) hostname (after network reconnect).
# Modifies the 'net.hostname' system property.
#
# (C)MMXIII Ickis <ickis@nerpter77.com>.  Permission to use, copy, modify, and
# distribute this software and its documentation for non-commercial purposes and
# without fee is hereby granted.

if [ "$1" != "" ]; then
  setprop net.hostname $1

  case "$2" in
    'reconnect')
      if [ "`ifconfig wlan0 | grep -o \"up\"`" = "up" ]; then
        ifconfig wlan0 down
        ifconfig wlan0 up
      fi
    ;;
    '');;
    *) echo "Usage: $0 HOSTNAME [reconnect]";;
  esac
else
  echo "Usage: $0 HOSTNAME [reconnect]"
fi

df_pl

df.pl

df.pl is a perl script that executes df (specifically, it executes df -alB1) and formats the output.

there's an error new window internal link with properly formatting filesystems whose labels are in excess of 20 characters in length (such is the case with anything redhat or redhat-based).  when this happens, the label in question is truncated to 20 characters and then put on a line with all fields set to zero while the actual fields are put on a line with a blank label.  this may or may not be a big deal in interpreting results since they're alphabetized.

this script has no dependencies and should run under practically, if not literally, any version of perl on bsd, unix, or any linux-based operating system.

expand/collapse df.pl
believe it or not, there are comments! no, really there are! really!

#!/usr/bin/perl
#
# df.pl
#
# (C)MMV Ickis <ickis@nerpter77.com>.  All rights reserved.
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for non-commercial or commercial purposes and without fee is
# hereby granted.

# Execute the shell command, $command.
$command = `df -alB1`;

# Format for displaying the result(s).
$text_format = '%-22.20s%-9.7s%-9.7s%-9.7s%-7.5s%s%-.20s';
$number_format = '%-22.20s%6.2f%-3.1s%6.2f%-3.1s%6.2f%-3.1s%5.4s%-2.1s%s%-.20s';
$separator = '-' x 20;

# Split the value of $command, @df, at any new lines.
@df = split(/\n/, $command);

# Remove the "header" from the value of $command, @df.
shift(@df);

# Sort the value of $command, @df, alphabetically.
@df = sort @df;

# Subroutine for returning the letter of the associated byte size: B, K, M,
# or G.
sub byte_letter
{
  local($n);
  $n = @_[0];

  if (($n / 1073741824) > 1) { return ('G'); }
  elsif (($n / 1048576) > 1) { return ('M'); }
  elsif (($n / 1024) > 1) { return ('K'); }
  else { return ('B'); }
}

# Subroutine for converting and returning bytes to bytes, kilobytes,
# megabytes, or gigabytes.
sub byte_size
{
  local($n);
  $n = @_[0];

  if (($n / 1073741824) > 1) { return ($n / 1073741824); }
  elsif (($n / 1048576) > 1) { return ($n / 1048576); }
  elsif (($n / 1024) > 1) { return ($n / 1024); }
  else { return ($n); }
}

# Subroutine for returning the usage of a mount point.
sub byte_usage
{
  local($dividend);
  $dividend = @_[0];
  local($divisor);
  $divisor = @_[1];

  if ($divisor > 0) { return (sprintf('%.0f%', ($dividend / $divisor) * 100)); }
  else { return ('0%'); }
}

# Split the value of $command, @df, at any whitespace.
for ($i = 0; $i < @df; $i += 1) { @df[$i] = [ split(/\s+/, @df[$i]) ]; }

# Format result "header".
printf($text_format, 'Filesystem:', 'Size:', 'Used:', 'Avail:', 'Use%:', 'Mount Point:', "\n");
printf($text_format, $separator, $separator, $separator, $separator, $separator, $separator, "\n");

# Format and populate result "table".
for ($i = 0; $i < scalar(@df); $i += 1)
{
  printf($number_format, $df[$i][0], &byte_size($df[$i][1]), &byte_letter($df[$i][1]), &byte_size($df[$i][2]), &byte_letter($df[$i][2]), &byte_size($df[$i][3]), &byte_letter($df[$i][3]), &byte_usage($df[$i][2], $df[$i][1]), '', $df[$i][5], "\n");
  $total_size += $df[$i][1];
  $total_used += $df[$i][2];
  $total_avail += $df[$i][3];
}

# Format result totals.
$total_usage = sprintf('%.0f', ($total_used / $total_size) * 100);
printf($text_format, $separator, $separator, $separator, $separator, $separator, $separator, "\n");
printf($number_format, 'Total:', &byte_size($total_size), &byte_letter($total_size), &byte_size($total_used), &byte_letter($total_used), &byte_size($total_avail), &byte_letter($total_avail), $total_usage . '%', '', '-', "\n");

dragoncln_pl_dragon_cleanup

dragoncln.pl (dragon cleanup)

this is my first script working at a managed security services provider as an information security professional.  in addition to this script being my first as an infosec pro, it was my first perl script.  i bought a copy of perl for dummies new window internal link which i used as a reference.  ran as a cron job, it replaced the manual task of having to access the shell on an enterasys dragon ips/ids manager to purge its logs.  this log purging was done once the log partition had become full.

reading its comments (i know, i know... i never comment my code... save for when i've a financial incentive to do so), you can see how the logic traces the thought process which would be used in the manual task it's replacing.

this script has no dependencies.

expand/collapse dragoncln.pl
as previously stated, unbelievably, there are comments! no, really! there are! in addition to this, personally identifiable information has been redacted from said comments.

#!/usr/bin/perl
#
#  Dragon Cleanup
#
#  Removes files and directories from multiple directory paths, intended for
#  use with Dragon to remove log files/directories.
#
#  Anthony XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.
#  (C)2004 XXXXXXXXXXXXXXX.  All rights reserved.

$then = 30; # 'Time' to determine how old files must be before removing.

# Loop to check command line arguments (directory paths).
for($i = 0; $i <= $#ARGV; $i += 1)
{
  if (-e $ARGV[$i]) # Make sure the directory path exists.
  {
    if (-d $ARGV[$i]) # Make sure the directory path is indeed that.
    {
      chdir($ARGV[$i]); # Change Perl's working directory to the specified directory.
      opendir(DIR, $ARGV[$i]); # Open the directory to get a full listing of its contents.
      @files = readdir(DIR); # Read the directory.

      # Reomval criteria is as follows: a file, a directory, not executable,
      # not a link, not the current directory, not the parent directory, and
      # as old or older than $then.
      foreach $file (@files)
      {
        if ((((-f $file) || (-d $file)) && ((!-x $file) && (!-l $file))) && (($file ne '.') && ($file ne '..')))
        {
          # The line below removes which file(s)/dir(s) meet the criteria.
          #if (-C $file > $then) { system("rm -r $file") }

          # The lines below are purely for debugging purposes.  They displays
          # which file(s)/dir(s) meet the criteria to be removed.
          if (-C $file > $then)
          {
            $c = -C $file;
            print "$file $c\n";
          }
        }
      }

      closedir(DIR); # Close the directory.
    }
  }
}
©mmxxi ickis, ickis@nerpter77.com mail link.  all rights reserved.  updates rss linkprivacy policy.