mirror of
https://github.com/radareorg/radare2.git
synced 2024-12-12 23:46:36 +00:00
321 lines
5.5 KiB
Bash
Executable File
321 lines
5.5 KiB
Bash
Executable File
#!/bin/sh
|
|
# ragg2-cc : a shellcode compiler -- pancake - 2011-2016
|
|
#
|
|
# 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" >&2
|
|
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
|
|
arm64|aarch64|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
|
|
|
|
JMP=jmp
|
|
case "$A" in
|
|
arm|aarch64|arm64|thumb|arm32)
|
|
JMP=b
|
|
;;
|
|
mips|mips32|mips64)
|
|
JMP=b
|
|
;;
|
|
esac
|
|
|
|
FMT=elf
|
|
if [ "$K" = darwin ]; then
|
|
OBJCOPY=gobjcopy
|
|
FMT=mach0
|
|
ARCH="$A"
|
|
if [ "$ARCH" = x86 ]; then
|
|
if [ "${B}" = 32 ]; then
|
|
ARCH=i386
|
|
TRIPLET=darwin-x86-32
|
|
else
|
|
ARCH=x86_64
|
|
TRIPLET=darwin-x86-64
|
|
fi
|
|
case "$B" in
|
|
32)
|
|
CFLAGS="-arch $ARCH "
|
|
LDFLAGS="-arch $ARCH -shared -c"
|
|
;;
|
|
64)
|
|
CFLAGS="-arch $ARCH"
|
|
LDFLAGS="-arch $ARCH -shared -c"
|
|
;;
|
|
esac
|
|
else
|
|
LDFLAGS="-shared -c"
|
|
fi
|
|
SHDR="
|
|
.text
|
|
${JMP} _main"
|
|
else
|
|
OBJCOPY=objcopy
|
|
SHDR="
|
|
.section .text
|
|
.globl main
|
|
// .type main, @function
|
|
${JMP} main
|
|
"
|
|
if [ "$A" = x86 ]; then
|
|
case "$B" in
|
|
64)
|
|
CFLAGS="-fPIC -fPIE -pie -fpic -m64"
|
|
LDFLAGS="-fPIC -fPIE -pie -fpic -m64"
|
|
TRIPLET=linux-x86-64
|
|
;;
|
|
*)
|
|
CFLAGS="-fPIC -fPIE -pie -fpic -m32"
|
|
LDFLAGS="-fPIC -fPIE -pie -fpic -m32"
|
|
TRIPLET=linux-x86-32
|
|
;;
|
|
esac
|
|
else
|
|
CFLAGS="-fPIC -fPIE -pie -fpic -nostartfiles"
|
|
LDFLAGS="-fPIC -fPIE -pie -fpic -nostartfiles"
|
|
fi
|
|
fi
|
|
|
|
[ "$A$K" ] && TRIPLET="$K-$A-$B"
|
|
|
|
case "$K" in
|
|
windows)
|
|
#TEXT="__TEXT.__text"
|
|
TEXT=".text"
|
|
FMT=pe
|
|
;;
|
|
darwin)
|
|
#TEXT="__TEXT.__text"
|
|
#TEXT="0.__text"
|
|
TEXT=0.__TEXT.__text
|
|
FMT=mach0
|
|
;;
|
|
*|linux)
|
|
TEXT=".text"
|
|
FMT=elf
|
|
;;
|
|
esac
|
|
|
|
USE_CLANG=0
|
|
case "$K-$A-$B" in
|
|
darwin-arm-64)
|
|
CC="xcrun --sdk iphoneos gcc -arch arm64"
|
|
USE_CLANG=1
|
|
TEXT=0.__TEXT.__text
|
|
;;
|
|
darwin-arm-32)
|
|
USE_CLANG=1
|
|
CC="xcrun --sdk iphoneos gcc -arch armv7"
|
|
TEXT=0.__TEXT.__text
|
|
;;
|
|
esac
|
|
|
|
OPT=-Os
|
|
CFLAGS="${CFLAGS} -nostdinc -include ${SFLIBPATH}/${TRIPLET}/sflib.h"
|
|
if [ 1 = "${USE_CLANG}" ]; then
|
|
CFLAGS="${CFLAGS} -fomit-frame-pointer -fno-zero-initialized-in-bss"
|
|
else
|
|
CFLAGS="${CFLAGS} -z execstack -fomit-frame-pointer -finline-functions -fno-zero-initialized-in-bss"
|
|
fi
|
|
LDFLAGS="${LDFLAGS} -nostdlib"
|
|
|
|
|
|
rmtemps() {
|
|
[ -z "$D" ] && rm -f $F.tmp $F.text $F.s $F.o
|
|
}
|
|
|
|
fail() {
|
|
echo "ERROR: $@"
|
|
rmtemps
|
|
exit 1
|
|
}
|
|
|
|
if [ "$D" ]; then
|
|
echo "==> Compile"
|
|
echo "${CC} ${CFLAGS} -o $F.tmp -S ${OPT} $F"
|
|
fi
|
|
rm -f "$F.bin"
|
|
echo ${CC} ${CFLAGS} -o "$F.tmp" -S ${OPT} "$F"
|
|
${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
|
|
|
|
echo ==============================
|
|
|
|
if [ "$D" ]; then
|
|
echo "==> Assemble"
|
|
echo "${CC} ${LDFLAGS} ${OPT} -o $F.o $F.s"
|
|
fi
|
|
echo "${CC} ${LDFLAGS} ${OPT} -o $F.o $F.s"
|
|
${CC} ${LDFLAGS} ${OPT} -o "$F.o" "$F.s" || fail 'compile object'
|
|
|
|
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 [ ! -f "$F.o" ]; then
|
|
echo "Cannot find $F.o"
|
|
exit 1
|
|
fi
|
|
if [ "`du $F.text|awk '{print $1}'`" = 0 ]; then
|
|
# use objcopy as falback for rabin2
|
|
echo "FALLBACK: Using objcopy instead of 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 ${FMT} -a $A -o "$O" || fail "ragg2 cannot generate executable. Use -x"
|
|
echo "$O"
|
|
rmtemps
|
|
exit 0
|