/* modified code from fullsec.c written by ccexplore */ #include #include #include #include "pgchip.h" #define ExeLen 128 /* includes null terminator */ char ExeIn[ExeLen + 4]; /* + 4 to allow for appending ".exe" */ char ExeOut[ExeLen + 4]; /* + 4 to allow for appending ".exe" */ /* hold the temp filename used during saving */ /* ExeLen + 4 for prepending rest of path (see getTmpFile) */ char ExeTemp[ExeLen + 4 + L_tmpnam]; /* hold user response to questions, typically a yes/no answer */ /* includes room for null terminator */ char YesNo[2]; #define AnswerYes (YesNo[0] == 'Y' || YesNo[0] == 'y') #define ExeOutF_CREATE 0 #define ExeOutF_REPLACE 1 unsigned int tmpCount = 0; int main() { int status, outStatus; FILE *ExeInF = NULL, *ExeOutF = NULL; unsigned const char *whattowrite; printf("This is pgchip.exe, version 1\n\n"); status = getInFile(ExeIn, &ExeInF); switch (status) { case FF_Original: whattowrite = patch1data; outStatus = getOutFile("patched", ExeIn, ExeOut, &ExeOutF); break; case FF_Patched1: whattowrite = originaldata; outStatus = getOutFile("unpatched", ExeIn, ExeOut, &ExeOutF); break; default: return status; } strcpy(ExeTemp, ExeOut); switch (outStatus) { case ExeOutF_REPLACE: printf ("\nCreating temporary file..."); if (getTmpFile(ExeTemp, &ExeOutF) == 0) { printf ("success!\n" "Now writing to temporary file %s...", ExeTemp); if (patch(ExeInF, ExeOutF, whattowrite) == 0) { printf ("success!\n" "Now deleting your old %s file...", ExeOut); fclose(ExeInF); fclose(ExeOutF); if (remove(ExeOut) == 0) { printf ("success!\n"); printf ("And finally, renaming the new file %s to %s...", ExeTemp, ExeOut); if (rename(ExeTemp, ExeOut) == 0) { printf ("success!\n"); status = 0; break; } else printf ("FAILED!\n"); } else { printf ("\nError! Cannot delete file!\n"); } printf ("\nAs a result, the new file has been written to %s instead of %s.\n" "Sorry for the inconvenience!\n", ExeTemp, ExeOut); return -1; } else printf ("\nError while writing to temporary file %s!\n", ExeTemp); } else printf ("\nError creating temporary file!\n"); printf ("Program must directly overwrite %s! Proceed (Y/N)? ", ExeOut); scanf (" %1s", YesNo); if (!AnswerYes) { status = -1; break; } /* purposely no BREAK here */ case ExeOutF_CREATE: fclose(ExeOutF); if ((ExeOutF = fopen(ExeOut, "wb")) != NULL) { printf ("\nWriting to file %s...", ExeOut); if ((status = patch(ExeInF, ExeOutF, whattowrite)) == 0) { printf ("success!\n"); break; } } printf ("\nError writing to file %s! Program gives up!\n", ExeOut); status = -1; break; default: /* defensive programming; code should never reached here */ printf ("Internal error occurred in program during SAVE!\n" "Please e-mail a bug report to pieguy@ecst.csuchico.edu\n"); return -1; } fclose (ExeInF); fclose (ExeOutF); if (status == 0) { printf ("%s has been successfully patched/unpatched.\n", ExeIn); return 0; } else { printf ("%s was NOT successfully patched/unpatched!\n", ExeIn); return -1; } } void prependext(char *exefilename) { char *c; c = strrchr(exefilename, '\\'); if (c == NULL) { c = strrchr(exefilename, ':'); if (c == NULL) c = exefilename; } c = strrchr(c, '.'); /* only append an extension if extension not already exists, including an empty extension */ if (c == NULL) { strcat(exefilename, ".exe"); } } int getInFile(char* ExeIn, FILE **ExeInF) { int status; do { if (*ExeInF != NULL) fclose(*ExeInF); printf ("\nEnter file to patch/unpatch: "); scanf ("%127s",ExeIn); prependext(ExeIn); if ((*ExeInF = fopen(ExeIn,"rb")) == NULL) { printf ("\nError opening %s for input!",ExeIn); status = -1; } else { printf ("\nFile successfully opened! Examining file...\n"); status = checkFileType(*ExeInF); switch (status) { case FF_Invalid: printf ("%s does not appear to be a valid CHIPS.EXE file!\n" "Proceed anyway (Y/N)? ", ExeIn); scanf ("%1s", YesNo); if (AnswerYes) { do { printf("\npatch or unpatch (P/U)? "); scanf ("%1s", YesNo); if (YesNo[0] == 'p' || YesNo[0] == 'P') return FF_Original; else if (YesNo[0] == 'u' || YesNo[0] == 'U') return FF_Patched1; else printf("please enter either p or u.\n"); } while (1); } else { status = -1; break; } case -FF_Original: printf ("%s looks similar to the original CHIPS.EXE file, but\n" "the filesize is larger!\n" "Proceed to patch anyway (Y/N)? ", ExeIn); scanf ("%1s", YesNo); if (AnswerYes) return FF_Original; else { status = -1; break; } case FF_Original: printf ("%s has been recognized as an original CHIPS.EXE file.\n" "Proceed to patch (Y/N)? ", ExeIn); scanf ("%1s", YesNo); if (AnswerYes) return FF_Original; else { status = 0; break; } case -FF_Patched1: printf ("%s looks similar to the pgchip-patched " "CHIPS.EXE file, but\n" "the filesize is larger!\n" "Proceed to unpatch anyway (Y/N)? ", ExeIn); scanf ("%1s", YesNo); if (AnswerYes) return FF_Patched1; else { status = -1; break; } case FF_Patched1: printf ("%s has been recognized as a " "pgchip-patched CHIPS.EXE file.\n" "Proceed to unpatch (revert back to original CHIPS.EXE) " "(Y/N)? ", ExeIn); scanf ("%1s", YesNo); if (AnswerYes) return FF_Patched1; else { status = 0; break; } default: /* defensive programming; code should never reached here */ printf ("unrecognized status code %d in function getInFile!\n" "Please e-mail a bug report to pieguy@ecst.csuchico.edu\n",status); return -1; } } printf ("\nTry a different file (Y/N)? "); scanf ("%1s",YesNo); if (AnswerYes) continue; else return status; } while (1); } int checkFileType(FILE *ExeInF) { int returnCode, i; long int len; int b, beforeaft; fseek(ExeInF, 0, SEEK_END); len = ftell(ExeInF); if (len < CHIPFILESIZE) return FF_Invalid; returnCode= (fileMatches(ExeInF, originaldata)&FF_Original)| (fileMatches(ExeInF, patch1data)&FF_Patched1); if (len > CHIPFILESIZE) return -returnCode; else return returnCode; } int fileMatches(FILE *ExeInF, unsigned const char *pattern){ //returns -1 if match, 0 otherwise long int pos=0; int b; unsigned char c; unsigned short int s; unsigned long int l; fseek(ExeInF, 0, SEEK_SET); while(1){ c=pattern[pos++]; if(c!=0xff){ b=fgetc(ExeInF); if(b==EOF || (unsigned char)b!=c) return 0; }else{ c=pattern[pos++]; if(c==0){ b=fgetc(ExeInF); if(b==EOF || (unsigned char)b!=0xff) return 0; }else if(c!=0xff){ if(fseek(ExeInF, c, SEEK_CUR)!=0) return 0; }else{ s=(pattern[pos]<<8)+pattern[pos+1]; pos+=2; if(s!=0xffff){ if(fseek(ExeInF, s, SEEK_CUR)!=0) return 0; }else{ l=(((((pattern[pos]<<8)+pattern[pos+1])<<8) +pattern[pos+2])<<8)+pattern[pos+3]; pos+=4; if(l!=0xffffffff){ if(fseek(ExeInF, l, SEEK_CUR)!=0) return 0; }else{ return -1; } } } } } } int getOutFile(char* filetypeString, char* ExeIn, char* ExeOut, FILE **ExeOutF){ do { int fileexist; printf("\nEnter pathname to save this %s CHIPS.EXE to: ", filetypeString, ExeIn); scanf("%127s", ExeOut); prependext(ExeOut); if (*ExeOutF != NULL) fclose(*ExeOutF); *ExeOutF = fopen(ExeOut,"rb"); fclose(*ExeOutF); fileexist = (*ExeOutF != NULL); if (fileexist) { printf("\nFile already exists! Overwrite (Y/N)? "); scanf("%1s", YesNo); if (!AnswerYes) { *ExeOutF = NULL; continue; } } else { if ((*ExeOutF = fopen(ExeOut,"ab")) == NULL) { printf("\nTrouble creating new file %s. " "You must try a different pathname.\n", ExeOut); continue; } } return fileexist; } while (1); } int patch(FILE *ExeInF, FILE *ExeOutF, unsigned const char *pattern) { int i, b; long int pos=0; unsigned char c; unsigned short int s; unsigned long int l; if (fseek(ExeInF, 0L, SEEK_SET) != 0) return -1; if (fseek(ExeOutF, 0L, SEEK_SET) != 0) return -1; /* first just copy the whole thing */ while ((b = fgetc(ExeInF)) != EOF) { b = fputc((char)b, ExeOutF); if (b == EOF) return -1; /* EOF on fputc means error */ } if (fseek(ExeOutF, 0L, SEEK_SET) != 0) return -1; /* now do the patches */ while(1){ c=pattern[pos++]; if(c!=0xff){ b=fputc(c, ExeOutF); if(b==EOF) return -1; }else{ c=pattern[pos++]; if(c==0){ b=fputc(0xff, ExeOutF); if(b==EOF) return -1; }else if(c!=0xff){ if(fseek(ExeOutF, c, SEEK_CUR)!=0) return -1; }else{ s=(pattern[pos]<<8)+pattern[pos+1]; pos+=2; if(s!=0xffff){ if(fseek(ExeOutF, s, SEEK_CUR)!=0) return -1; }else{ l=(((((pattern[pos]<<8)+pattern[pos+1])<<8) +pattern[pos+2])<<8)+pattern[pos+3]; pos+=4; if(l!=0xffffffff){ if(fseek(ExeOutF, l, SEEK_CUR)!=0) return -1; }else{ break; } } } } } return 0; } int getTmpFile(char *tmpFilename, FILE **ExeOutF) { FILE *tmpF = NULL; char *filenamepart; if ((filenamepart = strrchr(tmpFilename, '\\')) == NULL && (filenamepart = strrchr(tmpFilename, ':')) == NULL) filenamepart = tmpFilename; else filenamepart++; while (tmpCount < TMP_MAX) { tmpCount++; tmpnam(filenamepart); fclose(tmpF); if ((tmpF = fopen(tmpFilename, "rb")) != NULL) { continue; } else { if ((tmpF = fopen(tmpFilename, "wb")) == NULL) continue; else { *ExeOutF = tmpF; return 0; } } } return -1; }