这个程序是XXX报表数据管理系统(行业软件),程序是Delphi编的,没加壳。OK,用DEDE反编译,找到SoftRegister.pas的文件(这是个注册窗体文件),找到
*
Possible String Reference to: '祝贺'
|
0065210B B924246500
mov ecx, $00652424
*
Possible String Reference to: '您已经完成了XX报表的注册,您可以....(不写了)
00652110 BA2C246500
mov edx, $0065242C
*
Reference to TApplication instance
|
00652115 A1B8896D00
mov eax, dword ptr [$006D89B8]
0065211A
8B00 mov
eax, [eax]
*
Reference to : TApplication._PROC_00457374()
|
0065211C E85352E0FF
call 00457374
00652121
8B45FC mov
eax, [ebp-$04]
*
Reference to field TSoftRegisterform.OFFS_0234
|
00652124 C7803402000001000000
mov dword ptr [eax+$0234], $00000001
0065212E EB29
jmp
00652159
00652130 6A30
push $30 (查找这一句是从哪里跳来的,害我这么苦)
*
Possible String Reference to: '警告'
|
00652132 B9CC216500
mov ecx, $006521CC
*
Possible String Reference to: '软件注册码错误!您可以...(不写了)
00652137 BA60246500
mov edx, $00652460
*
Reference to TApplication instance
|
0065213C A1B8896D00
mov eax, dword ptr [$006D89B8]
00652141
8B00 mov
eax, [eax]
*
Reference to : TApplication._PROC_00457374()
|
00652143 E82C52E0FF
call 00457374
经查是从00651FDD跳来的,
00651FD5 5A pop edx
*
Reference to: Unit_00484DE4.Proc_00485348
|
00651FD6 E86D33E3FF
call 00485348
00651FDB
84C0 test
al, al
00651FDD 0F844D010000
jz 00652130
好了,让我们打开调试软件装入(我用的是ollyDbg,我只会用滚动条拉动设断点,哪位大侠有直接打入地址的方法请告诉我),在00651FD5处设断
当按下注册按纽时中断,按F8跳过00651FD6这个call时al变成了0,哈哈就是这个call,重装入,F7进入这个call,
00485348
/$ 53 PUSH EBX
00485349
|. 56 PUSH ESI
0048534A
|. 57 PUSH EDI
0048534B
|. 8BF9 MOV EDI,ECX
0048534D
|. 8BF2 MOV ESI,EDX
0048534F
|. 8BD8 MOV EBX,EAX
00485351
|. 33C0 XOR EAX,EAX
00485353
|. E8 20050000 CALL REPORT.00485878 算机器码(每台电脑都不同,算法不研究,反正软件里有生成了)
00485358
|. 8BC8 MOV ECX,EAX
0048535A
|. 8BD6 MOV EDX,ESI
0048535C
|. 8BC3 MOV EAX,EBX
0048535E
|. E8 19070000 CALL REPORT.00485A7C 关键call,算法全靠它了,进去!
00485363
|. 3BF8 CMP EDI,EAX 算出来的注册码放在EAX,EDI放你输进去的注册码
00485365
|. 0F94C0 SETE AL 不相等设0
00485368 |.
5F POP EDI
00485369 |.
5E POP ESI
0048536A |.
5B POP EBX
0048536B \.
C3 RETN
进入
00485A7C
.
.
.
.
(上面都是判断输入内容的格试对错,不理它,看下面的算法
00485AF0
|. BB 01000000 MOV EBX,1
;
放入计算姓名初始长度
00485AF5 |> 8B45 FC /MOV
EAX,DWORD PTR SS:[EBP-4] ; 得到用户的姓名
00485AF8
|. 33C9 |XOR ECX,ECX
; 清零
00485AFA |. 8A4C18 FF |MOV CL,BYTE
PTR DS:[EAX+EBX-1] ; 放入姓名的循环字节到cl(第一个字节,第二个字节,循环..)
00485AFE
|. 83E1 07 |AND ECX,7
;
和7作与运算后的值(以下简称X)
00485B01 |. 8B45 FC
|MOV EAX,DWORD PTR SS:[EBP-4] ; 得到用户的姓名
00485B04
|. 0FB64418 FF |MOVZX EAX,BYTE PTR DS:[EAX+EBX-1]
; 放入姓名的循环字节到EAX
00485B09 |. 50
|PUSH EAX
00485B0A |. 8B45 F4
|MOV EAX,DWORD PTR SS:[EBP-C] ;
EAX得到机器码DWORD
00485B0D |. 5A
|POP EDX
; 字节放回到EDX
00485B0E
|. 51 |PUSH ECX
; X放入堆栈ECX
00485B0F |. 8BCA
|MOV ECX,EDX
00485B11 |. 99
|CDQ
; 机器码扩展放入EDX:EAX
00485B12
|. F7F9 |IDIV ECX
; 机器码除以循环字节
00485B14 |. 59
|POP ECX
; 把和7作与运算的后的字节放ECX
00485B15
|. D3E2 |SHL EDX,CL
; 余数向左移动X,CL
00485B17 |. 03FA
|ADD EDI,EDX
; EDI加上EDXED
00485B19 |.
43 |INC EBX
00485B1A |.
4E |DEC ESI
00485B1B |.^
75 D8 \JNZ SHORT REPORT.00485AF5
00485B1D |>
8B45 F8 MOV EAX,DWORD PTR SS:[EBP-8]
; 单位名称
00485B20 |. E8 ABE7F7FF
CALL REPORT.004042D0
; 得到单位名称的长度
00485B25 |. 8BF0
MOV ESI,EAX
00485B27 |. 85F6
TEST ESI,ESI
00485B29 |. 7E 21
JLE SHORT REPORT.00485B4C
00485B2B |. BB 01000000
MOV EBX,1
00485B30 |> 8B45 F8 /MOV EAX,DWORD
PTR SS:[EBP-8] ; 单位名称放入EAX,DWO
00485B33
|. 0FB64418 FF |MOVZX EAX,BYTE PTR DS:[EAX+EBX-1]
; 循环字节X
00485B38 |. 8BD0
|MOV EDX,EAX
00485B3A |. 83CA FF
|OR EDX,FFFFFFFF
; or EDX
00485B3D |. 2355 F4
|AND EDX,DWORD PTR SS:[EBP-C]
; 与机器码作与运算
00485B40 |. 8B4D F8
|MOV ECX,DWORD PTR SS:[EBP-8] ; 单位名称放入ECX
00485B43
|. 0FAFD0 |IMUL EDX,EAX
00485B46 |.
03FA |ADD EDI,EDX
00485B48 |.
43 |INC EBX
00485B49 |.
4E |DEC ESI
00485B4A |.^
75 E4 \JNZ SHORT REPORT.00485B30
00485B4C |>
8BC7 MOV EAX,EDI
00485B4E |.
E8 AD2BF8FF CALL REPORT.00408700
; 得到EAX的前四位
00485B53 |. 8BD8
MOV EBX,EAX
00485B55 |. 66:0FAF5D
F4 IMUL BX,WORD PTR SS:[EBP-C]
; 前四位乘以后机器码四位
00485B5A |. 0FB7DB
MOVZX EBX,BX
00485B5D |. 03DF
ADD EBX,EDI
00485B5F |. 8B45 F4
MOV EAX,DWORD PTR SS:[EBP-C] ; 机器码放入EAX
00485B62
|. E8 992BF8FF CALL REPORT.00408700 机器码前四位放入EAX
00485B67
|. 66:F7EF IMUL DI
; AX*DI
00485B6A |. 0FB7C0
MOVZX EAX,AX
00485B6D |. 03D8
ADD EBX,EAX
00485B6F |. 8BFB
MOV EDI,EBX (EDI数值就是注册码,此进算完成)
00485B71 |. 33C0
XOR EAX,EAX
00485B73 |. 5A
POP EDX
00485B74 |. 59
POP ECX
00485B75 |. 59
POP ECX
00485B76 |. 64:8910
MOV DWORD PTR FS:[EAX],EDX
00485B79 |. 68 A05B4800 PUSH
REPORT.00485BA0
00485B7E |> 8D45 EC LEA
EAX,DWORD PTR SS:[EBP-14]
00485B81 |. BA 02000000 MOV EDX,2
00485B86
|. E8 E9E4F7FF CALL REPORT.00404074
00485B8B |. 8D45
F8 LEA EAX,DWORD PTR SS:[EBP-8]
00485B8E |. BA
02000000 MOV EDX,2
00485B93 |. E8 DCE4F7FF CALL REPORT.00404074
00485B98
\. C3 RETN
看出来算法,怎样把它编出来呢,我不会asm,会用delphi,好吧,就用delphi。
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, forms,
Dialogs, StdCtrls;
type
Tform1 = class(Tform)
Edit1: TEdit;
Label1: TLabel;
Label2: TLabel;
Edit2:
TEdit;
Button1: TButton;
Label3: TLabel;
Edit3: TEdit;
Edit4: TEdit;
Label4:
TLabel;
Label5: TLabel;
procedure Button1Click(Sender: TObject);
private
{ Private declarations
}
public
{ Public declarations }
end;
function strto16(achar:char):integer;
function strto16h(astr:string):integer;
var
form1: Tform1;
implementation
{$R
*.dfm}
function Add1(i, j: Integer): Integer;
var
Temp: Integer;
k: Integer;
begin
Temp := 0;
for k := 1 to
j do
Inc(Temp, i);
Result := Temp;
end;
function
Add2(i, j: Integer): Integer;
var
temp: Integer;
k:
Integer;
begin
if j=0 then
begin
result:=1;
exit;
end;
temp := 1;
for k := 1 to j do
temp
:= Add1(temp, i);
Result := temp;
end;
function
strto16(achar:char):integer;
begin
case achar of
'0': result:=0;
'1':result:=1;
'2':result:=2;
'3':result:=3;
'4':result:=4;
'5':result:=5;
'6':result:=6;
'7':result:=7;
'8':result:=8;
'9':result:=9;
'A':result:=10;
'B':result:=11;
'C':result:=12;
'D':result:=13;
'E':result:=14;
'F':result:=15;
end;
end;
function
strto16h(astr:string):integer;
var heji,i:integer;
begin
heji:=0;
for
i:=length(astr)downto 1 do
begin
heji:=heji+strto16(astr[i])*add2(16,length(astr)-i);
end;
result:=heji;
end;
//上面主要是编一个strto16的函数,把十六进制转成10进制,不知道有没有现成的。 procedure len1:=length(namestr); //姓名长度 danweistr:=edit2.text; len2:=length(danweistr); //单位长度 serialstr:=edit3.text; asm
var len1,len2,i,cx1,cx2,cx3,cx4:integer;
sumsum1,sumsum:integer;
temp1,namestr,danweistr,serialstr:string;
begin
namestr:=edit1.text; //姓名字串
cx2:=strto16h(edit3.Text);//把字符机器码转成10进制的形式,如机器码是'A012BC01'十进制就是2685582337。
xor
edi,edi
xor edx,edx
xor eax,eax
xor ebx,ebx
MOV ESI,len1
MOV EBX,1
//
; 放入计算姓名初始长度
@sub1:
MOV EAX,namestr
// ; 得到用户的姓名
XOR ECX,ECX
//
; 清零
MOV CL,BYTE PTR DS:[EAX+EBX-1] //
; 放入姓名的循环字节到CL
AND ECX,7
//
; 和7作与运算后的值(以下简称X)
MOV EAX,namestr //
; 得到用户的姓名
MOVZX EAX,BYTE PTR DS:[EAX+EBX-1]
// ; 放入姓名的循环字节到EAX
PUSH EAX //
MOV
EAX,cx2 // ; EAX得到机器码DWORD
POP
EDX //
; 字节放回到EDX
PUSH ECX //
; X放入堆栈ECX
MOV ECX,EDX //
CDQ
//
; 机器码扩展放入EDX:EAX
IDIV ECX //
; 机器码除以循环字节
POP ECX //
;
把和7作与运算的后的字节放ECX
SHL EDX,CL //
; 余数向左移动X,CL
ADD
EDI,EDX //
; EDI加上EDX
INC EBX
DEC ESI
JNZ
@sub1 //
MOV EAX,danweistr
//
//00485B20 |. E8 ABE7F7FF CALL REPORT.004042D0
MOV ESI,len2 //直接使用长单位长度
TEST ESI,ESI
JLE
@sub3
MOV EBX,1
@sub2:
MOV EAX,danweistr // 单位放入EAX
MOVZX
EAX,BYTE PTR DS:[EAX+EBX-1] // 循环字节X
MOV EDX,EAX
OR
EDX,$FFFFFFFF // or EDX
AND EDX,cx2 //
与机器码作与运算DWORD
MOV ECX,danweistr // 单位放入ECX,DWO
IMUL EDX,EAX
ADD
EDI,EDX
INC EBX
DEC ESI
JNZ @sub2
@sub3:
MOV EAX,EDI
//CALL
REPORT.00408700 这句用下面句代替
SHR EAX ,16 //
MOV EBX,EAX
//
IMUL BX,WORD PTR cx2 //
前四位乘以后机器码四位
MOVZX EBX,BX
ADD EBX,EDI
MOV
EAX,cx2 // 机器码EAX
SHR
EAX,16
//CALL REPORT.00408700
IMUL DI
// 低字AXD
MOVZX EAX,AX
ADD EBX,EAX
MOV EDI,EBX
MOV EAX,EDI
shr eax,16
MOV &sumsum,EAX (放前四位到变量sumsum)
shl edi,16
shr edi,16
mov &sumsum1,edi(放后四位到变量sumsum1)
end;
//为什么要分开,因为数值变量放不下
showmessage('你要的注册码是:'+IntToHex(sumsum,4)+'-'+IntToHex(sumsum1,4));
//intohex函数是把十进制转成十六进制字符
end;
//好了,就这样,运行你打入姓名,单位,机器码,就会弹出注册码!
//但为什么sumsum,sumsum1变量不能进行赋值操作,象Edit4.text:=sumsum+sumsum1就出错,我就弄不懂了,哪位能教我?
end.
初学crack,菜鸟一只,希望共同进步!