master131 God-Like





Join Date: Nov 2011 Posts: 165 Reputation: 6393

Rep Power: 224



here is my analysis of the psuedo-code from the first function (file hasn't been approved yet).



First they decrypt v108 which contains 4653127 using a simple xor of 0x1B.

Code: for ( i = 0; *((_WORD *)&v108 + i); ++i ) { if ( i == 4 ) v60 = v142[0]; else v60 = *((_WORD *)&v108 + i) ^ 0x1B; *((_WORD *)&v108 + i) = v60; }

Code: v114 = import_CreateFileW(&v108, 0x80000000u /* GENERIC_READ */, 3 /* FILE_SHARE_READ | FILE_SHARE_WRITE */, 0, 3 /* OPEN_EXISTING */, 0, 0);

Code: for ( i = 0; *((_WORD *)&v63 + i); ++i ) { if ( i ) v59 = *((_WORD *)&v63 + i) ^ 0x1B; else v59 = v142[0]; *((_WORD *)&v63 + i) = v59; }

Code: v139 = import_GetVolumeInformationW(&v63, 0, 0, v141 + 56, 0, 0, 0, 0); Why didn't they just use DeviceIoControl instead of NtFsControlFile?)

Code: v96 = ((int (__stdcall *)(int, _DWORD, _DWORD, _DWORD, char *, unsigned int, _DWORD, _DWORD, int *, unsigned int))NtFsControlFile)( v114, 0, 0, 0, &v61, 0x900F4u, // FSCTL_QUERY_USN_JOURNAL 0, 0, &v136, // Output buffer for USN_JOURNAL_DATA_V0 structure. 0x38u /* sizeof(USN_JOURNAL_DATA_V0) */);

Code: v135 = import_VirtualAlloc(0, 0x4000000u, 0x3000u /* MEM_COMMIT | MEM_RESERVE */, 4 /* PAGE_READWRITE */);

Code: // READ_USN_JOURNAL_DATA_V0 structure. v126 = v104; // StartUsn = 0 (v104 = 0i64) v127 = 0x80000000u; // ReasonMask = USN_REASON_CLOSE v128 = 1; // ReturnOnlyOnClose = 1 v129 = 0; // Timeout v130 = 0; // Timeout v131 = 0; // BytesToWaitFor v132 = 0; // BytesToWaitFor v133 = v136; // USNJournalID v134 = v137; // USNJournalID v96 = ((int (__stdcall *)(int, _DWORD, _DWORD, _DWORD, char *, unsigned int, __int64 *, signed int, int, unsigned int))NtFsControlFile)( v114, 0, 0, 0, &v61, 0x900BBu, // FSCTL_READ_USN_JOURNAL &v126, // READ_USN_JOURNAL_DATA_V0 structure. 40, // Input buffer size. v135, // Output buffer for USN, followed by (optional) USN_RECORD structures. 0x4000000u /* Same output buffer size */);



Take note how StartUsn is set to zero, this will essentially list every file that has been recently closed. I tested this code locally in a sample application using the exact same parameters/flags and it listed over 6000 records/entries (750 unique files) after calling NtFsControlFile twice after each other.



You can find the application that I used to list these here:

http://www.unknowncheats.me/forum/844730-post77.html



Now this is where stuff gets a bit interesting, it starts iterating through each USN record in the journal and first checks if the file name buffer is larger than 32 bytes (note that these are unicode strings, so longer than 16 characters). It then reads the last 16 letters of the file name one and "normalises" it by making it lower-case. Note that USN records store the file name only, they are not full paths (only way to get a full path is to reconstruct it using the parent USN). Also, USN records are not limited to files, they can include folders too.

Code: if ( (unsigned int)*(_WORD *)(v118 + 56) /* v118->FileNameLength */ > 0x20 /* 32 */ ) { v119 = v118 + *(_WORD *)(v118 + 58) /* v118-> FileNameOffset */ + *(_WORD *)(v118 + 56) /* v118->FileNameLength */ - 32; for ( i = 0; (unsigned int)i < 0x10; ++i ) { if ( (signed int)*(_WORD *)v119 >= 65 /* 'A' */) { if ( (signed int)*(_WORD *)v119 <= 90 /* 'Z' */) *(_WORD *)v119 += 32; } v144[i] = *(_WORD *)v119; v119 += 2; }

Code: *(_DWORD *)(v118 + 40) /* v118->Reason */ &= 0x80303370u; /* USN_REASON_CLOSE | USN_REASON_STREAM_CHANGE | USN_REASON_REPARSE_POINT_CHANGE | USN_REASON_RENAME_NEW_NAME | USN_REASON_RENAME_OLD_NAME | USN_REASON_FILE_DELETE | USN_REASON_FILE_CREATE | USN_REASON_NAMED_DATA_TRUNCATION | USN_REASON_NAMED_DATA_EXTEND | USN_REASON_NAMED_DATA_OVERWRITE */ v145 = *(_DWORD *)(v118 + 40);

Code: MD5Init(&v115); MD5Update((int)&v115, v144, 0x24u); MD5Final(&v120, &v115); v9 = 4; v10 = &unk_10009008; // *** Hash #1 *** v11 = &v120; v8 = 1; do { if ( !v9 ) break; v8 = *(_DWORD *)v11 == *(_DWORD *)v10; v11 += 4; v10 = (char *)v10 + 4; --v9; } while ( v8 ); Code: v17 = 4; v18 = &unk_10009018; // *** Hash #2 **** v19 = &v120; v16 = 1; do { if ( !v17 ) break; v16 = *(_DWORD *)v19 == *(_DWORD *)v18; v19 += 4; v18 = (char *)v18 + 4; --v17; }

Code: if ( (unsigned int)*(_WORD *)(v118 + 56) /* v118->FileNameLength */ > 8) { v119 = v118 + *(_WORD *)(v118 + 58) /* v118-> FileNameOffset */ + *(_WORD *)(v118 + 56) /* v118->FileNameLength */ - 8; for ( i = 0; (unsigned int)i < 4; ++i ) { if ( (signed int)*(_WORD *)v119 >= 65 /* 'A' */) { if ( (signed int)*(_WORD *)v119 <= 90 /* 'Z' */) *(_WORD *)v119 += 32; } v99[i] = *(_WORD *)v119; v99[i] ^= v116[i] << 8; v119 += 2; } v67 = &v116[i]; v125 = &v99[i]; for ( i = 0; (unsigned int)i < 8; ++i ) *((_BYTE *)v125 + i) = ((unsigned __int16)v67[i] >> 8) ^ v67[i]; *(_DWORD *)(v118 + 40) &= 0x80303372u; // USN_REASON_CLOSE | USN_REASON_STREAM_CHANGE | USN_REASON_REPARSE_POINT_CHANGE | USN_REASON_RENAME_NEW_NAME | USN_REASON_RENAME_OLD_NAME | USN_REASON_FILE_DELETE | USN_REASON_FILE_CREATE | USN_REASON_NAMED_DATA_TRUNCATION | USN_REASON_NAMED_DATA_EXTEND | USN_REASON_NAMED_DATA_OVERWRITE | USN_REASON_DATA_EXTEND v101 = *(_DWORD *)(v118 + 40); MD5Init(&v115); MD5Update((int)&v115, v99, 0x14u); MD5Final(&v120, &v115); v30 = 4; v31 = &unk_10009028; // *** Hash #3 *** v32 = &v120; v29 = 1; do { if ( !v30 ) break; v29 = *(_DWORD *)v32 == *(_DWORD *)v31; v32 += 4; v31 = (char *)v31 + 4; --v30; } while ( v29 ); if ( v29 ) goto LABEL_135; v34 = 4; v35 = &unk_10009038; // *** Hash #4 *** v36 = &v120; v33 = 1; do { if ( !v34 ) break; v33 = *(_DWORD *)v36 == *(_DWORD *)v35; v36 += 4; v35 = (char *)v35 + 4; --v34; } while ( v33 ); Code: v47 = 4; v48 = &unk_10009048; // *** Hash #5 *** v49 = &v120; v46 = 1; do { if ( !v47 ) break; v46 = *(_DWORD *)v49 == *(_DWORD *)v48; v49 += 4; v48 = (char *)v48 + 4; --v47; } while ( v46 ); Code: v51 = 4; v52 = &unk_10009058; // *** Hash #6 *** v53 = &v120; v50 = 1; do { if ( !v51 ) break; v50 = *(_DWORD *)v53 == *(_DWORD *)v52; v53 += 4; v52 = (char *)v52 + 4; --v51; } while ( v50 ); Thanks for this poink,(file hasn't been approved yet).First they decrypt v108 which contains 4653127 using a simple xor of 0x1B.Then they're calling CreateFileW with v108 which now contains "c:\\" to obtain a handle of the drive.Then they decrypt v63 which has a value of 2162808 using the same xor method.Now, v63 contains, you guessed it, "c:". They then call GetVolumeInformationW passing a buffer to the (optional) lpVolumeSerialNumber parameter and put the value into the output packet that will be sent to their server, essentially logging the serial number of your C drive.Then they call NtFsControlFile with the FSCTL_QUERY_USN_JOURNAL control code with a buffer size of 0x38 meaning the output buffer will store a USN_JOURNAL_DATA_V0 structure (rather than a USN_JOURNAL_DATA_V1 struct). (Now they allocate 0x4000000 bytes (64MB) using VirtualAlloc.Again, they call NtFsControlFile but this time with FSCTL_READ_USN_JOURNAL. This will check for any file changes from a previously saved USN (in this case, the one obtained from the previous call to NtFsControlFile), also note that the reason mask has been set to only notify when a file has been closed.At this point, it seems like they could be monitoring file changes using USN journals as seen in this MSDN example . USN journal records and its stages can be briefly read here . USN journal records are written whenever a file is modified in someway making it very easy for VAC to know when something changes on your C drive (in this case they've limited it to when a file closes).Take note how StartUsn is set to zero, this willYou can find the application that I used to list these here:Now this is where stuff gets a bit interesting, it starts iterating through each USN record in the journal and first checks if the file name buffer is larger than 32 bytes (note that these are unicode strings, so longer than 16 characters). It then reads the last 16 letters of the file name one and "normalises" it by making it lower-case. Note that USN records store the file name, they are not full paths (only way to get a full path is to reconstruct it using the parent USN). Also, USN records are not limited to files,It then checks the Reason field of the USN_RECORD struct and discards any flags that do not match.Afterwards, the partial file name and the Reason flags are hashed using MD5 and compared to 2 hashes (it's probably one of the ones @ poink posted, but there are actually 6 so he's missed 4).Similarly, the same thing is repeated again, this time with a FileNameLength of 8 (4 characters) and only the last 4 characters are taken (essentially the file extension for files). Also, this time it's compared with 4 hashes. Last edited by master131; 27th September 2013 at 03:40 AM .