• Use [hide] Content [/hide] to prevent leeching of your content.

VAC Update 4/9/2016

FaTaN

Member
VAC Update 4/8/2016 analysed
[HIDE]
The important scan looks at a specific process on a volume, either by looking up the drive path by process id or by volume serial, presumably they can target specific USB devices?

signedint __cdecl VAC_ScanFunc1(int a1,int a2,int a3)
{
int v3;// [email protected]<script data-cfhash='f9e31' type="text/javascript">/* */</script>
signedint result;// [email protected]/* */
int v5;// [email protected]/* */
int v6;// [email protected]/* */
struct_v1 *v7;// [email protected]/* */
unsignedint v8;// [email protected]/* */
struct_v1 *v9;// [email protected]/* */
VacOutput1*v10;// [email protected]/* */
unsigned __int8 *dwScanFlags;// [email protected]/* */
char v13;// [sp+0h] [bp-31E4h]@7
struct_pScan moduleScan;// [sp+2730h] [bp-AB4h]@12
CHAR FileName;// [sp+30A8h] [bp-13Ch]@13
ModuleScanWrapper scanWrapper;// [sp+31ACh] [bp-38h]@13
int v17;// [sp+31BCh] [bp-28h]@15
int iLastError;// [sp+31C0h] [bp-24h]@7
char v19;// [sp+31C7h] [bp-1Dh]@12
int dwFunctionAddress;// [sp+31C8h] [bp-1Ch]@7
int v21;// [sp+31CCh] [bp-18h]@7
int v22;// [sp+31D0h] [bp-14h]@13
int v23;// [sp+31D4h] [bp-10h]@13
int v24;// [sp+31D8h] [bp-Ch]@14
VacInput1*pInScan;// [sp+31DCh] [bp-8h]@5
VacOutput1*pScan;// [sp+31E0h] [bp-4h]@3 MAPDST

if(*(_DWORD *)a3 >=0xF40u)
{
pScan =(VacOutput1*)a2;
*(_DWORD *)a3 =0x1000;
zeromem(pScan,0,0x1000u);
zeromem(pScan,0,0xF40u);
if(SetupIAT())
{
pInScan =(VacInput1*)(a1 +0x20);
pScan->iScanIndex =3;
zeromem(&pScan->field_944,0,0x20u);
pScan->field_964 =0;
if( pInScan->dwProcessId || pInScan->bCheckProcess )
{
pScan->dwProcessId = pInScan->dwProcessId;
memclear(&moduleScan);
dwScanFlags =(unsigned __int8 *)GetScanFlags(&v19,16);
pScan->iScanResult =StoreProcessPathsAndModules(&moduleScan, pScan->dwProcessId,*dwScanFlags);
if(!pScan->iScanResult )
{
v23 =(int)&pScan->field_E1C;
pScan->dwLowDateTime = moduleScan.dwLowDateTime;
pScan->dwHighDateTime = moduleScan.dwHighDateTime;
ModuleScanWrapper::ModuleScanWrapper(&scanWrapper,(VacProcScan2*)&moduleScan);
pScan->szProcessImageFileName[0]=0;
FileName=0;
v22 = pInScan->lpvFunctionAddress;
if( pInScan->lpvFunctionAddress )
{
GetPathFromAddress(&scanWrapper,(void*)pInScan->lpvFunctionAddress,&FileName,260u);
}
else
{
GetProcessImageFileNameA(moduleScan.hProcessHandle,&FileName,260);
GetCDriveName(&gSystemInfo,(int)&FileName,260);
v24 = sub_10013C50((VacProcScan2*)&moduleScan,(int)&FileName);
if( v24 )
{
v17 = v24;
if(*(_QWORD *)(v24 +8))
v22 =*(_DWORD *)(v24 +8);
}
}
if(FileName)
{
strcpy_0((int)pScan->szProcessImageFileName,(int)&FileName,256u);
sub_1000F440(&scanWrapper, v3,(int)&FileName, v22,(int)&pScan->iScanResult2,(int)&pScan->field_944, v23);
v23 =0;
sub_1000D7C0(&FileName,(int)pScan->field_928,(int)&pScan->field_928[8]);
}
sub_1000F440(&scanWrapper, v3,0, v22,(int)&pScan->gap_24[1024],(int)&pScan->field_944, v23);
}
sub_100088B0(&moduleScan);
}
else
{
dwFunctionAddress =0;
v21 =0;
memcpy((int)&dwFunctionAddress,(int)&pInScan->lpvFunctionAddress,4);
memcpy((int)&v21,(int)pInScan->gap48,4);
struct_v1::struct_v1((struct_v1 *)&v13);
iLastError =0;
pScan->iScanResult =GetVolumeBySerialAndOpenHandle(
(struct_v1 *)&v13,
pInScan->dwDeviceSerial,
dwFunctionAddress,
v21,
&iLastError);
pScan->iLastError = iLastError;
pScan->iScanResult2 = pScan->iScanResult;
if(!pScan->iScanResult )
{
pScan->iScanResult =CreateExtraSection((struct_v1 *)&v13);
pScan->iScanResult2 = pScan->iScanResult;
if(!pScan->iScanResult )
{
PrepareModule((struct_v1 *)&v13,(struct_a2 *)&pScan->iScanResult2);
sub_1000F700((struct_v1 *)&v13,(int)&pScan->field_E1C);
}
v5 =(int)&pScan->field_944;
v6 =(int)&pScan->iScanResult2;
v7 =(struct_v1 *)GetThis(&v13);
v8 =GetFileSize_0(v7);
v9 =(struct_v1 *)GetThis(&v13);
sub_1000FAC0(v9, v8, v6, v5);
}
*(_DWORD *)&pScan->field_928[0]= pInScan->dwDeviceSerial;
v10 = pScan;
*(_DWORD *)&pScan->field_928[8]= dwFunctionAddress;
*(_DWORD *)&v10->field_928[12]= v21;
sub_10004F10(&v13);
}
sub_10009CE0();
result =0;
}
else
{
pScan->iScanResult =78;
result =0;
}
}
else
{
result =4;
}
return result;
}
Then, for the target image it reads in the PE header and and seemingly creates a new section called ".extra" although I'm not sure why at the moment.

