Skip to content

Instantly share code, notes, and snippets.

@mr-fixit
Last active March 22, 2021 18:45
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mr-fixit/5db589ba7f5f7028aba65fc7c9731370 to your computer and use it in GitHub Desktop.
Save mr-fixit/5db589ba7f5f7028aba65fc7c9731370 to your computer and use it in GitHub Desktop.
#!/bin/bash
# scan path[s] for files, folders or ZIPs containing Xcode projects with suspicious contents
if [[ $# == 0 ]]; then
echo "usage: $0 [--verbose] path [path2 ...]"
echo " path can be a folder or a file"
exit
fi
function do_file() {
FILE=$1
if [[ -z $QUIET ]]; then
echo "do_file(): '${FILE}'"
fi
FILE_TYPE=`file -b --mime "$FILE"`
if [[ $FILE_TYPE =~ "application/gzip" ]]; then
echo "error: $0 doesn't do gzip files like $FILE"
elif [[ $FILE_TYPE =~ "application/zip" ]]; then
# echo the path on any line containing pbxproj by JMPing over the first 3 fields
unzip -l "$FILE" | \
awk '/pbxproj/ {JMP=3; for (i=1; i<=NF-JMP; i++) $i = $(i+JMP); NF-=JMP; print}' | \
while read PBX_INTERNAL_PATH; do
if [[ -z $QUIET ]]; then
echo "project path in zip file: '$PBX_INTERNAL_PATH'"
fi
TMP_PROJECT=`mktemp`
unzip -p "$FILE" "$PBX_INTERNAL_PATH" > $TMP_PROJECT
do_project $TMP_PROJECT "$FILE"
done
elif [[ "$FILE" =~ ".pbxproj" ]]; then
do_project "$FILE"
elif [[ -z $QUIET ]]; then
echo \'$FILE\' is not a ZIP file
fi
}
function do_project() {
PBXPROJ="$1"
ZIPFILE="$2"
# look for any hidden files
grep $QUIET '/\.[^.]' "$PBXPROJ"
no_hidden=$?
# look for XCSSET malware
grep $QUIET xcuserdata/.xcassets/Assets.xcassets "$PBXPROJ"
no_xcsset=$?
# look for 'eval' in build phases
grep 'shellScript.*eval' "$PBXPROJ"
no_eval=$?
# report
if [[ -s "$ZIPFILE" ]]; then
IN_ZIP=" in ${ZIPFILE}"
fi
if (( ! $no_xcsset )); then
echo " ${PBX_INTERNAL_PATH}${IN_ZIP} is infected with XCSSET malware"
fi
if (( ! $no_hidden )); then
echo " ${PBX_INTERNAL_PATH}${IN_ZIP} references hidden files"
fi
if (( ! $no_eval )); then
echo " ${PBX_INTERNAL_PATH}${IN_ZIP} contains eval expressions in shell-script build phases (see above)"
fi
if (( $no_xcsset | ! $no_hidden | ! $no_eval )); then
echo " ${PBX_INTERNAL_PATH}${IN_ZIP} appears to be OK"
fi
}
QUIET=-q
for PARAM in "$@"; do
if [[ $PARAM = --verbose ]]; then QUIET=""; continue; fi
if [[ -z $QUIET ]]; then
echo "PARAM='${PARAM}'"
fi
find "${PARAM}" -type f | while read FILE; do do_file "${FILE}"; done
done
@mr-fixit
Copy link
Author

mr-fixit commented Aug 20, 2020

This is a script that’ll scan folders, projects or ZIPs for the XCSSET malware.

Trend Micro's Technical Brief: https://documents.trendmicro.com/assets/pdf/XCSSET_Technical_Brief.pdf

There are at least two infected repos out there:

You can DL them as ZIPs if you want to see a positive test.

In addition to specifically testing for XCSSET, this script also looks for project files that reference ANY hidden file (where "hidden" is defined as "name starts with dot").

There's more to do, but you have to start somewhere.

@mr-fixit
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment