分享

巧妙编程实现QQ安全登录

 quasiceo 2014-06-13
巧妙编程实现QQ安全登录
花的神明

《软件报》2008年第11期  邮发代号:61-74

   QQ是我们很常用的聊天软件,当登录QQ时,一般都是在其登录窗口中输入QQ号码和密码,之后才可以进入聊天窗口。但是,现在很多木马程序往往通过各种手段来截取您的QQ密码,例如设置键盘钩子,伪造QQ登录界面等。虽然QQ提供了nProtect键盘加密保护技术,不过最新的QQ木马完全可以直接破解该保护技术,在QQ用户毫无察觉的情况下直接截取QQ密码信息。如何才能打破常规,实现QQ安全快速登录呢?

实际上,除了使用正常的QQ登录对话框实现登录操作外,还可以使用QQ命令行实现登录操作。QQ命令行的格式为“QQ.exe /START QQUIN:QQ号码 PWDHASH:加密后的QQ密码 /STAT:登录状态”,其中的“QQ.exe”表示QQ的完整程序路径,例如“C:\Program Files\Tencent\QQ.exe”,“QQUIN”参数后面跟随QQ号码,“PWDHASH”参数后面跟随加密后的QQ密码。在执行登录操作时,QQ根据取得您输入的QQ密码后,使用MD5散列算法对其进行加密处理,得到16个字节的MD5散列值,然后使用BASE64编码对该散列值进行后编码处理,之后得到的值才可以用于登录操作。“STAT”参数后跟登录状态值,其中“40”表示隐身登录,“41”表示正常登录。QQ主程序利用取得的QQ号码,加密后的密码以及登录状态参数。因此,只要取得了您的QQ密码的编码信息,就可以在CMD窗口中使用命令行安全登录QQ了。因为没有使用QQ的登录对话框,再狡猾的病毒也无法探知您的QQ密码信息。根据以上原理,这里就使用Delphi 设计一个实用的QQ命令行生成程序。

在Delphi 中创建一个新的项目,在表单中放置一个名称为“num”的编辑框,用于输入QQ号码,放置一个名称为“pass”的编辑框,用于输入QQ密码,放置一个标题为“隐身登录”的CheckBox控件,用于判断是否使用隐身登录,放置一个名称为“edit1”的编辑框,用于显示完整的QQ登录命令语句,放置一个名称为“button1”的按钮,用于产生QQ命令行。注意在程序开头的“Uses”栏中应该包含“IdHashMessageDigest”单元,它实际上包含在Delphi 7内置的Indy控件包中,这里要使用其中包含的HashValue函数计算QQ密码的16字节的MD5 散列值,然后再用BASE64编码对该散列值进行编码得到的所需的密码数据。该函数完整的格式为“function HashValue(AStream: TStream): T4x4LongWordRecord; override;”,其中的参数类型是一个流或者字符串对象,经过计算可以返回T4x4LongWordRecord类型的值。在窗体的创建事件中,取得QQ的安装路径。,相关的程序片段为: 



with reg do //reg为Tregistry对象

begin

rootkey:=HKEY_LOCAL_MACHINE;

if openkey(’SOFTWARE\TENCENT\PLATFORM_TYPE_LIST\1’,true) then //使用openkey函数打开QQ在注册表中的相关主键

begin

qqpath:= ReadString(’TypePath’);//使用readstring函数读取QQ安装路径

end;

CloseKey;

Destroy;

end;

end;



程序中主要的部分是计算QQ密码的加密后的散列值,其具体程序为:



function GetCommandLine(QQNum, QQPw: string; QQState: integer): string;

type

   TempChar = array[0..15] of char;//定义16个字节的数组,用于保存MD5散列值

var

   md5: TIdHashMessageDigest5;//定义一个Hash散列对象,其中的TIdHashMessageDigest5 类是在 IdHashMessageDigest 单元中声明的