signedint __thiscall GatherPEInformationAndCreateSection(struct_v1 *this)
{
signedint result;// [email protected]<script data-cfhash='f9e31' type="text/javascript">/* */</script>
unsignedint v2;// [email protected]<script data-cfhash='f9e31' type="text/javascript">/* */</script>
unsignedint v3;// [email protected]<script data-cfhash='f9e31' type="text/javascript">/* */</script>
int v4;// [sp+Ch] [bp-2Ch]@9
int v5;// [sp+10h] [bp-28h]@9
DWORD dwFileSize;// [sp+14h] [bp-24h]@5
unsignedint dwSectionAlignment;// [sp+18h] [bp-20h]@6
signedint iHeaderResult;// [sp+1Ch] [bp-1Ch]@3
DWORD dwSecondToLastSectionPhysicalAddress;// [sp+24h] [bp-14h]@9
IMAGE_SECTION_HEADER *pSecondToLastSection;// [sp+28h] [bp-10h]@9
DWORD dwSizeOfSections;// [sp+2Ch] [bp-Ch]@5
IMAGE_SECTION_HEADER *pLastSection;// [sp+30h] [bp-8h]@9
struct_v1 *v13;// [sp+34h] [bp-4h]@1

v13 =this;
if(IsFileHandleValid(this))
{
iHeaderResult =GetPEHeaderInformation(v13);
if( iHeaderResult )
{
Cleanup(v13);
result = iHeaderResult;
}
else
{
dwSizeOfSections =GetSizeOfSections(v13);
dwFileSize =GetFileSize_0(v13);
if( v13->bIs64bit )
dwSectionAlignment = v13->optionalHeader64.SectionAlignment;
else
dwSectionAlignment = v13->optionalHeader32.SectionAlignment;
if( dwSizeOfSections < dwFileSize )
{
v4 = dwFileSize - dwSizeOfSections;
++v13->fileHeader64.NumberOfSections;
v13->pSectionHeaders =(IMAGE_SECTION_HEADER *)HeapAlloc_0(
v13->pSectionHeaders,
40* v13->fileHeader64.NumberOfSections);
pSecondToLastSection =&v13->pSectionHeaders[v13->fileHeader64.NumberOfSections-2];
pLastSection =&v13->pSectionHeaders[v13->fileHeader64.NumberOfSections-1];
v5 = pSecondToLastSection->SizeOfRawData;
dwSecondToLastSectionPhysicalAddress = pSecondToLastSection->Misc.PhysicalAddress;
if( dwSecondToLastSectionPhysicalAddress < v5 )
dwSecondToLastSectionPhysicalAddress = sub_100064A0(v5, dwSectionAlignment);
v2 = sub_100064A0(
dwSecondToLastSectionPhysicalAddress + pSecondToLastSection->VirtualAddress,
dwSectionAlignment);
v3 = sub_100064A0(v4, dwSectionAlignment);
zeromem(pLastSection,0,0x28u);
pLastSection->PointerToRawData= dwSizeOfSections;
pLastSection->VirtualAddress= v2;
pLastSection->SizeOfRawData= v4;
pLastSection->Misc.PhysicalAddress= v3;
pLastSection->Characteristics=0x2000000;
memcpy((int)pLastSection,(int)".extra",7);
}
result =0;
}
}
else
{
result =2;
}
return result;
}
We then see some code you would expect to see in a manual mapper such as fixing relocations, the IAT, and resources.
int __cdecl PrepareModule(struct_v1 *a1, struct_a2 *pPreparedModule)

