Windows核心编程——dllmain和dll劫持

1.关于dll

问题:如果有多个进程加载同一个dll,其中一个进程修改了dll的导出变量,是否影响其他进程中的变量值?

        不会, 这算是一种写实拷贝技术,修改的时候修改的不是原来  的内存,是新的内存。
        一个进程启动时,系统会为每个进程都预留了4G内存,不同进程的高2g内存都指向了物理内存条的系统领空(内核),低2G映射到物理内存条不同的位置,进程上的内存称之为虚拟内存,内存条上内存称为物理内存,原则上系统内存不能访问,所以进程最多访问2G内存。
        进程中我们修改自己内存时,实际上修改的是映射上物理内存上的某个值

Windows核心编程——dllmain和dll劫持

 

 

       当不同进程加载一个dll时,A、B加载dll,dll首先加载到物理内存,
然后会映射dll内容分别到A、B进程的某个地址范围。A、B读内容时是互不影响的,但如果A修改dll,系统会把数据单独拷贝出来(写实拷贝),放在物理内存其他地方,A修改的是系统开辟的那块新空间
       所以不同进程之间,虽然访问的是同一个dll的一个的导出的变量,
但实际上他们直接的读写和修改是相互不影响的,这叫做写实拷贝

  2.LoadLibrary和FreeLibrary计数器
    操作系统为每一个库文件维护各种的计数器(引用记数),每次使
用LoadLibrary装载库文件时候,计数器递增,每次FreeLibrary时计数器递减。
    直到计数器减到0,也就是库文件没有被任何程序使用的时候,操
作系统才会将它从物理地址内存中真正释放掉,否则只是某个进程的地址空间中解除内存映射关系。
    每一个应用程序中使用FreeLibrary函数并不影响另一个exe使用
同一库文件。

2.dllmain

  微软为dll提供了一个main函数(入口函数),当dll加载时,这
个函数会自动调用或执行(系统自动调用)。

dllMain主要用于dll的初始化和反初始化

  BOOL WINAPI DllMain(
    HANDLE hinstDLL,    //dll加载到进程的基质  (=HMODULE)
    DWORD dwReason,     //表明dllmain什么时候被调用的
    
            DLL_PROCESS_ATTACH - 进程加载dll, 当dll被映射到进程虚拟地址空间中
           DLL_PROCESS_DETACH - 进程卸载dll, 当dll从进程虚拟地址空间中取消映射的时候
        
    LPVOID lpvReserved);
    

 

测试dllmain:

    BOOL WINAPI DllMain(
        HINSTANCE hinstDLL,
        DWORD fdwReason,
        LPVOID lpvReserved
    )
    {
        OutputDebugString("DLLMain");
        return TRUE;
    }
    
    return TRUE ;告诉系统初始化成功
                  

  

  隐式加载 - 会弹出一个0xc0000142错误,并且会再次调用dllmain,并传入DLL_PROCESS_DETACH
  显示加载 - loadlibrary会返回NULL,并且会再次调用dllmain,并传入DLL_PROCESS_DETACH

 

 Windows核心编程——dllmain和dll劫持

加载这个dll

 

调试DLL的方法:

     配置属性->调试->命令,填入加载此dll的exe的路径
     就可选择相应的exe调试dll       显示加载 - loadli

 

3.DLL劫持

问题:

   有个a.exe,加载了b.dll, 我有个自己的c.dll,如果在保证a的功能正常的前提下,让a加载自己的c.dll?
   答:c改名成b.dll,b.dll改名成bo.dll,c导出所有和bo.dll同名的函数,并全部转发给bo.dll,从而实现让a加载c.dll。

   函数转发:  虽然有导出函数名,但是本dll并未实现此函数,此函数的实现在其他dll里面

 用Dependency Walker 打开user32可以看到:Windows核心编程——dllmain和dll劫持

 

所谓dll劫持就是:

   病毒通过一些手段来劫持或者替换正常的DLL,欺骗正常程序加载预先准备好的恶意DLL。

上一篇:DLLMain函数


下一篇:动态链接库DLL