新手破解练习Crackme160之124 - noos.3

这个程序是VB写的p-code模式编译的, 基本上就不能在OD中调试破解了~ 我们直接用VB Decompiler来看源码,

Private Sub Proc_1_0_41FB38
  'Data Table: 41D4B0
  Dim var_AC As Long
  Dim var_A8 As Long
  Dim var_B4 As Double
  loc_41F475: ReDim var_E8(0 To &H3D)
  loc_41F48C: var_E8(0) = "0"
  loc_41F49B: var_E8(1) = "1"
  loc_41F4AA: var_E8(2) = "2"
  loc_41F4B9: var_E8(3) = "3"
  loc_41F4C8: var_E8(4) = "4"
  loc_41F4D7: var_E8(5) = "5"
  loc_41F4E6: var_E8(6) = "6"
  loc_41F4F5: var_E8(7) = "7"
  loc_41F504: var_E8(8) = "8"
  loc_41F513: var_E8(9) = "9"
  loc_41F522: var_E8(&HA) = "A"
  loc_41F531: var_E8(&HB) = "B"
  loc_41F540: var_E8(&HC) = "C"
  loc_41F54F: var_E8(&HD) = "D"
  loc_41F55E: var_E8(&HE) = "E"
  loc_41F56D: var_E8(&HF) = "F"
  loc_41F57C: var_E8(&H10) = "G"
  loc_41F58B: var_E8(&H11) = "H"
  loc_41F59A: var_E8(&H12) = "I"
  loc_41F5A9: var_E8(&H13) = "J"
  loc_41F5B8: var_E8(&H14) = "K"
  loc_41F5C7: var_E8(&H15) = "L"
  loc_41F5D6: var_E8(&H16) = "M"
  loc_41F5E5: var_E8(&H17) = "N"
  loc_41F5F4: var_E8(&H18) = "O"
  loc_41F603: var_E8(&H19) = "P"
  loc_41F612: var_E8(&H1A) = "Q"
  loc_41F621: var_E8(&H1B) = "R"
  loc_41F630: var_E8(&H1C) = "S"
  loc_41F63F: var_E8(&H1D) = "T"
  loc_41F64E: var_E8(&H1E) = "U"
  loc_41F65D: var_E8(&H1F) = "V"
  loc_41F66C: var_E8(&H20) = "W"
  loc_41F67B: var_E8(&H21) = "X"
  loc_41F68A: var_E8(&H22) = "Y"
  loc_41F699: var_E8(&H23) = "Z"
  loc_41F6A8: var_E8(&H24) = "a"
  loc_41F6B7: var_E8(&H25) = "b"
  loc_41F6C6: var_E8(&H26) = "c"
  loc_41F6D5: var_E8(&H27) = "d"
  loc_41F6E4: var_E8(&H28) = "e"
  loc_41F6F3: var_E8(&H29) = "f"
  loc_41F702: var_E8(&H2A) = "g"
  loc_41F711: var_E8(&H2B) = "h"
  loc_41F720: var_E8(&H2C) = "i"
  loc_41F72F: var_E8(&H2D) = "j"
  loc_41F73E: var_E8(&H2E) = "k"
  loc_41F74D: var_E8(&H2F) = "l"
  loc_41F75C: var_E8(&H30) = "m"
  loc_41F76B: var_E8(&H31) = "n"
  loc_41F77A: var_E8(&H32) = "o"
  loc_41F789: var_E8(&H33) = "p"
  loc_41F798: var_E8(&H34) = "q"
  loc_41F7A7: var_E8(&H35) = "r"
  loc_41F7B6: var_E8(&H36) = "s"
  loc_41F7C5: var_E8(&H37) = "t"
  loc_41F7D4: var_E8(&H38) = "u"
  loc_41F7E3: var_E8(&H39) = "v"
  loc_41F7F2: var_E8(&H3A) = "w"
  loc_41F801: var_E8(&H3B) = "x"
  loc_41F810: var_E8(&H3C) = "y"
  loc_41F81F: var_E8(&H3D) = "z"
  loc_41F833: var_98 = Array(var_E8) 'Variant
  loc_41F83A: var_9C = vbNullString
  loc_41F842: var_AC = &H18
  loc_41F84A: var_A8 = &H1C
  loc_41F85A: For var_4E0 = 0 To 9: var_A4 = var_4E0 'Long
  loc_41F875:   var_CC(var_A4) = CVar(((var_A4 * var_A4) * var_A4))
  loc_41F88D:   var_CC(var_A4) = (var_CC(var_A4) + 23)
  loc_41F894: Next var_4E0 'Long
  loc_41F8A6: For var_4E8 = &HA To &H23: var_A4 = var_4E8 'Long
  loc_41F8C7:   var_B4 = CDbl((var_A8 * 2) Xor CLng(Asc("MTV")))
  loc_41F8E1:   var_CC(var_A4) = CVar(((var_B4 + CDbl(5)) + CDbl(5)))
  loc_41F8EB:   var_A8 = (var_A8 + 1)
  loc_41F8F1: Next var_4E8 'Long
  loc_41F903: For var_4F0 = &H24 To &H3D: var_A4 = var_4F0 'Long
  loc_41F924:   var_B4 = CDbl((var_AC * 2) Xor CLng(Asc("TMF")))
  loc_41F93E:   var_CC(var_A4) = CVar(((var_B4 + CDbl(&H3E)) + CDbl(&H3E)))
  loc_41F948:   var_AC = (var_AC + 1)
  loc_41F94E: Next var_4F0 'Long
  loc_41F95F: Set var_4F4 = MemVar_420008.txtCode
  loc_41F976: var_9E = CByte((Len(Main.txtCode.Text) + 1)) 'Byte
  loc_41F992: For var_4FC = CByte(1) To CByte((CInt(var_9E) - 1)): var_A0 = var_4FC 'Byte
  loc_41F9A4:   Set var_4F4 = MemVar_420008.txtCode
  loc_41F9D2:   var_E4(CLng(var_A0)) = Mid(CVar(Main.txtCode.Text), CLng(var_A0), 1)
  loc_41F9E2: Next var_4FC 'Byte
  loc_41FA01: For var_524 = 1 To CLng((CInt(var_9E) - 1)): var_A8 = var_524 'Long
  loc_41FA14:   For var_52C = 0 To &H3D: var_A4 = var_52C 'Long
  loc_41FA37:     If (var_E4(var_A8) = var_98(var_A4)) Then
  loc_41FA4D:       var_88 = CStr((CVar(CStr(0)) + var_CC(var_A4)))
  loc_41FA5F:       var_88 = CStr((CDbl(var_88) * CDbl(var_A8)))
  loc_41FA62:     End If
  loc_41FA65:   Next var_52C 'Long
  loc_41FA6D: Next var_524 'Long
  loc_41FA81: If (CDbl(var_88) = &H2309A2E62AFA8) Then
  loc_41FA87:   Me(16) = "Thank you for registering"
  loc_41FACC:   Me(20) = CLng((Mid(var_88, 8, 1) + Mid(var_88, 1, 1)))
  loc_41FB1E:   Me(24) = CLng((Mid(var_88, &HD, 1) + Mid(var_88, 5, 1)))
  loc_41FB30: End If
  loc_41FB30: Unknown_41F430()
  loc_41FB35: Exit Sub
