CreateSvcRpc - 一个自定义的RPC客户端,以SYSTEM用户身份执行程序

admin 2022年4月15日10:41:54CreateSvcRpc - 一个自定义的RPC客户端,以SYSTEM用户身份执行程序已关闭评论82 views字数 17881阅读59分36秒阅读模式

翻译

原文地址:https://www.x86matthew.com/view_post?id=create_svc_rpc

功能: 一个自定义的RPC客户端,以SYSTEM用户身份执行程序


Windows RPC协议是一个我以前没有做过很多实验的领域。我现在已经创建了一个自定义的RPC客户端,它使用原始数据与ntsvcs管道进行通信。这意味着可以只使用CreateFile和WriteFile APIs来创建和执行一个Windows服务。

RPC协议似乎有一些记录,但相关的信息非常零散,我发现从头开始逆向工程更容易。

我通过拦截NtWriteFile、NtReadFile和NtFsControlFile函数,记录了Windows服务API的通信。我分析了这个数据流,以逐步建立我自己的RPC客户端。

在我的第一个版本运行后,我在Wireshark文档中发现了一些有用的信息,这些信息帮助我在RPC头文件中标注了剩余的未知字段。

CreateSvcRpc - 一个自定义的RPC客户端,以SYSTEM用户身份执行程序

以下是完整的程序代码:

