Anti exploit bits

Contenu du snippet

Récement, une faille dans le module BITS (Background Intelligent Transfer Service) de Windows a été mise en évidence, notamment via le proof of concept de Frank Boldewin. Cf par exemple http://aispirit.over-blog.com/article-6679733.html.

Voici donc un exemple de code source surveillant les téléchargements BITS pour supprimer les URLs blacklistées.

Il s'agit de la v1 pour montrer que cet exploit peut être contré!

Pour le paramétrer :
AntiBITSModeValue = KILLJOB; ou alors REMOVEFILE (non implémenté encore, mais je ne suis pas sur que c'est possible d'obtenir un grain aussi fin !)

Source / Exemple :


//fichier AntiBITS.h
int KILLJOB = 1;
int REMOVEFILE = 2;

//AntiBITS.cpp
#define _WIN32_WINNT 0x0400
#define _WIN32_DCOM

#include <stdio.h>
#include <windows.h>
#include <objbase.h>
#include <bits.h>
#include "AntiBITS.h"

#pragma hdrstop
#pragma comment(lib, "bits.lib")
#pragma comment(lib, "ole32.lib")

int AntiBITSModeValue;

bool startwith(LPWSTR word, char* start){
if(wcslen(word) < strlen(start)) return false;
for(int i = 0; i < strlen(start); i++){
	//printf("compare %c %c\n", start[i], word[i]);
	if(start[i] != word[i]) return false;
}
return true;
}
int handleFile(LPWSTR pLocalFileName = NULL, LPWSTR pRemoteFileName = NULL){

	printf("[file found]\n %ws, %ws \n", pLocalFileName, pRemoteFileName);

	char* black = "http://www.reconstructer.org";
	if(startwith(pRemoteFileName, black)) return S_FALSE;

	//if the file is not allowed, return S_FALSE;
	return S_OK;
}