begin

   md5 := TIdHashMessageDigest5.Create;//创建一个Hash散列对象

   result := ’ /START QQUIN:’ + QQNum + ’ PWDHASH:’ + Base64(TempChar(md5.HashValue(QQPw))) + ’ /STAT:’ + IntToStr(QQState); //使用MD5加密算法计算QQ密码的散列值,之后使用自定义的Base64()函数对其进行编码,之后将使用预设格式组合QQ号码,加密后的密码以及隐身登录标记,之后将将HashValue函数的值转换成字符集

   md5.Free; //释放MD5散列对象

end;



当点击“button1”按钮时,产生完整的QQ登录命令行,如果勾选“隐身登录”项,表示使用隐身登录模式,否则的话,表示使用正常登录模式。在“edit1”中即可显示不同模式下的完整命令行。例如“"C:\PROGRA~1\Tencent\QQ\QQ.exe"  /START QQUIN:2899802 PWDHASH:SAPAtFJ97zat6d6vB9Sw/A== /STAT:41”,可以看到QQ密码已经被加密处理过了,这里使用的是正常的登录模式。当然,这里的QQ号码和加密登录密码是假设的。此外,当点击了“button1”按钮后,同时还会在该程序的运行路径中创建一个名为“secureQQ.bat”的批处理文件,其中包含完整的QQ登录命令行,之后双击该批处理文件,即可快速登录到QQ上了。别人即使得到该文件,也无法得到真实的QQ密码。只要您的QQ密码设置的复杂,利用MD5算法加密过的密码几乎无法破解的。相关的命令行为:



procedure TForm1.Button1Click(Sender: TObject);

var

  F: TextFile;

  fn: string;

begin

if  num.Text=’’ then

 begin

 Messagebox(handle,’请输入您的QQ号码!’,’提示’,mb_OK);

 exit;

 end;

if pass.Text=’’  then

  begin

  Messagebox(handle,’请输入您的QQ密码!’,’提示’,mb_OK);

  exit;

  end;

  if checkbox1.Checked then

  begin

  edit1.Enabled:=true;

  edit1.Text:=qqpath+’ ’+GetCommandLine(num.Text  ,pass.Text  ,40);//将QQ主文件路径和参数信息组合在一起,使用GetCommandLine函数计算QQ密码的散列值,如果Checkbox1处于选择状态,表示使用隐身登录

  end

else //否则表示正常登录

  begin

  edit1.Enabled:=true;

  edit1.Text:=’"’+qqpath+’"’+’ ’+GetCommandLine(num.Text  ,pass.Text  ,41);

  end;

  fn:=ExtractFilePath(paramstr(0))+’\’+’secureQQ.bat’;//创建批处理文件,将完整的QQ命令行写入该文件中

  if fileexists(fn) then

    DeleteFile(fn);

    AssignFile(F, fn);

    Rewrite(F);

    writeln(F, ’@Echo off’);

    writeln(F, edit1.text);

    CloseFile(F);

end;

完整的源代码为:(该程序在Delphi7中调试通过)

unit Unit1;

interface

uses

  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

  Dialogs,IdHashMessageDigest, StdCtrls,Registry, ExtCtrls;

type

  TForm1 = class(TForm)

    num: TEdit;

    Label2: TLabel;

    Label3: TLabel;

    Button1: TButton;

    pass: TEdit;

    Edit1: TEdit;

    Label1: TLabel;

    CheckBox1: TCheckBox;

    procedure Button1Click(Sender: TObject);

    procedure FormCreate(Sender: TObject);

    procedure numKeyPress(Sender: TObject; var Key: Char);

    procedure passKeyPress(Sender: TObject; var Key: Char);

  private

    { Private declarations }

  public

    { Public declarations }

  end;

  const

      fSeedA = 831022 ;

      fSeedB = 8310 ;

      fKey=1983 ;

var

  Form1: TForm1;

  qqpath:string;

