radare2/binr/ragg2/ragg2-cc

258 lines
4.4 KiB
Bash
Executable File

#!/bin/sh
# ragg2-cc : a shellcode compiler -- pancake - 2011-2013
#
# Supported operating systems:
# - GNU/Linux
# - OSX
# - BSD
# Supported compilers
# - gcc
# - clang
# TODO
# add support for arm
# add support for nested shellcodes
# Find which compiler is installed
if [ -z "${CC}" ]; then
for a in llvm-gcc clang gcc ; do
$a --version >/dev/null 2>&1
if [ $? = 0 ]; then
CC="$a"
break
fi
done
if [ -z "${CC}" ]; then
echo "Cannot find CC" > /dev/stderr
exit 1
fi
fi
# Get path for sflib
if [ -z "${SFLIBPATH}" ]; then
SFLIBPATH="$(r2 -hh | grep INCDIR | awk '{print $2}')"/sflib
fi
if [ ! -d "${SFLIBPATH}" ]; then
echo "Cannot find ${SFLIBPATH}"
echo "Define SFLIBPATH env var or fix the r2 installation"
exit 1
fi
# Get local architecture
case "$(uname -m)" in
"x86_64")
B=64
;;
*)
B=32
;;
esac
dohelp() {
cat<<EOF
Usage: ragg2-cc [-cdsvx] [-a arch] [-b bits] [-k kernel] [-o output] [file.c]
-a x86 set arch (x86, arm)
-b 32 bits (32, 64)
-c generate compiled shellcode
-d enable debug mode
-k linux set kernel (darwin, linux)
-o file set output file
-s generate assembly
-v show version
-x show hexpair bytes
EOF
}
case "`uname`" in
Darwin)
K=darwin
;;
*)
K=linux
;;
esac
X=0
C=""
D=""
O=""
F=""
ASM=0
A=x86
while : ; do
[ -z "$1" ] && break
F=$1
case "$F" in
-a) # architecture (x86, mips, arm)
shift
A=$1
[ -z "$A" ] && { echo "Missing argument for -a" ; exit 1; }
;;
-b) # register size (32, 64, ...)
shift
B=$1
[ -z "$B" ] && { echo "Missing argument for -b" ; exit 1; }
;;
-k) # kernel
shift
K=$1
[ -z "$K" ] && { echo "Missing argument for -k" ; exit 1; }
;;
-x) # execute
X=1
;;
-c) # set configuration option
C=1
;;
-d) # patch dword (4 bytes) at given offset
D=1
;;
-s) # show assembler
ASM=1
;;
-o) # output file
shift
O=$1
if [ -z "$O" ]; then
echo "Missing argument for -o"
exit 1
fi
;;
-h) # help
dohelp
exit 0
;;
-v) # version
ragg2 -v | sed -e 's,2,2-cc,'
exit 0
;;
esac
shift
done
if [ -z "$F" ]; then
dohelp
exit 1
fi
if [ "`uname`" = Darwin ]; then
OBJCOPY=gobjcopy
case "$B" in
32)
CFLAGS="-arch i386 "
LDFLAGS="-arch i386 -shared -c"
ARCH=darwin-x86-32
;;
64)
CFLAGS="-arch x86_64"
LDFLAGS="-arch x86_64 -shared -c"
ARCH=darwin-x86-64
;;
esac
SHDR="
.text
jmp _main"
else
OBJCOPY=objcopy
SHDR="
.section .text
.globl main
.type main, @function
jmp main
"
case "$B" in
64)
CFLAGS="-fPIC -fPIE -pie -fpic -m64"
LDFLAGS="-fPIC -fPIE -pie -fpic -m64"
ARCH=linux-x86-64
;;
*)
CFLAGS="-fPIC -fPIE -pie -fpic -m32"
LDFLAGS="-fPIC -fPIE -pie -fpic -m32"
ARCH=linux-x86-32
;;
esac
fi
[ "$A$K" ] && ARCH="$K-$A-$B"
OPT=-Os
CFLAGS="${CFLAGS} -nostdinc -include ${SFLIBPATH}/${ARCH}/sflib.h"
CFLAGS="${CFLAGS} -z execstack"
CFLAGS="${CFLAGS} -fomit-frame-pointer -finline-functions -fno-zero-initialized-in-bss"
LDFLAGS="${LDFLAGS} -nostdlib"
case "$K" in
darwin)
#TEXT="__TEXT.__text"
TEXT="0.__text"
;;
*|linux)
TEXT=".text"
;;
esac
rmtemps() {
[ -z "$D" ] && rm -f $F.tmp $F.text $F.s $F.o
}
fail() {
rmtemps
exit 1
}
if [ "$D" ]; then
echo "==> Compile"
echo "${CC} ${CFLAGS} -o $F.tmp -S ${OPT} $F"
fi
rm -f "$F.bin"
${CC} ${CFLAGS} -o "$F.tmp" -S ${OPT} "$F" || fail
echo "${SHDR}" > $F.s
cat "$F.tmp" \
| sed -e s,rdata,text, -e s,rodata,text, -e 's,get_pc_thunk.bx,__getesp__,g' \
| grep -v .cstring | grep -v size | grep -v ___main | grep -v section \
| grep -v __alloca | grep -v zero | grep -v cfi >> $F.s
rm -f "$F.tmp"
if [ $ASM = 1 ]; then
echo "$F.s"
exit 0
fi
if [ "$D" ]; then
echo "==> Assemble"
echo "${CC} ${LDFLAGS} ${OPT} -o $F.o $F.s"
fi
${CC} ${LDFLAGS} ${OPT} -o "$F.o" "$F.s" || fail
if [ "$D" ]; then
echo "==> Link"
#echo "${OBJCOPY} -j .text -O binary $F.o $.text"
echo "rabin2 -o '$F.text' -O d/S/${TEXT} $F.o"
fi
rabin2 -o "$F.text" -O d/S/${TEXT} $F.o
if [ "`du $F.text|awk '{print $1}'`" = 0 ]; then
# use objcopy as falback for rabin2
${OBJCOPY} -j .text -O binary $F.o $F.text || fail
fi
if [ "$C" = 1 ]; then
if [ "$O" ]; then
mv "$F.text" "$O"
else
O="$F.text"
fi
echo "$O"
exit 0
fi
[ "$X" = 1 ] && exec rax2 -S < "$F.text"
if [ "$D" ]; then
# hexdump -C $F.text
rax2 -S - < $F.text
ls -l $F.text
fi
[ -z "$O" ] && O="$F.bin"
ragg2 -b "$B" -C "$F.text" -F -o "$O" || fail
echo "$O"
rmtemps
exit 0