参考链接:https://payloads.online/archivers/2020-04-02/1
psexec详细用法:https://www.itprotoday.com/compute-engines/psexec
实现过程:
- 编写server服务程序
- 连接SMB共享
- 上传文件到共享目录
- 创建服务
- 启动服务
- 停止服务
- 删除服务
- 删除文件
服务server源码:
#include <stdio.h>
#include <Windows.h>
#define SLEEP_TIME 5000 /*间隔时间*/
#define LOGFILE "C:\\1\\log.txt" /*信息输出文件*/
SERVICE_STATUS ServiceStatus; /*服务状态*/
SERVICE_STATUS_HANDLE hStatus; /*服务状态句柄*/
void ServiceMain(int argc, char** argv);
void CtrlHandler(DWORD request);
int InitService();
int main(int argc, CHAR * argv[])
{
WCHAR WserviceName[] = TEXT("Monitor");
SERVICE_TABLE_ENTRY ServiceTable[2];
ServiceTable[0].lpServiceName = WserviceName;
ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;
ServiceTable[1].lpServiceName = NULL;
ServiceTable[1].lpServiceProc = NULL;
StartServiceCtrlDispatcher(ServiceTable);
return 0;
}
int WriteToLog(const char* str)
{
FILE* pfile;
fopen_s(&pfile, LOGFILE, "a+");
if (pfile == NULL)
{
return -1;
}
fprintf_s(pfile, "%s\n", str);
fclose(pfile);
return 0;
}
/*Service initialization*/
int InitService()
{
CHAR Message[] = "Monitoring started.";
OutputDebugString(TEXT("Monitoring started."));
int result;
result = WriteToLog(Message);
return(result);
}
/*Control Handler*/
void CtrlHandler(DWORD request)
{
switch (request)
{
case SERVICE_CONTROL_STOP:
WriteToLog("Monitoring stopped.");
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus(hStatus, &ServiceStatus);
return;
case SERVICE_CONTROL_SHUTDOWN:
WriteToLog("Monitoring stopped.");
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus(hStatus, &ServiceStatus);
return;
default:
break;
}
/* Report current status */
SetServiceStatus(hStatus, &ServiceStatus);
return;
}
void ServiceMain(int argc, char** argv)
{
WCHAR WserviceName[] = TEXT("Monitor");
int error;
ServiceStatus.dwServiceType =
SERVICE_WIN32;
ServiceStatus.dwCurrentState =
SERVICE_START_PENDING;
/*在本例中只接受系统关机和停止服务两种控制命令*/
ServiceStatus.dwControlsAccepted =
SERVICE_ACCEPT_SHUTDOWN |
SERVICE_ACCEPT_STOP;
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwServiceSpecificExitCode = 0;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;
hStatus = ::RegisterServiceCtrlHandler(
WserviceName,
(LPHANDLER_FUNCTION)CtrlHandler);
if (hStatus == (SERVICE_STATUS_HANDLE)0)
{
WriteToLog("RegisterServiceCtrlHandler failed");
return;
}
WriteToLog("RegisterServiceCtrlHandler success");
/* Initialize Service */
error = InitService();
if (error)
{
/* Initialization failed */
ServiceStatus.dwCurrentState =
SERVICE_STOPPED;
ServiceStatus.dwWin32ExitCode = -1;
SetServiceStatus(hStatus, &ServiceStatus);
return;
}
/*向SCM 报告运行状态*/
ServiceStatus.dwCurrentState =
SERVICE_RUNNING;
SetServiceStatus(hStatus, &ServiceStatus);
/*do something you want to do in this while loop*/
MEMORYSTATUS memstatus;
while (ServiceStatus.dwCurrentState ==
SERVICE_RUNNING)
{
char buffer[16];
GlobalMemoryStatus(&memstatus);
int availmb = memstatus.dwAvailPhys / 1024 / 1024;
sprintf_s(buffer, 100, "available memory is %dMB", availmb);
int result = WriteToLog(buffer);
if (result)
{
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
ServiceStatus.dwWin32ExitCode = -1;
SetServiceStatus(hStatus,
&ServiceStatus);
return;
}
Sleep(SLEEP_TIME);
}
WriteToLog("service stopped");
return;
}
自实现psexec源码:
#include <iostream>
#include <WinSock2.h>
#include <Windows.h>
#include <winnetwk.h>
#pragma comment(lib, "ws2_32")
#pragma comment(lib, "Mpr.lib")
#pragma comment(lib,"Advapi32.lib")
DWORD ConnectSMBServer(LPCWSTR lpwsHost, LPCWSTR lpwsUser, LPCWSTR lpwsPassword);
BOOL UploadFileBySMB(LPCWSTR lpwsSrcPath, LPCWSTR lpwsDstPath);
BOOL CreateServiceWithSCM(LPCWSTR lpwsSCMServer, LPCWSTR lpwsServiceName, LPCWSTR lpwsServicePath);
int wmain(int argc, wchar_t* argv[])
{
LPCWSTR lpwsHost = TEXT("192.168.100.20"); // 目标机器地址
LPCWSTR lpwsUserName = TEXT("Administrator"); // 账号
LPCWSTR lpwsPassword = TEXT("123456"); // 密码
LPCWSTR lpwsSrcPath = TEXT("D:\\server.exe"); // 本地文件路径
LPCWSTR lpwsDstPath = TEXT("\\\\192.168.100.20\\admin$\\NewPsexec.exe"); // 远程文件路径
LPCWSTR lpwsServiceName = TEXT("NewPsexec"); // 服务名称
LPCWSTR lpwsServicePath = TEXT("%SystemRoot%\\NewPsexec.exe"); // 目标机器落地位置
if (ConnectSMBServer(lpwsHost, lpwsUserName, lpwsPassword) == 0) {
BOOL bRetVal = FALSE;
bRetVal = UploadFileBySMB(lpwsSrcPath, lpwsDstPath);
if (bRetVal) {
std::cout << "Upload Success !" << std::endl;
// 如果上传成功即可创建服务
CreateServiceWithSCM(lpwsHost, lpwsServiceName, lpwsServicePath);
}
else {
std::cout << "Upload Failed ! Error : " << GetLastError() << std::endl;
return GetLastError();
}
}
}
DWORD ConnectSMBServer(LPCWSTR lpwsHost, LPCWSTR lpwsUserName, LPCWSTR lpwsPassword)
{
// 用于存放SMB共享资源格式
PWCHAR lpwsIPC = new WCHAR[MAX_PATH];
DWORD dwRetVal; // 函数返回值
NETRESOURCE nr; // 连接的详细信息
DWORD dwFlags; // 连接选项
ZeroMemory(&nr, sizeof(NETRESOURCE));
swprintf(lpwsIPC, MAX_PATH, TEXT("\\\\%s\\admin$"), lpwsHost);
nr.dwType = RESOURCETYPE_ANY; // 枚举所有资源
nr.lpLocalName = NULL;
nr.lpRemoteName = lpwsIPC; // 资源的网络名
nr.lpProvider = NULL;
// 如果设置了此位标志,则操作系统将在用户登录时自动尝试恢复连接。
dwFlags = CONNECT_UPDATE_PROFILE;
dwRetVal = WNetAddConnection2(&nr, lpwsPassword, lpwsUserName, dwFlags);
if (dwRetVal == NO_ERROR) {
// 返回NO_ERROR则成功
wprintf(L"Connection added to %s\n", nr.lpRemoteName);
return dwRetVal;
}
wprintf(L"WNetAddConnection2 failed with error: %u\n", dwRetVal);
return -1;
}
BOOL UploadFileBySMB(LPCWSTR lpwsSrcPath, LPCWSTR lpwsDstPath)
{
DWORD dwRetVal;
dwRetVal = CopyFile(lpwsSrcPath, lpwsDstPath, FALSE);
return dwRetVal > 0 ? TRUE : FALSE;
}
BOOL CreateServiceWithSCM(LPCWSTR lpwsSCMServer, LPCWSTR lpwsServiceName, LPCWSTR lpwsServicePath)
{
std::wcout << TEXT("Will Create Service ") << lpwsServiceName << std::endl;
SC_HANDLE hSCM;
SC_HANDLE hService;
SERVICE_STATUS ss;
// GENERIC_WRITE = STANDARD_RIGHTS_WRITE | SC_MANAGER_CREATE_SERVICE | SC_MANAGER_MODIFY_BOOT_CONFIG
hSCM = OpenSCManager(lpwsSCMServer, SERVICES_ACTIVE_DATABASE, SC_MANAGER_ALL_ACCESS);
if (hSCM == NULL) {
std::cout << "OpenSCManager Error: " << GetLastError() << std::endl;
return -1;
}
hService = CreateService(
hSCM, // 服务控制管理器数据库的句柄
lpwsServiceName, // 要安装的服务的名称
lpwsServiceName, // 用户界面程序用来标识服务的显示名称
GENERIC_ALL, // 访问权限
SERVICE_WIN32_OWN_PROCESS, // 与一个或多个其他服务共享一个流程的服务
SERVICE_DEMAND_START, // 当进程调用StartService函数时,由服务控制管理器启动的服务 。
SERVICE_ERROR_IGNORE, // 启动程序将忽略该错误并继续启动操作
lpwsServicePath, // 服务二进制文件的标准路径
NULL,
NULL,
NULL,
NULL,
NULL);
if (hService == NULL) {
std::cout << "CreateService Error: " << GetLastError() << std::endl;
return -1;
}
std::wcout << TEXT("Create Service Success : ") << lpwsServicePath << std::endl;
hService = OpenService(hSCM, lpwsServiceName, GENERIC_ALL);
if (hService == NULL) {
std::cout << "OpenService Error: " << GetLastError() << std::endl;
return -1;
}
std::cout << "OpenService Success!" << std::endl;
StartService(hService, NULL, NULL);
return 0;
}