implementation

{$R *.dfm}

function Base64(Src: string): string;//Base64编码生成函数

const

   DataSet = ’ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/’;

var

   i, ModLen: integer;

   Current: string;

   Buf: array[1..3] of Byte;

   NewBuf: array[1..4] of Byte;

begin

   result := ’’;

   if Src = ’’ then

      exit;

   ModLen := Length(Src) mod 3;

   while Length(Src) > 0 do

   begin

      FillChar(Buf, 3, #0);

      Current := Copy(Src, 1, 3);

      Src := Copy(Src, 4, Length(Src) - 3);

      for i := 1 to 3 do

         Buf[i] := Ord(Current[i]);

      NewBuf[1] := Buf[1] shr 2;

      NewBuf[2] := (Buf[1] shl 6 shr 2 or Buf[2] shr 4) and $3F;

      NewBuf[3] := (Buf[2] shl 4 shr 2 or Buf[3] shr 6) and $3F;

      NewBuf[4] := Buf[3] and $3F;

      for i := 1 to 4 do

         result := result + DataSet[NewBuf[i] + 1];

   end;

   if ModLen >= 1 then

      result[Length(result)] := ’=’;

   if ModLen = 1 then

      result[Length(result) - 1] := ’=’;

end;

function GetCommandLine(QQNum, QQPw: string; QQState: integer): string;

type

   TempChar = array[0..15] of char;

var

   md5: TIdHashMessageDigest5;

begin

   md5 := TIdHashMessageDigest5.Create;

   result := ’ /START QQUIN:’ + QQNum + ’ PWDHASH:’ + Base64(TempChar(md5.HashValue(QQPw))) + ’ /STAT:’ + IntToStr(QQState);

   md5.Free;

end;

procedure TForm1.Button1Click(Sender: TObject);

var

  F: TextFile;

  fn: string;

begin

if  num.Text=’’ then

 begin

 Messagebox(handle,’请输入您的QQ号码!’,’提示’,mb_OK);//如果QQ号码为空,弹出提示信息

 exit;

 end;

if pass.Text=’’  then

  begin

  Messagebox(handle,’请输入您的QQ密码!’,’提示’,mb_OK); //如果QQ密码为空,弹出提示信息

  exit;

  end;

  if checkbox1.Checked then

  begin

  edit1.Enabled:=true;

  edit1.Text:=qqpath+’ ’+GetCommandLine(num.Text  ,pass.Text  ,40);

  end

else

  begin

  edit1.Enabled:=true;

  edit1.Text:=’"’+qqpath+’"’+’ ’+GetCommandLine(num.Text  ,pass.Text  ,41);

  end;

  fn:=ExtractFilePath(paramstr(0))+’\’+’secureQQ.bat’;

  if fileexists(fn) then

    DeleteFile(fn);

    AssignFile(F, fn);

    Rewrite(F);

    writeln(F, ’@Echo off’);

    writeln(F, edit1.text);

    CloseFile(F);

end;

procedure TForm1.FormCreate(Sender: TObject);

 var

 reg:TRegistry;

begin

reg:=TRegistry.Create;

with reg do

begin

rootkey:=HKEY_LOCAL_MACHINE;

if openkey(’SOFTWARE\TENCENT\PLATFORM_TYPE_LIST\1’,true) then

begin

qqpath:= ReadString(’TypePath’);

end;

CloseKey;

Destroy;

end;

end;

procedure TForm1.numKeyPress(Sender: TObject; var Key: Char);

begin

   if not (Key in [’0’..’9’,#8,#13]) then Key:=#0;// 判断QQ号码是否为数字

   if key=#13 then

   pass.SetFocus;// 当点击回车键时,转移输入焦点

end;

procedure TForm1.passKeyPress(Sender: TObject; var Key: Char);

begin

if key=#13 then

 Button1.Click();

end;

end.

转载自: http://

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多