#!/bin/bash mkdir -p db die() { echo >&2 $1 exit 1 } dump_symbols() { readelf -Ws $1 | perl -n -e '/: (\w*).*?(\w+)@@GLIBC_/ && print "$2 $1\n"' } extract_label() { perl -n -e '/(\w+)/ && print $1' } dump_libc_start_main_ret() { if [ `echo "$2" | egrep "i386|amd64" - ` ] \ && [ -x "$(command -v objdump)" ]; then local call_main=`objdump -D $1 \ | egrep -A 100 '<__libc_start_main.*>' \ | grep call \ | egrep -B 1 '' \ | head -n 1 \ | extract_label` local offset=`objdump -D $1 | egrep -A 1 "(^| )$call_main:" | tail -n 1 | extract_label` elif [ `echo "$2" | egrep "armel|armhf|arm64" - ` ] \ && [ -x "$(command -v aarch64-linux-gnu-objdump)" ]; then local call_main=`aarch64-linux-gnu-objdump -D $1 \ | egrep -A 100 '<__libc_start_main.*>' \ | grep -Pe "(bl\t|blr\t|blx\t|bx\t)" \ | egrep -B 1 '' \ | head -n 1 \ | extract_label` local offset=`aarch64-linux-gnu-objdump -D $1 \ | egrep -A 1 "(^| )$call_main:" \ | tail -n 1 \ | extract_label` fi if [[ "$offset" != "" ]]; then echo "__libc_start_main_ret $offset" fi } dump_bin_sh() { local offset=`strings -a -t x $1 | grep '/bin/sh' | head -n 1 | extract_label` if [[ "$offset" != "" ]]; then echo "str_bin_sh $offset" fi } process_libc() { local libc=$1 local id=$2 local info=$3 local sha256=$4 [[ -d db/$info ]] || mkdir db/$info echo " -> Writing libc to db/${info}/${id}.so" cp $libc db/${info}/${id}.so echo " -> Writing symbols to db/${info}/${id}.symbols" (dump_symbols $libc; dump_libc_start_main_ret $libc $id; dump_bin_sh $libc) \ > db/${info}/${id}.symbols echo " -> Writing SHA-256 to db/${info}/${id}.sha256" echo "$sha256" > db/${info}/${id}.sha256 } check_id() { local id=$1 local info=$2 if [[ -e db/${info}/${id}.sha256 ]]; then echo " -> Already have this version, 'rm db/${info}/${id}.*' to force" return 1 fi return 0 } check_sha256() { local sha256=$1 local libc=`grep -r $sha256 db/ 2>/dev/null | cut -d ':' -f 1 - 2>/dev/null | sed 's/\.sha256/\.so/gI'` if [[ "$libc" != "" ]]; then echo " -> Found SHA-256 match: $libc" return 1 fi return 0 } # ===== Debian and Ubuntu ===== # get_deb() { local url="$1" local info="$2" local tmp=`mktemp -d || mktemp -d -t "libc-database" || die "Cannot get temp dir"` echo "Getting $info" echo " -> Location: $url" local id=`echo $url | perl -n -e '/(libc6[^\/]*)\./ && print $1' | sed 's/\%2b/+/gI'` echo " -> ID: $id" check_id $id $info || return echo " -> Downloading package" wget $url 2>/dev/null -O $tmp/pkg.deb || die "Failed to download package from $url" echo " -> Extracting package" pushd $tmp 1>/dev/null ar x pkg.deb || die "ar failed" tar xf data.tar.* || die "tar failed" popd 1>/dev/null local libc=`find $tmp -name libc.so.6 || die "Cannot locate libc.so.6"` if [[ ! -e $libc ]]; then echo " -> The package does not seem to contain a valid libc (e.g. just contains a broken symbolic link)" return fi local sha256=`sha256sum $libc` check_sha256 $sha256 || return process_libc $libc $id $info $sha256 rm -rf $tmp } get_current_ubuntu() { local version=$1 local arch=$2 local pkg=$3 local info=ubuntu-$version-$arch-$pkg echo "Getting package location for ubuntu-$version-$arch" local url=`(wget http://packages.ubuntu.com/$version/$arch/$pkg/download -O - 2>/dev/null \ | grep -oh 'http://[^"]*libc6[^"]*.deb') || die "Failed to get package version"` get_deb $url $info } get_all_debian() { local info=debian-$1 local url=$2 for f in `wget $url/ -O - 2>/dev/null | egrep -oh 'libc6(-i386|-i686|-amd64|-armel|-armhf|-arm64)?(-cross)?_[^"]*(i386|amd64|armel|armhf|arm64|all)\.deb' | grep -v ""`; do get_deb $url/$f $info done } get_all_ubuntu() { local info=ubuntu-$1 local url=$2 for f in `wget $url/ -O - 2>/dev/null | egrep -oh 'libc6(-i386|-i686|-amd64|-armel|-armel-armhf|-armhf|-arm64)?(-cross)?_[^"]*(i386|amd64|armel|armhf|arm64|all)\.deb' | grep -v ""`; do get_deb $url/$f $info done } # ===== Local ===== # add_local() { local libc=$1 [[ -e $libc ]] || return local info="local" local id="local-`sha256sum $libc`" echo "Adding local libc $libc (id $id)" check_id $id $info || return local sha256=`sha256sum $libc` check_sha256 $sha256 || return process_libc $libc $id $info $sha256 }