/* * SfExtractDropper * * Purpose: * * Extract Sirefef/ZeroAccess from image resource. * * CNG variant * */ UINT SfExtractDropper( LPWSTR lpCommandLine ) { BOOL cond = FALSE, bSuccess = FALSE; ULONG c, uKey = 0, imagesz; WCHAR szInputFile[MAX_PATH + 1]; WCHAR szOutputFile[MAX_PATH + 1]; WCHAR szKey[MAX_PATH]; PVOID ImageBase = NULL, EncryptedData = NULL, DecryptedData = NULL; IStream *pImageStream = NULL; ULONG_PTR gdiplusToken = 0; GdiplusStartupInput input; GdiplusStartupOutput output; PVOID BitmapPtr = NULL; GdiPlusBitmapData BitmapData; GdiPlusRect rect; SIZE_T sz; PULONG ptr, i_ptr; //input file c = 0; RtlSecureZeroMemory(szInputFile, sizeof(szInputFile)); GetCommandLineParam(lpCommandLine, 1, (LPWSTR)&szInputFile, MAX_PATH, &c); if (c == 0) { SfcuiPrintText(g_ConOut, T_SFEXTRACTUSAGE, g_ConsoleOutput, FALSE); return (UINT)-1; } //output file c = 0; RtlSecureZeroMemory(&szOutputFile, sizeof(szOutputFile)); GetCommandLineParam(lpCommandLine, 2, (LPWSTR)&szOutputFile, MAX_PATH, &c); if (c == 0) { _strcpy(szOutputFile, TEXT("extracted.bin")); } //key c = 0; RtlSecureZeroMemory(&szKey, sizeof(szKey)); GetCommandLineParam(lpCommandLine, 3, (LPWSTR)&szKey, MAX_PATH, &c); if ((c == 0) || (c > 10)) { SfcuiPrintText(g_ConOut, T_SFEXTRACTUSAGE, g_ConsoleOutput, FALSE); return (UINT)-1; } c = 0; if (locase_w(szKey[1]) == 'x') { c = 2; } uKey = hextoul(&szKey[c]); do { ImageBase = SfuCreateFileMappingNoExec(szInputFile); if (ImageBase == NULL) break; c = 0; EncryptedData = SfLdrQueryResourceData(1, ImageBase, &c); if ((EncryptedData == NULL) || (c == 0)) break; pImageStream = SHCreateMemStream((BYTE *)EncryptedData, (UINT)c); if (pImageStream == NULL) break; RtlSecureZeroMemory(&input, sizeof(input)); RtlSecureZeroMemory(&output, sizeof(output)); input.GdiplusVersion = 1; if (GdiplusStartup(&gdiplusToken, &input, &output) != GdiplusOk) break; BitmapPtr = NULL; if (GdipCreateBitmapFromStream(pImageStream, &BitmapPtr) != GdiplusOk) break; RtlSecureZeroMemory(&rect, sizeof(rect)); if ( (GdipGetImageWidth(BitmapPtr, (UINT *)&rect.Width) == GdiplusOk) && (GdipGetImageHeight(BitmapPtr, (UINT *)&rect.Height) == GdiplusOk) ) { RtlSecureZeroMemory(&BitmapData, sizeof(BitmapData)); if (GdipBitmapLockBits(BitmapPtr, &rect, ImageLockModeRead, PixelFormat32bppARGB, &BitmapData) == GdiplusOk) { c = (rect.Width * rect.Height); imagesz = sizeof(ULONG) * c; sz = imagesz; DecryptedData = NULL; NtAllocateVirtualMemory(NtCurrentProcess(), &DecryptedData, 0, &sz, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); if (DecryptedData) { i_ptr = (PULONG)BitmapData.Scan0; ptr = DecryptedData; while (c > 0) { *ptr = *i_ptr ^ uKey; ptr++; i_ptr++; c--; } bSuccess = (SfuWriteBufferToFile(szOutputFile, DecryptedData, imagesz, FALSE, FALSE) == imagesz); sz = 0; NtFreeVirtualMemory(NtCurrentProcess(), &DecryptedData, &sz, MEM_RELEASE); } GdipBitmapUnlockBits(BitmapPtr, &BitmapData); } } } while (cond); if (bSuccess == FALSE) { SfcuiPrintText(g_ConOut, T_SFEXTRACTFAIL, g_ConsoleOutput, FALSE); } else { SfcuiPrintText(g_ConOut, szOutputFile, g_ConsoleOutput, TRUE); SfcuiPrintText(g_ConOut, T_SFEXTRACTED, g_ConsoleOutput, TRUE); } if (BitmapPtr != NULL) { GdipDisposeImage(&BitmapPtr); } if (gdiplusToken != 0) { GdiplusShutdown(gdiplusToken); } if (pImageStream != NULL) { pImageStream->lpVtbl->Release(pImageStream); } if (ImageBase != NULL) { NtUnmapViewOfSection(NtCurrentProcess(), ImageBase); } return 0; }
UINT SfDecryptPayload( LPWSTR lpParameter ) { BOOL cond = FALSE, bSuccess = FALSE; PBYTE cng_object, hashdata, decrypted, enc_data, extracted; ULONG obj_sz, rlen, hdatasz, enc_data_size; BCRYPT_ALG_HANDLE h_alg = NULL; BCRYPT_HASH_HANDLE h_hash = NULL; BCRYPT_KEY_HANDLE h_rc4key = NULL; NTSTATUS status; HANDLE pheap = NULL; PIMAGE_FILE_HEADER fheader; PVOID pdll = NULL; WCHAR InputFile[MAX_PATH + 1], OutputFile[MAX_PATH + 1]; rlen = 0; RtlSecureZeroMemory(InputFile, sizeof(InputFile)); GetCommandLineParam(lpParameter, 1, InputFile, MAX_PATH, &rlen); if (rlen == 0) { SfcuiPrintText(g_ConOut, T_SFDECRYPTUSAGE, g_ConsoleOutput, FALSE); return (UINT)-1; } do { rlen = 0; GetCommandLineParam(lpParameter, 2, OutputFile, MAX_PATH, &rlen); if (rlen == 0) _strcpy(OutputFile, TEXT("out.bin")); pdll = SfuCreateFileMappingNoExec(InputFile); if (pdll == NULL) break; enc_data_size = 0; enc_data = SfuQueryResourceData(2, pdll, &enc_data_size); if (enc_data == NULL) break; fheader = &(RtlImageNtHeader(pdll)->FileHeader); status = BCryptOpenAlgorithmProvider(&h_alg, BCRYPT_MD5_ALGORITHM, NULL, 0); if (!NT_SUCCESS(status)) break; obj_sz = 0; rlen = 0; status = BCryptGetProperty(h_alg, BCRYPT_OBJECT_LENGTH, (PUCHAR)&obj_sz, sizeof(obj_sz), &rlen, 0); if (!NT_SUCCESS(status)) break; hdatasz = 0; rlen = 0; status = BCryptGetProperty(h_alg, BCRYPT_HASH_LENGTH, (PUCHAR)&hdatasz, sizeof(hdatasz), &rlen, 0); if (!NT_SUCCESS(status)) break; pheap = HeapCreate(0, 0, 0); if (pheap == NULL) break; cng_object = HeapAlloc(pheap, HEAP_ZERO_MEMORY, obj_sz); if (cng_object == NULL) break; hashdata = HeapAlloc(pheap, HEAP_ZERO_MEMORY, hdatasz); if (hashdata == NULL) break; status = BCryptCreateHash(h_alg, &h_hash, cng_object, obj_sz, NULL, 0, 0); if (!NT_SUCCESS(status)) break; status = BCryptHashData(h_hash, (PUCHAR)fheader, sizeof(IMAGE_FILE_HEADER), 0); if (!NT_SUCCESS(status)) break; status = BCryptFinishHash(h_hash, hashdata, hdatasz, 0); if (!NT_SUCCESS(status)) break; BCryptDestroyHash(h_hash); BCryptCloseAlgorithmProvider(h_alg, 0); HeapFree(pheap, 0, cng_object); h_alg = NULL; h_hash = NULL; status = BCryptOpenAlgorithmProvider(&h_alg, BCRYPT_RC4_ALGORITHM, NULL, 0); if (!NT_SUCCESS(status)) break; obj_sz = 0; rlen = 0; status = BCryptGetProperty(h_alg, BCRYPT_OBJECT_LENGTH, (PUCHAR)&obj_sz, sizeof(obj_sz), &rlen, 0); if (!NT_SUCCESS(status)) break; cng_object = HeapAlloc(pheap, HEAP_ZERO_MEMORY, obj_sz); if (cng_object == NULL) break; status = BCryptGenerateSymmetricKey(h_alg, &h_rc4key, cng_object, obj_sz, hashdata, hdatasz, 0); if (!NT_SUCCESS(status)) break; decrypted = HeapAlloc(pheap, HEAP_ZERO_MEMORY, enc_data_size); if (decrypted == NULL) break; rlen = 0; status = BCryptEncrypt(h_rc4key, enc_data, enc_data_size, NULL, NULL, 0, decrypted, enc_data_size, &rlen, 0); if (!NT_SUCCESS(status)) break; bSuccess = FALSE; enc_data_size = rlen; rlen = 0; extracted = SfcabExtractMemory(decrypted, enc_data_size, &rlen); if (extracted) { if (SfuWriteBufferToFile(OutputFile, extracted, rlen, FALSE, FALSE) == rlen) { bSuccess = TRUE; } LocalFree(extracted); } else { //failed to extract, drop cab as is if (SfuWriteBufferToFile(OutputFile, decrypted, enc_data_size, FALSE, FALSE) == enc_data_size) { bSuccess = TRUE; } } if (bSuccess) { SfcuiPrintText(g_ConOut, T_SFDECRYPTED, g_ConsoleOutput, FALSE); SfcuiPrintText(g_ConOut, OutputFile, g_ConsoleOutput, FALSE); } } while (cond); if (bSuccess == FALSE) { SfcuiPrintText(g_ConOut, T_SFDECRYPTFAIL, g_ConsoleOutput, FALSE); } if (h_rc4key != NULL) BCryptDestroyKey(h_rc4key); if (h_hash != NULL) BCryptDestroyHash(h_hash); if (h_alg != NULL) BCryptCloseAlgorithmProvider(h_alg, 0); if (pheap != NULL) HeapDestroy(pheap); if (pdll != 0) NtUnmapViewOfSection(NtCurrentProcess(), (PVOID)pdll); return 0; }