多个checkbox,选中一部分当作密码。直接上注册机原码然后简单说下道理。
1 // ChechkBoxReverse.cpp : Defines the entry point for the console application. 2 // 3 4 #include "stdafx.h" 5 #include "windows.h" 6 7 DWORD getGroupSize(int All, int SelectItem);//组合数个数 8 void addToArry(char *p, char *Positions, char count); 9 void GetGroupMain(char *Group, char *Ppositions, int GroupMaxItem, int SelectItems, int CurrentPosition, int CurrentIdex);//组合集合数组,集合最大值,排列个数,集合默认从0开始 10 char checkID[] = { 0x16, 0x49, 0x5e, 0x15, 0x27, 0x26, 0x21, 0x25, 0x1d, 0x59, 0x53, 0x37, 0x31, 0x48, 0x5d, 0x0c, 0x61, 0x52, 0x4d }; 11 bool isFirst = true; 12 int _tmain(int argc, _TCHAR* argv[]) 13 { 14 DWORD CheckSum[20] = {0}; 15 int length = strlen(checkID); 16 for (int i = 0; i < length-1; i++) 17 { 18 CheckSum[i] = (DWORD)(checkID[i])*(i + 1)*checkID[i + 1]; 19 } 20 DWORD ResualtSum = 0xf35466 / 0x4d; 21 for (int i = 1; i <= 17; i++) 22 { 23 DWORD GroupCount = getGroupSize(17, i); 24 char *Group = (char *)malloc(i*GroupCount); 25 GetGroupMain(Group, NULL, 16, i, -1, 0); 26 27 /* 28 for (int j = 0; j < GroupCount; j++) 29 { 30 for (int k = 0; k < i; k++) 31 { 32 printf_s("%d ", *(char *)(j*i + k + Group)); 33 } 34 } 35 printf_s(" "); 36 int a = 1; 37 */ 38 39 for (int j = 0; j < GroupCount; j++) 40 { 41 DWORD tempSum = 0; 42 for (int k = 0; k < i; k++) 43 { 44 tempSum = tempSum + CheckSum[*(char *)(j*i + k +Group)]; 45 } 46 if (tempSum == ResualtSum) 47 { 48 int counts = 0; 49 for (int l = 0; l < i; l++) 50 { 51 printf_s("%d ", *(char *)(j*i + l + Group)); 52 } 53 printf_s("count=%d,index is ", i); 54 system("pause"); 55 return 0; 56 } 57 } 58 59 isFirst = true; 60 free(Group); 61 } 62 system("pause"); 63 return 0; 64 } 65 void GetGroupMain(char *Group,char *Ppositions ,int GroupMaxItem, int SelectItems,int CurrentPosition,int CurrentIdex)//组合集合数组,集合最大值,排列个数,集合默认从0开始 66 { 67 68 for (int i = CurrentPosition + 1; i <= GroupMaxItem-SelectItems+1+CurrentIdex; i++) 69 { 70 if (CurrentIdex == SelectItems - 1) 71 { 72 if (CurrentIdex == 0) 73 { 74 char a = i; 75 addToArry(Group, &a, SelectItems); 76 } 77 else 78 { 79 *(Ppositions + CurrentIdex) = i; 80 addToArry(Group, Ppositions, SelectItems); 81 } 82 } 83 else 84 { 85 char* PointPositions = (char*)malloc(CurrentIdex + 2); 86 if (CurrentIdex!=0) 87 memcpy(PointPositions, Ppositions, CurrentIdex); 88 *(PointPositions + CurrentIdex) = i; 89 GetGroupMain(Group, PointPositions, GroupMaxItem, SelectItems, i, CurrentIdex + 1); 90 } 91 } 92 free(Ppositions); 93 return; 94 } 95 96 char* CurrentOffset=0; 97 void addToArry(char *p, char *Positions,char count) 98 { 99 if (isFirst) 100 CurrentOffset = p; 101 isFirst = false; 102 for (int i = 0; i < count; i++) 103 { 104 char a = *(Positions + i); 105 *(CurrentOffset++) = a; 106 } 107 } 108 DWORD getGroupSize(int All, int SelectItem)//组合数个数 109 { 110 UINT64 sum = 1; 111 for (int i = All; i> All - SelectItem; i--) 112 { 113 sum = sum *i; 114 } 115 for (int i = SelectItem; i >= 1; i--) 116 { 117 sum = sum /i; 118 } 119 return sum; 120 }
每个checkbox都有一个ID对应,然后索引从0开始遍历,遇到选中的box择将他的ID乘下个box再乘下个的索引,一直到最后连加起来再将最后的和做一个简单运算,再与一个固定值比较,正确则完成。
那么通过逆向简单运算得到最后的和。再假设所有box被选中算出值,这个问题就变成了先这么多值中选出一些相加,看最后和是否等于一个值。
于是这个算法的主要部分在于怎么选出这几个值。于是我在GetGroupMain这个函数中列出了不同个数的所有可能索引取值,最后去试。主要思路就是这样。用了一个递归算法选和组合数公式。在free运用上要比较注意,指针在不停的传递,肯定有更好的办法,但是不细想了。