新手破解练习Crackme160之112 - CrackMe
-
脱壳
这个程序也是有UPD壳, 用UPD Unpacker可以脱壳成功~ 运行后作者弹框提示不能修改原文件, 不能脱壳~, 文件名也不能改变_, 所以我们先将原文件备份一个, 下面就直接对原文件操作, 不改名, 并保证文件大小不变~ 直接用UE结合VB Decompiler来破解~
-
正常破解
这个程序做法很新颖, 前面那些都没有遇到过的, 不让脱壳, 看代码无从下手~ OD载入程序后, 发现全是乱码形式的, 所以我们先用VB Decompiler先分析脱壳后的程序, 发现是P-Code模式的, 果然OD没办法玩了~
Form_Load事件中看到调用了很多子程序
Private Sub Form_Load() '404420
'Data Table: 4030F8
loc_4043FC: Proc_1_5_404640() ' 是否有NMSCMW50这个窗体程序在运行, 应该是什么破解工具吧, 我电脑中没有
loc_404401: Proc_1_8_404C24() ' 判断文件名是否为CrackMe.exe, 不区分大小写, 文件大小是否为0x3A00(14848字节)
loc_404406: Proc_1_6_404A48() ' 判断电脑系统目录下是否有w32dasm8.ini, 这个我电脑有, 第一个弹框是这个
loc_40440B: Proc_1_4_404580() ' 是否有RegmonClass这个程序正在运行, 应该也是破解工具吧, 我也没有
loc_404410: Proc_1_3_404810() ' 验证注册表中是否有IDA软件注册项, 我用的绿色版没这个项
loc_404415: Proc_1_8_404C24() ' 又一次验证文件名和大小
loc_40441A: Proc_1_2_405180() ' 生成一个机器码显示在界面上
loc_40441F: Exit Sub
End Sub
我们直接运行原文件, 正常会被弹框提示错误~ 因为我们正在破解它, 对比弹框信息找到对方的方法, 把里面的if判断条件改为相反的即可, 前面的破文有过p-code模式下的破解方法, 即是将if条件改为 if not, 代码中的1C改为1D, 下面以我电脑为例举例操作一下:
第一个弹框是Proc_1_6_404A48(),
Private Sub Proc_1_6_404A48
'Data Table: 402C8C
loc_404979: Me(4) = CStr(Space(&HFF))
loc_4049A9: Me(8) = GetWindowsDirectory(Me(4), &HFF)
loc_4049CC: Me(4) = CStr(Left(Me(4), Me(8)))
loc_4049EB: Me(0) = Dir(CVar(Me(4) & "\w32dasm8.ini"), 6)
loc_4049FE: If (Me(0) <> vbNullString) Then '条件在这里
loc_404A1A: MsgBox("W32Dasm detected! Please uninstall this Cracking Program!", 0, var_CC, var_EC, var_10C)
loc_404A3A: Me.Global.Unload MemVar_406008
loc_404A42: End
loc_404A44: End If
loc_404A44: Exit Sub
End Sub
VB Decompiler切换到HEX Editor面板中查看16进制代码对应的为: FB 3D 1C DC, UE中搜索原文件这行代码在000015d0h这位置附近, 我们把1C改为1D保存, 重新执行程序便可跳过验证~, 如果还有别的弹框可以同理操作, 我电脑只有这个弹框, 运行后直接来到主界面了~
按钮事件中作者又把上面的验证来一遍~ 并多了一个验证loc_404469: Proc_1_7_404720(), 是否有winice.exe, 如果你有的话, 用上面同样的方式跳过验证~, 最后一个方法loc_40446E: Proc_1_1_404EAC() 才是真正的算法验证处, 输入不能为空, 不能小于8位, 再来到Proc_1_0_405730()这个方法继续验证,
Private Sub Proc_1_0_405730
'Data Table: 402C8C
Dim var_D0 As Integer
Dim var_E4 As Variant
Dim var_88 As TextBox
loc_4051E4: Set var_88 = MemVar_406008.Text4
loc_40520C: Me(68) = Replace(frmMain.Text4.Text, "-", vbNullString, 1, -1, 0) ' 将机器码中的减号都去掉
loc_40521C: Me(76) = CStr(0)
loc_405230: For var_90 = 1 To CInt(Len(Me(68))): Me(96) = var_90 'Integer ' 循环将机器码每一位加起来
loc_405257: Me(72) = CStr(Mid(Me(68), CLng(Me(96)), 1))
loc_405279: Me(76) = CStr((CDbl(Asc(Me(72))) + CDbl(Me(76))))
loc_405284: Next var_90 'Integer
loc_40528D: Me(80) = CStr(0)
loc_4052A6: Set var_88 = MemVar_406008.Text1
loc_4052BC: For var_D4 = 1 To CInt(Len(frmMain.Text1.Text)): Me(98) = var_D4 'Integer ' 循环将名称每一位加起来
loc_4052CE: Set var_88 = MemVar_406008.Text1
loc_4052F6: Me(84) = CStr(Mid(CVar(frmMain.Text1.Text), CLng(Me(98)), 1))
loc_40531D: Me(80) = CStr((CDbl(Asc(Me(84))) + CDbl(Me(80))))
loc_405328: Next var_D4 'Integer
loc_405331: Me(88) = CStr(0)
loc_40534A: Set var_88 = MemVar_406008.Text2
loc_405360: For var_E8 = 1 To CInt(Len(frmMain.Text2.Text)): Me(100) = var_E8 'Integer ' 循环将公司每一位加起来
loc_405372: Set var_88 = MemVar_406008.Text2
loc_40539A: Me(92) = CStr(Mid(CVar(frmMain.Text2.Text), CLng(Me(100)), 1))
loc_4053C1: Me(88) = CStr((CDbl(Asc(Me(92))) + CDbl(Me(88))))
loc_4053CC: Next var_E8 'Integer
loc_4053DD: Set var_88 = MemVar_406008.Text1
loc_405424: Me(104) = CStr(Mid(CVar(Replace(frmMain.Text1.Text, " ", vbNullString, 1, -1, 0)), 4, 2)) ' 去空格
loc_405449: Set var_88 = MemVar_406008.Text2
loc_405490: Me(108) = CStr(Mid(CVar(Replace(frmMain.Text2.Text, " ", vbNullString, 1, -1, 0)), 5, 3))
loc_4054B5: Set var_88 = MemVar_406008.Text4
loc_4054FC: Me(112) = CStr(Mid(CVar(Replace(frmMain.Text4.Text, " ", vbNullString, 1, -1, 0)), 5, 3))
loc_405521: Set var_88 = MemVar_406008.Text3
loc_40552F: var_E4 = CVar(frmMain.Text3.Text) 'String
loc_40558C: var_D0 = Ucase(CVar("34" & Me(112) & "-" & Me(76) & StrReverse(Me(80)) & "-" & Me(108) & Me(88) & "-" & Me(104))) ' 组装新串
loc_4055B7: If CBool(var_E4 <> var_D0) Then ' 对比
loc_4055D3: MsgBox("Incorrect Serial Number!", 0, var_D0, var_E4, var_11C)
loc_4055EF: Set var_88 = MemVar_406008.Text1
loc_4055F5: frmMain.Text1.Text = vbNullString
loc_405609: Set var_88 = MemVar_406008.Text2
loc_40560F: frmMain.Text2.Text = vbNullString
loc_405623: Set var_88 = MemVar_406008.Text3
loc_405629: frmMain.Text3.Text = vbNullString
loc_405631: Exit Sub
loc_405632: GoTo loc_40572F
loc_405635: End If
loc_405646: .Visible =
loc_405659: Set var_88 = MemVar_406008.Text2
loc_40565F: frmMain.Text2.Visible = False
loc_405672: Set var_88 = MemVar_406008.Text3
loc_405678: frmMain.Text3.Visible = False
loc_40568B: Set var_88 = MemVar_406008.Text4
loc_405691: frmMain.Text4.Visible = False
loc_4056A4: Set var_88 = MemVar_406008.Label1
loc_4056AA: frmMain.Label1.Visible = False
loc_4056BD: Set var_88 = MemVar_406008.Label2
loc_4056C3: frmMain.Label2.Visible = False
loc_4056D6: Set var_88 = MemVar_406008.Label3
loc_4056DC: frmMain.Label3.Visible = False
loc_4056EF: Set var_88 = MemVar_406008.Label4
loc_4056F5: frmMain.Label4.Visible = False
loc_405708: Set var_88 = MemVar_406008.cmdCheck
loc_40570E: frmMain.cmdCheck.Visible = False
loc_405721: Set var_88 = MemVar_406008.Label5
loc_405727: frmMain.Label5.Visible = True
loc_40572F: ' Referenced from: 405632
loc_40572F: Exit Sub
End Sub
分析完代码, 算法就明朗了~ 下面开始写注册机~ keygen.c
#include <stdio.h>
#include <string.h>
void myreplace(char *str, char *oldstr, char *newstr){
int len = strlen(str);
int i=0,j=0;
for(i=0; i<len; i++){
if(str[i] != oldstr[0]) continue;
if(newstr != "") str[i] = newstr[0];
else {
for(j=i; j<len-1; j++) str[j] = str[j+1];
str[j] = '\0';
len--;
}
}
return;
}
int main() {
char name[21] = {0}; //用户名
char comp[21] = {0}; //公司名
char sysc[21] = {0}; //机器码
char code[61] = {0}; //系列号
int lenn,lenc,lens;
int namev=0, compv=0, syscv=0;
int in=0;
char a;
unsigned int eax = 0xFFFFFF00;
printf("请输入用户名(8位以上): ");
in = 0; while((a=getchar()) != '\n') name[in++] = a;
printf("请输入公司名(8位以上): ");
in = 0; while((a=getchar()) != '\n') comp[in++] = a;
printf("请输入机器码: ");
in = 0; while((a=getchar()) != '\n') sysc[in++] = a;
lenn = strlen(name);
lenc = strlen(comp);
lens = strlen(sysc);
int ci = 0;
//34
code[ci++] = '3';
code[ci++] = '4';
//Me(112)
for(int i=0; i<lens; i++){
if(sysc[i] == '-') continue;
syscv += sysc[i];
}
lenc = strlen(sysc);
myreplace(sysc, (char*)" ", (char*)"");
code[ci++] = sysc[4];
code[ci++] = sysc[5];
code[ci++] = sysc[6];
//Me(76)
code[ci++] = '-';
char syscStr[20];
sprintf(syscStr, "%d", syscv); //转字符串
lens = strlen(syscStr);
for(int i=0; i<lens; i++){
code[ci++] = (char)syscStr[i];
}
//StrReverse(Me(80))
for(int i=0; i<lenn; i++){
namev += name[i];
}
char nameStr[20];
sprintf(nameStr, "%d", namev);
lens = strlen(nameStr);
for(int i=lens-1; i>=0; i--){ //这个是倒序
code[ci++] = (char)nameStr[i];
}
//Me(108)
code[ci++] = '-';
for(int i=0; i<lenc; i++){
compv += comp[i];
}
myreplace(comp, (char*)" ", (char*)"");
code[ci++] = comp[4];
code[ci++] = comp[5];
code[ci++] = comp[6];
//Me(88)
char compStr[20];
sprintf(compStr, "%d", compv);
lenc = strlen(compStr);
for(int i=0; i<lenc; i++){
code[ci++] = (char)compStr[i];
}
//Me(104)
code[ci++] = '-';
myreplace(name, (char*)" ", (char*)"");
code[ci++] = name[3] < 96 ? name[3] : (name[3] - 32); //转大写
code[ci++] = name[4] < 96 ? name[4] : (name[4] - 32); //转大写
printf("注册码为: %s\n", code);
getchar();getchar();
return 0;
}
输入验证后出现了个异常, 提示路径/文件访问错误~ , 说明新加的那个验证需要访问文件~ 经核对是我电脑C盘锁了, 没有读写权限~ 放到虚拟机验证成功~
上面注册机运行示例:
请输入用户名(8位以上): abcabcabc
请输入公司名(8位以上): 123123123
请输入机器码: F54-E071B513-052
注册码为: 34E07-766288-231450-AB
请输入用户名(8位以上): abc abc abc
请输入公司名(8位以上): 123 123 123
请输入机器码: F54-E071B513-052
注册码为: 34E07-766649-231514-AB
用VB写更简单些, 大部分可以直接复制VB Decompiler中的代码: keygen.vbs
name = inputbox("请输入用户名")
company = inputbox("请输入公司名")
unique = inputbox("请输入机器码")
s1 = Replace(unique, "-", vbNullString, 1, -1, vbBinaryCompare)
ss1 = 0
For i = 1 To Len(s1)
ss1 = ss1 + Asc(Mid(s1, i, 1))
Next
ss2 = 0
For i = 1 To Len(name)
ss2 = ss2 + Asc(Mid(name, i, 1))
Next
ss3 = 0
For i = 1 To Len(company)
ss3 = ss3 + Asc(Mid(company, i, 1))
Next
s3 = Replace(name, " ", vbNullString, 1, -1, vbBinaryCompare)
s4 = Mid(s3, 4, 2)
s5 = Replace(company, " ", vbNullString, 1, -1, vbBinaryCompare)
s6 = Mid(s5, 5, 3)
s7 = Replace(unique, " ", vbNullString, 1, -1, vbBinaryCompare)
s8 = Mid(s7, 5, 3)
getSerial = UCase("34" & s8 & "-" & CStr(ss1) & StrReverse(ss2) & "-" & s6 & ss3 & "-" & s4)
msgbox "机器码: "&unique&chr(13)&chr(10)&"用户名: "&name&chr(13)&chr(10)&"公司名: "&company&chr(13)&chr(10)&"序列号: "&getSerial,0,"注册机"
1~160每个破解过程,在吾爱破解论坛都有高手破解过了,也有整理好现成的, 我这边主要就是自己动手操作的过程,与他们的不太一样
附上高手们的连接: 点击前往查看
使用的工具连接(工具有点多有点大,可以先下OD,其它的后面慢慢下) 点击前往下载
新人入门教程"玩玩破解,写给新人看" 点击前往查看
我就是从这里开始的,对我这样的小白感觉超级友好~
下面是我的OD的界面布局,我觉得这4个是最常用的界面,其它的我基本上没用到~