End Sub

这个是算法关键部分, 需要暴破的话, 将loc_41FA81这行的if 改为 if not 即可(切换到HEX Editor, 跳转到地址:41FA81, 将1C改为1D, 保存), 这样暴破完只能变成黄灯, 因为要变绿灯还需要验证正确的注册码(loc_41FACC ~ loc_41FB1E)
上面代码翻译回来是:

#include <stdio.h>
#include <string.h>

char* cstr(long v);
long clng(char *str);

int main() {
	char *code = "123456";
	char *var_E8 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
	char *var_88 = "";
	int var_AC = 0x18, var_A8 = 0x1C;
	unsigned int var_CC[62] = {0}; 
	int len = strlen(code);
	int len1 = len + 1;
	
	for(int i=0; i<=9; i++){
		var_CC[i] = i * i * i + 23;
	}
	for(int i=0xA; i<=0x23; i++){
		var_CC[i] = ((var_A8 * 2) ^ 'M') + 5;
	}
	for(int i=0x24; i<=0x3D; i++){
		var_CC[i] = ((var_AC * 2) ^ 'T') + 0x3E;
	}
	for(int i=0; i<len; i++){
		for(int j=0; j<=0x3D; j++){
			if(code[i] == var_E8[j]){
				var_88 = cstr((clng((char *)var_88) + var_CC[j]) * i);
			}
		}
	}
	
	if(var_88 == "616388714737576"){
		//成功 
	}
	
	getchar();getchar();
	return 0;
}

