All pastes #1787383 Raw Edit

arab

public text v1 · immutable
#1787383 ·published 2010-02-05 20:25 UTC
rendered paste body
#define _CRT_SECURE_NO_WARNINGS/* {{{ Header includes */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <assert.h>#define _WIN32_WINNT	0x0500#include <TCHAR.H>#include <Windows.h>#include "include/common.h"#include "include/config.h"/* }}} *//* {{{ VS #pragmas */#pragma comment(lib, "Advapi32.lib")/* }}} *//* {{{ Type definitions and data structures */struct packed_res_s {	struct packed_res_s *next;	WORD nameId; BYTE *buf; SIZE_T bufsz, size2; DWORD hash, hash2;};/* }}} *//* {{{ Static prototypes */static BOOL CALLBACK _EnumResNameProc(HMODULE, LPCTSTR, LPTSTR, LONG_PTR);static BOOL _DecryptData(BYTE *, SIZE_T *, BYTE *, SIZE_T);#ifdef BUILD_DEBUGstatic void _fini(void);#endif /* BUILD_DEBUG *//* }}} *//* {{{ Static subr */staticBOOLCALLBACK_EnumResNameProc(	HMODULE		hModule,	LPCTSTR		lpszType,	LPTSTR		lpszName,	LONG_PTR	lParam){	LPTSTR lpszName_endptr = NULL;	unsigned long nameId_l = 0L; WORD nameId = 0;	struct packed_res_s			**plres = (struct packed_res_s **) lParam,			 *pres = NULL;	HRSRC hResInfo = NULL; HGLOBAL hResData = NULL;	BYTE *buf = NULL; SIZE_T bufsz = 0;	DWORD sizeCurrent = 0L, hashCurrent = 0L, size2 = 0L, hash2 = 0L;	DWORD hash = 0L;	/* Ignore resources with a non-numeric name. */	if(!IS_INTRESOURCE(lpszName))		return TRUE;	else	nameId = (WORD) lpszName;	/* Obtain the location of, a handle to, a pointer to the actual data	 * of, and the size of the latter for the named RT_RCDATA resource	 * currently being enumerated. */	if(NULL == (hResInfo = FindResource(hModule, lpszName, lpszType)))		rtl$errExit(EXIT_FAILURE, "FindResourceA");	if(NULL == (hResData = LoadResource(hModule, hResInfo)))		rtl$errExit(EXIT_FAILURE, "LoadResource");	if(NULL == (buf = LockResource(hResData)))		rtl$errExit(EXIT_FAILURE, "LockResource");	if(0 == (bufsz = SizeofResource(hModule, hResInfo)))		rtl$errExit(EXIT_FAILURE, "SizeofResource");	/* Ignore resource data smaller than the obligatory header. */	if(bufsz < (sizeof(DWORD) * 5)) {		rtl$warn("Ignored RT_RCDATA resource %u with a size of "		         "%u bytes (minimum %u.)",		         nameId, bufsz, sizeof(DWORD) * 5);		return TRUE;	};	/* Copy the {size, hash value}s stored in the header, and validate	 * the data following the latter via both the size aswell as the	 * hash value parameters. */	sizeCurrent = *((DWORD *) buf); size2 = *((DWORD *) buf + 1);	hashCurrent = *((DWORD *) buf + 2); hash2 = *((DWORD *) buf + 3);	bufsz -= sizeof(DWORD) * 4; buf += sizeof(DWORD) * 4;	if(bufsz < sizeCurrent) {		rtl$warn("Ignored RT_RCDATA resource %u with an advertised "		         "data size of %u bytes (%u bytes actually present.)",		         nameId, sizeCurrent, bufsz);		return TRUE;	} else	bufsz = sizeCurrent;	if(hashCurrent != (hash = _fnv32(buf, bufsz))) {		rtl$warn("Ignored RT_RCDATA resource %u with an advertised "		         "hash value of 0x%08X (vs. 0x%08X in the header.)",		         nameId, hash, hashCurrent);		return TRUE;	};	/* Allocate memory for the next item in the linked list of packed	 * resource descriptors, or for the first element given an empty	 * list. */	if(NULL == (*plres)) {		if(NULL == ((*plres) = HeapAlloc(			GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pres))))			rtl$errExit(EXIT_FAILURE, "HeapAlloc");		else	pres = (*plres);	} else {		for(pres = (*plres); NULL != pres;		    pres = pres->next)			if(NULL == pres->next)				break;		if(NULL == (pres->next = HeapAlloc(			GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pres->next))))			rtl$errExit(EXIT_FAILURE, "HeapAlloc");		else	pres = pres->next;	};	/* Link the now validated data buffer and its parameters into the	 * tail item of the list. */	pres->nameId = nameId;	pres->size2 = size2; pres->hash2 = hash2;	pres->buf = buf; pres->bufsz = bufsz;	pres->hash = hashCurrent;	return TRUE;}staticBOOL_DecryptData(	BYTE		*buf,	SIZE_T		*pbufsz,	BYTE		*key,	SIZE_T		 keysz){	HCRYPTPROV hProv; HCRYPTKEY hKey; 	SIZE_T decrypt_blocksz = 0, npos = 0, nbytes = 0;	BOOL bEod = FALSE;	/* Acquire a handle to the unnamed default key container within the	 * Enhanced Cryptographic Provider, to be employed for data decryption	 * with RC4 (as PROV_RSA_FULL specifies.) */	if(FALSE == CryptAcquireContext(		&(hProv), NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, 0)) {		rtl$error("CryptAcquireContext"); return FALSE; };	/* Transfer the specified key into the CSP we acquired a handle for	 * beforehand. */	if(0 == CryptImportKey(hProv, key, keysz, 0, 0, &(hKey))) {		rtl$error("CryptImportKey"); return FALSE; };	/* Determine the block size and the amount of blocks needed	 * to decrypt. */	decrypt_blocksz = 1000 - (1000 % CRYPT_BLOCKSZ);	/* Iteratively decrypt the COFF object's data, block by block. */	for(npos = 0, bEod = FALSE; npos < (*pbufsz);	    npos += decrypt_blocksz) {		/* Determine whether this is the last block to decrypt, and		 * adjust the count of bytes plus End-of-Data flag		 * accordingly; otherwise, use the full block size. */                if(decrypt_blocksz > ((*pbufsz) - npos)) {			nbytes = (*pbufsz) - npos;			bEod = TRUE;		} else	nbytes = decrypt_blocksz;		nbytes = 1;		/* Decrypt this block in-place, writing the result out into		 * the buffer at the same position. */		if(FALSE == CryptDecrypt(			hKey, (HCRYPTHASH) NULL, bEod, 0,			buf + npos, &(nbytes))) {			rtl$error("CryptDecrypt"); return FALSE; };	};	return TRUE;}/* }}} *//* {{{ Entry and exit points */intAPIENTRYWinMain(	HINSTANCE	hInstance,	HINSTANCE	hPrevInstance,	LPSTR		lpCmdLine,	int		nCmdShow){	struct packed_res_s *lres = NULL, *res = NULL, *res_key = NULL;#ifdef BUILD_DEBUG	/* Allocate a console and redirect the standard devices for our	 * process into the former given a debugging build. */	rtl$redirectIO();	atexit(_fini);#endif /* BUILD_DEBUG */	/*	 * Iteratively enumerate all RT_RCDATA resources linked into this here	 * executing module, linking valid, packed, encrypted COFF object data	 * and corresponding session keys into our list to decrypt later on. */	if(FALSE == EnumResourceNames(		GetModuleHandle(NULL), RT_RCDATA, _EnumResNameProc,		(LONG_PTR) &(lres))) 		rtl$errExit(EXIT_FAILURE, "EnumResourceNames");	if(NULL == lres) {		rtl$warn("No valid packed RT_RCDATA resources found, exiting.");		return EXIT_FAILURE;	};	for(res = lres; NULL != res; res = res->next) {		if(res->nameId & 1) {			/* Chase the corresponding session key. */			for(res_key = lres; NULL != res_key;			    res_key = res_key->next)				if((res_key->nameId) == (res->nameId - 1))					break;			if(NULL == res_key) {				rtl$warn("Unable to locate session key for "				         "resource #%u, aborting.",				         res->nameId);				return EXIT_FAILURE;			};			if(FALSE == _DecryptData(				res->buf, &(res->bufsz),				res_key->buf, res_key->bufsz)) {				rtl$warn("Unable to decrypt resource #%u, "				         "aborting.", res->nameId);				return EXIT_FAILURE;			} else	rtl$notice("Decrypted resource #%u", res->nameId);		};	};	return EXIT_SUCCESS;}#ifdef BUILD_DEBUGstaticvoid_fini(	void){	fprintf(stderr, "Process exited, Sleep(INFINITE)ing.\n");	Sleep(INFINITE);}#endif /* BUILD_DEBUG *//* }}} *//* * vim:ts=8 sw=8 noexpandtab foldmethod=marker */