卸载远端进程模块(张佩)

         卸载远端进程的模块(张佩)
    我看到了很多用创建远端线程的方法注入dll的文章,内容大同小异。但奇怪的是,没有一篇文章介绍如何把注入的远端线程卸载掉的方法。为了实践自己的好奇心,我试着实现了一下,使用的是类似注入dll的方法。
    1.首先我想到调用什么API卸载DLL。我想到用遍历IAT的方法,找到唯一的dll名字,然后将它隐藏。我虽然没有实际去做,但我立刻就意识到了此方法的缺点:只是修改了IAT,而没有真正地卸载,因为我还不知道实现卸载的技术细节。后来我想到用FreeLibrary函数。其实看到注入过程使用了LoadLibrary函数,应该条件反应地想到用FreeLibrary。但我并没有第一反应地想到它。
    2.实现方法:创建远端线程。
    好了,来看看FreeLibrary这个函数吧,很幸运我可以用它来作为远端线程的回调函数,看看它的声明是怎样的:
    BOOL FreeLibrary(HMODULE hModule);
    如果要想成为远端线程的回调函数,其声明格式应该是这样的:
    DWORD WINAPI ThreadProc(LPVOID lpParameter);
    LPVOID可以强转成HMODULE句柄,DWORD也可以强转成BOOL型变量。所以FreeLibrary是可以作为远端线程的回调函数的。FreeLibrary需要一个参数,HMODULE句柄。为了得到这个句柄,必须遍历进程的句柄列表。

// 传入指定进程的进程ID,还有你要查找的模块地址。
HMODULE GetProcessModule (DWORD dwPID, LPWSTR czDllName)
{
    HMODULE        hMod        = NULL;
    BOOL          bFound      = FALSE;
    HANDLE        hModuleSnap = NULL;
    MODULEENTRY32W me32        = {0};

    // Take a snapshot of all modules in the specified process.
    hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID);
    if (hModuleSnap == INVALID_HANDLE_VALUE)
        return (FALSE);

    // Fill the size of the structure before using it.

    me32.dwSize = sizeof(MODULEENTRY32W);

    // Walk the module list of the process, and find the module of
    // interest. Then copy the information to the buffer pointed
    // to by lpMe32 so that it can be returned to the caller.

    if (Module32FirstW(hModuleSnap, &me32))
    {
        do
        {
            if(0 == lstrcmpiW(czDllName, me32.szExePath)){
                hMod = me32.hModule;
            }

            printf("%S/n", me32.szExePath);
        }
        while (hMod == NULL && Module32NextW(hModuleSnap, &me32));
    }
    else
        hMod = NULL;           // could not walk module list

    // Do not forget to clean up the snapshot object.

    CloseHandle (hModuleSnap);

    return hMod;
}
    从这个函数返回的是一个模块句柄,它将作为回调函数的参数被写入指定进程中。写入过程和注入DLL时使用的方法是一样的。
    获得FreeLibrary函数全局指针:
    pfnFreeLibrary = (PTHREAD_START_ROUTINE)
        GetProcAddress( GetModuleHandleW(L"Kernel32"), "FreeLibrary" );
    if( pfnFreeLibrary==NULL )
    {
        printf( "Err 0x%08x: GetProcAddressW/n", GetLastError() );
        goto ERROR_EXIT;
    }
    写入模块句柄参数:
    hRemoteProcess = OpenProcess(         PROCESS_QUERY_INFORMATION|PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_VM_WRITE|PROCESS_VM_READ,
        FALSE,
        pid );
    if( hRemoteProcess==NULL )
    {
        printf( "Err 0x%08x: OpenProcess/n", GetLastError() );
        goto ERROR_EXIT;
    }

    dwSize = 4;
    szRemoteDllPath = (WCHAR*)VirtualAllocEx(
        hRemoteProcess,
        NULL,
        dwSize,
        MEM_COMMIT,
        PAGE_READWRITE );
    if( szRemoteDllPath==NULL )
    {
        printf( "Err 0x%08x: VirtualAllocEx/n", GetLastError() );
        goto ERROR_EXIT;
    }

    rc = WriteProcessMemory(
        hRemoteProcess,
        szRemoteDllPath,
        (PVOID)(&hM),
        dwSize,
        NULL );
    if( rc==0 )
    {        
        printf( "Err 0x%08x: WriteProcessMemory/n", GetLastError() );
        goto ERROR_EXIT;
    }
    创建远端线程并等其执行结束:
    hRemoteThread = CreateRemoteThread(
        hRemoteProcess,
        NULL,
        0,
        pfnFreeLibrary,
        hM,
        0,
        NULL );
    if( hRemoteThread==NULL )
    {        
        printf( "Err 0x%08x: CreateRemoteThread/n", GetLastError() );
        goto ERROR_EXIT;
    }

    rc = WaitForSingleObject( hRemoteThread, 5000 );
    if( rc!=WAIT_OBJECT_0 )
    {
        if( szRemoteDllPath!=NULL )
        {
            VirtualFreeEx( hRemoteProcess, szRemoteDllPath, 0, MEM_RELEASE );
        }
    }

    到此完工,转载请注明出处,作者张佩。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值