char* cstr(long v){
	char str[20] = {0};
	char rlt[20] = {0};
	int len = 0;
	while(v > 0){
		str[len] = v % 10;
		v /= 10;
		len++;
	}
	for(int i=len-1; i>=0; i--){
		rlt[len - 1 - i] = str[i];
	}
	return rlt;
}

long clng(char *str){
	long rlt = 0;
	int len = strlen(str);
	for(int i=0; i<len; i++){
		rlt *= 10;
		rlt += str[len-1-i] - 0x30;
	}
	return rlt;
}

其中var_CC的值是固定的, 我们可以先计算出来

unsigned int var_CC[] = {
23, 24, 31, 50, 87, 148, 239, 366, 535, 752, //// 前10个数字,由 (i * i * i + 23) 生成
122, 68, 176, 392, 984, 1912, 3640, 7352, 14776, 29624, 59320, 118712, 237496, 475064, 950200, 1900472,
3801016, 7602104, 15204280, 30408632, 60817336, 121634744, 243269560, 486539192, 973078456, 1946156984, //// 中间26个数字
162, 116, 208, 536, 904, 1704, 3176, 6376, 12776, 25576, 51176, 102376, 204776, 409576, 819176, 1638376,
3276776, 6553576, 13107176, 26214376, 52428776, 104857576, 209715176, 419430376, 838860776, 1677721576 //// 最后26个数字
};

