slm_key() - Generate or decode a license key
SYNTAX
int slm_key(instance, way, key, keydata, options)
SLM_INSTANCE instance;
int way;
char *key;
struct slm_keydata *keydata;
unsigned long options;
呵呵,这是很古老的C的函数定义了,这里way、keydata、options是关键的参数,由于没有Elanlm的SDK,所以不知道keydata的结构定义,而Elanapi是ELANLM V4的帮助,其中描述的slm_keydata结构感觉与V5版本比有很多不同。所以只好从代码中分析way、options和keydata的意义和结构了。
首先用’Y’(edit->function->set function type)命令将slm_key的原型写好,如图:
注意‘add eax, 0B9h’是将keydata指针偏移到0xb9处,然后作为DoChkServerID的第三个参数传入DoChkServerID。看看它的原型:
int __cdecl DoChkServerID(int arg1, int arg2, int arg_ServerSum, int arg4, int arg5, int arg6)
我们可以单步跟进DoChkServerID函数,盯住arg_ServerSum是怎么被使用的,可以用硬件断点,也可以一步步跟,对于这样没有保护的代码,我更喜欢一步步跟,最后到下面代码:
T_SLM_KEYDATA = packed record
…;
acFeature:array[0..3] of char;
acbyUmknown:array[0..28] of char;
acServerCodeSum:array[0..3] of char;
…
end;
PT_SLM_KEYDATA = ^T_SLM_KEYDATA;
PT_SLM_INSTANCE = ^DWORD;
T_slm_startapi = function(var pSlm_instance:PT_SLM_INSTANCE):integer; stdcall;
T_slm_endapi = function(pSlm_instance:PT_SLM_INSTANCE):integer; stdcall;
T_slm_key = function(pSlm_instance:PT_SLM_INSTANCE;
way:integer;key:pchar;keydata:PT_SLM_KEYDATA;options:integer):integer; stdcall;
T_DoEnCodeOrCode = function(pSlm_instance:PT_SLM_INSTANCE;arg_out:pchar;
arg_way:integer;arg_in:pchar):integer;stdcall;
T_DoGetSumInAsc4 = function(pcIn,pcOut:pchar):integer;stdcall;
function CalcServerCodeSum(sServerCode:string):string;
var
acDeCode:array[0..1024] of char;
acSum:array[0..1024] of char;
begin
fillchar(acDeCode,sizeof(acDeCode),#0);
fillchar(acSum,sizeof(acDeCode),#0);
slm_DoEnCodeOrCode(p_slm_instance,@acDeCode,1,pchar(sServerCode));
slm_DoGetSumInAsc4(@acDeCode,@acSum);
result := result + acSum[0];
result := result + acSum[1];
result := result + acSum[2];
result := result + acSum[3];
end;
function InitElanlmApi:integer;
begin
result :=-1;
if LibHandle = 0 then
begin
LibHandle := LoadLibrary('elanlm.dll');
if LibHandle = 0 then
begin
ShowMessage('load Elanlm error!');
result := -1;
exit;
end;
@slm_startapi := GetProcAddress(LibHandle,'slm_startapi');
@slm_endapi := GetProcAddress(LibHandle,'slm_endapi');
@slm_key := GetProcAddress(LibHandle,'slm_key');
//下面XXXX和ZZZZ分别是slm_DoEnCodeOrCode和slm_DoGetSumInAsc4
//相对于slm_key的偏移。
DWORD(@slm_DoEnCodeOrCode):= DWORD(@slm_key)+XXXX;
DWORD(@slm_DoGetSumInAsc4) := DWORD(@slm_key)+ ZZZZ;
if ((@slm_startapi = nil) or (@slm_endapi = nil) or (@slm_key = nil)) then
begin
FreeLibrary(LibHandle);
ShowMessage('Get Elanlm Api error!');
result := -1;
exit;
end;
p_slm_instance := nil;
result := slm_startapi(p_slm_instance);
end;
end;
// 调用这个函数前必须先调InitElanlmApi
function elamlmCreateKey(sFeature:string;sServerCode:string):string;
var
pKeydata:PT_SLM_KEYDATA;
iResult,i:integer;
s,sSum:string;
acMyKey:array[0..100] of char;
dw:DWORD;
begin
GetMem(pKeydata,sizeof(T_SLM_KEYDATA));
fillchar(pKeydata^,sizeof(T_SLM_KEYDATA),#0);
…
pKeydata^.acFeature[0] := sFeature[1];
pKeydata^.acFeature[1] := sFeature[2];;
pKeydata^.acFeature[2] := sFeature[3];;
pKeydata^.acFeature[3] := sFeature[4];;
sSum := CalcServerCodeSum(sServerCode);
pKeydata^.acServerCodeSum[0] := sSum[1];
pKeydata^.acServerCodeSum[1] := sSum[2]';
pKeydata^.acServerCodeSum[2] := sSum[3];
pKeydata^.acServerCodeSum[3] := sSum[4];
…
try
iResult := slm_key(p_slm_instance,0,pchar(@acMyKey),pKeydata,2);
if (iResult = 0) then
begin
s:='';
for i := 0 to sizeof(acMyKey) - 1 do
begin
if acMyKey[i] = #0 then
break;
s := s + acMyKey[i];
end;
result := result + format('%s',[s]);
end
else
begin
result := format('slm_key return error:%x,%d',[iResult,iResult]);
end;
finally
FreeMem(pKeydata);
end;
end;