首页
社区
课程
招聘
[讨论]dll加载到内存后(自己进程、自己dll),删除dll文件,显示被占用,应该调用哪个API解除?R3层
2023-2-10 23:27 10576

[讨论]dll加载到内存后(自己进程、自己dll),删除dll文件,显示被占用,应该调用哪个API解除?R3层

2023-2-10 23:27
10576

别说查全局句柄表,加载dll后文件句柄应该已经关闭回收了,用工具查了自己进程的文件句柄,没有这个dll的文件句柄


[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。

收藏
点赞3
打赏
分享
最新回复 (17)
雪    币: 775
活跃值: (2292)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
AperOdry 2023-2-10 23:50
2
2
重映射后就能正常删除了
雪    币: 248
活跃值: (1031)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
sixL 2023-2-11 02:56
3
1
;// Load the DLL
invoke        LoadLibrary,CStr("test.dll")
.if rax == NULL
       invoke        ErrorMessage,CStr("DLL failed to load")
       return FALSE
.else
       mov        Dll_Handle,rax
.endif
...

;// unload the DLL
invoke        FreeLibrary,Dll_Handle ;//如果其它进程还在用,只是断开本进程的映射,不能从内存中卸载。如果本进程是最后一个使用该DLL的进程,则该DLL就从内存中卸载。
雪    币: 1792
活跃值: (5199)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
PEDIY 2023-2-11 06:42
4
0
sixL ;// Load the DLL invoke LoadLibrary,CStr("test.dll") .if rax == NULL invoke ErrorMessa ...

3Q热心八戒儿胸。不让它内存中卸载哦, 只删除这个文件嚄

雪    币: 248
活跃值: (1031)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
sixL 2023-2-11 12:12
5
0
PEDIY 3Q热心八戒儿胸。不让它内存中卸载哦, 只删除这个文件嚄

这是非正常操作,不能删除这个DLL文件(在正常情况下)。
设置DLL文件的目的是:许多进程使用相同的功能函数的代码仅在内存中只保留一份代码数据。显示被占用,这说明别的进程在用,你把这个文件删除,别的进程如何用?

最后于 2023-2-11 12:13 被sixL编辑 ,原因: 修改
雪    币: 1792
活跃值: (5199)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
PEDIY 2023-2-11 12:19
6
0
sixL PEDIY 3Q热心八戒儿胸。不让它内存中卸载哦, 只删除这个文件嚄 这是非正常操作,不能删除这个DLL文件(在正常情况下)。设置DLL文件的目 ...

别的进程没在用, 它也说是被占用. 憨厚滴小八戒儿看来还是不太懂啊, 哈哈哈

雪    币: 364
活跃值: (1366)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
wujimaa 1 2023-2-11 17:09
7
0

A.dll  创建一线程内存加载自己, 名为B.dll。B.dll  调用A.dll导出函数,用于卸载A.dll。以前做过,找不到代码了。

最后于 2023-2-11 17:11 被wujimaa编辑 ,原因:
雪    币: 1792
活跃值: (5199)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
PEDIY 2023-2-12 13:02
8
0
wujimaa A.dll  创建一线程内存加载自己, 名为B.dll。B.dll  调用A.dll导出函数,用于卸载A.dll。以前做过,找不 ...

不卸载dll, 只删除文件就行

雪    币: 543
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
酋长哥 2023-2-12 23:37
9
1
  如果您在自己的进程中加载了一个DLL,并且希望删除该DLL文件,但是因为DLL已经被加载到内存,因此删除文件时会报错,提示文件被占用。
  要解决这个问题,您需要调用Windows API中的FreeLibrary函数,该函数用于释放加载到内存中的DLL。在您程序结束前,您应该显式地调用FreeLibrary函数来释放DLL,这样就可以避免DLL被占用的问题。
代码如下:
HMODULE hModule = LoadLibrary("YourDLL.dll");
//Do something with your dll
FreeLibrary(hModule);
雪    币: 364
活跃值: (1366)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
wujimaa 1 2023-2-13 09:14
10
1
PEDIY 不卸载dll, 只删除文件就行

卸载dl,就能删除文件。内存的还是你原来dll.是多加载一次。  A B代码合在一起。



////////////////////////////////////////  A.dll /////////////////////////////////////////////////////////



typedef ULONG (WINAPI *PFNFreeFakeDll)(

   HMODULE hModule // specifiy TRUE if reboot needed after install

   );


DWORD ThreadProc(  LPVOID lpParameter)

{


HMODULE hMod=(HMODULE)lpParameter;


    DWORD dwDataLength=sizeof(g_szDllData);

char*pdll_data=NULL;

pdll_data=(char*)malloc(dwDataLength+1);

if(pdll_data==NULL)

return -1;



RtlZeroMemory(pdll_data,dwDataLength);

RtlCopyMemory(pdll_data,g_szDllData,dwDataLength);


// int nCount=60;

// 

// while(nCount-->0)

// {

// OutputDebugStringA("wait------\n");

// Sleep(1000);

// }


HMEMORYMODULE h=MemoryLoadLibrary(pdll_data);

if(h){

        PFNFreeFakeDll func=(PFNFreeFakeDll)MemoryGetProcAddress(h,"DllGetClassObjec");

if(func)

{

func(hMod);

}

}


Sleep(100);


//TerminateThread(GetCurrentThread(),0);

   

return 0;

}



//B.dll



DWORD WINAPI FreeDllThreadProc(

   LPVOID lpParameter

   )

{


HMODULE hModule = (HMODULE)lpParameter;

if(hModule == NULL)

return 0;


TCHAR szDllFilePath[MAX_PATH]={0};

GetModuleFileName(hModule,szDllFilePath,MAX_PATH);


Sleep(10000);

FreeLibrary(hModule);


TCHAR ProcessName[MAX_PATH] ={0};

GetCurrentProcessName(ProcessName,MAX_PATH);


if(0!=_tcsicmp(ProcessName,L"explorer.exe"))

{

//3分钟后删除文件

ULONG nCount =0;

while(nCount< 3*6)

{

Sleep(10000);

nCount++;

}

}



DeleteFile(szDllFilePath);


return 0;

}


ULONG WINAPI DllGetClassObjec (HMODULE hModule)

{

if(hModule == NULL)

return -1;


//这里要线程去freedll

CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)FreeDllThreadProc,hModule,0,NULL);