{
struct_this v3;// [sp+4h] [bp-90h]@4
int v4;// [sp+78h] [bp-1Ch]@6
int v5;// [sp+7Ch] [bp-18h]@20
int v6;// [sp+80h] [bp-14h]@18
int v7;// [sp+84h] [bp-10h]@12
int v8;// [sp+88h] [bp-Ch]@16
int iNumberOfSections;// [sp+8Ch] [bp-8h]@6
int i;// [sp+90h] [bp-4h]@8

pPreparedModule->bNumberOfSections = LOBYTE(a1->fileHeader64.NumberOfSections);
pPreparedModule->dwTimeDateStamp = a1->fileHeader64.TimeDateStamp;
if( a1->bIs64bit )
{
pPreparedModule->dwEntryPoint = a1->optionalHeader64.AddressOfEntryPoint;
pPreparedModule->dwCheckSum = a1->optionalHeader64.CheckSum;
}
else
{
pPreparedModule->dwEntryPoint = a1->optionalHeader32.AddressOfEntryPoint;
pPreparedModule->dwCheckSum = a1->optionalHeader32.CheckSum;
}
sub_10003C10(&v3,1);
if(RelocateImage(a1,&v3,0))
{
pPreparedModule->dword28 = v3.dword6C;
memcpy((int)&pPreparedModule->data[1],(int)v3.pbSomeData,16);
}
sub_10009520(&v3);
v4 =0;
iNumberOfSections = a1->fileHeader64.NumberOfSections;
if( iNumberOfSections >12)
iNumberOfSections =12;
for( i =0; i < iNumberOfSections;++i )
{
sub_10009520(&v3);
if( sub_10003C70(a1,&v3, i))
{
pPreparedModule->field_34= v3.dword6C;
memcpy((int)&pPreparedModule->data[i +4],(int)v3.pbSomeData,16);
}
v7 =0;
memcpy((int)pPreparedModule->header.szSectionName,(int)&a1->pSectionHeaders,8);
pPreparedModule->header.dwCharacteristics = a1->pSectionHeaders.Characteristics;
pPreparedModule->header.dwSizeOfRawData = a1->pSectionHeaders.SizeOfRawData;
pPreparedModule->header.dwVirtualAddress = a1->pSectionHeaders.VirtualAddress;
pPreparedModule->header.dwZero = v7;
if( pPreparedModule->dwEntryPoint > a1->pSectionHeaders.VirtualAddress
&& pPreparedModule->dwEntryPoint < a1->pSectionHeaders.SizeOfRawData+ a1->pSectionHeaders.VirtualAddress)
v4 = i;
}
v8 =0;
if(HandleResources(a1,&pPreparedModule->data[3],&v8))
pPreparedModule->dword30 = v8;
pPreparedModule->bNumberOfSectionsPlus4 = iNumberOfSections +4;
v6 =CollectDebugInformation((int)a1);
if(!v6 )
strcpy_0((int)pPreparedModule->szPdbName,(int)a1->szPdbName,0x104u);
v5 =0;
sub_10009FA0(&v3);
return v5;
}