结果必须是616, 388, 714, 737, 576才算成功, 算法还是很好理解的, 就是将输入的每一位值+后一位值再乘以位数, 所以我们需要把这个值因式分解一下, 其中一个值必然是位数:
616388714737576 = 2 * 2 * 2 * 11 * 1019 * 6873814733, 由这个可以看出, 位数有可能是8位或11位, 我们分别尝试一下, 都用最大值z对应的值1677721576,
8位: ((((((((0+1946156984)1 + 1946156984)2 + 1946156984)3 + ... + 1946156984)8 = 213,298,805,446,400 (计算器直接算出来), 这个比结果小, 不行, 所以只能是11位了
11位: (((((((((((0+1677721576)1 + 1677721576)2 + 1677721576)3 + ... + 1677721576)11 = 1.82E+17 (计算器直接算出来) 这个符合要求
现在我们已经确定了是11位, 那我们开始倒过来算, (优先使用最大值z, 将大数快速转为小数)
第11位: z(1677721576) => 616388714737576 / 11 - 1677721576 = 56,033,659,981,840
第10位: z(1677721576) => 56,033,659,981,840 / 10 - 1677721576 = 5,601,688,276,608
第09位: z(1677721576) => 5,601,688,276,608 / 9 - 1677721576 = 620,732,086,936
第08位: z(1677721576) => 620,732,086,936 / 8 - 1677721576 = 75,913,789,291
第07位: z(1677721576) => 75,913,789,291 / 7 - 1677721576 = ? 这里除以7除不尽了, 说明上一位(08)不能是z, 回退
620,732,086,936 = 8 * 77,591,510,867, 77,591,510,867这个数 减掉一个值后需要被 7整除, 所以, 我们mod 7一下得 3, var_CC中没有3, 所以只能是3+7x, [24,31,87,535,752, 122, 1704]符号
第08位: f(1704) => 620,732,086,936 / 8 - 1704 = 77,591,509,163
第07位: 6(239) => 77,591,509,163 / 7 - 239 = 11,084,501,070 (/7, %6=5, 5+6x, [23, 239]符合)
第06位: W(243269560) => 11,084,501,070 / 6 - 243269560 = 1,604,147,285(/6, %5=0, 5x, [50,535,3640,59320,950200,15204280,243269560] 符合)
第05位: a(162) => 1,604,147,285 / 5 - 162 = 369,483,216 (/5, %4=1, 没有符合) 所以本次尝试不对, , 第8位可以继续换, 最终是会成功的, , 按这思路, 可以用递归写出所有尝试~

注册机代码(直接复制了大佬的)

 #include <iostream>
 #include <string.h>
 #include <time.h>
 
unsigned long long base[] = {
        23, 24, 31, 50, 87, 148, 239, 366, 535, 752,     //CrackMe中生成前10个数字,由  (i * i * i + 23) 生成
 
        122,  68, 176, 392, 984, 1912, 3640, 7352, 14776, 29624, 59320, 118712, 237496, 475064, 950200, 1900472, 
        3801016, 7602104, 15204280, 30408632, 60817336, 121634744, 243269560, 486539192, 973078456, 1946156984,  //// 中间26个数字
 
        162, 116, 208, 536, 904, 1704, 3176, 6376, 12776, 25576, 51176, 102376, 204776, 409576, 819176, 1638376,
        3276776, 6553576, 13107176, 26214376, 52428776, 104857576, 209715176, 419430376, 838860776, 1677721576    //// 最后26个数字
    };
 
char sn_str[] = "0123456789ABCDEDGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
 
//char sn_ok[22] = {'-'};
 char sn_ok[] = "----------------------";
 int sn_bit[22] = {0};
 
int testSN(unsigned long long sn, int bit);
 int main(int argc, char** argv) {
         
        //unsigned long long sn = 4330972930LL;//616388714737576LL;
        unsigned long long sn_result = 616388714737576LL;
         
        sn_ok[21] = '\0';
 
        int n=0;
        /// unlock code 最多20个字符,先取得与sn_result能整除几个索引值(也就是长度值) 
        for(int i=20; i>1; i--) {
                if((sn_result % i) == 0) {
                        sn_bit[n++] = i;
                }
        }
      
        /* 
        // 616388714737576 = 2 * 2 * 2 * 11 * 1019 * 6873814733
        // 可能是8位或11位 
         */
        for(int i=0; i<n; i++) {
                printf("n(%d) = %d\n", i, sn_bit[i]);
        }
         
        time_t timep;
        time (&timep);
        printf("\nStart time: %s\n", ctime(&timep));
 
        if(n>2) {
                n = 2;/// 只测试 11位,8位unlockcode 
        }
        for(int i=0; i<n; i++) {
                sn_ok[sn_bit[i]] = '\0';
                printf("\ntest bits = %d\n", sn_bit[i]);
                int b = testSN(sn_result, sn_bit[i]);
                if(b == 1) {
                        printf("\nUnlock Code: %s\n", sn_ok);
                        break;
                }
        }
        time (&timep);
        printf("\nEnd time: %s", ctime(&timep));
 
        //system("pause");
         
        return 0;
 }
 
int count = 0;
 
int testSN(unsigned long long sn, int bit) {
        sn  = sn / bit;
        bit = bit - 1;
        for(int j=61; j>=0; j--) {
                unsigned long long sn1 = sn - base[j];
                if(sn1<0) {
                        continue;
                }
                if((bit==0)) {
                        if((sn1==0)) {
                                sn_ok[bit] = sn_str[j];
                                printf("sn_ok = %s\n", &sn_ok[bit]);
                                return 0;
                        } else {
                                continue;
                        } 
                }
                if((sn1 % bit) == 0) {
                        sn_ok[bit] = sn_str[j];
                        //printf("bit=%d, sn_part = %s\n", bit+1, sn_ok);
                        int b = testSN(sn1, bit);
                        if(b==1) {
                                //printf("\nSN_OK: %s\n", sn_ok);
                                return 1;
                        } else {
                                sn_ok[bit] = '-';
                        }
                }
        }
         
        return 0;
 }

示例:
sn_ok = LSgbo3t8zzz
sn_ok = SLgbo3t8zzz
sn_ok = LSgmd3t8zzz
sn_ok = SLgmd3t8zzz
sn_ok = LS9mJ3t8zzz
sn_ok = SL9mJ3t8zzz
sn_ok = ASmNf3r8zzz
sn_ok = SAmNf3r8zzz
sn_ok = Skf5q3p8zzz
sn_ok = kSf5q3p8zzz
sn_ok = LSgbp3p8zzz
sn_ok = SLgbp3p8zzz
sn_ok = LSgnd3p8zzz
sn_ok = SLgnd3p8zzz
sn_ok = JdTOd3p8zzz
sn_ok = dJTOd3p8zzz
sn_ok = SdKOd3p8zzz

 
 
 
这是160个软件part1
这是160个软件part2

1~160每个破解过程,在吾爱破解论坛都有高手破解过了,也有整理好现成的, 我这边主要就是自己动手操作的过程,与他们的不太一样
附上高手们的连接: 点击前往查看
使用的工具连接(工具有点多有点大,可以先下OD,其它的后面慢慢下) 点击前往下载

新人入门教程"玩玩破解,写给新人看" 点击前往查看
我就是从这里开始的,对我这样的小白感觉超级友好~

下面是我的OD的界面布局,我觉得这4个是最常用的界面,其它的我基本上没用到~
OD界面布局

posted @ 2024-07-29 15:19  hankerstudio  阅读(9)  评论(0)    收藏  举报