1 /*
2 	29/12/2006 - 13/10/2014
3 	XORSearch V1.11.1, search for a XOR, ROL, ROT, SHIFT or ADD encoded string in a file
4 	Use -s to save the XOR, ROL, ROT, SHIFT or ADD encoded file containing the string
5 	Use -l length to limit the number of printed characters (50 by default)
6 	Use -i to ignore the case when searching
7 	Use -u to search for Unicode strings (limited support)
8 	Use -f to provide a file with search strings
9 	Use -n length to print the length neighbouring charaters (before & after the found keyword)
10 	Use -h to search for hex strings
11 	Use -k to decode with embedded keys
12 	Source code put in public domain by Didier Stevens, no Copyright
13 	https://DidierStevens.com
14 	Use at your own risk
15 
16 	Shortcommings, or todo's ;-)
17 	- optimize embedded keys algos for speed
18 	- no pipe support (file redirection)
19 	- file must fit in memory
20 
21 	History:
22 		15/01/2007: multiple hits, only printable characters, length argument
23 		08/08/2007: 1.2: added ROL 1 to 7 encoding
24 		17/12/2007: 1.3: findfile
25 		18/04/2009: 1.4: ROT encoding
26 		12/01/2010: 1.5: added (limited) Unicode support; -n option
27 		15/01/2010: 1.6: added hex support
28 		29/10/2012: 1.7: Dropped malloc.h
29 		16/02/2013: 1.8: Added SHIFT encoding
30 		15/06/2013: 1.9: Added embedded keys decoding
31 		16/06/2013: Continued embedded keys decoding
32 		10/07/2013: Added InsertSorted to optimize embedded keys algos for speed
33 		11/07/2013: Continued InsertSorted
34 		19/07/2013: 1.9.1: code cleanup, refactoring
35 		13/10/2013: 1.9.2: Added ucOffset to PrintFinds
36 		14/02/2014: 1.10.0: Added option -p and -e
37 		17/02/2014: Compatibility checking of option -p with other options
38 		20/03/2014: changed ulE_lfanew (unsigned long) to uiE_lfanew (unsigned int)
39 		23/03/2014: 1.10.0: fixes for xcode gcc warnings
40 		27/08/2014: 1.11.0 added ADD encoding, bugfix ParseNumericArg, wildcards search engine
41 		29/08/2014: XORSearch returns 0 when strings are found, 1 when nothing is found, and -1 if error
42 		30/08/2014: added wildcard rules parsing, score, option -d
43 		04/09/2014: added support for jumps in rules (J;?)
44 		15/09/2014: added Realloc
45 		27/09/2014: added option -L
46 		11/10/2014: 1.11.1: fixes for xcode gcc warnings
47 		13/10/2014: added option -x
48 
49 */
50 
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <sys/stat.h>
54 #include <string.h>
55 #include <ctype.h>
56 #include <limits.h>
57 
58 #define countof(array)	(sizeof(array) / sizeof(array[0]))
59 
60 #define XSIZE 1024
61 
62 #define OPR_XOR "XOR"
63 #define OPR_ROL "ROL"
64 #define OPR_ROT "ROT"
65 #define OPR_SHIFT "SHIFT"
66 #define OPR_XOR32 "XOR32"
67 #define OPR_ADD "ADD"
68 
69 #define SEARCHTYPE_STOP			0
70 #define SEARCHTYPE_ASCII		1
71 #define SEARCHTYPE_UNICODE	2
72 #define SEARCHTYPE_HEX			3
73 #define SEARCHTYPE_WILDCARD 4
74 
75 #define WILDCARD_MODE_BYTE 0
76 #define WILDCARD_MODE_BITS 1
77 #define WILDCARD_MODE_JUMP 2
78 #define WILDCARD_MODE_STOP 3
79 
80 typedef struct
81 {
82 	unsigned char ucMode; //WILDCARD_MODE_
83 	unsigned char ucByte;
84 	unsigned char ucMaskFixed;
85 	unsigned char ucBitsFixed;
86 	unsigned char ucMaskVariable1;
87 	char cVariableName1;
88 	unsigned char ucMaskVariable2;
89 	char cVariableName2;
90 	unsigned char ucJumpBytes;
91 } WILDCARD;
92 
93 typedef struct
94 {
95 	int iSearchType;
96 	char *pcSearchString;
97 	int iSearchLength;
98 	char *pcWildcardName;
99 	int iScore;
100 	WILDCARD *pWildcards;
101 	int iPrintASCII;
102 } SEARCH;
103 
104 int *piFoundIndex;
105 int *piFoundSize;
106 
StartsWith(char * szString,char * szPrefix)107 int StartsWith(char *szString, char *szPrefix)
108 {
109 	if (strlen(szString) < strlen(szPrefix))
110 		return 0;
111 	return !strncmp(szString, szPrefix, strlen(szPrefix));
112 }
113 
compare(char cX,char cY,int iFlagIgnoreCase)114 int compare(char cX, char cY, int iFlagIgnoreCase)
115 {
116 	if (iFlagIgnoreCase && isalpha(cX) && isalpha(cY))
117 		return tolower(cX) == tolower(cY);
118 	else
119 		return cX == cY;
120 }
121 
122 // Search algorithm: http://www-igm.univ-mlv.fr/~lecroq/string/node8.html#SECTION0080
PreKMP(char * pcX,int iXLength,int aiKMPNext[],int iFlagIgnoreCase)123 void PreKMP(char *pcX, int iXLength, int aiKMPNext[], int iFlagIgnoreCase)
124 {
125 	int iIter1, iIter2;
126 
127 	iIter1 = 0;
128 	iIter2 = aiKMPNext[0] = -1;
129 	while (iIter1 < iXLength)
130 	{
131 		while (iIter2 > -1 && !compare(pcX[iIter1], pcX[iIter2], iFlagIgnoreCase))
132 			iIter2 = aiKMPNext[iIter2];
133 		iIter1++;
134 		iIter2++;
135 		if (compare(pcX[iIter1], pcX[iIter2], iFlagIgnoreCase))
136 			aiKMPNext[iIter1] = aiKMPNext[iIter2];
137 		else
138 			aiKMPNext[iIter1] = iIter2;
139 	}
140 }
141 
KMP(char * pcX,int iXLength,char * pcY,int iYLength,int iFlagIgnoreCase)142 int KMP(char *pcX, int iXLength, char *pcY, int iYLength, int iFlagIgnoreCase)
143 {
144 	int iIter1, iIter2, aiKMPNext[XSIZE];
145 	int iCountFinds = 0;
146 
147 	if (iXLength > XSIZE)
148 	{
149 		fprintf(stderr, "KMP size error\n");
150 		return 0;
151 	}
152 
153 	/* Preprocessing */
154 	PreKMP(pcX, iXLength, aiKMPNext, iFlagIgnoreCase);
155 
156 	/* Searching */
157 	iIter1 = iIter2 = 0;
158 	while (iIter2 < iYLength)
159 	{
160 		while (iIter1 > -1 && !compare(pcX[iIter1], pcY[iIter2], iFlagIgnoreCase))
161 			iIter1 = aiKMPNext[iIter1];
162 		iIter1++;
163 		iIter2++;
164 		if (iIter1 >= iXLength)
165 		{
166 			piFoundIndex[iCountFinds] = iIter2-iIter1;
167 			piFoundSize[iCountFinds++] = iXLength;
168 			iIter1 = aiKMPNext[iIter1];
169 		}
170 	}
171 	return iCountFinds;
172 }
173 
WildcardSearch(SEARCH * pSearch,unsigned char * pucBuffer,long lSize,char * sOperation,unsigned char ucOffset,unsigned int uiOperand,int iMaxLength,int * piScore)174 int WildcardSearch(SEARCH *pSearch, unsigned char *pucBuffer, long lSize, char *sOperation, unsigned char ucOffset, unsigned int uiOperand, int iMaxLength, int *piScore)
175 {
176 	int iFound;
177 	unsigned char *pucFoundCharFirst;
178 	unsigned char *pucSearchBuffer;
179 	int iIter;
180 	int iPosition;
181 	unsigned char *pucLastByteInBuffer;
182 	int aiVariables[26];
183 
184 	pucSearchBuffer = pucBuffer;
185 	pucLastByteInBuffer = pucBuffer + lSize - 1;
186 	iFound = 0;
187 	while(1)
188 	{
189 		pucFoundCharFirst = memchr(pucSearchBuffer, pSearch->pWildcards[0].ucByte, lSize - (pucSearchBuffer - pucBuffer));
190 		if (pucFoundCharFirst == NULL)
191 			break;
192 		for (iIter = 0; iIter < 26; iIter ++)
193 			aiVariables[iIter] = -1;
194 		iIter = 1;
195 		iPosition = 1;
196 		while (pSearch->pWildcards[iIter].ucMode != WILDCARD_MODE_STOP)
197 		{
198 			if (pSearch->pWildcards[iIter].ucMode == WILDCARD_MODE_BYTE)
199 			{
200 				if ((pucFoundCharFirst + iPosition) > pucLastByteInBuffer || pSearch->pWildcards[iIter].ucByte != *(pucFoundCharFirst + iPosition))
201 					break;
202 				iIter++;
203 				iPosition++;
204 			}
205 			else if (pSearch->pWildcards[iIter].ucMode == WILDCARD_MODE_BITS)
206 			{
207 				if ((pucFoundCharFirst + iPosition) > pucLastByteInBuffer || pSearch->pWildcards[iIter].ucBitsFixed != (*(pucFoundCharFirst + iPosition) & pSearch->pWildcards[iIter].ucMaskFixed))
208 					break;
209 				if (pSearch->pWildcards[iIter].ucMaskVariable1 != 0)
210 				{
211 					unsigned char ucMask = pSearch->pWildcards[iIter].ucMaskVariable1;
212 					unsigned char ucValue = *(pucFoundCharFirst + iPosition) & ucMask;
213 					while ((ucMask & 0x01) == 0)
214 					{
215 						ucMask = ucMask >> 1;
216 						ucValue = ucValue >> 1;
217 					}
218 					if (aiVariables[pSearch->pWildcards[iIter].cVariableName1] == -1)
219 						aiVariables[pSearch->pWildcards[iIter].cVariableName1] = ucValue;
220 					else if (aiVariables[pSearch->pWildcards[iIter].cVariableName1] != ucValue)
221 						break;
222 				}
223 				if (pSearch->pWildcards[iIter].ucMaskVariable2 != 0)
224 				{
225 					unsigned char ucMask = pSearch->pWildcards[iIter].ucMaskVariable2;
226 					unsigned char ucValue = *(pucFoundCharFirst + iPosition) & ucMask;
227 					while ((ucMask & 0x01) == 0)
228 					{
229 						ucMask = ucMask >> 1;
230 						ucValue = ucValue >> 1;
231 					}
232 					if (aiVariables[pSearch->pWildcards[iIter].cVariableName2] == -1)
233 						aiVariables[pSearch->pWildcards[iIter].cVariableName2] = ucValue;
234 					else if (aiVariables[pSearch->pWildcards[iIter].cVariableName2] != ucValue)
235 						break;
236 				}
237 				iIter++;
238 				iPosition++;
239 			}
240 			else if (pSearch->pWildcards[iIter].ucMode == WILDCARD_MODE_JUMP)
241 			{
242 				if (4 == pSearch->pWildcards[iIter].ucJumpBytes && (pucFoundCharFirst + iPosition + 3) > pucLastByteInBuffer)
243 					break;
244 				switch (pSearch->pWildcards[iIter].ucJumpBytes)
245 				{
246 					case 1:
247 						iPosition += 1 + *(char *)(pucFoundCharFirst + iPosition);
248 						break;
249 					case 4:
250 						iPosition += 4 + *(int *)(pucFoundCharFirst + iPosition);
251 						break;
252 				}
253 				//a// fix for integer overflow
254 				if ((pucFoundCharFirst + iPosition) < pucBuffer || (pucFoundCharFirst + iPosition) > pucLastByteInBuffer)
255 					break;
256 				iIter++;
257 			}
258 		}
259 		if (pSearch->pWildcards[iIter].ucMode == WILDCARD_MODE_STOP)
260 		{
261 			iFound = 1;
262 			*piScore += pSearch->iScore;
263 			if (!strcmp(sOperation, OPR_XOR32))
264 				printf("Found %s %08X offset +%d position %08lX: %s ", sOperation, uiOperand, ucOffset, pucFoundCharFirst - pucBuffer, pSearch->pcWildcardName);
265 			else if (strcmp(sOperation, OPR_ROT))
266 				printf("Found %s %02X position %08lX: %s ", sOperation, uiOperand, pucFoundCharFirst - pucBuffer, pSearch->pcWildcardName);
267 			else
268 				printf("Found %s %02d position %08lX: %s ", sOperation, uiOperand, pucFoundCharFirst - pucBuffer, pSearch->pcWildcardName);
269 			for (iIter = 0; iIter < iMaxLength && pSearch->pWildcards[iIter].ucMode != WILDCARD_MODE_STOP && pucFoundCharFirst + iIter <= pucLastByteInBuffer; iIter++)
270 				if (pSearch->pWildcards[iIter].ucMode == WILDCARD_MODE_JUMP)
271 				{
272 					int iIter2;
273 					for (iIter2 = 0; iIter2 < pSearch->pWildcards[iIter].ucJumpBytes; iIter2++)
274 						printf("%02X", ((unsigned char *)pucFoundCharFirst)[iIter + iIter2]);
275 					break;
276 				}
277 				else if (pSearch->iPrintASCII)
278 					putchar(((unsigned char *)pucFoundCharFirst)[iIter]);
279 				else
280 					printf("%02X", ((unsigned char *)pucFoundCharFirst)[iIter]);
281 			putchar('\n');
282 		}
283 		pucSearchBuffer = pucFoundCharFirst + 1;
284 	}
285 
286 	return iFound;
287 }
288 
WildcardSearches(SEARCH * pSearch,unsigned char * pucBuffer,long lSize,char * sOperation,unsigned char ucOffset,unsigned int uiOperand,int iMaxLength,int * piScore)289 int WildcardSearches(SEARCH *pSearch, unsigned char *pucBuffer, long lSize, char *sOperation, unsigned char ucOffset, unsigned int uiOperand, int iMaxLength, int *piScore)
290 {
291 	int iFound = 0;
292 	int iIter;
293 
294 	for (iIter = 0; pSearch[iIter].iSearchType != SEARCHTYPE_STOP; iIter++)
295 	{
296 		if (WildcardSearch(&pSearch[iIter], pucBuffer, lSize, sOperation, ucOffset, uiOperand, iMaxLength, piScore))
297 			iFound = 1;
298 	}
299 	return iFound;
300 }
301 
ParseIntegerArg(const char * szArg)302 long ParseIntegerArg(const char *szArg)
303 {
304 	char *szError;
305 	long lResult;
306 
307 	lResult = strtol(szArg, &szError, 0);
308 	if (*szError != '\0' || lResult == LONG_MIN || lResult == LONG_MAX)
309 		return -1;
310 	else
311 		return lResult;
312 }
313 
ParseHexArg(const char * szArg)314 long ParseHexArg(const char *szArg)
315 {
316 	long lResult = 0;
317 
318 	while (*szArg != '\0')
319 	{
320 		if (*szArg >= '0' && *szArg <= '9')
321 			lResult = lResult * 0x10 + *szArg - '0';
322 		else if (*szArg >= 'a' && *szArg <= 'f')
323 			lResult = lResult * 0x10 + *szArg - 'a' + 10;
324 		else if (*szArg >= 'A' && *szArg <= 'F')
325 			lResult = lResult * 0x10 + *szArg - 'A' + 10;
326 		else
327 			return -1;
328 		if (lResult == LONG_MIN || lResult == LONG_MAX)
329 			return -1;
330 		szArg++;
331 	}
332 	return lResult;
333 }
334 
ParseNumericArg(const char * szArg)335 long ParseNumericArg(const char *szArg)
336 {
337 	if (!strncmp(szArg, "0x", 2))
338 		return(ParseHexArg(szArg + 2));
339 	else
340 		return(ParseIntegerArg(szArg));
341 }
342 
ParseArgs(int argc,char ** argv,int * piSave,int * piMaxLength,int * piIgnoreCase,char ** ppcFile,char ** ppcSearch,char ** ppcSearchFile,int * piUnicode,int * piNeighbourgLength,int * piHex,int * piKeys,int * piPEFile,int * piExcludeByte,int * piWildcard,int * piWildcardEmbedded,char ** ppcDisable,int * piList,int * piHexFile)343 int ParseArgs(int argc, char **argv, int *piSave, int *piMaxLength, int *piIgnoreCase, char **ppcFile, char **ppcSearch, char **ppcSearchFile, int *piUnicode, int *piNeighbourgLength, int *piHex, int *piKeys, int *piPEFile, int *piExcludeByte, int *piWildcard, int *piWildcardEmbedded, char **ppcDisable, int *piList, int *piHexFile)
344 {
345 	int iIterArgv;
346 	int iCountParameters;
347 	int iFlagMaxLength;
348 	int iFlagNeighbourgLength;
349 	int iFlagSearchFile;
350 	int iFlagExcludeByte;
351 	int iFlagDisable;
352 	char *pcFlags;
353 
354 	iCountParameters = 0;
355 	iFlagMaxLength = 0;
356 	iFlagNeighbourgLength = 0;
357 	iFlagSearchFile = 0;
358 	iFlagExcludeByte = 0;
359 	iFlagDisable = 0;
360 	*piSave = 0;
361 	*piMaxLength = -1;
362 	*piNeighbourgLength = -1;
363 	*piIgnoreCase = 0;
364 	*ppcSearch = NULL;
365 	*ppcSearchFile = NULL;
366 	*piUnicode = 0;
367 	*piHex = 0;
368 	*piKeys = 0;
369 	*piPEFile = 0;
370 	*piExcludeByte = -1;
371 	*piWildcard = 0;
372 	*piWildcardEmbedded = 0;
373 	*ppcDisable = NULL;
374 	*piList = 0;
375 	*piHexFile = 0;
376 
377 	for (iIterArgv = 1; iIterArgv < argc; iIterArgv++)
378 	{
379 		if (argv[iIterArgv][0] == '-')
380 		{
381 			if (iFlagMaxLength || iFlagSearchFile || iFlagDisable)
382 				return 1;
383 			pcFlags = argv[iIterArgv] + 1;
384 			while (*pcFlags)
385 				switch (*pcFlags++)
386 				{
387 					case 's':
388 						*piSave = 1;
389 						break;
390 					case 'i':
391 						*piIgnoreCase = 1;
392 						break;
393 					case 'l':
394 						iFlagMaxLength = 1;
395 						break;
396 					case 'f':
397 						iFlagSearchFile = 1;
398 						break;
399 					case 'u':
400 						*piUnicode = 1;
401 						break;
402 					case 'n':
403 						iFlagNeighbourgLength = 1;
404 						break;
405 					case 'h':
406 						*piHex = 1;
407 						break;
408 					case 'k':
409 						*piKeys = 1;
410 						break;
411 					case 'p':
412 						*piPEFile = 1;
413 						break;
414 					case 'e':
415 						iFlagExcludeByte = 1;
416 						break;
417 					case 'w':
418 						*piWildcard = 1;
419 						break;
420 					case 'W':
421 						*piWildcardEmbedded = 1;
422 						break;
423 					case 'd':
424 						iFlagDisable = 1;
425 						break;
426 					case 'L':
427 						*piList = 1;
428 						break;
429 					case 'x':
430 						*piHexFile = 1;
431 						break;
432 					default:
433 						return 1;
434 				}
435 		}
436 		else if (iFlagMaxLength)
437 		{
438 			*piMaxLength = ParseNumericArg(argv[iIterArgv]);
439 			if (*piMaxLength < 1)
440 				return 1;
441 			iFlagMaxLength = 0;
442 		}
443 		else if (iFlagExcludeByte)
444 		{
445 			*piExcludeByte = ParseNumericArg(argv[iIterArgv]);
446 			if (*piExcludeByte < 0x00 || *piExcludeByte > 0xFF)
447 				return 1;
448 			iFlagExcludeByte = 0;
449 		}
450 		else if (iFlagNeighbourgLength)
451 		{
452 			*piNeighbourgLength = ParseNumericArg(argv[iIterArgv]);
453 			if (*piNeighbourgLength < 1)
454 				return 1;
455 			iFlagNeighbourgLength = 0;
456 		}
457 		else if (iFlagSearchFile)
458 		{
459 			*ppcSearchFile = argv[iIterArgv];
460 			iFlagSearchFile = 0;
461 		}
462 		else if (iFlagDisable)
463 		{
464 			*ppcDisable = argv[iIterArgv];
465 			iFlagDisable = 0;
466 		}
467 		else if (iCountParameters == 0)
468 		{
469 			*ppcFile = argv[iIterArgv];
470 			iCountParameters++;
471 		}
472 		else if (iCountParameters == 1)
473 		{
474 			*ppcSearch = argv[iIterArgv];
475 			iCountParameters++;
476 		}
477 		else
478 			iCountParameters++;
479 	}
480 	if (1 == *piList)
481 		return iCountParameters == 0 ? 0 : 1;
482 	else if (iCountParameters != 2 && *ppcSearchFile == NULL && *piPEFile == 0 && *piWildcardEmbedded == 0)
483 		return 1;
484 	else if (iCountParameters != 1 && *ppcSearchFile != NULL)
485 		return 1;
486 	else if (iCountParameters != 1 && *piPEFile != 0)
487 		return 1;
488 	else if (iCountParameters != 1 && *piWildcardEmbedded != 0)
489 		return 1;
490 	else if (*piMaxLength != -1 && *piNeighbourgLength != -1)
491 		return 1;
492 	else if ((*piUnicode && *piHex) || (*piUnicode && (*piWildcard || *piWildcardEmbedded)) || (*piHex && (*piWildcard || *piWildcardEmbedded)) || (*piWildcard && *piWildcardEmbedded))
493 		return 1;
494 	else if (*piKeys && *piExcludeByte != -1)
495 		return 1;
496 	else if (*piPEFile != 0 && *ppcSearchFile != NULL)
497 		return 1;
498 	else if (*piPEFile != 0 && *piIgnoreCase != 0)
499 		return 1;
500 	else if (*piPEFile != 0 && *piUnicode != 0)
501 		return 1;
502 	else if (*piPEFile != 0 && *piHex != 0)
503 		return 1;
504 	else if (*piPEFile != 0 && *piNeighbourgLength != -1)
505 		return 1;
506 	else if (*piWildcardEmbedded != 0 && *ppcSearchFile != NULL)
507 		return 1;
508 	else
509 		return 0;
510 }
511 
XOR(unsigned char * pcBuffer,long lSize,unsigned char cXOR,int iExcludeByte)512 void XOR(unsigned char *pcBuffer, long lSize, unsigned char cXOR, int iExcludeByte)
513 {
514 	unsigned char *pucLastByteInBuffer;
515 
516 	pucLastByteInBuffer = pcBuffer + lSize - 1;
517 	while (pcBuffer <= pucLastByteInBuffer)
518 	{
519 		if (iExcludeByte < 0 || iExcludeByte != *pcBuffer)
520 			*pcBuffer ^= cXOR;
521 		pcBuffer++;
522 	}
523 }
524 
XOR32(unsigned int * puiBuffer,long lSize,unsigned int uiOffset,unsigned int uiXOR)525 void XOR32(unsigned int *puiBuffer, long lSize, unsigned int uiOffset, unsigned int uiXOR)
526 {
527 	unsigned int *pucLastUIntInBuffer;
528 
529 	pucLastUIntInBuffer = ((unsigned int *)((unsigned char *)puiBuffer + lSize)) - 1;
530 	puiBuffer = (unsigned int *)((unsigned char *)puiBuffer + uiOffset);
531 	while (puiBuffer <= pucLastUIntInBuffer)
532 		*puiBuffer++ ^= uiXOR;
533 }
534 
ROL(unsigned char * pcBuffer,long lSize,int iExcludeByte)535 void ROL(unsigned char *pcBuffer, long lSize, int iExcludeByte)
536 {
537 	unsigned char *pucLastByteInBuffer;
538 
539 	pucLastByteInBuffer = pcBuffer + lSize - 1;
540 	while (pcBuffer <= pucLastByteInBuffer)
541 	{
542 		if (iExcludeByte < 0 || iExcludeByte != *pcBuffer)
543 			*pcBuffer = *pcBuffer << 1 | *pcBuffer >> 7;
544 		pcBuffer++;
545 	}
546 }
547 
ROT(unsigned char * pcBuffer,long lSize,int iExcludeByte)548 void ROT(unsigned char *pcBuffer, long lSize, int iExcludeByte)
549 {
550 	unsigned char *pucLastByteInBuffer;
551 
552 	pucLastByteInBuffer = pcBuffer + lSize - 1;
553 	while (pcBuffer <= pucLastByteInBuffer)
554 	{
555 		if (iExcludeByte < 0 || iExcludeByte != *pcBuffer)
556 		{
557 			if ((*pcBuffer >= 'a' && *pcBuffer < 'z') || (*pcBuffer >= 'A' && *pcBuffer < 'Z'))
558 				(*pcBuffer)++;
559 			else if (*pcBuffer == 'z')
560 				*pcBuffer = 'a';
561 			else if (*pcBuffer == 'Z')
562 				*pcBuffer = 'A';
563 		}
564 		pcBuffer++;
565 	}
566 }
567 
SHIFT(unsigned char * pcBuffer,long lSize,int iExcludeByte)568 void SHIFT(unsigned char *pcBuffer, long lSize, int iExcludeByte)
569 {
570 	unsigned char *pucLastByteInBuffer;
571 	unsigned char ucFirstBit;
572 
573 	pucLastByteInBuffer = pcBuffer + lSize - 1;
574 	ucFirstBit = *pcBuffer >> 7;
575 	while (pcBuffer <= pucLastByteInBuffer - 1)
576 	{
577 		if (iExcludeByte < 0 || iExcludeByte != *pcBuffer)
578 			*pcBuffer = *pcBuffer << 1 | *(pcBuffer + 1) >> 7;
579 		pcBuffer++;
580 	}
581 	if (iExcludeByte < 0 || iExcludeByte != *pucLastByteInBuffer)
582 		*pucLastByteInBuffer = *pucLastByteInBuffer << 1 | ucFirstBit;
583 }
584 
ADD(unsigned char * pcBuffer,long lSize,int iExcludeByte)585 void ADD(unsigned char *pcBuffer, long lSize, int iExcludeByte)
586 {
587 	unsigned char *pucLastByteInBuffer;
588 
589 	pucLastByteInBuffer = pcBuffer + lSize - 1;
590 	while (pcBuffer <= pucLastByteInBuffer)
591 	{
592 		if (iExcludeByte < 0 || iExcludeByte != *pcBuffer)
593 			*pcBuffer = *pcBuffer + 1;
594 		pcBuffer++;
595 	}
596 }
597 
SaveFile(char * pcFile,char * sOperation,unsigned char ucXOR,void * pBuffer,long lSize)598 void SaveFile(char *pcFile, char *sOperation, unsigned char ucXOR, void *pBuffer, long lSize)
599 {
600 	char szFileNameSave[XSIZE];
601 	FILE *fOut;
602 
603 	snprintf(szFileNameSave, XSIZE, "%s.%s.%02X", pcFile, sOperation, ucXOR);
604 	if ((fOut = fopen(szFileNameSave, "wb")) == NULL)
605 		fprintf(stderr, "error opening file %s\n", szFileNameSave);
606 	else
607 	{
608 		if (fwrite(pBuffer, lSize, 1, fOut) != 1)
609 			fprintf(stderr, "error writing file %s\n", szFileNameSave);
610 		fclose(fOut);
611 	}
612 }
613 
PrintFinds(int iCountFinds,int iMaxLength,char * sOperation,unsigned char ucOffset,unsigned int uiOperand,off_t otFileSize,void * pBuffer,int iSearchType,int iNeighbourgLength)614 void PrintFinds(int iCountFinds, int iMaxLength, char *sOperation, unsigned char ucOffset, unsigned int uiOperand, off_t otFileSize, void *pBuffer, int iSearchType, int iNeighbourgLength)
615 {
616 	int iIter1, iIter2;
617 	int iMaxPrint;
618 	int iStart;
619 	int iStop;
620 	int iStep;
621 
622 	for (iIter1 = 0; iIter1 < iCountFinds; iIter1++)
623 	{
624 		if (!strcmp(sOperation, OPR_XOR32))
625 			printf("Found %s %08X offset +%d position %04X", sOperation, uiOperand, ucOffset, piFoundIndex[iIter1]);
626 		else if (strcmp(sOperation, OPR_ROT))
627 			printf("Found %s %02X position %04X", sOperation, uiOperand, piFoundIndex[iIter1]);
628 		else
629 			printf("Found %s %02d position %04X", sOperation, uiOperand, piFoundIndex[iIter1]);
630 		if (iNeighbourgLength > 0)
631 			printf("(-%d): ", iNeighbourgLength);
632 		else
633 			printf(": ");
634 		if (iNeighbourgLength > 0)
635 		{
636 			iStep = iSearchType == SEARCHTYPE_UNICODE ? 2 : 1;
637 			iStart = piFoundIndex[iIter1] - iNeighbourgLength * iStep;
638 			if (iStart < 0)
639 				iStart = 0;
640 			iStop = piFoundIndex[iIter1] + piFoundSize[iIter1] + iNeighbourgLength * iStep;
641 			if (iStop > otFileSize)
642 				iStop = otFileSize;
643 			for (iIter2 = iStart; iIter2 < iStop; iIter2 += iStep)
644 				if (SEARCHTYPE_HEX == iSearchType)
645 					printf("%02X", ((unsigned char *)pBuffer)[iIter2]);
646 				else
647 					if (isprint(((unsigned char *)pBuffer)[iIter2]))
648 						putchar(((unsigned char *)pBuffer)[iIter2]);
649 					else
650 						putchar('.');
651 		}
652 		else
653 		{
654 			iMaxPrint = iMaxLength;
655 			iStep = iSearchType == SEARCHTYPE_UNICODE ? 2 : 1;
656 			for (iIter2 = piFoundIndex[iIter1]; iIter2 < otFileSize && (SEARCHTYPE_HEX == iSearchType || ((unsigned char *)pBuffer)[iIter2]); iIter2 += iStep)
657 			{
658 				if (SEARCHTYPE_HEX == iSearchType)
659 					printf("%02X", ((unsigned char *)pBuffer)[iIter2]);
660 				else
661 					if (isprint(((unsigned char *)pBuffer)[iIter2]))
662 						putchar(((unsigned char *)pBuffer)[iIter2]);
663 					else
664 						putchar('.');
665 				if (iMaxLength > 0 && --iMaxPrint == 0)
666 					break;
667 			}
668 		}
669 		putchar('\n');
670 	}
671 }
672 
673 
strncpy0(char * pszDestination,char * pszSource,size_t stNum)674 char *strncpy0(char *pszDestination, char *pszSource, size_t stNum)
675 {
676 	strncpy(pszDestination, pszSource, stNum);
677 	pszDestination[stNum - 1] = '\0';
678 	return pszDestination;
679 }
680 
IsHexDigit(char cHexDigit)681 int IsHexDigit(char cHexDigit)
682 {
683 	return (cHexDigit >= '0' && cHexDigit <= '9') || (cHexDigit >= 'A' && cHexDigit <= 'F') || (cHexDigit >= 'a' && cHexDigit <= 'f');
684 }
685 
HexDigitToNibble(char cHexDigit)686 int HexDigitToNibble(char cHexDigit)
687 {
688 	if (cHexDigit >= '0' && cHexDigit <= '9')
689 		return cHexDigit - '0';
690 	if (cHexDigit >= 'A' && cHexDigit <= 'F')
691 		return cHexDigit - 'A' + 10;
692 	if (cHexDigit >= 'a' && cHexDigit <= 'f')
693 		return cHexDigit - 'a' + 10;
694 	return -1;
695 }
696 
Hexstring2Binary(char * pcHexString,char * pcBinary)697 int Hexstring2Binary(char *pcHexString, char *pcBinary)
698 {
699 	int iCount = 0;
700 
701 	while ('\0' != *pcHexString && '\0' != *(pcHexString + 1) && iCount < XSIZE)
702 		if (IsHexDigit(*pcHexString) && IsHexDigit(*(pcHexString + 1)))
703 		{
704 			pcBinary[iCount++] = (char) HexDigitToNibble(*pcHexString) * 0x10 + HexDigitToNibble(*(pcHexString + 1));
705 			pcHexString += 2;
706 		}
707 		else
708 			return -1;
709 	if ('\0' != *pcHexString)
710 		return -2;
711 	else
712 		return iCount;
713 }
714 
GetSearchString(char * pcArgSearch,char * pcArgSearchFile,int iSearchType,int * piLength)715 char *GetSearchString(char *pcArgSearch, char *pcArgSearchFile, int iSearchType, int *piLength)
716 {
717 	static char szSearch[XSIZE+1];
718 	static int iArgSearchReturned;
719 	static FILE *fSearchFile;
720 	int iIter;
721 
722 	if (iArgSearchReturned)
723 	{
724 		iArgSearchReturned = 0;
725 		return NULL;
726 	}
727 
728 	if (pcArgSearch == NULL)
729 	{
730 		if (fSearchFile == NULL)
731 			if ((fSearchFile = fopen(pcArgSearchFile, "r")) == NULL)
732 			{
733 				fprintf(stderr, "error opening file %s\n", pcArgSearchFile);
734 				exit(-1);
735 			}
736 		if (fgets(szSearch, XSIZE, fSearchFile) == NULL)
737 		{
738 			fclose(fSearchFile);
739 			fSearchFile = NULL;
740 			return NULL;
741 		}
742 		else
743 		{
744 			if (strlen(szSearch) > 0 && szSearch[strlen(szSearch) - 1] == '\n')
745 				szSearch[strlen(szSearch) - 1] = '\0';
746 			switch (iSearchType)
747 			{
748 				case SEARCHTYPE_ASCII:
749 					*piLength = strlen(szSearch);
750 					break;
751 				case SEARCHTYPE_UNICODE:
752 					*piLength = 2 * strlen(szSearch);
753 					for (iIter = XSIZE / 2; iIter > 0; iIter--)
754 						szSearch[2 * iIter] = szSearch[iIter];
755 					for (iIter = 1; iIter <= XSIZE; iIter += 2)
756 						szSearch[iIter] = '\0';
757 					break;
758 				case SEARCHTYPE_HEX:
759 					*piLength = Hexstring2Binary(szSearch, szSearch);
760 					if (*piLength < 0)
761 					{
762 						fprintf(stderr, "Error parsing hex string\n");
763 						exit(-1);
764 					}
765 					break;
766 				default:
767 					fprintf(stderr, "Panic: 0001\n");
768 					exit(-1);
769 			}
770 			return szSearch;
771 		}
772 	}
773 	else
774 	{
775 		iArgSearchReturned = 1;
776 		switch (iSearchType)
777 		{
778 			case SEARCHTYPE_ASCII:
779 				strncpy0(szSearch, pcArgSearch, XSIZE);
780 				*piLength = strlen(szSearch);
781 				break;
782 			case SEARCHTYPE_UNICODE:
783 				strncpy0(szSearch, pcArgSearch, XSIZE / 2);
784 				*piLength = 2 * strlen(szSearch);
785 				for (iIter = XSIZE / 2; iIter > 0; iIter--)
786 					szSearch[2 * iIter] = szSearch[iIter];
787 				for (iIter = 1; iIter <= XSIZE; iIter += 2)
788 					szSearch[iIter] = '\0';
789 				break;
790 			case SEARCHTYPE_HEX:
791 				*piLength = Hexstring2Binary(pcArgSearch, szSearch);
792 				if (*piLength < 0)
793 				{
794 					fprintf(stderr, "Error parsing hex string: %s\n", pcArgSearch);
795 					exit(-1);
796 				}
797 				break;
798 			case SEARCHTYPE_WILDCARD:
799 				break;
800 			default:
801 				fprintf(stderr, "Panic: 0002\n");
802 				exit(-1);
803 		}
804 		return szSearch;
805 	}
806 }
807 
BinarySearch(unsigned int * puiArray,unsigned int uiElement,int iMinimum,int iMaximum,unsigned int * puiIndex)808 int BinarySearch(unsigned int *puiArray, unsigned int uiElement, int iMinimum, int iMaximum, unsigned int *puiIndex)
809 {
810 	int iMiddle;
811 
812 	if (iMaximum < iMinimum)
813 	{
814 		*puiIndex = iMinimum;
815 		return 0;
816 	}
817 	else
818 	{
819 		iMiddle = iMinimum + ((iMaximum - iMinimum) / 2);
820 		if (puiArray[iMiddle] > uiElement)
821 			return BinarySearch(puiArray, uiElement, iMinimum, iMiddle - 1, puiIndex);
822 		else if (puiArray[iMiddle] < uiElement)
823 			return BinarySearch(puiArray, uiElement, iMiddle + 1, iMaximum, puiIndex);
824 		else
825 		{
826 			*puiIndex = iMiddle;
827 			return 1;
828 		}
829 	}
830 }
831 
InsertSorted(unsigned int uiElement,unsigned int * puiArray,unsigned int uiArraySize,unsigned int * uiArrayCount)832 void InsertSorted(unsigned int uiElement, unsigned int *puiArray, unsigned int uiArraySize, unsigned int *uiArrayCount)
833 {
834 	unsigned int uiIndex;
835 	unsigned int uiIter;
836 
837 	if (*uiArrayCount >= uiArraySize)
838 		return;
839 	if (*uiArrayCount == 0)
840 	{
841 		puiArray[(*uiArrayCount)++] = uiElement;
842 		return;
843 	}
844 
845 	if (BinarySearch(puiArray, uiElement, 0, *uiArrayCount - 1, &uiIndex))
846 		return;
847 
848 	if (uiIndex == *uiArrayCount)
849 	{
850 		if (puiArray[*uiArrayCount - 1] != uiElement)
851 			puiArray[(*uiArrayCount)++] = uiElement;
852 	}
853 	else
854 	{
855 		for (uiIter = *uiArrayCount + 1; uiIndex < uiIter; uiIter--)
856 			puiArray[uiIter] = puiArray[uiIter - 1];
857 		puiArray[uiIndex] = uiElement;
858 		(*uiArrayCount)++;
859 	}
860 }
861 
SearchForPEFile(unsigned char * pucBuffer,long lSize,char * sOperation,unsigned char ucOffset,unsigned int uiOperand,int iMaxLength)862 int SearchForPEFile(unsigned char *pucBuffer, long lSize, char *sOperation, unsigned char ucOffset, unsigned int uiOperand, int iMaxLength)
863 {
864 	int iFound;
865 	unsigned char *pucFoundCharM;
866 	unsigned char *pucSearchBuffer;
867 	unsigned char *pucLastByteInBuffer;
868 	unsigned int uiE_lfanew;
869 	unsigned char *pucPEHeader;
870 	int iIter;
871 
872 	iFound = 0;
873 	pucSearchBuffer = pucBuffer;
874 	pucLastByteInBuffer = pucBuffer + lSize - 1;
875 	while(1)
876 	{
877 		pucFoundCharM = memchr(pucSearchBuffer, 'M', lSize - (pucSearchBuffer - pucBuffer));
878 		if (pucFoundCharM == NULL)
879 			break;
880 		if (pucFoundCharM + 0x40 - 1 > pucLastByteInBuffer) // Is the size OK for a IMAGE_DOS_HEADER?
881 			break;
882 		pucSearchBuffer = pucFoundCharM + 1;
883 		if (*(pucFoundCharM + 1) != 'Z')
884 			continue;
885 		uiE_lfanew = *(unsigned int *)(pucFoundCharM + 0x3C);
886 		pucPEHeader = pucFoundCharM + uiE_lfanew;
887 		if (pucPEHeader < pucBuffer || pucPEHeader + 0x01 > pucLastByteInBuffer) // Can we check for "PE" without buffer underrun/overrun?
888 			continue;
889 		if (*(pucPEHeader) != 'P' || *(pucPEHeader + 0x01) != 'E')
890 			continue;
891 
892 		iFound = 1;
893 		if (!strcmp(sOperation, OPR_XOR32))
894 			printf("Found %s %08X offset +%d position %08lX: %08X ", sOperation, uiOperand, ucOffset, pucFoundCharM - pucBuffer, uiE_lfanew);
895 		else if (strcmp(sOperation, OPR_ROT))
896 			printf("Found %s %02X position %08lX: %08X ", sOperation, uiOperand, pucFoundCharM - pucBuffer, uiE_lfanew);
897 		else
898 			printf("Found %s %02d position %08lX: %08X ", sOperation, uiOperand, pucFoundCharM - pucBuffer, uiE_lfanew);
899 		for (iIter = 0; iIter < iMaxLength && pucFoundCharM + 0x40 + iIter <= pucLastByteInBuffer; iIter++)
900 		{
901 			if (isprint(*(pucFoundCharM + 0x40 + iIter)))
902 				putchar(*(pucFoundCharM + 0x40 + iIter));
903 			else
904 				putchar('.');
905 		}
906 		putchar('\n');
907 	}
908 
909 	return iFound;
910 }
911 
AllocAndCopyString(char * szArg,int iLength)912 char *AllocAndCopyString(char *szArg, int iLength)
913 {
914 	char *szReturn;
915 	szReturn = calloc(iLength + 1, 1);
916 
917 	if (NULL == szReturn)
918 		return NULL;
919 	return strncpy0(szReturn, szArg, iLength + 1);
920 }
921 
Realloc(void * pvData,size_t sElement,int * piCount,int iIncrement)922 void *Realloc(void* pvData, size_t sElement, int *piCount, int iIncrement)
923 {
924 	void *pvResult;
925 	size_t sOld;
926 	size_t sNew;
927 
928 	sOld = sElement * *piCount;
929 	*piCount += iIncrement;
930 	sNew = sElement * *piCount;
931 	pvResult = realloc(pvData, sNew);
932 	if (NULL == pvResult)
933 		return NULL;
934 	memset((void *)((unsigned char *)pvResult + sOld), 0, sNew - sOld);
935 	return pvResult;
936 }
937 
CheckHexDigit(char cDigit)938 int CheckHexDigit(char cDigit)
939 {
940 	if (cDigit >= '0' && cDigit <= '9')
941 		return cDigit - '0';
942 	else if (cDigit >= 'a' && cDigit <= 'f')
943 		return cDigit - 'a' + 10;
944 	else if (cDigit >= 'A' && cDigit <= 'F')
945 		return cDigit - 'A' + 10;
946 	else
947 		return -1;
948 }
949 
ParseBits(char * szBits,WILDCARD * pWildcard)950 int ParseBits(char *szBits, WILDCARD *pWildcard)
951 {
952 	int iIter;
953 	int iCountVariable = 0;
954 
955 	pWildcard->ucMode = WILDCARD_MODE_BITS;
956 	pWildcard->ucMaskFixed = 0;
957 	pWildcard->ucBitsFixed = 0;
958 	pWildcard->ucMaskVariable1 = 0;
959 	pWildcard->cVariableName1 = 0;
960 	pWildcard->ucMaskVariable2 = 0;
961 	pWildcard->cVariableName2 = 0;
962 
963 	for (iIter = 0; iIter < 8; iIter++)
964 	{
965 		if ('0' == szBits[iIter])
966 		{
967 			pWildcard->ucMaskFixed |= 1 << (7 - iIter);
968 		}
969 		else if ('1' == szBits[iIter])
970 		{
971 			pWildcard->ucMaskFixed |= 1 << (7 - iIter);
972 			pWildcard->ucBitsFixed |= (szBits[iIter] - '0') * 1 << (7 - iIter);
973 		}
974 		else if ('?' == szBits[iIter])
975 		{
976 			if (1 == iCountVariable)
977 				pWildcard->ucMaskVariable1 |= 1 << (7 - iIter);
978 			else if (2 == iCountVariable)
979 				pWildcard->ucMaskVariable2 |= 1 << (7 - iIter);
980 		}
981 		else if (szBits[iIter] >= 'A' && szBits[iIter] <= 'Z')
982 		{
983 			if (0 == iCountVariable)
984 			{
985 				pWildcard->ucMaskVariable1 |= 1 << (7 - iIter);
986 				pWildcard->cVariableName1 = szBits[iIter] - 'A';
987 				iCountVariable++;
988 			}
989 			else if (1 == iCountVariable)
990 			{
991 				pWildcard->ucMaskVariable2 |= 1 << (7 - iIter);
992 				pWildcard->cVariableName2 = szBits[iIter] - 'A';
993 				iCountVariable++;
994 			}
995 			else
996 				return -1;
997 		}
998 		else
999 			return -1;
1000 	}
1001 
1002 	return 0;
1003 }
1004 
ParseJump(char * szJump,WILDCARD * pWildcard)1005 int ParseJump(char *szJump, WILDCARD *pWildcard)
1006 {
1007 	pWildcard->ucMode = WILDCARD_MODE_JUMP;
1008 	pWildcard->ucJumpBytes = 0;
1009 
1010 	if ('1' == szJump[0] || '4' == szJump[0])
1011 	{
1012 		pWildcard->ucJumpBytes = szJump[0] - '0';
1013 		return 0;
1014 	}
1015 	else
1016 		return -1;
1017 }
1018 
1019 #define PREFIX_STRE "str="
1020 
ParseWildcards(char * szWildcard)1021 WILDCARD *ParseWildcards(char *szWildcard)
1022 {
1023 	WILDCARD *pWildcards;
1024 	char *pcWildcard;
1025 	int iIter;
1026 	int iSizeBuffer;
1027 
1028 	iSizeBuffer = 0x100;
1029 	iIter = 0;
1030 	pWildcards = calloc(sizeof(WILDCARD), iSizeBuffer);
1031 	if (NULL == pWildcards)
1032 		return NULL;
1033 
1034 	pcWildcard = szWildcard;
1035 	if (strlen(pcWildcard) > strlen(PREFIX_STRE) && StartsWith(pcWildcard, PREFIX_STRE))
1036 	{
1037 		pcWildcard += strlen(PREFIX_STRE);
1038 		while (strlen(pcWildcard) != 0)
1039 		{
1040 			pWildcards[iIter].ucMode = WILDCARD_MODE_BYTE;
1041 			pWildcards[iIter++].ucByte = pcWildcard[0];
1042 			pcWildcard++;
1043 			if (iIter == iSizeBuffer)
1044 			{
1045 				pWildcards = Realloc(pWildcards, sizeof(WILDCARD), &iSizeBuffer, 0x100);
1046 				if (NULL == pWildcards)
1047 					return NULL;
1048 			}
1049 		}
1050 	}
1051 	else
1052 		while (strlen(pcWildcard) != 0)
1053 		{
1054 			if (strlen(pcWildcard) >= 2 && -1 != CheckHexDigit(pcWildcard[0]) && -1 != CheckHexDigit(pcWildcard[1]))
1055 			{
1056 				pWildcards[iIter].ucMode = WILDCARD_MODE_BYTE;
1057 				pWildcards[iIter++].ucByte = CheckHexDigit(pcWildcard[0]) * 0x10 + CheckHexDigit(pcWildcard[1]);
1058 				pcWildcard += 2;
1059 			}
1060 			else if ('(' == *pcWildcard && strlen(pcWildcard) >= 12 && 'B' == pcWildcard[1] && ';' == pcWildcard[2] && ')' == pcWildcard[11])
1061 			{
1062 				if (0 == iIter)
1063 					return 0;
1064 				if (-1 == ParseBits(AllocAndCopyString(pcWildcard + 3, 8), &pWildcards[iIter++]))
1065 					return NULL;
1066 				pcWildcard += 12;
1067 			}
1068 			else if ('(' == *pcWildcard && strlen(pcWildcard) >= 5 && 'J' == pcWildcard[1] && ';' == pcWildcard[2] && ')' == pcWildcard[4])
1069 			{
1070 				if (0 == iIter)
1071 					return 0;
1072 				if (-1 == ParseJump(AllocAndCopyString(pcWildcard + 3, 1), &pWildcards[iIter++]))
1073 					return NULL;
1074 				pcWildcard += 5;
1075 			}
1076 			else
1077 				return NULL;
1078 			if (iIter == iSizeBuffer)
1079 			{
1080 				pWildcards = Realloc(pWildcards, sizeof(WILDCARD), &iSizeBuffer, 0x100);
1081 				if (NULL == pWildcards)
1082 					return NULL;
1083 			}
1084 		}
1085 
1086 	pWildcards[iIter].ucMode = WILDCARD_MODE_STOP;
1087 
1088 	pWildcards = realloc(pWildcards, sizeof(WILDCARD) * (iIter + 1));
1089 	if (NULL == pWildcards)
1090 		return NULL;
1091 
1092 	return pWildcards;
1093 }
1094 
ParseRule(char * pcRule,char ** ppcName,int * piScore,char ** ppcWildcards,WILDCARD ** ppWildcards)1095 unsigned int ParseRule(char *pcRule, char **ppcName, int *piScore, char **ppcWildcards, WILDCARD **ppWildcards)
1096 {
1097 	char *pcSeparator1;
1098 	char *pcSeparator2;
1099 	char *pcSeparator3;
1100 	char *szScore;
1101 
1102 	pcSeparator1 = strchr(pcRule, ':');
1103 	if (NULL == pcSeparator1)
1104 		return -1;
1105 	pcSeparator2 = strchr(pcSeparator1 + 1, ':');
1106 	if (NULL == pcSeparator2)
1107 		return -1;
1108 	pcSeparator3 = strchr(pcSeparator2 + 1, ':');
1109 	if (NULL != pcSeparator3)
1110 		return -1;
1111 
1112 	*ppcName = AllocAndCopyString(pcRule, pcSeparator1 - pcRule);
1113 	if (NULL == *ppcName)
1114 		return -1;
1115 	szScore = AllocAndCopyString(pcSeparator1 + 1, pcSeparator2 - pcSeparator1 - 1);
1116 	if (NULL == szScore)
1117 		return -1;
1118 	*piScore = (int) ParseIntegerArg(szScore);
1119 	if (-1 == *piScore)
1120 		return -1;
1121 	*ppcWildcards = AllocAndCopyString(pcSeparator2 + 1, strlen(pcSeparator2 + 1));
1122 	if (NULL == *ppcWildcards)
1123 		return -1;
1124 
1125 	*ppWildcards = ParseWildcards(pcSeparator2 + 1);
1126 	if (NULL == *ppWildcards)
1127 		return -1;
1128 
1129 	return 0;
1130 }
1131 
AddRule(SEARCH ** ppSearch,int * piSize,int * piIndex,char * pcRule)1132 int AddRule(SEARCH **ppSearch, int *piSize, int *piIndex, char *pcRule)
1133 {
1134 	char *pcName;
1135 	int iScore;
1136 	char *pcWildcards;
1137 	WILDCARD *pWildcards;
1138 
1139 	if (0 == *piSize)
1140 	{
1141 		*piSize = 10;
1142 		*ppSearch = calloc(sizeof(SEARCH), *piSize);
1143 		if (NULL == *ppSearch)
1144 			return -1;
1145 	}
1146 
1147 	if (*piIndex >= *piSize - 1)
1148 	{
1149 		*ppSearch = Realloc(*ppSearch, sizeof(SEARCH), piSize, 10);
1150 		if (NULL == *ppSearch)
1151 			return -1;
1152 	}
1153 
1154 	if (ParseRule(pcRule, &pcName, &iScore, &pcWildcards, &pWildcards))
1155 		return -1;
1156 
1157 	(*ppSearch)[*piIndex].iSearchType = SEARCHTYPE_WILDCARD;
1158 	(*ppSearch)[*piIndex].pcWildcardName = pcName;
1159 	(*ppSearch)[*piIndex].iScore = iScore;
1160 	(*ppSearch)[*piIndex].iPrintASCII = StartsWith(pcWildcards, PREFIX_STRE);
1161 	(*ppSearch)[(*piIndex)++].pWildcards = pWildcards;
1162 
1163 	(*ppSearch)[*piIndex].iSearchType = SEARCHTYPE_STOP;
1164 
1165 	return 0;
1166 }
1167 
InitializeSearch(char * pcRule,char * szFile,int iFlagEmbedded)1168 SEARCH *InitializeSearch(char *pcRule, char *szFile, int iFlagEmbedded)
1169 {
1170 	SEARCH *pSearch;
1171 	int iSize;
1172 	int iIndex;
1173 	int iIter;
1174 	FILE *fRules;
1175 	char szLine[1024];
1176 	char *aszEmbeddedRules[] =
1177 	{
1178 		"Function prolog signature:10:558bec83c4",
1179 		"Function prolog signature:10:558bec81ec",
1180 		"Function prolog signature:10:558beceb",
1181 		"Function prolog signature:10:558bece8",
1182 		"Function prolog signature:10:558bece9",
1183 		"Indirect function call tris:10:FFB7(B;????????)(B;????????)(B;????????)(B;????????)FF57(B;????????)",
1184 		"GetEIP method 4 FLDZ/FSTENV [esp-12]:10:D9EED97424F4(B;01011???)",
1185 		"GetEIP method 1:10:E800000000(B;01011???)",
1186 		"GetEIP method 2:10:EB(J;1)E8(J;4)(B;01011???)",
1187 		"GetEIP method 3:10:E9(J;4)E8(J;4)(B;01011???)",
1188 		"GetEIP method 4:10:D9EE9BD97424F4(B;01011???)",
1189 		"Find kernel32 base method 1:10:648B(B;00???101)30000000",
1190 		"Find kernel32 base method 1bis:10:64A130000000",
1191 		"Find kernel32 base method 2:10:31(B;11A??A??)(B;10100A??)30648B(B;00B??A??)",
1192 		"Find kernel32 base method 3:10:6830000000(B;01011A??)648B(B;00B??A??)",
1193 		"Structured exception handling :10:648B(B;00???101)00000000",
1194 		"Structured exception handling bis:10:64A100000000",
1195 		"API Hashing:10:AC84C07407C1CF0D01C7EBF481FF",
1196 		"API Hashing bis:10:AC84C07407C1CF0701C7EBF481FF",
1197 //	"API-Hashing signature:10:74(B;????????)c1(B;????????)0d(B;????????)(B;????????)(B;????????)(B;????????), // too many false positives
1198 //	"API-Hashing signature:10:74(B;????????)c1(B;????????)07(B;????????)(B;????????)(B;????????)(B;????????), // too many false positives
1199 //	"API-Hashing signature:10:74(B;????????)c1(B;????????)0b03(B;????????)(B;????????)(B;????????)(B;????????), // too many false positives
1200 		"Indirect function call:10:FF75(B;A???????)FF55(B;A???????)",
1201 		"Indirect function call bis:10:FFB5(B;A???????)(B;B???????)(B;C???????)(B;D???????)FF95(B;A???????)(B;B???????)(B;C???????)(B;D???????)",
1202 		"OLE file magic number:10:D0CF11E0",
1203 		"Suspicious strings:2:str=UrlDownloadToFile",
1204 		"Suspicious strings:2:str=GetTempPath",
1205 		"Suspicious strings:2:str=GetWindowsDirectory",
1206 		"Suspicious strings:2:str=GetSystemDirectory",
1207 		"Suspicious strings:2:str=WinExec",
1208 		"Suspicious strings:2:str=ShellExecute",
1209 		"Suspicious strings:2:str=IsBadReadPtr",
1210 		"Suspicious strings:2:str=IsBadWritePtr",
1211 		"Suspicious strings:2:str=CreateFile",
1212 		"Suspicious strings:2:str=CloseHandle",
1213 		"Suspicious strings:2:str=ReadFile",
1214 		"Suspicious strings:2:str=WriteFile",
1215 		"Suspicious strings:2:str=SetFilePointer",
1216 		"Suspicious strings:2:str=VirtualAlloc",
1217 		"Suspicious strings:2:str=GetProcAddr",
1218 		"Suspicious strings:2:str=LoadLibrary",
1219 	};
1220 
1221 	pSearch = NULL;
1222 	iSize = 0;
1223 	iIndex = 0;
1224 
1225 	if (iFlagEmbedded)
1226 	{
1227 		for (iIter = 0; iIter < countof(aszEmbeddedRules); iIter++)
1228 			if (AddRule(&pSearch, &iSize, &iIndex, aszEmbeddedRules[iIter]) != 0)
1229 				return NULL;
1230 	}
1231 	else if (NULL != szFile)
1232 	{
1233 		if ((fRules = fopen(szFile, "r")) == NULL)
1234 		{
1235 			fprintf(stderr, "error opening file %s\n", szFile);
1236 			exit(-1);
1237 		}
1238 		while (fgets(szLine, sizeof(szLine), fRules) != NULL)
1239 		{
1240 			if (strlen(szLine) > 0 && szLine[strlen(szLine) - 1] == '\n')
1241 				szLine[strlen(szLine) - 1] = '\0';
1242 			if (strlen(szLine) > 0 && szLine[0] != '#')
1243 				if (AddRule(&pSearch, &iSize, &iIndex, szLine) != 0)
1244 				{
1245 					fclose(fRules);
1246 					return NULL;
1247 				}
1248 		}
1249 		fclose(fRules);
1250 	}
1251 	else
1252 	{
1253 		if (AddRule(&pSearch, &iSize, &iIndex, pcRule) != 0)
1254 			return NULL;
1255 	}
1256 
1257 	return pSearch;
1258 }
1259 
List(SEARCH * pSearch)1260 void List(SEARCH *pSearch)
1261 {
1262 	int iIter1;
1263 	int iIter2;
1264 	int iIter3;
1265 	int iVariable1WasPrinted;
1266 	int iVariable2WasPrinted;
1267 
1268 	for (iIter1 = 0; pSearch[iIter1].iSearchType != SEARCHTYPE_STOP; iIter1++)
1269 	{
1270 		printf("%s:%d:", pSearch[iIter1].pcWildcardName, pSearch[iIter1].iScore);
1271 		if (1 == pSearch[iIter1].iPrintASCII)
1272 		{
1273 			printf("str=");
1274 			for (iIter2 = 0; pSearch[iIter1].pWildcards[iIter2].ucMode != WILDCARD_MODE_STOP; iIter2++)
1275 				printf("%c", pSearch[iIter1].pWildcards[iIter2].ucByte);
1276 		}
1277 		else
1278 		{
1279 			for (iIter2 = 0; pSearch[iIter1].pWildcards[iIter2].ucMode != WILDCARD_MODE_STOP; iIter2++)
1280 				switch (pSearch[iIter1].pWildcards[iIter2].ucMode)
1281 				{
1282 					case WILDCARD_MODE_BYTE:
1283 						printf("%02X", pSearch[iIter1].pWildcards[iIter2].ucByte);
1284 						break;
1285 					case WILDCARD_MODE_BITS:
1286 						iVariable1WasPrinted = 0;
1287 						iVariable2WasPrinted = 0;
1288 						printf("(B;");
1289 						for (iIter3 = 7; iIter3 >= 0; iIter3--)
1290 							if ((pSearch[iIter1].pWildcards[iIter2].ucMaskFixed >> iIter3) & 0x01)
1291 								printf("%d", (pSearch[iIter1].pWildcards[iIter2].ucBitsFixed >> iIter3) & 0x01);
1292 							else if ((pSearch[iIter1].pWildcards[iIter2].ucMaskVariable1 >> iIter3) & 0x01)
1293 							{
1294 								if (0 == iVariable1WasPrinted)
1295 								{
1296 									printf("%c", pSearch[iIter1].pWildcards[iIter2].cVariableName1 + 'A');
1297 									iVariable1WasPrinted = 1;
1298 								}
1299 								else
1300 									printf("?");
1301 							}
1302 							else if ((pSearch[iIter1].pWildcards[iIter2].ucMaskVariable2 >> iIter3) & 0x01)
1303 							{
1304 								if (0 == iVariable2WasPrinted)
1305 								{
1306 									printf("%c", pSearch[iIter1].pWildcards[iIter2].cVariableName2 + 'A');
1307 									iVariable2WasPrinted = 1;
1308 								}
1309 								else
1310 									printf("?");
1311 							}
1312 							else
1313 								printf("?");
1314 						printf(")");
1315 						break;
1316 					case WILDCARD_MODE_JUMP:
1317 						printf("(J;%d)", pSearch[iIter1].pWildcards[iIter2].ucJumpBytes);
1318 						break;
1319 				}
1320 		}
1321 		printf("\n");
1322 	}
1323 }
1324 
ReadFile(char * pcArgFile,off_t * potFileSize,void ** ppBuffer)1325 int ReadFile(char *pcArgFile, off_t *potFileSize, void **ppBuffer)
1326 {
1327 	struct stat statFile;
1328 	FILE *fIn;
1329 
1330 	if (stat(pcArgFile, &statFile) != 0)
1331 	{
1332 		fprintf(stderr, "error opening file %s\n", pcArgFile);
1333 		return -1;
1334 	}
1335 
1336 	*potFileSize = statFile.st_size;
1337 	if (*potFileSize == 0)
1338 	{
1339 		fprintf(stderr, "file %s is empty\n", pcArgFile);
1340 		return -1;
1341 	}
1342 	if ((*ppBuffer = malloc(*potFileSize)) == NULL)
1343 	{
1344 		fprintf(stderr, "file %s is too large %lld\n", pcArgFile, *potFileSize);
1345 		return -1;
1346 	}
1347 
1348 	if ((fIn = fopen(pcArgFile, "rb")) == NULL)
1349 	{
1350 		fprintf(stderr, "error opening file %s\n", pcArgFile);
1351 		free(*ppBuffer);
1352 		return -1;
1353 	}
1354 	if (fread(*ppBuffer, *potFileSize, 1, fIn) != 1)
1355 	{
1356 		fprintf(stderr, "error reading file %s\n", pcArgFile);
1357 		fclose(fIn);
1358 		free(*ppBuffer);
1359 		return -1;
1360 	}
1361 	fclose(fIn);
1362 
1363 	return 0;
1364 }
1365 
IsWhitespace(char cHexDigit)1366 int IsWhitespace(char cHexDigit)
1367 {
1368 	return (cHexDigit >= 0x09 && cHexDigit <= 0x0D) || (cHexDigit == 0x20);
1369 }
1370 
ReadHexFile(char * pcArgFile,off_t * potFileSize,void ** ppBuffer)1371 int ReadHexFile(char *pcArgFile, off_t *potFileSize, void **ppBuffer)
1372 {
1373 	FILE *fIn;
1374 	int iChar;
1375 	int iFirstNibble;
1376 	int iCountCharacters;
1377 	off_t otBufferSize;
1378 	void *pBuffer;
1379 
1380 	otBufferSize = 1024*1024;
1381 	if ((*ppBuffer = malloc(otBufferSize)) == NULL)
1382 	{
1383 		fprintf(stderr, "file %s is too large\n", pcArgFile);
1384 		return -1;
1385 	}
1386 
1387 	if ((fIn = fopen(pcArgFile, "r")) == NULL)
1388 	{
1389 		fprintf(stderr, "error opening file %s\n", pcArgFile);
1390 		free(*ppBuffer);
1391 		return -1;
1392 	}
1393 
1394 	iFirstNibble = -1;
1395 	*potFileSize = 0;
1396 	iCountCharacters = 0;
1397 	do
1398 	{
1399 		if (EOF != (iChar = fgetc(fIn)) && !IsWhitespace(iChar))
1400 		{
1401 			iCountCharacters++;
1402 			if (IsHexDigit(iChar))
1403 			{
1404 				if (-1 == iFirstNibble)
1405 					iFirstNibble = HexDigitToNibble(iChar);
1406 				else
1407 				{
1408 					if (*potFileSize < otBufferSize)
1409 					{
1410 						*((char *)(*ppBuffer) + *potFileSize) = iFirstNibble * 0x10 + HexDigitToNibble(iChar);
1411 						(*potFileSize)++;
1412 						iFirstNibble = -1;
1413 					}
1414 					else
1415 					{
1416 						otBufferSize = otBufferSize + 1024*1024;
1417 						pBuffer = realloc(*ppBuffer, otBufferSize);
1418 						if (NULL == pBuffer)
1419 						{
1420 							fprintf(stderr, "file %s is too large\n", pcArgFile);
1421 							free(*ppBuffer);
1422 							fclose(fIn);
1423 							return -1;
1424 						}
1425 						*ppBuffer = pBuffer;
1426 						*((char *)(*ppBuffer) + *potFileSize) = iFirstNibble * 0x10 + HexDigitToNibble(iChar);
1427 						(*potFileSize)++;
1428 						iFirstNibble = -1;
1429 					}
1430 				}
1431 			}
1432 			else
1433 			{
1434 				fprintf(stderr, "file %s contains unexpected character at 0x%X (not hex digit and not whitespace): 0x%02X\n", pcArgFile, iCountCharacters, iChar);
1435 				free(*ppBuffer);
1436 				fclose(fIn);
1437 				return -1;
1438 			}
1439 		}
1440 	} while (EOF != iChar);
1441 	fclose(fIn);
1442 
1443 	if (-1 != iFirstNibble)
1444 	{
1445 		fprintf(stderr, "file %s contains uneven number of hex digits\n", pcArgFile);
1446 		free(*ppBuffer);
1447 		return -1;
1448 	}
1449 
1450 	if (*potFileSize == 0)
1451 	{
1452 		fprintf(stderr, "file %s is empty\n", pcArgFile);
1453 		free(*ppBuffer);
1454 		return -1;
1455 	}
1456 
1457 	return 0;
1458 }
1459 
main(int argc,char ** argv)1460 int main(int argc, char **argv)
1461 {
1462 	struct stat statFile;
1463 	void *pBuffer;
1464 	void *pBufferCopy;
1465 	unsigned char ucOPRIter;
1466 	char *pcArgFile;
1467 	char *pcArgSearch;
1468 	char *pcArgSearchFile;
1469 	char *pcSearch;
1470 	char *pcDisable;
1471 	int iFlagSave;
1472 	int iFlagIgnoreCase;
1473 	int iMaxLength;
1474 	int iCountFinds;
1475 	int iFound;
1476 	int iFlagUnicode;
1477 	int iSearchLength;
1478 	int iNeighbourgLength;
1479 	int iFlagHex;
1480 	int iFlagKeys;
1481 	int iFlagPEFile;
1482 	int iSearchType;
1483 	int iExcludeByte;
1484 	int iFlagWildcard;
1485 	int iFlagWildcardEmbedded;
1486 	int iFlagList;
1487 	int iFlagHexFile;
1488 	unsigned int *pui32bitKeys;
1489 	unsigned int uiSize32bitKeys;
1490 	unsigned int uiCount32bitKeys;
1491 	unsigned int uiIter32bitKeys;
1492 	int iIterBuffer;
1493 	int iScore;
1494 	union
1495 	{
1496 		unsigned int uiKey;
1497 		unsigned char ucKey[4];
1498 	} uk1, uk2;
1499 	SEARCH *pSearch;
1500 	int iFoundSomething;
1501 	off_t otFileSize;
1502 	int iResult;
1503 
1504 	if (ParseArgs(argc, argv, &iFlagSave, &iMaxLength, &iFlagIgnoreCase, &pcArgFile, &pcArgSearch, &pcArgSearchFile, &iFlagUnicode, &iNeighbourgLength, &iFlagHex, &iFlagKeys, &iFlagPEFile, &iExcludeByte, &iFlagWildcard, &iFlagWildcardEmbedded, &pcDisable, &iFlagList, &iFlagHexFile))
1505 	{
1506 		fprintf(stderr, "Usage: XORSearch [-siuhkpwWLx] [-l length] [-n length] [-f search-file] [-e byte] [-d encodings] file string|hex|rule\n"
1507 										"XORSearch V1.11.1, search for a XOR, ROL, ROT, SHIFT or ADD encoded string in a file\n"
1508 										"Use -x when the file to search is a hexdump\n"
1509 										"Use -s to save the XOR, ROL, ROT, SHIFT or ADD encoded file containing the string\n"
1510 										"Use -l length to limit the number of printed characters (50 by default, 38 with option -p)\n"
1511 										"Use -i to ignore the case when searching\n"
1512 										"Use -u to search for Unicode strings (limited support)\n"
1513 										"Use -f to provide a file with search strings\n"
1514 										"Use -n length to print the length neighbouring charaters (before & after the found keyword)\n"
1515 										"Use -h to search for hex strings\n"
1516 										"Use -k to decode with embedded keys\n"
1517 										"Use -p to search for PE-files\n"
1518 										"Use -w to search with wildcards\n"
1519 										"Use -W to search with embedded wildcards\n"
1520 										"Use -L to list embedded wildcards\n"
1521 										"Use -e to exclude a particular byte-value from encoding\n"
1522 										"Use -d to disable encoding(s) 1: XOR 2: ROL 3: ROT 4: SHIFT 5: ADD\n"
1523 										"Options -l and -n are mutually exclusive\n"
1524 										"Options -u and -h are mutually exclusive\n"
1525 										"Options -k and -e are mutually exclusive\n"
1526 										"Option -p is not compatible with options -i, -u, -h and -n\n"
1527 										"When using -p, do not provide a search string or use -f\n"
1528 										"When using -W, do not provide a search string or use -f\n"
1529 										"Use option -L without arguments or other options\n"
1530 										"Source code put in the public domain by Didier Stevens, no Copyright\n"
1531 										"Use at your own risk\n"
1532 										"https://DidierStevens.com\n");
1533 		return -1;
1534 	}
1535 	if (iMaxLength == -1)
1536 	{
1537 		if (iFlagPEFile)
1538 			iMaxLength = 38;
1539 		else
1540 			iMaxLength = 50;
1541 	}
1542 
1543 	if (iFlagList)
1544 	{
1545 		pSearch = InitializeSearch(NULL, NULL, 1);
1546 		if (NULL == pSearch)
1547 		{
1548 			fprintf(stderr, "Error: parsing rule\n");
1549 			return -1;
1550 		}
1551 
1552 		List(pSearch);
1553 
1554 		return 0;
1555 	}
1556 
1557 	if (iFlagUnicode)
1558 		iSearchType = SEARCHTYPE_UNICODE;
1559 	else if (iFlagHex)
1560 		iSearchType = SEARCHTYPE_HEX;
1561 	else if (iFlagWildcard || iFlagWildcardEmbedded)
1562 		iSearchType = SEARCHTYPE_WILDCARD;
1563 	else
1564 		iSearchType = SEARCHTYPE_ASCII;
1565 
1566 	if (iFlagWildcard || iFlagWildcardEmbedded)
1567 	{
1568 		pSearch = InitializeSearch(pcArgSearch, pcArgSearchFile, iFlagWildcardEmbedded);
1569 		if (NULL == pSearch)
1570 		{
1571 			fprintf(stderr, "Error: parsing rule\n");
1572 			return -1;
1573 		}
1574 	}
1575 
1576 	if (strlen(pcArgFile) >= XSIZE-1)
1577 	{
1578 		fprintf(stderr, "Error: filename is too long\n");
1579 		return -1;
1580 	}
1581 
1582 	if (pcArgSearchFile != NULL)
1583 	{
1584 		if (stat(pcArgSearchFile, &statFile) != 0)
1585 		{
1586 			fprintf(stderr, "error opening file %s\n", pcArgSearchFile);
1587 			return -1;
1588 		}
1589 	}
1590 	else if (pcArgSearch != NULL && strlen(pcArgSearch) >= XSIZE-2)
1591 	{
1592 		fprintf(stderr, "Error: search string is too long\n");
1593 		return -1;
1594 	}
1595 
1596 	if (iFlagHexFile)
1597 		iResult = ReadHexFile(pcArgFile, &otFileSize, &pBuffer);
1598 	else
1599 		iResult = ReadFile(pcArgFile, &otFileSize, &pBuffer);
1600 	if (0 != iResult)
1601 		return iResult;
1602 
1603 	if ((pBufferCopy = malloc(otFileSize)) == NULL)
1604 	{
1605 		fprintf(stderr, "file %s is too large %lld\n", pcArgFile, otFileSize);
1606 		free(pBuffer);
1607 		return -1;
1608 	}
1609 	memcpy(pBufferCopy, pBuffer, otFileSize);
1610 
1611 	if (iFlagKeys && otFileSize < 4)
1612 	{
1613 		fprintf(stderr, "file %s is too small for option -k\n", pcArgFile);
1614 		free(pBuffer);
1615 		free(pBufferCopy);
1616 		return -1;
1617 	}
1618 
1619 	pui32bitKeys = NULL;
1620 	uiSize32bitKeys = (otFileSize - 3) * 2;
1621 	if (iFlagKeys)
1622 		if ((pui32bitKeys = malloc(uiSize32bitKeys * sizeof(unsigned int))) == NULL)
1623 		{
1624 			fprintf(stderr, "file %s is too large for copy %lld\n", pcArgFile, otFileSize);
1625 			uiSize32bitKeys = 0;
1626 		}
1627 
1628 	if (NULL != pui32bitKeys)
1629 	{
1630 		uiCount32bitKeys = 0;
1631 		for (iIterBuffer = 0; iIterBuffer < otFileSize - 3; iIterBuffer++)
1632 		{
1633 			uk1.uiKey = *(unsigned int *)((unsigned char *)pBuffer + iIterBuffer);
1634 			if (!(uk1.ucKey[0] == uk1.ucKey[1] && uk1.ucKey[0] == uk1.ucKey[2] && uk1.ucKey[0] == uk1.ucKey[3]))
1635 			{
1636 				InsertSorted(uk1.uiKey, pui32bitKeys, uiSize32bitKeys, &uiCount32bitKeys);
1637 				uk2.ucKey[3] = uk1.ucKey[0];
1638 				uk2.ucKey[2] = uk1.ucKey[1];
1639 				uk2.ucKey[1] = uk1.ucKey[2];
1640 				uk2.ucKey[0] = uk1.ucKey[3];
1641 				InsertSorted(uk2.uiKey, pui32bitKeys, uiSize32bitKeys, &uiCount32bitKeys);
1642 			}
1643 		}
1644 	}
1645 
1646 	if ((piFoundIndex = (int *)malloc(otFileSize * sizeof(int))) == NULL)
1647 	{
1648 		fprintf(stderr, "file %s is too large %lld\n", pcArgFile, otFileSize);
1649 		free(pBuffer);
1650 		free(pBufferCopy);
1651 		return -1;
1652 	}
1653 
1654 	if ((piFoundSize = (int *)malloc(otFileSize * sizeof(int))) == NULL)
1655 	{
1656 		fprintf(stderr, "file %s is too large %lld\n", pcArgFile, otFileSize);
1657 		free(pBuffer);
1658 		free(pBufferCopy);
1659 		free(piFoundIndex);
1660 		return -1;
1661 	}
1662 
1663 	iFoundSomething = 0;
1664 	iScore = 0;
1665 	if (iFlagKeys)
1666 	{
1667 		printf("Testing %d keys\n", uiCount32bitKeys);
1668 		for (uiIter32bitKeys = 0; uiIter32bitKeys < uiCount32bitKeys; uiIter32bitKeys++)
1669 		{
1670 			for (ucOPRIter = 0; ucOPRIter < 4; ucOPRIter++)
1671 			{
1672 				XOR32(pBuffer, otFileSize, ucOPRIter, pui32bitKeys[uiIter32bitKeys]);
1673 
1674 				iFound = 0;
1675 				if (iFlagPEFile)
1676 					iFound = SearchForPEFile((unsigned char *)pBuffer, otFileSize, OPR_XOR32, ucOPRIter, pui32bitKeys[uiIter32bitKeys], iMaxLength);
1677 				else if (iSearchType == SEARCHTYPE_WILDCARD)
1678 					iFound = WildcardSearches(pSearch, pBuffer, otFileSize, OPR_XOR32, 0, ucOPRIter, iMaxLength, &iScore);
1679 				else
1680 					do
1681 					{
1682 						pcSearch = GetSearchString(pcArgSearch, pcArgSearchFile, iSearchType, &iSearchLength);
1683 						if (pcSearch && iSearchLength > 0)
1684 						{
1685 							iCountFinds = KMP(pcSearch, iSearchLength, pBuffer, otFileSize, iFlagIgnoreCase);
1686 							if (iCountFinds > 0)
1687 							{
1688 								PrintFinds(iCountFinds, iMaxLength, OPR_XOR32, ucOPRIter, pui32bitKeys[uiIter32bitKeys], otFileSize, pBuffer, iSearchType, iNeighbourgLength);
1689 								iFound = 1;
1690 							}
1691 						}
1692 					} while (pcSearch);
1693 
1694 				if (iFound && iFlagSave)
1695 					SaveFile(pcArgFile, OPR_XOR32, pui32bitKeys[uiIter32bitKeys], pBuffer, otFileSize);
1696 
1697 				iFoundSomething |= iFound;
1698 
1699 				memcpy(pBuffer, pBufferCopy, otFileSize);
1700 			}
1701 		}
1702 	}
1703 	else
1704 	{
1705 		ucOPRIter = 0;
1706 
1707 		if (NULL == pcDisable || !strchr(pcDisable, '1'))
1708 		{
1709 			do
1710 			{
1711 				XOR((unsigned char *) pBuffer, otFileSize, ucOPRIter, iExcludeByte);
1712 
1713 				iFound = 0;
1714 				if (iFlagPEFile)
1715 					iFound = SearchForPEFile((unsigned char *)pBuffer, otFileSize, OPR_XOR, 0, ucOPRIter, iMaxLength);
1716 				else if (iSearchType == SEARCHTYPE_WILDCARD)
1717 					iFound = WildcardSearches(pSearch, pBuffer, otFileSize, OPR_XOR, 0, ucOPRIter, iMaxLength, &iScore);
1718 				else
1719 					do
1720 					{
1721 						pcSearch = GetSearchString(pcArgSearch, pcArgSearchFile, iSearchType, &iSearchLength);
1722 						if (pcSearch && iSearchLength > 0)
1723 						{
1724 							iCountFinds = KMP(pcSearch, iSearchLength, pBuffer, otFileSize, iFlagIgnoreCase);
1725 							if (iCountFinds > 0)
1726 							{
1727 								PrintFinds(iCountFinds, iMaxLength, OPR_XOR, 0, ucOPRIter, otFileSize, pBuffer, iSearchType, iNeighbourgLength);
1728 								iFound = 1;
1729 							}
1730 						}
1731 					} while (pcSearch);
1732 
1733 				if (iFound && iFlagSave)
1734 					SaveFile(pcArgFile, OPR_XOR, ucOPRIter, pBuffer, otFileSize);
1735 
1736 				iFoundSomething |= iFound;
1737 
1738 				memcpy(pBuffer, pBufferCopy, otFileSize);
1739 			} while (++ucOPRIter);
1740 		}
1741 
1742 		if (NULL == pcDisable || !strchr(pcDisable, '2'))
1743 		{
1744 			for (ucOPRIter = 1; ucOPRIter < 8; ucOPRIter++)
1745 			{
1746 				ROL((unsigned char *) pBuffer, otFileSize, iExcludeByte);
1747 
1748 				iFound = 0;
1749 				if (iFlagPEFile)
1750 					iFound = SearchForPEFile((unsigned char *)pBuffer, otFileSize, OPR_ROL, 0, ucOPRIter, iMaxLength);
1751 				else if (iSearchType == SEARCHTYPE_WILDCARD)
1752 					iFound = WildcardSearches(pSearch, pBuffer, otFileSize, OPR_ROL, 0, ucOPRIter, iMaxLength, &iScore);
1753 				else
1754 					do
1755 					{
1756 						pcSearch = GetSearchString(pcArgSearch, pcArgSearchFile, iSearchType, &iSearchLength);
1757 						if (pcSearch && iSearchLength > 0)
1758 						{
1759 							iCountFinds = KMP(pcSearch, iSearchLength, pBuffer, otFileSize, iFlagIgnoreCase);
1760 							if (iCountFinds > 0)
1761 							{
1762 								PrintFinds(iCountFinds, iMaxLength, OPR_ROL, 0, ucOPRIter, otFileSize, pBuffer, iSearchType, iNeighbourgLength);
1763 								iFound = 1;
1764 							}
1765 						}
1766 					} while (pcSearch);
1767 
1768 				if (iFound && iFlagSave)
1769 					SaveFile(pcArgFile, OPR_ROL, ucOPRIter, pBuffer, otFileSize);
1770 
1771 				iFoundSomething |= iFound;
1772 			}
1773 			memcpy(pBuffer, pBufferCopy, otFileSize);
1774 		}
1775 
1776 		if (NULL == pcDisable || !strchr(pcDisable, '3'))
1777 		{
1778 			for (ucOPRIter = 25; ucOPRIter >= 1; ucOPRIter--)
1779 			{
1780 				ROT((unsigned char *) pBuffer, otFileSize, iExcludeByte);
1781 
1782 				iFound = 0;
1783 				if (iFlagPEFile)
1784 					iFound = SearchForPEFile((unsigned char *)pBuffer, otFileSize, OPR_ROT, 0, ucOPRIter, iMaxLength);
1785 				else if (iSearchType == SEARCHTYPE_WILDCARD)
1786 					iFound = WildcardSearches(pSearch, pBuffer, otFileSize, OPR_ROT, 0, ucOPRIter, iMaxLength, &iScore);
1787 				else
1788 					do
1789 					{
1790 						pcSearch = GetSearchString(pcArgSearch, pcArgSearchFile, iSearchType, &iSearchLength);
1791 						if (pcSearch && iSearchLength > 0)
1792 						{
1793 							iCountFinds = KMP(pcSearch, iSearchLength, pBuffer, otFileSize, iFlagIgnoreCase);
1794 							if (iCountFinds > 0)
1795 							{
1796 								PrintFinds(iCountFinds, iMaxLength, OPR_ROT, 0, ucOPRIter, otFileSize, pBuffer, iSearchType, iNeighbourgLength);
1797 								iFound = 1;
1798 							}
1799 						}
1800 					} while (pcSearch);
1801 
1802 				if (iFound && iFlagSave)
1803 					SaveFile(pcArgFile, OPR_ROT, ucOPRIter, pBuffer, otFileSize);
1804 
1805 				iFoundSomething |= iFound;
1806 			}
1807 			memcpy(pBuffer, pBufferCopy, otFileSize);
1808 		}
1809 
1810 		if (NULL == pcDisable || !strchr(pcDisable, '4'))
1811 		{
1812 			for (ucOPRIter = 1; ucOPRIter < 8; ucOPRIter++)
1813 			{
1814 				SHIFT((unsigned char *) pBuffer, otFileSize, iExcludeByte);
1815 
1816 				iFound = 0;
1817 				if (iFlagPEFile)
1818 					iFound = SearchForPEFile((unsigned char *)pBuffer, otFileSize, OPR_SHIFT, 0, ucOPRIter, iMaxLength);
1819 				else if (iSearchType == SEARCHTYPE_WILDCARD)
1820 					iFound = WildcardSearches(pSearch, pBuffer, otFileSize, OPR_SHIFT, 0, ucOPRIter, iMaxLength, &iScore);
1821 				else
1822 					do
1823 					{
1824 						pcSearch = GetSearchString(pcArgSearch, pcArgSearchFile, iSearchType, &iSearchLength);
1825 						if (pcSearch && iSearchLength > 0)
1826 						{
1827 							iCountFinds = KMP(pcSearch, iSearchLength, pBuffer, otFileSize, iFlagIgnoreCase);
1828 							if (iCountFinds > 0)
1829 							{
1830 								PrintFinds(iCountFinds, iMaxLength, OPR_SHIFT, 0, ucOPRIter, otFileSize, pBuffer, iSearchType, iNeighbourgLength);
1831 								iFound = 1;
1832 							}
1833 						}
1834 					} while (pcSearch);
1835 
1836 				if (iFound && iFlagSave)
1837 					SaveFile(pcArgFile, OPR_SHIFT, ucOPRIter, pBuffer, otFileSize);
1838 
1839 				iFoundSomething |= iFound;
1840 			}
1841 			memcpy(pBuffer, pBufferCopy, otFileSize);
1842 		}
1843 
1844 		if (NULL == pcDisable || !strchr(pcDisable, '5'))
1845 		{
1846 			do
1847 			{
1848 				ADD((unsigned char *) pBuffer, otFileSize, iExcludeByte);
1849 
1850 				iFound = 0;
1851 				if (iFlagPEFile)
1852 					iFound = SearchForPEFile((unsigned char *)pBuffer, otFileSize, OPR_ADD, 0, ucOPRIter, iMaxLength);
1853 				else if (iSearchType == SEARCHTYPE_WILDCARD)
1854 					iFound = WildcardSearches(pSearch, pBuffer, otFileSize, OPR_ADD, 0, ucOPRIter, iMaxLength, &iScore);
1855 				else
1856 					do
1857 					{
1858 						pcSearch = GetSearchString(pcArgSearch, pcArgSearchFile, iSearchType, &iSearchLength);
1859 						if (pcSearch && iSearchLength > 0)
1860 						{
1861 							iCountFinds = KMP(pcSearch, iSearchLength, pBuffer, otFileSize, iFlagIgnoreCase);
1862 							if (iCountFinds > 0)
1863 							{
1864 								PrintFinds(iCountFinds, iMaxLength, OPR_ADD, 0, ucOPRIter, otFileSize, pBuffer, iSearchType, iNeighbourgLength);
1865 								iFound = 1;
1866 							}
1867 						}
1868 					} while (pcSearch);
1869 
1870 				if (iFound && iFlagSave)
1871 					SaveFile(pcArgFile, OPR_ADD, ucOPRIter, pBuffer, otFileSize);
1872 
1873 				iFoundSomething |= iFound;
1874 			} while (++ucOPRIter);
1875 		}
1876 	}
1877 
1878 	free(pBuffer);
1879 	free(pBufferCopy);
1880 	free(piFoundIndex);
1881 	free(piFoundSize);
1882 
1883 	if (iSearchType == SEARCHTYPE_WILDCARD)
1884 	{
1885 		printf("Score: %d\n", iScore);
1886 		return iScore;
1887 	}
1888 	else
1889 		return iFoundSomething ? 0 : 1;
1890 }
1891