void jobStatistics(IBackgroundCopyJob* pJob){

	LPWSTR data;
    BG_JOB_STATE jobState;
	CHAR* word;	
	BG_JOB_PROGRESS progress;

	pJob->GetDisplayName(&data); printf("%ws \n", data);
	pJob->GetOwner(&data ); printf("owned by %ws \n", data);
	pJob->GetState( &jobState);

	switch(jobState){
		case BG_JOB_STATE_QUEUED:
			word="Queued";
			break;

		case BG_JOB_STATE_CONNECTING:
			word = "connecting";	
break;
		case BG_JOB_STATE_TRANSFERRING:
			word="transferring";
break;
		case BG_JOB_STATE_SUSPENDED:
			word="suspended";
break;
		case BG_JOB_STATE_ERROR:
			word="error";
break;
		case BG_JOB_STATE_TRANSIENT_ERROR:
			word="transient error";
break;
		case BG_JOB_STATE_TRANSFERRED:
			word="transeferd";
		break;

		case BG_JOB_STATE_ACKNOWLEDGED:
			word="acknowledged";
break;

		case BG_JOB_STATE_CANCELLED:
			word="canceled";
break;
	}
	printf("state: %s \n", word);
/*

typedef enum 
{
  BG_JOB_STATE_QUEUED,
  BG_JOB_STATE_CONNECTING,
  BG_JOB_STATE_TRANSFERRING,
  BG_JOB_STATE_SUSPENDED,
  BG_JOB_STATE_ERROR,
  BG_JOB_STATE_TRANSIENT_ERROR,
  BG_JOB_STATE_TRANSFERRED,
  BG_JOB_STATE_ACKNOWLEDGED,
  BG_JOB_STATE_CANCELLED
}BG_JOB_STATE;

  • /
// printf("%ws, priority %i \n", data); // HRESULT GetPriority( BG_JOB_PRIORITY* pPriority); */ // HRESULT GetType( BG_JOB_TYPE* pJobType ); /*typedef struct _BG_JOB_PROGRESS { UINT64 BytesTotal; UINT64 BytesTransferred; ULONG FilesTotal; ULONG FilesTransferred; } BG_JOB_PROGRESS;
  • /
pJob->GetProgress( &progress); printf(" %i bytes on %i already transfered,%i files on %i files \n", progress.BytesTransferred, progress.BytesTotal, progress.FilesTransferred, progress.FilesTotal); //HRESULT GetDescription( LPWSTR* ppDescription); */ } /** Perform security test on a BITS job !
  • /
int handleJob(IBackgroundCopyJob* pJob){ printf("[BITS Job found]\n"); jobStatistics(pJob); HRESULT hr; HRESULT hresult = S_OK; IEnumBackgroundCopyFiles* pFiles = NULL; IBackgroundCopyFile* pFile = NULL; LPWSTR pLocalFileName = NULL; LPWSTR pRemoteFileName = NULL; ULONG cFileCount = 0; ULONG idx = 0; hr = pJob->EnumFiles(&pFiles); if(hr != S_OK){ printf("Error: unable to retreive the files list of the current job !"); return S_FALSE; } //Get the count of files in the job. pFiles->GetCount(&cFileCount); printf("%i files found for the current job\n" , cFileCount); //Enumerate the files in the job. for (idx=0; idx<cFileCount; idx++) { hr = pFiles->Next(1, &pFile, NULL); if (S_OK == hr) { //Get the local name of the file. hr = pFile->GetLocalName(&pLocalFileName); hr = pFile->GetRemoteName(&pRemoteFileName); hr = handleFile(pLocalFileName, pRemoteFileName); if(hr != S_OK){ //Cancel(); printf("> unauthorized transfert detected \n"); printf("> AntiBITS policy: %i \n", AntiBITSModeValue); if(AntiBITSModeValue == KILLJOB){ hr = pJob->Cancel(); char* msg = "failed"; if(hr == S_OK) msg = "success"; printf(">> kill the job ... %s \n", msg); break; } if(AntiBITSModeValue == REMOVEFILE){ //hr = pJob->Cancel(); char* msg = "NON IMPLEMENTED"; printf(" >> remove the unauthorized file transfert ... %s \n", msg); break; } }else{ printf("> file authorized \n"); } pFile->Release(); pFile = NULL; } else { //Handle error hresult = S_FALSE; break; } hresult = S_OK; } pFiles->Release(); pFiles = NULL; return hresult; } int main() { HRESULT hresult; //Use the IBackgroundCopyManager interface to create transfer jobs, retrieve an enumerator object that contains the jobs in the queue, and to retrieve individual jobs from the queue. //http://msdn2.microsoft.com/en-us/library/aa363050.aspx IBackgroundCopyManager * bgcopyman; ULONG idx = 0; ULONG cJobCount = 0; GUID jobid; IEnumBackgroundCopyJobs* pEnumJobs; IBackgroundCopyJob* pJob = NULL; AntiBITSModeValue = KILLJOB; hresult = CoInitializeEx(NULL,COINIT_APARTMENTTHREADED); if(SUCCEEDED(hresult)) { hresult = CoInitializeSecurity(NULL,-1,NULL,NULL, RPC_C_AUTHN_LEVEL_CONNECT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL,EOAC_NONE,0); if(SUCCEEDED(hresult)) hresult = CoCreateInstance(CLSID_BackgroundCopyManager, 0, CLSCTX_ALL, IID_IBackgroundCopyManager, (LPVOID *)&bgcopyman); } if (hresult!=S_OK) { //"erreur lors de l'initialisation des composants !" } /* HRESULT EnumJobs( DWORD dwFlags, IEnumBackgroundCopyJobs** ppEnumJobs );
  • /
hresult = bgcopyman -> EnumJobs(BG_JOB_ENUM_ALL_USERS, &pEnumJobs); if(hresult == E_ACCESSDENIED){ printf("The user must be an administrator or belong to an administrator group to enumerate jobs owned by another user.\n"); printf("Will check only user's jobs.\n"); hresult = bgcopyman -> EnumJobs(NULL, &pEnumJobs); if(hresult != S_OK){ printf("Fatal error : unable to start checks.\n"); } return -1; } printf("Successfull initialisations \n"); hresult = pEnumJobs -> GetCount(&cJobCount); printf("%i jobs found in the transfer queue \n" , cJobCount); //Enumerate the jobs in the queue. for (idx=0; idx<cJobCount; idx++) { /*HRESULT Next( ULONG celt, IBackgroundCopyJob** rgelt, ULONG* pceltFetched );
  • /
hresult = pEnumJobs->Next(1, &pJob, NULL); if (S_OK == hresult) { //Retrieve or set job properties. handleJob(pJob); pJob->Release(); pJob = NULL; } else { //Handle error break; } } pEnumJobs->Release(); pEnumJobs = NULL; CoUninitialize(); return 0; }

Conclusion :


Ce code étant plus un proof of concept, je n'ai pas fait l'effort pour le moment de bien le structurer, ou encore de changer le système blacklist (mode ouvert) en whitelist (mode fermé), ce qui est préférable

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.

Du même auteur (AiSpirit)