• DLL注入工作原理


    简介

    我最近研究了一个问题,Winlogon中两个线程的交互导致错误检查。一个线程是初始化GDI的Winlogon线程。这个场景的有趣之处在于另一个线程是如何在这个进程中结束的。

    线程在干什么?

    下面是线程堆栈的用户一半。线程试图加载DLL

    ChildEBP RetAddr Args to Child
    
    0058eaec 773901ad 773901d9 0058eafc 00240022 ntdll!KiFastSystemCallRet
    
    0058eb0c 775d96f3 775d1808 00000000 77e6f032 USER32!NtUserRegisterWindowMessage+0xc
    
    0058ed24 775e4755 00000000 00000001 7c837512 comctl32!InitGlobalMetrics+0x44
    
    0058ed3c 775e426a 00000031 0058ed68 7763490c comctl32!_ProcessAttach+0x98
    
    0058ed48 7763490c 775d0000 00000001 00000000 comctl32!DllMain+0x21
    
    0058ed68 7c81a352 775d0000 00000001 00000000 comctl32!_DllMainCRTStartup+0x52
    
    0058ed88 7c833465 776348ba 775d0000 00000001 ntdll!LdrpCallInitRoutine+0x14
    
    0058ee90 7c834311 00000000 00000000 7c8e2e58 ntdll!LdrpRunInitializeRoutines+0x367
    
    0058f124 7c834065 00000000 00080e98 0058f3ec ntdll!LdrpLoadDll+0x3cd
    
    0058f3a0 77e41bf3 00080e98 0058f3ec 0058f3cc ntdll!LdrLoadDll+0x198
    
    0058f408 77e5c70b 7c8e2e58 00000000 00000000 kernel32!LoadLibraryExW+0x1b2
    
    0058f41c 7c92a6a1 7c8e2e58 00000000 7c8e2e58 kernel32!LoadLibraryW+0x11
    
    0058f454 7c92a65f 7c8e2e58 7c8d0000 7c9297b6 SHELL32!SHFusionLoadLibrary+0x2a
    
    0058f460 7c9297b6 00000020 00000008 0058f6a8 SHELL32!DelayLoadCC+0x15
    
    0058f694 7c929728 0058f6a8 0000007c 00000001 SHELL32!SHFusionInitializeIDCC+0x92
    
    0058f8b4 7c92966f 7c8d0000 0000007c 00000001 SHELL32!SHFusionInitializeFromModuleID+0x3a
    
    0058f8c8 7c92962c 7c8d0000 00000001 0058f8f8 SHELL32!_ProcessAttach+0x34
    
    0058f8d8 7c92bb63 7c8d0000 00000001 00000000 SHELL32!DllMain+0x27
    
    0058f8f8 7c81a352 7c8d0000 00000001 00000000 SHELL32!_DllMainCRTStartup+0x52
    
    0058f918 7c833465 7c92bb1b 7c8d0000 00000001 ntdll!LdrpCallInitRoutine+0x14
    
    0058fa20 7c834311 00000000 00000000 00000004 ntdll!LdrpRunInitializeRoutines+0x367  

    这个函数是加载并调用init依赖DLL的函数

    0058fcb4 7c834065 00000000 00080760 0058ff7c ntdll!LdrpLoadDll+0x3cd
    
    0058ff30 77e41bf3 00080760 0058ff7c 0058ff5c ntdll!LdrLoadDll+0x198 

    0058ff5c是Unicode字符串指向DLL名称的指针

    0058ff98 77e5c70b 00570254 00000000 00000000 kernel32!LoadLibraryExW+0x1b2
    
    0058ffac 0057017e 00570254 00000000 00200008 kernel32!LoadLibraryW+0x11
    
    WARNING: Frame IP not in any known module. Following frames may be wrong.
    
    0058fff4 00000000 00570228 00905a4d 00000003 0x57017e

    正在加载的DLL依赖于其他DLL。加载第一个DLL时,将加载并初始化这些DLL。因此,如果DLL'A'调用了DLL'B',则加载程序在加载DLL'A'时加载DLL'B'。

    What is so unusual about this thread?

    如果你用!thread检查IP的起始地址,当它调用LoadLibraryW时,IP不在任何加载模块的范围内。
    1: kd> !thread
    
    THREAD 86edd020 Cid 7884.7528 Teb: 7ffdc000 Win32Thread: bc1adb48 RUNNING on processor 1
    
    Not impersonating
    
    DeviceMap e10018c0
    
    Owning Process 87c51d88 Image: winlogon.exe
    
    Wait Start TickCount 2567944 Ticks: 0
    
    Context Switch Count 4 LargeStack
    
    UserTime 00:00:00.015
    
    KernelTime 00:00:00.000
    
    Start Address 0x00570000

    Start Address。这不是显示在"!peb"输出的任何模块中。

    这个!PEB扩展将显示加载的模块列表和进程的地址范围。由于空间原因,此处未显示。但是这个地址不在任何加载的模块中。
    我们来看看函数:

    00570000 55 push ebp
    
    00570001 8bec mov ebp,esp
    
    00570003 83ec3c sub esp,3Ch
    
    00570006 8365e800 and dword ptr [ebp-18h],0
    
    0057000a 8365ec00 and dword ptr [ebp-14h],0
    
    0057000e 8365f800 and dword ptr [ebp-8],0
    
    00570012 8365dc00 and dword ptr [ebp-24h],0
    
    00570016 8365f000 and dword ptr [ebp-10h],0
    
     
    
    1: kd> u
    
    0057001a 8365e000 and dword ptr [ebp-20h],0
    
    0057001e 8365f400 and dword ptr [ebp-0Ch],0
    
    00570022 6a01 push 1
    
    00570024 8b4508 mov eax,dword ptr [ebp+8]        ß 第一个参数是指向函数列表的指针.
    
    00570027 ff5004 call dword ptr [eax+4]
    
    0057002a 8945fc mov dword ptr [ebp-4],eax
    
    0057002d 8b4508 mov eax,dword ptr [ebp+8]        ß Function block.
    
    00570030 ff5010 call dword ptr [eax+10h]
    
     
    
    1: kd> u
    
    00570033 8945e4 mov dword ptr [ebp-1Ch],eax
    
    00570036 837de400 cmp dword ptr [ebp-1Ch],0
    
    0057003a 0f84c0010000 je 00570200第一个参数是一个函数块。这就是作为初始参数传递的。传递了哪些函数?
    
     
    
    1: kd> dds 570228 l 5
    
    00570228 77e5c6fa kernel32!LoadLibraryW
    
    0057022c 77e6c2dc kernel32!SetErrorMode
    
    00570230 77e70531 kernel32!GetCurrentDirectoryW
    
    00570234 77e70d67 kernel32!SetCurrentDirectoryW
    
    00570238 77e63ec7 kernel32!GetProcessHeap

    这些函数是标准的kernel32调用。所以,问题是它为什么要这么做?

    线程在干什么?
    基于IP不在任何模块中的事实,IP是页对齐的,并且线程被传递函数地址作为它的初始参数,看起来这个线程被“注入”到这个进程中。
    线程是怎么注射的?
    不知道在另一个进程中分配了哪个进程。这个函数接受一个进程句柄作为输入,它可以是一个不同的进程。然后代码可以通过WriteProcessMemory移动到进程中。然后可以使用从VirtualAllocEx返回的内存地址的起始地址创建线程。
    我们结束了吗?
    不——还记得地址块吗?这是必需的,因为加载程序没有加载模块。所以函数没有被链接器解析。所以移动的代码之外的函数的地址是未知的。由于在WindowsServer2003中,某些DLL的函数保持在同一地址,因此可以将它们传递给另一个进程。Vista和beyond无法执行此操作,因此此方法将不起作用。

  • 相关阅读:
    Tomcat报错:Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/JFreeChartTest]]
    Md5 加密,加盐值
    ajax 分页 步骤和代码
    【每天学习一点点】numpy中的reshape中参数为-1
    smali文件语法参考
    google zxing 二维码扫描(android client分析)
    cygwin编译ffmpeg移植到android平台问题集锦
    Sequoyah 本机开发Native Development: Invalid path for NDK(路径无效) 解决方案
    优化模式--数据局部性
    程序猿,你也配吃10元的盒饭?
  • 原文地址:https://www.cnblogs.com/yilang/p/13617497.html
Copyright © 2020-2023  润新知