新手破解练习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
1~160每个破解过程,在吾爱破解论坛都有高手破解过了,也有整理好现成的, 我这边主要就是自己动手操作的过程,与他们的不太一样
附上高手们的连接: 点击前往查看
使用的工具连接(工具有点多有点大,可以先下OD,其它的后面慢慢下) 点击前往下载
新人入门教程"玩玩破解,写给新人看" 点击前往查看
我就是从这里开始的,对我这样的小白感觉超级友好~
下面是我的OD的界面布局,我觉得这4个是最常用的界面,其它的我基本上没用到~


浙公网安备 33010602011771号