special DLL Inject

   

SMSS进程DLL   inject


注入在Windows平台上很常见,一般分为两类:二进制代码注入和动态连接库(DLL)注入。二进制代码注入指的是将SHELLCODE一类的数据放入远程进程并在本地进程中启动远程进程使其开始运作。DLL注入指的是以二进制代码注入为基础,在远程进程中运行加载动态链接库(DLL)的代码,使其运作加载DLL。DLL注入以二进制代码注入为基础,但是实现的功能比二进制代码丰富,在测试过程中,对深入观察和修改程序行为具有不可替代的作用。本文以下将以DLL注入为主阐述注入SMSS进程的方法。

       SMSS是会话进程,它是Windows中一个很特殊的进程,作用是管理子系统并且初始系统化变量的进程。在Windows操作系统中,有许多进程可以进行DLL注入,包括系统级进程lsass.exe(管理登录),CSRSS.EXE,除了SYSTEM、IDLE和SMSS没有关于其注入方面的资料。由于SYSTEM实质是Windows内核进程(NTOSKRNL),IDLE是闲置进程,这两个都是系统虚拟出来的进程,不存在注入的可能性,但是SMSS属于后于SYSTEM和IDLE创建的进程,其也有模块加载,因此SMSS在注入上存在理论可能性,不过实现起来十分困难。

       传统注入方式,使用的是函数CreateRemoteThread在远程进程(需要注入的进程)里面去启动一个新线程执行加载DLL,但是SMSS却不能使用这类方法:

(1)因为它是在系统初始化后由SYSTEM创建,其实是一个内核进程,而且它创键CSRSS.exe,所以即使是利用DuplicateHandle都找不到它的进程句柄以进行操作。

(2)CreateRemoteThread是一个kernel32.dll中的函数,而SMSS中除了ntdll.dll导出的函数以外,就没有其它函数可以使用了。而CreateRemoteThread函数不能使用。

  由于SMSS不能选择用CreateRemoteThread,因此选用测试使用一种别的方法,函数补丁法,其原理如图1所示:

 

 

  函数补丁法的设计思路是:通过远程读写内存,注入一段ShellCode,但并非是利用CreateRemoteThread启动一个新线程来执行它,而是利用继续写远程进程内存的方式,改变远程进程一些必调函数的入口或者IAT,函数在运行的时候,就会自动调用我们事先准备的ShellCode实现DLL的加载。

       由于CreateRemoteThread函数无法使用,因此只能采用由ntdll.dll导出的LdrLoadDll去加载DLL从而实现。因为这个函数才是LoadLibraryExW的实现者,以下是测试成功的注入代码:

 

__asm

    {

       pushad

       pushfd        //  保护现场

 

       //这些还原代码由外部进行初始化

       mov    eax,0xEEEEEEEE

       mov    bl,0xFF           //存五个字节的内容

       mov    edx,0xDDDDDDDD    //存需要写东西的地址

       mov    [edx],eax

       mov    byte ptr [edx+4],bl

 

       //这些代码最后会重新初始化的

       mov    eax,fs:[0x30]

       mov    eax,dword ptr [eax+0x0c] //  Ldr : _PEB_LDR_DATA

       mov    eax,dword ptr [eax+0x1c] //  InInitializationOrderModuleList : _LIST_ENTRY

       mov    eax,dword ptr [eax+0x08] //  EntryInProgress

       mov    edi,eax                     //  edi = ntdll.dll首地址

       mov    eax,dword ptr [edi+3ch]     //  eax = PE首部

       mov    edx,dword ptr [eax+edi+78h]

       add    edx,edi                     //  edx = 引出表地址

       mov    ecx,dword ptr [edx+18h]     //  ecx = 输出函数的个数(NumberOfNames)

       mov    ebx,dword ptr [edx+20h]    

       add    ebx,edi                     //  ebx = 函数名地址(AddressOfNames)

 

    SEARCH:

       dec    ecx

       mov    esi,[ebx+ecx*4]

       add    esi,edi

      

       mov    eax,0x4c72644c

       cmp    [esi],eax         //  比较'LdrL'

       jne    SEARCH

 

       mov    eax,0x4464616f

       cmp    [esi+4],eax          //  比较'oadD'

       jne    SEARCH

 

       cmp    word ptr [esi+8],0x6c6c     //  比较'll'

       jne    SEARCH

 

       //  如果是LdrLoadDll(表明地址已找到)

       mov    ebx,dword ptr [edx+24h]

       add    ebx,edi                     //  ebx = 序号数组的地址

 

       mov    ecx,dword ptr [ebx+ecx*2]   //  ecx = 计算出序号值

       and    ecx,0x0000ffff

       mov    ebx,dword ptr [edx+1ch]    

       add    ebx,edi                     //  ebx = 函数地址起始位置

       mov    eax,dword ptr [ebx+ecx*4]  

       add    eax,edi                  //  eax = 利用序号值,得出LdrLoadDll的地址

 

//LdrLoadDllLdrLoadDll(NULL, 0, &uni_input, &hHandle);

 

       //  先存入UNISTRING的值到内存中

       push   0x00000000

       push   0x006C006C

       push   0x0064002E

       push   0x00740073

       push   0x00650074

       mov    edx,esp    //edx = UNISTRING的数据

      

       //  预留存储空间

       sub    esp,0x0c

       mov    dword ptr [esp+4],0x00120010    //10 00 12 00 (UNICODE前面两个字符)

       mov    [esp+8],edx

       xor    ecx,ecx

       mov    [esp],ecx      //初始化OUT指针

 

       push   esp //PHANDLE  ModuleHandle

       mov    ebx,esp

       add    ebx,8

       push   ebx //PUNICODE_STRING ModuleFileName

       push   0   //ULONG       Flags

       push   0   //PWCHAR   PathToFile

       call   eax

 

       //  维持平衡

       add    esp,0x20   //0xc+5*4=32

      

       popfd

       popad         //  还原现场

    }  

 

    __asm

    {

       _emit  0x90  

       _emit  0x90

       _emit  0x90  

       _emit  0x90

       _emit  0x90   //  需要还原原始代码,5个字节最好

      

       _emit  0xE9  

        _emit 0x90

        _emit 0x90      

        _emit 0x90      

        _emit 0x90

    }

 

  前面说到,SMSS本来就是一个由内核创建的进程,它本身也就不支持在Win32下运行,所以DLL也必须是特殊的写法才行,Native的。为了验证注入SMSS的成功性,我把system32下面的sfcfiles.dll改名为test.dll,然后再一次重复试验,可以成功注入,如图2所示:

 

 

  由此得出结论是,通过设计的测试流程,SMSS通过函数补丁的方式,注入加载DLL。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值