Subversion Repositories filter_foundry

Rev

Rev 510 | Rev 532 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /*
  2.     This file is part of "Filter Foundry", a filter plugin for Adobe Photoshop
  3.     Copyright (C) 2003-2009 Toby Thain, toby@telegraphics.com.au
  4.     Copyright (C) 2018-2022 Daniel Marschall, ViaThinkSoft
  5.  
  6.     This program is free software; you can redistribute it and/or modify
  7.     it under the terms of the GNU General Public License as published by
  8.     the Free Software Foundation; either version 2 of the License, or
  9.     (at your option) any later version.
  10.  
  11.     This program is distributed in the hope that it will be useful,
  12.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.     GNU General Public License for more details.
  15.  
  16.     You should have received a copy of the GNU General Public License
  17.     along with this program; if not, write to the Free Software
  18.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19. */
  20.  
  21. #include <stddef.h>
  22. #include <stdint.h>
  23.  
  24. #include "ff.h"
  25.  
  26. // Random seed for obfuscation "17 05 83 52 2a 97 16 74"
  27. // During the standalone-make process, this value will be changed by manipulating the 8BF file.
  28. // Therefore, the 32/64 bit 8BF files *MUST* contain the key contiguous and preferrpreferablyibly 4-aligned
  29. // Why do I use GetObfuscSeed?
  30. // 1. Because I prefer the key in side code segment so that it is better hidden than if it was in a data segment.
  31. // 2. Since the code segment is closer to the 8BF file start, the search+replace of the key is faster
  32. // Please also note:
  33. // The 8BF file *MUST* only contain the seed A SINGLE TIME
  34. // (In the Non-Standalone filter actually 3 times, because we have 2 resourced containing the 32/64 template DLLs)
  35. #if defined(__WATCOMC__)
  36.         uint64_t GetObfuscSeed() {
  37.                 // Due to "volatile", this value will only exist a single time in the binary file.
  38.                 // This char array will result in contiguous chars in OpenWatcom.
  39.                 // In MSVC++, the array will be built using several "mov ..." OP codes.
  40.                 volatile char seed[8] = { '\x17', '\x05', '\x83', '\x52', '\x2a', '\x97', '\x16', '\x74' };
  41.                 return (uint64_t)seed;
  42.         }
  43. #elif defined(_MSC_VER)
  44.         #ifdef _WIN64
  45.         // Note: For MSVCC 64-bit, neither making the method volatile, nor including a volatile variable did avoid inlining.
  46.         // so we use __declspec(noinline)
  47.         __declspec(noinline) uint64_t GetObfuscSeed() {
  48.                 // TODO: Not 4-byte aligned! (both variants)
  49.                 //volatile uint64_t seed = 0x7416972a52830517ull;
  50.                 //return seed;
  51.                 return 0x7416972a52830517ull;
  52.         }
  53.         #else
  54.         __declspec(noinline) uint64_t GetObfuscSeed() {
  55.                 //volatile int test = 0;
  56.                 uint64_t* addr = NULL;
  57.                 __asm {
  58.                         mov eax, seed // Doesn't work in OpenWatcom
  59.                         mov addr, eax
  60.                         jmp end
  61.                         align 4 // Doesn't work in OpenWatcom
  62.                         seed:
  63.                                 _emit 0x17 // Doesn't work in OpenWatcom
  64.                                 _emit 0x05
  65.                                 _emit 0x83
  66.                                 _emit 0x52
  67.                                 _emit 0x2A
  68.                                 _emit 0x97
  69.                                 _emit 0x16
  70.                                 _emit 0x74
  71.                                 /*
  72.                                 pop ss
  73.                                 add eax, 0x972a5283
  74.                                 push ss
  75.                                 jz seed
  76.                                 */
  77.                         end:
  78.                 }
  79.                 return addr == NULL ? 0 : *addr;
  80.         }
  81.         #endif
  82. #else
  83.         // Unfortunately, with this compiler, we don't know how to force the seed into the .code segment.
  84.         // So, we put it in the .data segment.
  85.         // Note: Due to "const volatile", this value will only exist a single time in the binary file.
  86.         const volatile uint64_t obfusc_seed = 0x7416972a52830517ull;
  87.         uint64_t GetObfuscSeed() {
  88.                 return obfusc_seed;
  89.         }
  90. #endif
  91.  
  92. // Random seed #2 for obfuscation "86 21 1f 3e f1 a2 87 ef"
  93. // Lies in the data segment. Same rules like for the random seed #1.
  94. const volatile uint64_t obfusc_seed2 = 0xef87a2f13e1f2186ull;
  95. #ifdef _MSC_VER
  96. __declspec(noinline)
  97. #endif
  98. uint64_t GetObfuscSeed2() {
  99.         // Additional seed for Obfusc V7. It is always in the data segment,
  100.         // while obfusc seed 1 is in the code segment (if the compiler allows it)
  101.         return obfusc_seed2;
  102. }
  103.  
  104. #ifdef WIN_ENV
  105. Boolean obfusc_seed_replace(FSSpec* dst, uint64_t search1, uint64_t search2, uint64_t replace1, uint64_t replace2, int maxamount1, int maxamount2) {
  106.         uint64_t srecord = 0;
  107.         int found1 = 0, found2 = 0;
  108.         Boolean done = false;
  109.         FILEREF fptr;
  110.         FILECOUNT cnt;
  111.  
  112.         if (FSpOpenDF(dst, fsRdWrPerm, &fptr) != noErr) return -1;
  113.  
  114.         cnt = sizeof(srecord);
  115.         while (FSRead(fptr, &cnt, &srecord) == noErr)
  116.         {
  117.                 if (cnt != sizeof(srecord)) break; // EOF reached
  118.                 if (srecord == search1) {
  119.                         srecord = replace1;
  120.                         SetFPos(fptr, fsFromMark, -1 * (long)sizeof(srecord));
  121.                         cnt = (int)sizeof(srecord);
  122.                         FSWrite(fptr, &cnt, &srecord);
  123.                         SetFPos(fptr, fsFromStart, 0); // important for fseek
  124.                         found1++;
  125.                         done = (found1 == maxamount1) && (found2 == maxamount2);
  126.                         if (done) break;
  127.                 }
  128.                 else if (srecord == search2) {
  129.                         srecord = replace2;
  130.                         SetFPos(fptr, fsFromMark, -1 * (long)sizeof(srecord));
  131.                         cnt = (int)sizeof(srecord);
  132.                         FSWrite(fptr, &cnt, &srecord);
  133.                         SetFPos(fptr, fsFromStart, 0); // important for fseek
  134.                         found2++;
  135.                         done = (found1 == maxamount1) && (found2 == maxamount2);
  136.                         if (done) break;
  137.                 }
  138.                 else {
  139.                         SetFPos(fptr, fsFromMark, -1 * (long)(sizeof(srecord) - 1));
  140.                 }
  141.         }
  142.         FSClose(fptr);
  143.  
  144.         return done;
  145. }
  146. #endif
  147.        
  148. int rand_msvcc(unsigned int* seed) {
  149.         *seed = *seed * 214013L + 2531011L;
  150.         return (*seed >> 16) & 0x7fff; /* Scale between 0 and RAND_MAX */
  151. }
  152.  
  153. int rand_openwatcom(unsigned int* seed) {
  154.         // https://github.com/open-watcom/open-watcom-v2/blob/master/bld/clib/math/c/rand.c
  155.         *seed = *seed * 1103515245L + 12345L;
  156.         return (*seed >> 16) & 0x7fff; /* Scale between 0 and RAND_MAX */
  157. }
  158.  
  159. void xorshift(unsigned char** p, uint32_t* x32, size_t num) {
  160.         size_t i;
  161.         unsigned char* x = *p;
  162.         for (i = 0; i < num; i++) {
  163.                 // https://de.wikipedia.org/wiki/Xorshift
  164.                 *x32 ^= *x32 << 13;
  165.                 *x32 ^= *x32 >> 17;
  166.                 *x32 ^= *x32 << 5;
  167.                 *x++ ^= *x32;
  168.         }
  169.         *p = x;
  170. }
  171.  
  172. void xorshift64(unsigned char** p, uint64_t* x64, size_t num) {
  173.         // https://de.wikipedia.org/wiki/Xorshift
  174.         size_t i;
  175.         unsigned char* x = *p;
  176.         for (i = 0; i < num; i++) {
  177.                 *x64 ^= *x64 << 13;
  178.                 *x64 ^= *x64 >> 7;
  179.                 *x64 ^= *x64 << 17;
  180.                 *x++ ^= *x64;
  181.         }
  182.         *p = x;
  183. }
  184.  
  185. #ifndef CHAR_BIT
  186. #define CHAR_BIT 8
  187. #endif
  188.  
  189. uint64_t rol_u64(uint64_t value, uint64_t by) {
  190.         return value << by | value >> ((uint64_t)sizeof(uint64_t) * CHAR_BIT - by);
  191. }
  192.  
  193. void rolshift(unsigned char** p, uint64_t* x64, size_t num) {
  194.         size_t i;
  195.         unsigned char* x = *p;
  196.         for (i = 0; i < num; i++) {
  197.                 *x++ ^= *x64;
  198.                 *x64 = rol_u64(*x64, 1);
  199.         }
  200.         *p = x;
  201. }
  202.  
  203. uint32_t crc32b(char *data, int nLength) {
  204.         int i, j, k;
  205.         uint32_t crc, mask;
  206.         char byte;
  207.  
  208.         i = 0;
  209.         crc = 0xFFFFFFFF;
  210.  
  211.         for(k=0;k<nLength;k++) {
  212.                 byte = data[k];
  213.                 crc = crc ^ byte;
  214.                 for (j = 7; j >= 0; j--) {
  215.                         mask = (-1) * (crc & 1);
  216.                         crc = (crc >> 1) ^ (0xEDB88320 & mask);
  217.                 }
  218.                 i++;
  219.         }
  220.         return ~crc;
  221. }
  222.  
  223. static const uint64_t crc64_tab[256] = {
  224.         0x0000000000000000ULL, 0x42F0E1EBA9EA3693ULL, 0x85E1C3D753D46D26ULL,
  225.         0xC711223CFA3E5BB5ULL, 0x493366450E42ECDFULL, 0x0BC387AEA7A8DA4CULL,
  226.         0xCCD2A5925D9681F9ULL, 0x8E224479F47CB76AULL, 0x9266CC8A1C85D9BEULL,
  227.         0xD0962D61B56FEF2DULL, 0x17870F5D4F51B498ULL, 0x5577EEB6E6BB820BULL,
  228.         0xDB55AACF12C73561ULL, 0x99A54B24BB2D03F2ULL, 0x5EB4691841135847ULL,
  229.         0x1C4488F3E8F96ED4ULL, 0x663D78FF90E185EFULL, 0x24CD9914390BB37CULL,
  230.         0xE3DCBB28C335E8C9ULL, 0xA12C5AC36ADFDE5AULL, 0x2F0E1EBA9EA36930ULL,
  231.         0x6DFEFF5137495FA3ULL, 0xAAEFDD6DCD770416ULL, 0xE81F3C86649D3285ULL,
  232.         0xF45BB4758C645C51ULL, 0xB6AB559E258E6AC2ULL, 0x71BA77A2DFB03177ULL,
  233.         0x334A9649765A07E4ULL, 0xBD68D2308226B08EULL, 0xFF9833DB2BCC861DULL,
  234.         0x388911E7D1F2DDA8ULL, 0x7A79F00C7818EB3BULL, 0xCC7AF1FF21C30BDEULL,
  235.         0x8E8A101488293D4DULL, 0x499B3228721766F8ULL, 0x0B6BD3C3DBFD506BULL,
  236.         0x854997BA2F81E701ULL, 0xC7B97651866BD192ULL, 0x00A8546D7C558A27ULL,
  237.         0x4258B586D5BFBCB4ULL, 0x5E1C3D753D46D260ULL, 0x1CECDC9E94ACE4F3ULL,
  238.         0xDBFDFEA26E92BF46ULL, 0x990D1F49C77889D5ULL, 0x172F5B3033043EBFULL,
  239.         0x55DFBADB9AEE082CULL, 0x92CE98E760D05399ULL, 0xD03E790CC93A650AULL,
  240.         0xAA478900B1228E31ULL, 0xE8B768EB18C8B8A2ULL, 0x2FA64AD7E2F6E317ULL,
  241.         0x6D56AB3C4B1CD584ULL, 0xE374EF45BF6062EEULL, 0xA1840EAE168A547DULL,
  242.         0x66952C92ECB40FC8ULL, 0x2465CD79455E395BULL, 0x3821458AADA7578FULL,
  243.         0x7AD1A461044D611CULL, 0xBDC0865DFE733AA9ULL, 0xFF3067B657990C3AULL,
  244.         0x711223CFA3E5BB50ULL, 0x33E2C2240A0F8DC3ULL, 0xF4F3E018F031D676ULL,
  245.         0xB60301F359DBE0E5ULL, 0xDA050215EA6C212FULL, 0x98F5E3FE438617BCULL,
  246.         0x5FE4C1C2B9B84C09ULL, 0x1D14202910527A9AULL, 0x93366450E42ECDF0ULL,
  247.         0xD1C685BB4DC4FB63ULL, 0x16D7A787B7FAA0D6ULL, 0x5427466C1E109645ULL,
  248.         0x4863CE9FF6E9F891ULL, 0x0A932F745F03CE02ULL, 0xCD820D48A53D95B7ULL,
  249.         0x8F72ECA30CD7A324ULL, 0x0150A8DAF8AB144EULL, 0x43A04931514122DDULL,
  250.         0x84B16B0DAB7F7968ULL, 0xC6418AE602954FFBULL, 0xBC387AEA7A8DA4C0ULL,
  251.         0xFEC89B01D3679253ULL, 0x39D9B93D2959C9E6ULL, 0x7B2958D680B3FF75ULL,
  252.         0xF50B1CAF74CF481FULL, 0xB7FBFD44DD257E8CULL, 0x70EADF78271B2539ULL,
  253.         0x321A3E938EF113AAULL, 0x2E5EB66066087D7EULL, 0x6CAE578BCFE24BEDULL,
  254.         0xABBF75B735DC1058ULL, 0xE94F945C9C3626CBULL, 0x676DD025684A91A1ULL,
  255.         0x259D31CEC1A0A732ULL, 0xE28C13F23B9EFC87ULL, 0xA07CF2199274CA14ULL,
  256.         0x167FF3EACBAF2AF1ULL, 0x548F120162451C62ULL, 0x939E303D987B47D7ULL,
  257.         0xD16ED1D631917144ULL, 0x5F4C95AFC5EDC62EULL, 0x1DBC74446C07F0BDULL,
  258.         0xDAAD56789639AB08ULL, 0x985DB7933FD39D9BULL, 0x84193F60D72AF34FULL,
  259.         0xC6E9DE8B7EC0C5DCULL, 0x01F8FCB784FE9E69ULL, 0x43081D5C2D14A8FAULL,
  260.         0xCD2A5925D9681F90ULL, 0x8FDAB8CE70822903ULL, 0x48CB9AF28ABC72B6ULL,
  261.         0x0A3B7B1923564425ULL, 0x70428B155B4EAF1EULL, 0x32B26AFEF2A4998DULL,
  262.         0xF5A348C2089AC238ULL, 0xB753A929A170F4ABULL, 0x3971ED50550C43C1ULL,
  263.         0x7B810CBBFCE67552ULL, 0xBC902E8706D82EE7ULL, 0xFE60CF6CAF321874ULL,
  264.         0xE224479F47CB76A0ULL, 0xA0D4A674EE214033ULL, 0x67C58448141F1B86ULL,
  265.         0x253565A3BDF52D15ULL, 0xAB1721DA49899A7FULL, 0xE9E7C031E063ACECULL,
  266.         0x2EF6E20D1A5DF759ULL, 0x6C0603E6B3B7C1CAULL, 0xF6FAE5C07D3274CDULL,
  267.         0xB40A042BD4D8425EULL, 0x731B26172EE619EBULL, 0x31EBC7FC870C2F78ULL,
  268.         0xBFC9838573709812ULL, 0xFD39626EDA9AAE81ULL, 0x3A28405220A4F534ULL,
  269.         0x78D8A1B9894EC3A7ULL, 0x649C294A61B7AD73ULL, 0x266CC8A1C85D9BE0ULL,
  270.         0xE17DEA9D3263C055ULL, 0xA38D0B769B89F6C6ULL, 0x2DAF4F0F6FF541ACULL,
  271.         0x6F5FAEE4C61F773FULL, 0xA84E8CD83C212C8AULL, 0xEABE6D3395CB1A19ULL,
  272.         0x90C79D3FEDD3F122ULL, 0xD2377CD44439C7B1ULL, 0x15265EE8BE079C04ULL,
  273.         0x57D6BF0317EDAA97ULL, 0xD9F4FB7AE3911DFDULL, 0x9B041A914A7B2B6EULL,
  274.         0x5C1538ADB04570DBULL, 0x1EE5D94619AF4648ULL, 0x02A151B5F156289CULL,
  275.         0x4051B05E58BC1E0FULL, 0x87409262A28245BAULL, 0xC5B073890B687329ULL,
  276.         0x4B9237F0FF14C443ULL, 0x0962D61B56FEF2D0ULL, 0xCE73F427ACC0A965ULL,
  277.         0x8C8315CC052A9FF6ULL, 0x3A80143F5CF17F13ULL, 0x7870F5D4F51B4980ULL,
  278.         0xBF61D7E80F251235ULL, 0xFD913603A6CF24A6ULL, 0x73B3727A52B393CCULL,
  279.         0x31439391FB59A55FULL, 0xF652B1AD0167FEEAULL, 0xB4A25046A88DC879ULL,
  280.         0xA8E6D8B54074A6ADULL, 0xEA16395EE99E903EULL, 0x2D071B6213A0CB8BULL,
  281.         0x6FF7FA89BA4AFD18ULL, 0xE1D5BEF04E364A72ULL, 0xA3255F1BE7DC7CE1ULL,
  282.         0x64347D271DE22754ULL, 0x26C49CCCB40811C7ULL, 0x5CBD6CC0CC10FAFCULL,
  283.         0x1E4D8D2B65FACC6FULL, 0xD95CAF179FC497DAULL, 0x9BAC4EFC362EA149ULL,
  284.         0x158E0A85C2521623ULL, 0x577EEB6E6BB820B0ULL, 0x906FC95291867B05ULL,
  285.         0xD29F28B9386C4D96ULL, 0xCEDBA04AD0952342ULL, 0x8C2B41A1797F15D1ULL,
  286.         0x4B3A639D83414E64ULL, 0x09CA82762AAB78F7ULL, 0x87E8C60FDED7CF9DULL,
  287.         0xC51827E4773DF90EULL, 0x020905D88D03A2BBULL, 0x40F9E43324E99428ULL,
  288.         0x2CFFE7D5975E55E2ULL, 0x6E0F063E3EB46371ULL, 0xA91E2402C48A38C4ULL,
  289.         0xEBEEC5E96D600E57ULL, 0x65CC8190991CB93DULL, 0x273C607B30F68FAEULL,
  290.         0xE02D4247CAC8D41BULL, 0xA2DDA3AC6322E288ULL, 0xBE992B5F8BDB8C5CULL,
  291.         0xFC69CAB42231BACFULL, 0x3B78E888D80FE17AULL, 0x7988096371E5D7E9ULL,
  292.         0xF7AA4D1A85996083ULL, 0xB55AACF12C735610ULL, 0x724B8ECDD64D0DA5ULL,
  293.         0x30BB6F267FA73B36ULL, 0x4AC29F2A07BFD00DULL, 0x08327EC1AE55E69EULL,
  294.         0xCF235CFD546BBD2BULL, 0x8DD3BD16FD818BB8ULL, 0x03F1F96F09FD3CD2ULL,
  295.         0x41011884A0170A41ULL, 0x86103AB85A2951F4ULL, 0xC4E0DB53F3C36767ULL,
  296.         0xD8A453A01B3A09B3ULL, 0x9A54B24BB2D03F20ULL, 0x5D45907748EE6495ULL,
  297.         0x1FB5719CE1045206ULL, 0x919735E51578E56CULL, 0xD367D40EBC92D3FFULL,
  298.         0x1476F63246AC884AULL, 0x568617D9EF46BED9ULL, 0xE085162AB69D5E3CULL,
  299.         0xA275F7C11F7768AFULL, 0x6564D5FDE549331AULL, 0x279434164CA30589ULL,
  300.         0xA9B6706FB8DFB2E3ULL, 0xEB46918411358470ULL, 0x2C57B3B8EB0BDFC5ULL,
  301.         0x6EA7525342E1E956ULL, 0x72E3DAA0AA188782ULL, 0x30133B4B03F2B111ULL,
  302.         0xF7021977F9CCEAA4ULL, 0xB5F2F89C5026DC37ULL, 0x3BD0BCE5A45A6B5DULL,
  303.         0x79205D0E0DB05DCEULL, 0xBE317F32F78E067BULL, 0xFCC19ED95E6430E8ULL,
  304.         0x86B86ED5267CDBD3ULL, 0xC4488F3E8F96ED40ULL, 0x0359AD0275A8B6F5ULL,
  305.         0x41A94CE9DC428066ULL, 0xCF8B0890283E370CULL, 0x8D7BE97B81D4019FULL,
  306.         0x4A6ACB477BEA5A2AULL, 0x089A2AACD2006CB9ULL, 0x14DEA25F3AF9026DULL,
  307.         0x562E43B4931334FEULL, 0x913F6188692D6F4BULL, 0xD3CF8063C0C759D8ULL,
  308.         0x5DEDC41A34BBEEB2ULL, 0x1F1D25F19D51D821ULL, 0xD80C07CD676F8394ULL,
  309.         0x9AFCE626CE85B507ULL
  310. };
  311.  
  312. /*
  313.  * ECMA 182 CRC64, taken from https://searchcode.com/file/68313281/lib/crc64.c/
  314.  */
  315. uint64_t crc64(const unsigned char* data, size_t len)
  316. {
  317.         uint64_t crc = 0;
  318.  
  319.         while (len--) {
  320.                 int i = ((int)(crc >> 56) ^ *data++) & 0xFF;
  321.                 crc = crc64_tab[i] ^ (crc << 8);
  322.         }
  323.  
  324.         return crc;
  325. }
  326.  
  327.  
  328. int obfuscation_version(PARM_T* pparm) {
  329.         uint32_t obfusc_info = pparm->unknown2;
  330.  
  331.         if (obfusc_info == 0x00000001) { // 01 00 00 00
  332.                 // Photoshop FilterFactory default initialization of field "unknown2" (no obfuscation)
  333.                 return 0;
  334.         }
  335.         else if (obfusc_info == 0x00000000) { // 00 00 00 00
  336.                 // Premiere FilterFactory default initialization of field "unknown1" (no obfuscation)
  337.                 // (Premiere Field "unknown1" has the offset of Photoshop's "unknown2" field)
  338.                 return 0;
  339.         }
  340.         else if (obfusc_info == 0x90E364A3) { // A3 64 E3 90
  341.                 // Version 1 obfuscation (Filter Foundry 1.4b8,9,10)
  342.                 return 1;
  343.         }
  344.         else if (obfusc_info == 0xE2CFCA34) { // 34 CA CF E2
  345.                 // Version 2 obfuscation (Filter Foundry 1.7b1)
  346.                 return 2;
  347.         }
  348.         else if ((obfusc_info >= 4) && (obfusc_info <= 0xFF)) { // xx 00 00 00
  349.                 // Version 4 obfuscation (Filter Foundry 1.7.0.7)
  350.                 // Version 5 obfuscation (Filter Foundry 1.7.0.8)
  351.                 // Version 6 obfuscation (Filter Foundry 1.7.0.10)
  352.                 // Version 7 obfuscation (Filter Foundry 1.7.0.17)
  353.                 // Future: Version 8, 9, ..., 255
  354.                 return obfusc_info;
  355.         }
  356.         else {
  357.                 // Version 3 obfuscation (Filter Foundry 1.7.0.5)
  358.                 // obfusc_info is the srand() seed and is equal to the time(0) build timestamp
  359.                 return 3;
  360.         }
  361. }
  362.  
  363. void obfusc(PARM_T* pparm, uint64_t* out_initial_seed, uint64_t* out_initial_seed2) {
  364.         // Version 7 obfuscation (Introduced in Filter Foundry 1.7.0.17)
  365.  
  366.         unsigned char* p;
  367.         uint64_t initial_seed, initial_seed2, rolseed;
  368.         uint32_t xorseed;
  369.         uint64_t xorseed2;
  370.         size_t size = sizeof(PARM_T);
  371.         int rand_iters, i, j;
  372.  
  373. #ifdef MAC_ENV
  374.         // Currently, make_mac.c does not implement modifying the executable code (TODO),
  375.         // so we will use the default initial_seed!
  376.         initial_seed = GetObfuscSeed();
  377.         initial_seed2 = GetObfuscSeed2();
  378. #else
  379.         // Give always the same seed if the parameters are the same. No random values.
  380.         // This initial seed will be returned and built into the executable code by make_win.c
  381.         pparm->unknown1 = 0;
  382.         pparm->unknown2 = 0;
  383.         pparm->unknown3 = 0;
  384.         initial_seed = crc64((unsigned char*)pparm, sizeof(PARM_T));
  385.         pparm->unknown3 = crc32b((char*)pparm, sizeof(PARM_T)); // make sure that the second seed is different
  386.         pparm->unknown2 = crc32b((char*)pparm, sizeof(PARM_T)); // make sure that the second seed is different
  387.         pparm->unknown1 = crc32b((char*)pparm, sizeof(PARM_T)); // make sure that the second seed is different
  388.         initial_seed2 = crc64((unsigned char*)pparm, sizeof(PARM_T));
  389. #endif
  390.  
  391.         // AFTER unknown1-3 have been set to 0 (again), calculate the checksum!
  392.         pparm->unknown1 = 0;
  393.         pparm->unknown2 = 0;
  394.         pparm->unknown3 = 0;
  395.         pparm->unknown1 = crc32b((char*)pparm, sizeof(PARM_T));
  396.  
  397.         xorseed = initial_seed & 0xFFFFFFFF;
  398.         p = (unsigned char*)pparm;
  399.         xorshift(&p, &xorseed, sizeof(PARM_T));
  400.  
  401.         rolseed = initial_seed;
  402.         p = (unsigned char*)pparm;
  403.         rolshift(&p, &rolseed, sizeof(PARM_T));
  404.  
  405.         rand_iters = 0xFFF - (initial_seed & 0xFF) + (initial_seed2 & 0xFF);
  406.         if (rand_iters < 0) rand_iters = 0;
  407.         for (j = rand_iters; j >= 0; j--) {
  408.                 uint32_t rand_seed = (initial_seed + initial_seed2 + j) & 0xFFFFFFFF;
  409.                 p = (unsigned char*)pparm;
  410.                 for (i = 0; i < 10; i++) {
  411.                         rand_msvcc(&rand_seed);
  412.                 }
  413.                 for (i = 0; i < (int)size; i++) {
  414.                         *p++ ^= (int)(rand_msvcc(&rand_seed) * 1.0 / ((double)RAND_MAX + 1) * 256);
  415.                 }
  416.         }
  417.  
  418.         xorseed2 = initial_seed2;
  419.         p = (unsigned char*)pparm;
  420.         xorshift64(&p, &xorseed2, sizeof(PARM_T));
  421.  
  422.         pparm->unknown2 = 7; // obfusc version
  423.  
  424.         *out_initial_seed = initial_seed;
  425.         *out_initial_seed2 = initial_seed2;
  426. }
  427.  
  428. void deobfusc(PARM_T* pparm) {
  429.         uint32_t obfusc_version;
  430.         size_t size = sizeof(PARM_T);
  431.  
  432.         obfusc_version = obfuscation_version(pparm);
  433.  
  434.         switch (obfusc_version) {
  435.                 case 0:
  436.                         // no obfuscation
  437.                         return;
  438.                 case 1: {
  439.                         // Version 1 obfuscation (Filter Foundry 1.4b8,9,10)
  440.                         // Filter built with VC++ (official release by Toby Thain)
  441.  
  442.                         unsigned char* p;
  443.                         size_t i;
  444.                         uint32_t seed;
  445.  
  446.                         seed = 0xdc43df3c;
  447.  
  448.                         for (i = size, p = (unsigned char*)pparm; i--;) {
  449.                                 *p++ ^= rand_msvcc(&seed);
  450.                         }
  451.                         break;
  452.                 }
  453.                 case 2: {
  454.                         // Version 2 obfuscation (Filter Foundry 1.7b1)
  455.                         // Compiler independent
  456.  
  457.                         unsigned char* p;
  458.                         size_t i;
  459.                         uint32_t seed;
  460.  
  461.                         seed = 0x95d4a68f;
  462.  
  463.                         for (i = size, p = (unsigned char*)pparm; i--;) {
  464.                                 seed ^= seed << 13;
  465.                                 seed ^= seed >> 17;
  466.                                 seed ^= seed << 5;
  467.                                 *p++ ^= seed;
  468.                         }
  469.                         break;
  470.                 }
  471.                 case 3: {
  472.                         // Version 3 obfuscation (Filter Foundry 1.7.0.5)
  473.                         // NO loading of other implementation supported, but that doesn't matter since
  474.                         // obfuscation and protection is combined in Filter Factory >= 1.7.0.5.
  475.                         // Using rand() is more secure, because it differs from compiler to compiler, so
  476.                         // it is harder to read a protected 8BF plugin.
  477.                         // Note that rand() in combination with srand() is deterministic, so it is safe
  478.                         // to use it: https://stackoverflow.com/questions/55438293/does-rand-function-in-c-follows-non-determinstc-algorithm
  479.                         // Note: 32-Bit FF is built using OpenWatcom (to support Win95), while 64-Bit FF is built using Microsoft Visual C++
  480.  
  481.                         unsigned char* p;
  482.                         size_t i;
  483.                         uint32_t seed;
  484.                         size_t seed_position;
  485.  
  486.                         seed = pparm->unknown2;
  487.                         seed_position = offsetof(PARM_T, unknown2); // = offsetof(PARM_T_PREMIERE, unknown1)
  488.  
  489.                         srand(seed);
  490.  
  491.                         p = (unsigned char*)pparm;
  492.                         for (i = 0; i < seed_position; i++) {
  493.                                 *p++ ^= (int)(rand() * 1.0 / ((double)RAND_MAX + 1) * 256);
  494.                         }
  495.                         *((uint32_t*)p) = 0; // here was the seed. Fill it with 0x00000000
  496.                         p += 4; // jump to the next DWORD
  497.                         for (i = 0; i < size - seed_position - 4; i++) {
  498.                                 *p++ ^= (int)(rand() * 1.0 / ((double)RAND_MAX + 1) * 256);
  499.                         }
  500.  
  501.                         break;
  502.                 }
  503.                 case 4:
  504.                 case 5: {
  505.                         // Version 4 obfuscation (Filter Foundry 1.7.0.7)
  506.                         // Version 5 obfuscation (Filter Foundry 1.7.0.8)
  507.                         // Not compiler dependent, but individual for each standalone filter
  508.                         // It is important that this code works for both x86 and x64 indepdently from the used compiler,
  509.                         // otherwise, the cross-make x86/x64 won't work!
  510.                         // Version 5 contains a seed requirement (checksum).
  511.  
  512.                         unsigned char* p;
  513.                         size_t seed_position;
  514.                         uint32_t seed, initial_seed;
  515.  
  516.                         initial_seed = GetObfuscSeed() & 0xFFFFFFFF; // this value will be manipulated during the building of each individual filter (see make_win.c)
  517.  
  518.                         seed = initial_seed;
  519.                         seed_position = offsetof(PARM_T, unknown2); // = offsetof(PARM_T_PREMIERE, unknown1)
  520.  
  521.                         if (obfusc_version == 5) {
  522.                                 // make v4 and v5 intentionally incompatible to avoid a downgrade-attack
  523.                                 seed ^= 0xFFFFFFFF;
  524.                         }
  525.  
  526.                         p = (unsigned char*)pparm;
  527.                         xorshift(&p, &seed, seed_position);
  528.                         *((uint32_t*)p) = 0; // here was the version info (4 or 5). Fill it with 0x00000000
  529.                         p += 4; // jump to the next DWORD
  530.                         xorshift(&p, &seed, size - seed_position - 4);
  531.  
  532.                         if (obfusc_version == 5) {
  533.                                 pparm->unknown2 = 0; // make sure crc32b matches always
  534.                                 if (crc32b((char*)pparm, sizeof(PARM_T)) != initial_seed) {
  535.                                         // Integrity check failed!
  536.                                         memset(pparm, 0, sizeof(PARM_T)); // invalidate everything
  537.                                 }
  538.                         }
  539.  
  540.                         break;
  541.                 }
  542.                 case 6:
  543.                 case 7: {
  544.                         // Version 6 obfuscation (Filter Foundry 1.7.0.10)
  545.                         // Version 7 obfuscation (Filter Foundry 1.7.0.17)
  546.                         // Not compiler dependent, but individual for each standalone filter
  547.                         // It is important that this code works for both x86 and x64 indepdently from the used compiler,
  548.                         // otherwise, the cross-make x86/x64 won't work!
  549.  
  550.                         unsigned char* p;
  551.                         uint32_t xorseed, checksum;
  552.                         uint64_t initial_seed, rolseed;
  553.  
  554.                         initial_seed = GetObfuscSeed(); // this value will be manipulated during the building of each individual filter (see make_win.c)
  555.  
  556.                         if (obfusc_version >= 7) {
  557.                                 uint64_t xorseed2, initial_seed2;
  558.                                 int rand_iters, i, j;
  559.  
  560.                                 initial_seed2 = GetObfuscSeed2(); // this value will be manipulated during the building of each individual filter (see make_win.c)
  561.                                 xorseed2 = initial_seed2;
  562.                                 p = (unsigned char*)pparm;
  563.                                 xorshift64(&p, &xorseed2, sizeof(PARM_T));
  564.  
  565.                                 rand_iters = 0xFFF - (initial_seed & 0xFF) + (initial_seed2 & 0xFF);
  566.                                 if (rand_iters < 0) rand_iters = 0;
  567.                                 for (j = 0; j <= rand_iters; j++) {
  568.                                         uint32_t rand_seed = (initial_seed + initial_seed2 + j) & 0xFFFFFFFF;
  569.                                         p = (unsigned char*)pparm;
  570.                                         for (i = 0; i < 10; i++) {
  571.                                                 rand_msvcc(&rand_seed);
  572.                                         }
  573.                                         for (i = 0; i < (int)size; i++) {
  574.                                                 *p++ ^= (int)(rand_msvcc(&rand_seed) * 1.0 / ((double)RAND_MAX + 1) * 256);
  575.                                         }
  576.                                 }
  577.                         }
  578.  
  579.                         rolseed = initial_seed;
  580.                         p = (unsigned char*)pparm;
  581.                         rolshift(&p, &rolseed, sizeof(PARM_T));
  582.  
  583.                         xorseed = initial_seed & 0xFFFFFFFF;
  584.                         p = (unsigned char*)pparm;
  585.                         xorshift(&p, &xorseed, sizeof(PARM_T));
  586.  
  587.                         checksum = pparm->unknown1;
  588.  
  589.                         pparm->unknown1 = 0;
  590.                         pparm->unknown2 = 0;
  591.                         pparm->unknown3 = 0;
  592.  
  593.                         if (checksum != crc32b((char*)pparm, sizeof(PARM_T))) {
  594.                                 // Integrity check failed!
  595.                                 memset(pparm, 0, sizeof(PARM_T)); // invalidate everything
  596.                         }
  597.  
  598.                         break;
  599.                 }
  600.                 default: {
  601.                         // Obfuscation version unexpected!
  602.                         memset(pparm, 0, sizeof(PARM_T)); // invalidate everything
  603.  
  604.                         // If "return" is present: Calling function will receive an invalid cbSize value, hence showing "incompatible obfuscation"
  605.                         // If "return" is not present: Then the code below will set a correct cbSize and iProtect flag if obfusc_version>=3, which will raise the error "filter is protected"
  606.                         return;
  607.                 }
  608.         }
  609.  
  610.         if ((pparm->cbSize != PARM_SIZE) &&
  611.                 (pparm->cbSize != PARM_SIZE_PREMIERE) &&
  612.                 (pparm->cbSize != PARM_SIG_MAC)) {
  613.                 memset(pparm, 0, sizeof(PARM_T)); // invalidate everything
  614.         }
  615.  
  616.         if (obfusc_version >= 3) {
  617.                 // Filter Foundry >= 1.7.0.5 combines obfuscation and protection
  618.                 // when a standalone filter is built. Theoretically, you can un-protect a
  619.                 // plugin, even if it is obfuscated, just by bit-flipping the LSB of byte 0x164.
  620.                 // Therefore, we enforce that the plugin is protected!
  621.                 pparm->iProtected = 1;
  622.  
  623.                 // Furthermore, if obfuscation 3+ failed (since the seed is individual for each 8BF file),
  624.                 // we still want that load_*.c is able to detect pparm->iProtected instead
  625.                 // of throwing the error "Incompatible obfuscation".
  626.                 pparm->cbSize = PARM_SIZE;
  627.                 pparm->standalone = 1;
  628.         }
  629.  
  630.         if (obfusc_version >= 1) {
  631.                 // information was lost due to obfuscation. Make sure it is zero.
  632.                 pparm->unknown2 = 0;
  633.         }
  634.  
  635.         if (obfusc_version >= 6) {
  636.                 // information was lost due to checksum. Make sure it is zero.
  637.                 pparm->unknown1 = 0;
  638.         }
  639. }
  640.