It then collects the debug directory and the PDB name if there is one (if you left this in your cheat you deserve to get detected)

signedint __thiscall CollectDebugInformation(intthis)
{
signedint result;// [email protected]<script data-cfhash='f9e31' type="text/javascript">/* */</script>
int v2;// [sp+0h] [bp-34h]@20
char pbGUID;// [sp+4h] [bp-30h]@23
DWORD dwRVA;// [sp+18h] [bp-1Ch]@1
unsignedint dwDebugDirSize;// [sp+1Ch] [bp-18h]@12
int v6;// [sp+20h] [bp-14h]@12
IMAGE_DATA_DIRECTORY *pDebugDir;// [sp+24h] [bp-10h]@2
int v8;// [sp+28h] [bp-Ch]@20
IMAGE_SECTION_HEADER *pDebugSection;// [sp+2Ch] [bp-8h]@6
struct_v1 *v10;// [sp+30h] [bp-4h]@1

v10 =(struct_v1 *)this;
zeromem((void*)(this+9288),0,0x1Cu);
zeromem(v10->szPdbGUID,0,0x10u);
zeromem(v10->szPdbName,0,0x104u);
dwRVA =0;
if( v10->bIs64bit )
pDebugDir =&v10->optionalHeader64.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG];
else
pDebugDir =&v10->optionalHeader32.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG];
if( pDebugDir->Size)
{
pDebugSection =GetEnclosingSectionHeader(v10, pDebugDir->VirtualAddress);
if( pDebugSection )
{
if(!IsFileHandleInvalid(v10))
dwRVA = pDebugSection->VirtualAddress- pDebugSection->PointerToRawData;
if(SetReadPosition(v10, pDebugDir->VirtualAddress- dwRVA,0))
{
SetPageSizeMaybe(
v10,
pDebugSection->VirtualAddress,
pDebugSection->Misc.PhysicalAddress+ pDebugSection->VirtualAddress);
v6 =95;
dwDebugDirSize = pDebugDir->Size;
while( dwDebugDirSize >=0x1C)
{
zeromem(&v10->debugDirectory,0,0x1Cu);
if(!ReadData(v10,(int)&v10->debugDirectory,0x1C))
{
v6 =13;
break;
}
dwDebugDirSize -=0x1C;
if( v10->debugDirectory.Type== IMAGE_DEBUG_TYPE_CODEVIEW )
break;
}
if( v10->debugDirectory.Type== IMAGE_DEBUG_TYPE_CODEVIEW )
{
if(SetReadPosition(v10, v10->debugDirectory.AddressOfRawData- dwRVA,0)
&& v10->debugDirectory.SizeOfData>=4)
{
v8 = v10->debugDirectory.SizeOfData;
if(ReadData(v10,(int)&v2,4))
{
if( v2 ==0x53445352) // "RSDS" (PDB signature)
{
if((unsignedint)v8 >=0x18&&ReadData(v10,(int)&pbGUID,20))// Read the GUID of the PDB
{
v8 -=24;
memcpy((int)v10->szPdbGUID,(int)&pbGUID,16);
if((unsignedint)v8 >0x104)
v8 =260;
if(ReadData(v10,(int)v10->szPdbName, v8))// Read the PDB name
v6 =0;
v10->szPdbName[259]=0;
}
else
{
v6 =95;
}
}
else
{
v6 =95;
}
}
}
else
{
v6 =12;
}
}
SetPageSizeMaybe(v10,0,0);
result =0;
}
else
{
result =12;
}
}
else
{
result =96;
}
}
else
{
result =94;
}
return result;
}
Finally, (if the original scan routine was searching via process id rather than volume serial it would also end up here too), the first 0x40000 bytes of image after the PE header. This is the main scanning function and it collects null bytes, printable characters, function prologs, function epilogs, and function calls.
int __cdecl BigScannen(int lpMemory,int dwBytesRead,ScanResults_*pScanResults,int a4,int a5,int a6)
{
int result;// [email protected]<script data-cfhash='f9e31' type="text/javascript">/* */</script>
int v7;// [sp+4h] [bp-9Ch]@1
int v8;// [sp+8h] [bp-98h]@11
unsignedint dwRetnSize;// [sp+Ch] [bp-94h]@28
int v10;// [sp+10h] [bp-90h]@5
unsignedint dwCallLocation;// [sp+14h] [bp-8Ch]@39
unsignedint v12;// [sp+18h] [bp-88h]@1
int v13;// [sp+1Ch] [bp-84h]@36
int v14;// [sp+20h] [bp-80h]@11
int v15;// [sp+24h] [bp-7Ch]@1
int v16;// [sp+28h] [bp-78h]@49
int v17;// [sp+2Ch] [bp-74h]@12
int iCurOpcode;// [sp+30h] [bp-70h]@3
int v19;// [sp+34h] [bp-6Ch]@9
unsignedint v20;// [sp+38h] [bp-68h]@25
int v21;// [sp+3Ch] [bp-64h]@34
int v22;// [sp+40h] [bp-60h]@1
int dwOpcodes;// [sp+44h] [bp-5Ch]@43
int v24[4];// [sp+48h] [bp-58h]@1
int v25[4];// [sp+58h] [bp-48h]@1
unsignedint v26;// [sp+68h] [bp-38h]@1
int v27[4];// [sp+6Ch] [bp-34h]@1
int v28[4];// [sp+7Ch] [bp-24h]@1
int v29;// [sp+8Ch] [bp-14h]@1
int v30;// [sp+90h] [bp-10h]@1
int i;// [sp+94h] [bp-Ch]@5
int dwReadOffset;// [sp+98h] [bp-8h]@1
unsignedint iScanCode;// [sp+9Ch] [bp-4h]@3

dwReadOffset =0;
v22 =0;
v29 =0;
v15 =0;
v27[0]=0x45D71892;
v27[1]=0x45D71892;
v27[2]=0x45D71892;
v27[3]=0x45D71892;
v28[0]=0x45D71892;
v28[1]=0x45D71892;
v28[2]=0x45D71892;
v28[3]=0x45D71892;
v24[0]=0;
v24[1]=0;
v24[2]=0;
v24[3]=0;
v25[0]=0;
v25[1]=0;
v25[2]=0;
result =4;
v25[3]=0;
v26 =0x45D71892;
v30 =0;
v7 =0;
v12 =0;
while( dwReadOffset < dwBytesRead )
{
iCurOpcode =*(_BYTE *)(dwReadOffset + lpMemory);
v26 = iCurOpcode +33* v26;
iScanCode =(unsigned __int8)bValidCharacter[iCurOpcode];
if( iScanCode <=9) // is not a printable character
{
v10 =0;
for( i =0; i <8;++i )
{
if( v24>=3&& v24!= v10 )
{
++pScanResults->iPrintableCharactersFound;
v10 = v24;
v19 = sub_100064C0(v27);
if( v19 >=0)
{
if( v19 <256)
{
v8 =1<< v19 %32;
v14 = v19 >>5;
*(_DWORD *)(a4 +4*(v19 >>5))|= v8;
}
v17 = v24;
if( i >=4)
v17 *=2;
sub_10008640(lpMemory, dwBytesRead, dwReadOffset, v17, a5, a6,(int)&v7);
}
}
}
}
else
{
++v24[0];
++v24[1];
++v24[2];
++v24[3];
++v25[0];
++v25[1];
++v25[2];
++v25[3];
v27[0]= iScanCode +33* v27[0];
v27[1]= iScanCode +33* v27[1];
v27[2]= iScanCode +33* v27[2];
v27[3]= iScanCode +33* v27[3];
v28[0]= iScanCode +33* v28[0];
v28[1]= iScanCode +33* v28[1];
v28[2]= iScanCode +33* v28[2];
v28[3]= iScanCode +33* v28[3];
}
if( iScanCode ==9) // underscore, space, etc
{
++v24[0];
++v24[1];
++v24[2];
++v24[3];
++v25[0];
++v25[1];
++v25[2];
++v25[3];
v27[0]=33* v27[0]+9;
v27[1]=33* v27[1]+9;
v27[2]=33* v27[2]+9;
v27[3]=33* v27[3]+9;
v28[0]=33* v28[0]+9;
v28[1]=33* v28[1]+9;
v28[2]=33* v28[2]+9;
v28[3]=33* v28[3]+9;
if( iCurOpcode !=0x20) // 0x20 = space
{
v27[3]=0x45D71892;
v24[3]=0;
v28[3]=0x45D71892;
v25[3]=0;
}
v27[v30]=0x45D71892;
v24[v30]=0;
v28[v30]=0x45D71892;
v25[v30++]=0;
v30 %=3;
}
elseif( iScanCode <9) // unprintable character
{
v24[0]=0;
v24[1]=0;
v24[2]=0;
v24[3]=0;
v27[0]=0x45D71892;
v27[1]=0x45D71892;
v27[2]=0x45D71892;
v27[3]=0x45D71892;
if( iScanCode ==1&& v12 ==1|| iScanCode !=1)
{
v25[0]=0;
v25[1]=0;
v25[2]=0;
v25[3]=0;
v28[0]=0x45D71892;
v28[1]=0x45D71892;
v28[2]=0x45D71892;
v28[3]=0x45D71892;
}
v20 = iScanCode -1;
switch( iScanCode )
{
case1u: // 0x00 (null terminator?)
++pScanResults->iNullBytes;
++v22;
break;
case2u: // 0xC2 (retn)
if( dwBytesRead - dwReadOffset >=2)
{
dwRetnSize =*(_BYTE *)(dwReadOffset + lpMemory +1);
if(!*(_BYTE *)(dwReadOffset + lpMemory +2)&& dwRetnSize <=0x20&&!(dwRetnSize &3))
{
++pScanResults->iNumFunctionRets;
++v29;
goto LABEL_34;
}
}
break;
case5u: // 0xE1 ???
LABEL_34:
v21 = sub_100064C0(v26);
if( v21 >=0&& v21 <256)
{
v13 = v21 >>5;
*(_DWORD *)(a4 +4*(v21 >>5))|=1<< v21 %32;
}
break;
case3u: // 0xE8 (call opcode)
if( dwBytesRead - dwReadOffset >=4)
{
dwCallLocation =*(_DWORD *)(dwReadOffset + lpMemory +1);
if((signedint)dwCallLocation <0x80000&& dwCallLocation >0xFFF80000)
{
++pScanResults->iNumFunctionCalls;
++v29;
}
}
break;
case4u: // 0x8B or 0xCC
dwOpcodes =*(_DWORD *)(lpMemory +(dwReadOffset &0xFFFFFFFC));
if( dwOpcodes ==0xCCCCCCCC&&(dwReadOffset &3)==3)// Int3 or uninitialised variables in debug build?
{
++pScanResults->dword4;
v26 =0x45D71892;
}
dwOpcodes &=0xFFFFFFu;
// Searching for either prolog:

// push ebp
// mov ebp, esp

// Or:

// push edi
// mov edi, ecx
if( dwOpcodes ==0xEC8B55|| dwOpcodes ==0xF98B57)
{
++pScanResults->iPrologsFound;
++v29;
v26 =0x45D71892;
}
break;
default:
break;
}
}
v12 = iScanCode;
++dwReadOffset;
result = dwReadOffset >>12;
v16 = dwReadOffset >>12;
if( dwReadOffset >>12!= v15 )
{
if( dwBytesRead ==4096)
{
result =(int)pScanResults;
pScanResults->dword24 +=4096- v22;
}
elseif( v22 !=4096)
{
result = pScanResults->dword24 +4096;
pScanResults->dword24 = result;
}
v22 =0;
if( v29 >50)
{
result = pScanResults->dword20 +4096;
pScanResults->dword20 = result;
}
v29 =0;
v15 = v16;
}
}
return result;
}

A note: by reading directly from disk VAC can render some cheats with drivers useless as its not opening the process from memory. This depends on the driver though.

Some of the signatures they're looking for:


Credits to CaptainJack.
[/HIDE]
 
Last edited:

blm95

Member
hello, do you have vac source code? I will buy; I have $14 paypal and a $10 subway gift card for it
 

blm95

Member
I drink all sorts of coffee. I have a Keurig 350 at my house with like 15 different types of coffee.
the best cup of coffee i've had was in Italy at a small chain named "Tazza d'Oro" (cup of gold). Dunkin donuts is pretty decent, but I like my coffee very strong (but starbucks tastes burnt)
 
Top Bottom