return 0;


}


最后于 2023-2-13 10:43 被wujimaa编辑 ,原因:
雪    币: 248
活跃值: (3779)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
luskyc 2023-2-16 11:08
11
0
R3层无法删除,不是句柄的问题,也没有API
雪    币: 1072
活跃值: (1324)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
厌倦 2023-2-16 18:43
12
0

7楼说的是对的,写个反射加载自身到内存,然后卸载自身模块,然后删除文件,还有你好非主流

最后于 2023-2-16 18:44 被厌倦编辑 ,原因:
雪    币: 8048
活跃值: (4340)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
sunsjw 1 2023-2-17 09:31
13
0
内存加载dll,有没有听说过?
雪    币: 4119
活跃值: (1500)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
Boring勇哥 2023-2-18 21:04
14
2

微软没有提供这个api,不过可以自己写一个:

NTSTATUS NTAPI RtlRemapImageVirtualMemory(_In_ PVOID BaseAddress) {
    NTSTATUS status;
    HANDLE SectionHandle = nullptr;
    MEMORY_BASIC_INFORMATION mbi{};
    LARGE_INTEGER Size;
    PVOID ViewBase = nullptr;;
    SIZE_T ViewSize;

    do {
        status = NtQueryVirtualMemory(
            NtCurrentProcess(),
            BaseAddress,
            MEMORY_INFORMATION_CLASS::MemoryBasicInformation,
            &mbi,
            sizeof(mbi),
            nullptr
        );
        if (!NT_SUCCESS(status))break;

        if ((mbi.Type & MEM_IMAGE) == 0) {
            status = STATUS_INVALID_PARAMETER;
            break;
        }

        ViewSize = Size.QuadPart = RtlImageNtHeader(mbi.AllocationBase)->OptionalHeader.SizeOfImage;

        status = NtCreateSection(
            &SectionHandle,
            SECTION_ALL_ACCESS,
            nullptr,
            &Size,
            PAGE_EXECUTE_READWRITE,
            SEC_COMMIT,
            nullptr
        );
        if (!NT_SUCCESS(status))break;

        status = NtMapViewOfSection(
            SectionHandle,
            NtCurrentProcess(),
            &ViewBase,
            0,
            0,
            nullptr,
            &ViewSize,
            SECTION_INHERIT::ViewUnmap,
            0,
            PAGE_EXECUTE_READWRITE
        );
        if (!NT_SUCCESS(status))break;

        //
        // 注意:如果镜像的地址空间不连续,此处可能需要分段复制
        //
        RtlCopyMemory(
            ViewBase,
            mbi.AllocationBase,
            Size.QuadPart
        );

        status = NtUnmapViewOfSection(
            NtCurrentProcess(),
            mbi.AllocationBase
        );
        if (!NT_SUCCESS(status))break;

        status = NtMapViewOfSection(
            SectionHandle,
            NtCurrentProcess(),
            &mbi.AllocationBase,
            0,
            0,
            nullptr,
            &ViewSize,
            SECTION_INHERIT::ViewUnmap,
            0,
            PAGE_EXECUTE_READWRITE
        );
        if (!NT_SUCCESS(status))break;

        status = NtUnmapViewOfSection(
            NtCurrentProcess(),
            ViewBase
        );

    } while (false);

    if (SectionHandle) NtClose(SectionHandle);
    return status;
}


雪    币: 302
活跃值: (1733)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
轻装前行 2023-3-16 11:47
15
0
精易论坛搜幽灵 dll
雪    币: 825
活跃值: (3495)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
逆向爱好者 2023-3-16 23:43
16
0
第一个办法就是内存注入(pe重定位,反射)
第二个办法是内核强删
雪    币: 19
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
美少女昕昕 2023-4-17 04:04
17
0
给文件设备发irp强删,内核。
雪    币: 35
活跃值: (1756)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
shuwoa 2023-4-18 05:41
18
0
理论上是不可能,在不卸载的情况下删除的,因为该DLL所处的物理内存即是文件内存.不过可以在卸载的一瞬间,重新拷贝DLL的内存到映射的内存中实现映射分离的效果.
游客
登录 | 注册 方可回帖
返回