Crack the AWave 4.0 - tips and source code // The original AWave 4.0 and this cracker has been put to // 166.111.72.98/incoming/scorn Cracking for AWave 4.0 ====================== The cracking for AWave 4.0 is very similar to 3.2. Just following changes: 1. file size has changed to be 0x83000 2. registration check code same as 3.2, just the code address changed: V3.2 => V4.0 408234 => 406708 408318 => 4068BC 3. the anti-crack code these codes has been slightly modified. first, the checksum var. (ds:[45B258]) is checked to be zero in somewhere to prevent change the init value (?). second, the checksum var has been registered into EDI in the check sum calculate code. the checksum of the image is same as V3.2, that is 0x3ADE68B1. The checksum value is at the file offset 0x2445 (0x22BF in V3.2). Both are not align to dword boundry. So the new checksum calculating procedure is different. (See source code AWCrack4.cpp for details). In order to not change the checksum init value in the DATA section, the one patch byte (to ensure the byte checksum of the image to be zero) has been moved to the zero-padding region (pad to multiple of page) of the CODE section. 4. after this patch crack, the AWave V4.0 is registered, but owned to nobody. In this way, choose the "Options/Program Setup..." will quit the program immediately. It is seemed like the V4.0 will check if the user name is empty or not. To walk around this problem, try this: 1). Install, patch, and run the AWave V3.2 2). Register the V3.2 using awave.key (you can change the user name because the program are already cracked, this step is just for write something into the registry database) 3). Install the AWave V4.0 and patch it. The registry are kept. another method is derectly change the registry database. in the HKEY_USERS\Default\Software\FMJ_Software\AWave: // goto awave section by searching "bAssFile" Usercode = "2729" // strings, can be anything Username = "Hacker" // strings, can be anything by NEM, 97/4/12 //==================================================================== // Cracker for AWave 4.0 // // complied by Turbo C++ // // by NEM, 97.4 //==================================================================== #include #include typedef unsigned char BYTE; typedef unsigned long DWORD; DWORD fsize = 0L; DWORD CalcCheckSum(FILE *fp) { DWORD checksum = 0L; fseek(fp, 0, SEEK_SET); for (long i = 0; i < (fsize >> 2); i++) { DWORD t; assert(fread(&t, 4, 1, fp) == 1); checksum ^= t; } return(checksum); } main(int argc, char *argv[]) { fprintf(stderr, "AWave 4.0 Cracker - by NEM, 1997\n\n"); char *fname = (argc == 1) ? "awave.exe" : argv[1]; FILE *fp = fopen(fname, "r+b"); assert(fp != NULL); fseek(fp, 0, SEEK_END); fsize = ftell(fp); fseek(fp, 0, SEEK_SET); assert(fsize == 0x83000L); // assert original checksum is valid DWORD CheckSum; fseek(fp, 0x2445L, SEEK_SET); assert(fread(&CheckSum, 4, 1, fp) == 1); assert(CheckSum == CalcCheckSum(fp)); fprintf(stderr, "CheckSum = %08lX\n", CheckSum); // patch it DWORD p; // patch function 4067D8, as per dword fseek(fp, 0x5EACL, SEEK_SET); assert(fread(&p, 4, 1, fp) == 1); assert(p == 0xEB01B004L); assert(fread(&p, 4, 1, fp) == 1); assert(p == 0x5FC38B02L); fseek(fp, 0x5EACL, SEEK_SET); p = 0xEB00B004L; assert(fwrite(&p, 4, 1, fp) == 1); p = 0x5FC03302L; assert(fwrite(&p, 4, 1, fp) == 1); // patch function 4068BC, as per dword fseek(fp, 0x5F90L, SEEK_SET); assert(fread(&p, 4, 1, fp) == 1); assert(p == 0xEBC03304L); assert(fread(&p, 4, 1, fp) == 1); assert(p == 0xC3BE0F0AL); fseek(fp, 0x5F90L, SEEK_SET); p = 0xEB01B004L; assert(fwrite(&p, 4, 1, fp) == 1); p = 0x90C0330AL; assert(fwrite(&p, 4, 1, fp) == 1); // recalculate checksum fseek(fp, 0x2445L, SEEK_SET); CheckSum = 0L; assert(fwrite(&CheckSum, 4, 1, fp) == 1); CheckSum = CalcCheckSum(fp); BYTE b, *bp0, *bp1; bp1 = (BYTE *)(&CheckSum); b = bp1[0] ^ bp1[1] ^ bp1[2] ^ bp1[3]; fseek(fp, 0x5A300L, SEEK_SET); assert(fwrite(&b, 1, 1, fp) == 1); CheckSum = CalcCheckSum(fp); DWORD NewCheckSum; bp0 = ((BYTE *)&CheckSum); bp1 = ((BYTE *)&NewCheckSum); bp1[0] = bp0[0]; bp1[1] = bp0[1] ^ bp1[0]; bp1[2] = bp0[2] ^ bp1[1]; bp1[3] = bp0[3] ^ bp1[2]; // should be 0 assert(bp1[3] == 0); fseek(fp, 0x2445L, SEEK_SET); assert(fwrite(&NewCheckSum, 4, 1, fp) == 1); assert(NewCheckSum == CalcCheckSum(fp)); fclose(fp); return(0); }