```

include

include

// rpc command ids

define RPC_CMD_ID_OPEN_SC_MANAGER 27

define RPC_CMD_ID_CREATE_SERVICE 24

define RPC_CMD_ID_START_SERVICE 31

define RPC_CMD_ID_DELETE_SERVICE 2

// rpc command output lengths

define RPC_OUTPUT_LENGTH_OPEN_SC_MANAGER 24

define RPC_OUTPUT_LENGTH_CREATE_SERVICE 28

define RPC_OUTPUT_LENGTH_START_SERVICE 4

define RPC_OUTPUT_LENGTH_DELETE_SERVICE 4

define MAX_RPC_PACKET_LENGTH 4096

define MAX_PROCEDURE_DATA_LENGTH 2048

define CALC_ALIGN_PADDING(VALUE_LENGTH, ALIGN_BYTES) ((((VALUE_LENGTH + ALIGN_BYTES - 1) / ALIGN_BYTES) * ALIGN_BYTES) - VALUE_LENGTH)

struct RpcBaseHeaderStruct
{
WORD wVersion;
BYTE bPacketType;
BYTE bPacketFlags;
DWORD dwDataRepresentation;
WORD wFragLength;
WORD wAuthLength;
DWORD dwCallIndex;
};

struct RpcRequestHeaderStruct
{
DWORD dwAllocHint;
WORD wContextID;
WORD wProcedureNumber;
};

struct RpcResponseHeaderStruct
{
DWORD dwAllocHint;
WORD wContextID;
BYTE bCancelCount;
BYTE bAlign[1];
};

struct RpcBindRequestContextEntryStruct
{
WORD wContextID;
WORD wTransItemCount;
BYTE bInterfaceUUID[16];
DWORD dwInterfaceVersion;
BYTE bTransferSyntaxUUID[16];
DWORD dwTransferSyntaxVersion;
};

struct RpcBindRequestHeaderStruct
{
WORD wMaxSendFrag;
WORD wMaxRecvFrag;
DWORD dwAssocGroup;
BYTE bContextCount;
BYTE bAlign[3];

RpcBindRequestContextEntryStruct Context;
};

struct RpcBindResponseContextEntryStruct
{
WORD wResult;
WORD wAlign;
BYTE bTransferSyntax[16];
DWORD dwTransferSyntaxVersion;
};

struct RpcBindResponseHeader1Struct
{
WORD wMaxSendFrag;
WORD wMaxRecvFrag;
DWORD dwAssocGroup;
};

struct RpcBindResponseHeader2Struct
{
DWORD dwContextResultCount;
RpcBindResponseContextEntryStruct Context;
};

struct RpcConnectionStruct
{
HANDLE hFile;
DWORD dwCallIndex;

DWORD dwInputError;

DWORD dwRequestInitialised;

BYTE bProcedureInputData[MAX_PROCEDURE_DATA_LENGTH];
DWORD dwProcedureInputDataLength;

BYTE bProcedureOutputData[MAX_PROCEDURE_DATA_LENGTH];
DWORD dwProcedureOutputDataLength;
};

DWORD RpcConvertUUID(char pString, BYTE pUUID, DWORD dwMaxLength)
{
BYTE bUUID[16];
BYTE bFixedUUID[16];
DWORD dwUUIDLength = 0;
BYTE bCurrInputChar = 0;
BYTE bConvertedByte = 0;
DWORD dwProcessedByteCount = 0;
BYTE bCurrOutputByte = 0;

// ensure output buffer is large enough
if(dwMaxLength < 16)
{
return 1;
}

// check uuid length
dwUUIDLength = strlen("00000000-0000-0000-0000-000000000000");
if(strlen(pString) != dwUUIDLength)
{
return 1;
}

// convert string to uuid
for(DWORD i = 0; i < dwUUIDLength; i++)
{
// get current input character
bCurrInputChar = (BYTE)((BYTE*)pString + i);

// check if a dash character is expected here
if(i == 8 || i == 13 || i == 18 || i == 23)
{
if(bCurrInputChar == '-')
{
continue;
}
else
{
return 1;
}
}
else
{
// check current input character value
if(bCurrInputChar >= 'a' && bCurrInputChar <= 'f')
{
bConvertedByte = 0xA + (bCurrInputChar - 'a');
}
else if(bCurrInputChar >= 'A' && bCurrInputChar <= 'F')
{
bConvertedByte = 0xA + (bCurrInputChar - 'A');
}
else if(bCurrInputChar >= '0' && bCurrInputChar <= '9')
{
bConvertedByte = 0 + (bCurrInputChar - '0');
}
else
{
// invalid character
return 1;
}

if((dwProcessedByteCount % 2) == 0)
{
bCurrOutputByte = bConvertedByte * 0x10;
}
else
{
bCurrOutputByte += bConvertedByte;

// store current uuid byte
bUUID[(dwProcessedByteCount - 1) / 2] = bCurrOutputByte;
}
dwProcessedByteCount++;
}
}

// fix uuid endianness
memcpy((void)bFixedUUID, (void)bUUID, sizeof(bUUID));
bFixedUUID[0] = bUUID[3];
bFixedUUID[1] = bUUID[2];
bFixedUUID[2] = bUUID[1];
bFixedUUID[3] = bUUID[0];
bFixedUUID[4] = bUUID[5];
bFixedUUID[5] = bUUID[4];
bFixedUUID[6] = bUUID[7];
bFixedUUID[7] = bUUID[6];

// store uuid
memcpy((void)pUUID, (void)bFixedUUID, sizeof(bUUID));

return 0;
}

DWORD RpcBind(RpcConnectionStruct pRpcConnection, char pInterfaceUUID, DWORD dwInterfaceVersion)
{
RpcBaseHeaderStruct RpcBaseHeader;
RpcBindRequestHeaderStruct RpcBindRequestHeader;
DWORD dwBytesWritten = 0;
DWORD dwBytesRead = 0;
BYTE bResponseData[MAX_RPC_PACKET_LENGTH];
RpcBaseHeaderStruct pRpcResponseBaseHeader = NULL;
RpcBindResponseHeader1Struct
pRpcBindResponseHeader1 = NULL;
RpcBindResponseHeader2Struct pRpcBindResponseHeader2 = NULL;
BYTE
pSecondaryAddrHeaderBlock = NULL;
WORD wSecondaryAddrLen = 0;
DWORD dwSecondaryAddrAlign = 0;

// set base header details
memset((void*)&RpcBaseHeader, 0, sizeof(RpcBaseHeader));
RpcBaseHeader.wVersion = 5;
RpcBaseHeader.bPacketType = 11;
RpcBaseHeader.bPacketFlags = 3;
RpcBaseHeader.dwDataRepresentation = 0x10;
RpcBaseHeader.wFragLength = sizeof(RpcBaseHeader) + sizeof(RpcBindRequestHeader);
RpcBaseHeader.wAuthLength = 0;
RpcBaseHeader.dwCallIndex = pRpcConnection->dwCallIndex;

// set bind request header details
memset((void*)&RpcBindRequestHeader, 0, sizeof(RpcBindRequestHeader));
RpcBindRequestHeader.wMaxSendFrag = MAX_RPC_PACKET_LENGTH;
RpcBindRequestHeader.wMaxRecvFrag = MAX_RPC_PACKET_LENGTH;
RpcBindRequestHeader.dwAssocGroup = 0;
RpcBindRequestHeader.bContextCount = 1;
RpcBindRequestHeader.Context.wContextID = 0;
RpcBindRequestHeader.Context.wTransItemCount = 1;
RpcBindRequestHeader.Context.dwTransferSyntaxVersion = 2;

// get interface UUID
if(RpcConvertUUID(pInterfaceUUID, RpcBindRequestHeader.Context.bInterfaceUUID, sizeof(RpcBindRequestHeader.Context.bInterfaceUUID)) != 0)
{
return 1;
}
RpcBindRequestHeader.Context.dwInterfaceVersion = dwInterfaceVersion;

// {8a885d04-1ceb-11c9-9fe8-08002b104860} (NDR)
if(RpcConvertUUID("8a885d04-1ceb-11c9-9fe8-08002b104860", RpcBindRequestHeader.Context.bTransferSyntaxUUID, sizeof(RpcBindRequestHeader.Context.bTransferSyntaxUUID)) != 0)
{
return 1;
}

// write base header
if(WriteFile(pRpcConnection->hFile, (void*)&RpcBaseHeader, sizeof(RpcBaseHeader), &dwBytesWritten, NULL) == 0)
{
return 1;
}

// write bind request header
if(WriteFile(pRpcConnection->hFile, (void*)&RpcBindRequestHeader, sizeof(RpcBindRequestHeader), &dwBytesWritten, NULL) == 0)
{
return 1;
}

// increase call index
pRpcConnection->dwCallIndex++;

// get bind response
memset((void)&bResponseData, 0, sizeof(bResponseData));
if(ReadFile(pRpcConnection->hFile, (void
)bResponseData, sizeof(bResponseData), &dwBytesRead, NULL) == 0)
{
return 1;
}

// get a ptr to the base response header
pRpcResponseBaseHeader = (RpcBaseHeaderStruct*)bResponseData;

// validate base response header
if(pRpcResponseBaseHeader->wVersion != 5)
{
return 1;
}
if(pRpcResponseBaseHeader->bPacketType != 12)
{
return 1;
}
if(pRpcResponseBaseHeader->bPacketFlags != 3)
{
return 1;
}
if(pRpcResponseBaseHeader->wFragLength != dwBytesRead)
{
return 1;
}

// get a ptr to the main bind response header body
pRpcBindResponseHeader1 = (RpcBindResponseHeader1Struct)((BYTE)pRpcResponseBaseHeader + sizeof(RpcBaseHeaderStruct));

// get secondary addr header ptr
pSecondaryAddrHeaderBlock = (BYTE)pRpcBindResponseHeader1 + sizeof(RpcBindResponseHeader1Struct);
wSecondaryAddrLen =
(WORD*)pSecondaryAddrHeaderBlock;

// validate secondary addr length
if(wSecondaryAddrLen > 256)
{
return 1;
}

// calculate padding for secondary addr value if necessary
dwSecondaryAddrAlign = CALC_ALIGN_PADDING((sizeof(WORD) + wSecondaryAddrLen), 4);

// get a ptr to the main bind response header body (after the variable-length secondary addr field)
pRpcBindResponseHeader2 = (RpcBindResponseHeader2Struct)((BYTE)pSecondaryAddrHeaderBlock + sizeof(WORD) + wSecondaryAddrLen + dwSecondaryAddrAlign);

// validate context count
if(pRpcBindResponseHeader2->dwContextResultCount != 1)
{
return 1;
}

// ensure the result value for context #1 was successful
if(pRpcBindResponseHeader2->Context.wResult != 0)
{
return 1;
}

return 0;
}

DWORD RpcConnect(char pPipeName, char pInterfaceUUID, DWORD dwInterfaceVersion, RpcConnectionStruct *pRpcConnection)
{
HANDLE hFile = NULL;
char szPipePath[512];
RpcConnectionStruct RpcConnection;

// set pipe path
memset(szPipePath, 0, sizeof(szPipePath));
_snprintf(szPipePath, sizeof(szPipePath) - 1, "\\.\pipe\%s", pPipeName);

// open rpc pipe
hFile = CreateFile(szPipePath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if(hFile == INVALID_HANDLE_VALUE)
{
return 1;
}

// initialise rpc connection data
memset((void*)&RpcConnection, 0, sizeof(RpcConnection));
RpcConnection.hFile = hFile;
RpcConnection.dwCallIndex = 1;

// bind rpc connection
if(RpcBind(&RpcConnection, pInterfaceUUID, dwInterfaceVersion) != 0)
{
return 1;
}

// store connection data
memcpy((void)pRpcConnection, (void)&RpcConnection, sizeof(RpcConnection));

return 0;
}

DWORD RpcSendRequest(RpcConnectionStruct pRpcConnection, DWORD dwProcedureNumber)
{
RpcBaseHeaderStruct RpcBaseHeader;
RpcRequestHeaderStruct RpcRequestHeader;
DWORD dwBytesWritten = 0;
BYTE bResponseData[MAX_RPC_PACKET_LENGTH];
RpcBaseHeaderStruct
pRpcResponseBaseHeader = NULL;
RpcResponseHeaderStruct pRpcResponseHeader = NULL;
DWORD dwProcedureResponseDataLength = 0;
DWORD dwBytesRead = 0;
BYTE
pTempProcedureResponseDataPtr = NULL;

// ensure rpc request has been initialised
if(pRpcConnection->dwRequestInitialised == 0)
{
return 1;
}

// clear initialised flag
pRpcConnection->dwRequestInitialised = 0;

// check for input errors
if(pRpcConnection->dwInputError != 0)
{
return 1;
}

// set base header details
memset((void*)&RpcBaseHeader, 0, sizeof(RpcBaseHeader));
RpcBaseHeader.wVersion = 5;
RpcBaseHeader.bPacketType = 0;
RpcBaseHeader.bPacketFlags = 3;
RpcBaseHeader.dwDataRepresentation = 0x10;
RpcBaseHeader.wFragLength = sizeof(RpcBaseHeader) + sizeof(RpcRequestHeader) + pRpcConnection->dwProcedureInputDataLength;
RpcBaseHeader.wAuthLength = 0;
RpcBaseHeader.dwCallIndex = pRpcConnection->dwCallIndex;

// set request header details
memset((void*)&RpcRequestHeader, 0, sizeof(RpcRequestHeader));
RpcRequestHeader.dwAllocHint = 0;
RpcRequestHeader.wContextID = 0;
RpcRequestHeader.wProcedureNumber = (WORD)dwProcedureNumber;

// write base header
if(WriteFile(pRpcConnection->hFile, (void*)&RpcBaseHeader, sizeof(RpcBaseHeader), &dwBytesWritten, NULL) == 0)
{
return 1;
}

// write request header
if(WriteFile(pRpcConnection->hFile, (void*)&RpcRequestHeader, sizeof(RpcRequestHeader), &dwBytesWritten, NULL) == 0)
{
return 1;
}

// write request body
if(WriteFile(pRpcConnection->hFile, (void*)pRpcConnection->bProcedureInputData, pRpcConnection->dwProcedureInputDataLength, &dwBytesWritten, NULL) == 0)
{
return 1;
}

// increase call index
pRpcConnection->dwCallIndex++;

// get bind response
memset((void)&bResponseData, 0, sizeof(bResponseData));
if(ReadFile(pRpcConnection->hFile, (void
)bResponseData, sizeof(bResponseData), &dwBytesRead, NULL) == 0)
{
return 1;
}

// get a ptr to the base response header
pRpcResponseBaseHeader = (RpcBaseHeaderStruct*)bResponseData;

// validate base response header
if(pRpcResponseBaseHeader->wVersion != 5)
{
return 1;
}
if(pRpcResponseBaseHeader->bPacketType != 2)
{
return 1;
}
if(pRpcResponseBaseHeader->bPacketFlags != 3)
{
return 1;
}
if(pRpcResponseBaseHeader->wFragLength != dwBytesRead)
{
return 1;
}

// get a ptr to the main response header body
pRpcResponseHeader = (RpcResponseHeaderStruct)((BYTE)pRpcResponseBaseHeader + sizeof(RpcBaseHeaderStruct));

// context ID must be 0
if(pRpcResponseHeader->wContextID != 0)
{
return 1;
}

// calculate command response data length
dwProcedureResponseDataLength = pRpcResponseBaseHeader->wFragLength - sizeof(RpcBaseHeaderStruct) - sizeof(RpcResponseHeaderStruct);

// store response data
if(dwProcedureResponseDataLength > sizeof(pRpcConnection->bProcedureOutputData))
{
return 1;
}
pTempProcedureResponseDataPtr = (BYTE*)pRpcResponseHeader + sizeof(RpcResponseHeaderStruct);
memcpy(pRpcConnection->bProcedureOutputData, pTempProcedureResponseDataPtr, dwProcedureResponseDataLength);

// store response data length
pRpcConnection->dwProcedureOutputDataLength = dwProcedureResponseDataLength;

return 0;
}

DWORD RpcInitialiseRequestData(RpcConnectionStruct *pRpcConnection)
{
// initialise request data
memset(pRpcConnection->bProcedureInputData, 0, sizeof(pRpcConnection->bProcedureInputData));
pRpcConnection->dwProcedureInputDataLength = 0;
memset(pRpcConnection->bProcedureOutputData, 0, sizeof(pRpcConnection->bProcedureOutputData));
pRpcConnection->dwProcedureOutputDataLength = 0;

// reset input error flag
pRpcConnection->dwInputError = 0;

// set initialised flag
pRpcConnection->dwRequestInitialised = 1;

return 0;
}

DWORD RpcAppendRequestData_Binary(RpcConnectionStruct pRpcConnection, BYTE pData, DWORD dwDataLength)
{
DWORD dwBytesAvailable = 0;

// ensure the request has been initialised
if(pRpcConnection->dwRequestInitialised == 0)
{
return 1;
}

// calculate number of bytes remaining in the input buffer
dwBytesAvailable = sizeof(pRpcConnection->bProcedureInputData) - pRpcConnection->dwProcedureInputDataLength;
if(dwDataLength > dwBytesAvailable)
{
// set input error flag
pRpcConnection->dwInputError = 1;

return 1;
}

// store data in buffer
memcpy((void*)&pRpcConnection->bProcedureInputData[pRpcConnection->dwProcedureInputDataLength], pData, dwDataLength);
pRpcConnection->dwProcedureInputDataLength += dwDataLength;

// align to 4 bytes if necessary
pRpcConnection->dwProcedureInputDataLength += CALC_ALIGN_PADDING(dwDataLength, 4);

return 0;
}

DWORD RpcAppendRequestData_Dword(RpcConnectionStruct pRpcConnection, DWORD dwValue)
{
// add dword value
if(RpcAppendRequestData_Binary(pRpcConnection, (BYTE
)&dwValue, sizeof(DWORD)) != 0)
{
return 1;
}

return 0;
}

DWORD RpcDisconnect(RpcConnectionStruct *pRpcConnection)
{
// close pipe handle
CloseHandle(pRpcConnection->hFile);

return 0;
}

int main(int argc, char argv[])
{
RpcConnectionStruct RpcConnection;
BYTE bServiceManagerObject[20];
BYTE bServiceObject[20];
DWORD dwReturnValue = 0;
char szServiceName[256];
DWORD dwServiceNameLength = 0;
char szServiceCommandLine[256];
DWORD dwServiceCommandLineLength = 0;
char
pExecCmd = NULL;

printf("CreateSvcRpc - www.x86matthew.com\n\n");

if(argc != 2)
{
printf("Usage: %s [exec_cmd]\n\n", argv[0]);

return 1;
}

// get cmd param
pExecCmd = argv[1];

// generate a temporary service name
memset(szServiceName, 0, sizeof(szServiceName));
snprintf(szServiceName, sizeof(szServiceName) - 1, "CreateSvcRpc%u", GetTickCount());
dwServiceNameLength = strlen(szServiceName) + 1;

// set service command line
memset(szServiceCommandLine, 0, sizeof(szServiceCommandLine));
_snprintf(szServiceCommandLine, sizeof(szServiceCommandLine) - 1, "cmd /c start %s", pExecCmd);
dwServiceCommandLineLength = strlen(szServiceCommandLine) + 1;

printf("Connecting to SVCCTL RPC pipe...\n");

// open SVCCTL v2.0
if(RpcConnect("ntsvcs", "367abb81-9844-35f1-ad32-98f038001003", 2, &RpcConnection) != 0)
{
printf("Failed to connect to RPC pipe\n");

return 1;
}

printf("Opening service manager...\n");

// OpenSCManager
RpcInitialiseRequestData(&RpcConnection);
RpcAppendRequestData_Dword(&RpcConnection, 0);
RpcAppendRequestData_Dword(&RpcConnection, 0);
RpcAppendRequestData_Dword(&RpcConnection, SC_MANAGER_ALL_ACCESS);
if(RpcSendRequest(&RpcConnection, RPC_CMD_ID_OPEN_SC_MANAGER) != 0)
{
// error
RpcDisconnect(&RpcConnection);

return 1;
}

// validate rpc output data length
if(RpcConnection.dwProcedureOutputDataLength != RPC_OUTPUT_LENGTH_OPEN_SC_MANAGER)
{
// error
RpcDisconnect(&RpcConnection);

return 1;
}

// get return value
dwReturnValue = (DWORD)&RpcConnection.bProcedureOutputData[20];

// check return value
if(dwReturnValue != 0)
{
printf("OpenSCManager error: %u\n", dwReturnValue);

// error
RpcDisconnect(&RpcConnection);

return 1;
}

// store service manager object
memcpy(bServiceManagerObject, (void*)&RpcConnection.bProcedureOutputData[0], sizeof(bServiceManagerObject));

printf("Creating temporary service...\n");

// CreateService
RpcInitialiseRequestData(&RpcConnection);
RpcAppendRequestData_Binary(&RpcConnection, bServiceManagerObject, sizeof(bServiceManagerObject));
RpcAppendRequestData_Dword(&RpcConnection, dwServiceNameLength);
RpcAppendRequestData_Dword(&RpcConnection, 0);
RpcAppendRequestData_Dword(&RpcConnection, dwServiceNameLength);
RpcAppendRequestData_Binary(&RpcConnection, (BYTE)szServiceName, dwServiceNameLength);
RpcAppendRequestData_Dword(&RpcConnection, 0);
RpcAppendRequestData_Dword(&RpcConnection, SERVICE_ALL_ACCESS);
RpcAppendRequestData_Dword(&RpcConnection, SERVICE_WIN32_OWN_PROCESS);
RpcAppendRequestData_Dword(&RpcConnection, SERVICE_DEMAND_START);
RpcAppendRequestData_Dword(&RpcConnection, SERVICE_ERROR_IGNORE);
RpcAppendRequestData_Dword(&RpcConnection, dwServiceCommandLineLength);
RpcAppendRequestData_Dword(&RpcConnection, 0);
RpcAppendRequestData_Dword(&RpcConnection, dwServiceCommandLineLength);
RpcAppendRequestData_Binary(&RpcConnection, (BYTE
)szServiceCommandLine, dwServiceCommandLineLength);
RpcAppendRequestData_Dword(&RpcConnection, 0);
RpcAppendRequestData_Dword(&RpcConnection, 0);
RpcAppendRequestData_Dword(&RpcConnection, 0);
RpcAppendRequestData_Dword(&RpcConnection, 0);
RpcAppendRequestData_Dword(&RpcConnection, 0);
RpcAppendRequestData_Dword(&RpcConnection, 0);
RpcAppendRequestData_Dword(&RpcConnection, 0);
if(RpcSendRequest(&RpcConnection, RPC_CMD_ID_CREATE_SERVICE) != 0)
{
// error
RpcDisconnect(&RpcConnection);

return 1;
}

// validate rpc output data length
if(RpcConnection.dwProcedureOutputDataLength != RPC_OUTPUT_LENGTH_CREATE_SERVICE)
{
// error
RpcDisconnect(&RpcConnection);

return 1;
}

// get return value
dwReturnValue = (DWORD)&RpcConnection.bProcedureOutputData[24];

// check return value
if(dwReturnValue != 0)
{
printf("CreateService error: %u\n", dwReturnValue);

// error
RpcDisconnect(&RpcConnection);

return 1;
}

// store service object
memcpy(bServiceObject, (void*)&RpcConnection.bProcedureOutputData[4], sizeof(bServiceObject));

printf("Executing '%s' as SYSTEM user...\n", pExecCmd);

// StartService
RpcInitialiseRequestData(&RpcConnection);
RpcAppendRequestData_Binary(&RpcConnection, bServiceObject, sizeof(bServiceObject));
RpcAppendRequestData_Dword(&RpcConnection, 0);
RpcAppendRequestData_Dword(&RpcConnection, 0);
if(RpcSendRequest(&RpcConnection, RPC_CMD_ID_START_SERVICE) != 0)
{
// error
RpcDisconnect(&RpcConnection);

return 1;
}

// validate rpc output data length
if(RpcConnection.dwProcedureOutputDataLength != RPC_OUTPUT_LENGTH_START_SERVICE)
{
// error
RpcDisconnect(&RpcConnection);

return 1;
}

// get return value
dwReturnValue = (DWORD)&RpcConnection.bProcedureOutputData[0];

// check return value
if(dwReturnValue != 0 && dwReturnValue != ERROR_SERVICE_REQUEST_TIMEOUT)
{
printf("StartService error: %u\n", dwReturnValue);

// error
RpcDisconnect(&RpcConnection);

return 1;
}

printf("Deleting temporary service...\n");

// DeleteService
RpcInitialiseRequestData(&RpcConnection);
RpcAppendRequestData_Binary(&RpcConnection, bServiceObject, sizeof(bServiceObject));
if(RpcSendRequest(&RpcConnection, RPC_CMD_ID_DELETE_SERVICE) != 0)
{
// error
RpcDisconnect(&RpcConnection);

return 1;
}

// validate rpc output data length
if(RpcConnection.dwProcedureOutputDataLength != RPC_OUTPUT_LENGTH_DELETE_SERVICE)
{
// error
RpcDisconnect(&RpcConnection);

return 1;
}

// get return value
dwReturnValue = (DWORD)&RpcConnection.bProcedureOutputData[0];

// check return value
if(dwReturnValue != 0)
{
printf("DeleteService error: %u\n", dwReturnValue);

// error
RpcDisconnect(&RpcConnection);

return 1;
}

printf("Finished\n");

// disconnect from rpc pipe
if(RpcDisconnect(&RpcConnection) != 0)
{
return 1;
}

return 0;
}
```

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年4月15日10:41:54
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   CreateSvcRpc - 一个自定义的RPC客户端,以SYSTEM用户身份执行程序http://cn-sec.com/archives/913078.html