学逆向论坛

找回密码
立即注册

只需一步,快速开始

发新帖

2万

积分

41

好友

1168

主题
发表于 2020-9-1 10:46:09 | 查看: 8657| 回复: 1
  先来看一下dll卸载的定义

【windows代码注入教程】第三课 DLL卸载

【windows代码注入教程】第三课 DLL卸载

【windows代码注入教程】第三课 DLL卸载

【windows代码注入教程】第三课 DLL卸载
  先介绍引用计数的概念

【windows代码注入教程】第三课 DLL卸载

【windows代码注入教程】第三课 DLL卸载

【windows代码注入教程】第三课 DLL卸载

【windows代码注入教程】第三课 DLL卸载
#include "windows.h"
#include "tlhelp32.h"
#include "tchar.h"

#define DEF_PROC_NAME(L"notepad.exe")
#define DEF_DLL_NAME(L"myhack.dll")

DWORD FindProcessID(LPCTSTR szProcessName)
{
    DWORD dwPID = 0xFFFFFFFF;
    HANDLE hSnapShot = INVALID_HANDLE_VALUE;
    PROCESSENTRY32 pe;

    // Get the snapshot of the system获取系统快照
    pe.dwSize = sizeof( PROCESSENTRY32 );
    hSnapShot = CreateToolhelp32Snapshot( TH32CS_SNAPALL, NULL );

    // find process查找进程
    Process32First(hSnapShot, &pe);
    do
    {
        if(!_tcsicmp(szProcessName, (LPCTSTR)pe.szExeFile))
        {
            dwPID = pe.th32ProcessID;
            break;
        }
    }
    while(Process32Next(hSnapShot, &pe));

    CloseHandle(hSnapShot);

    return dwPID;
}

BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege) 
{
    TOKEN_PRIVILEGES tp;
    HANDLE hToken;
    LUID luid;

    if( !OpenProcessToken(GetCurrentProcess(),
                          TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, 
              &hToken) )
    {
        _tprintf(L"OpenProcessToken error: %u", GetLastError());
        return FALSE;
    }

    if( !LookupPrivilegeValue(NULL,           // lookup privilege on local system
                              lpszPrivilege,  // privilege to lookup 
                              &luid) )        // receives LUID of privilege
    {
        _tprintf(L"LookupPrivilegeValue error: %u", GetLastError() ); 
        return FALSE; 
    }

    tp.PrivilegeCount = 1;
    tp.Privileges[0].Luid = luid;
    if( bEnablePrivilege )
        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    else
        tp.Privileges[0].Attributes = 0;

    // Enable the privilege or disable all privileges.
    if( !AdjustTokenPrivileges(hToken, 
                               FALSE, 
                               &tp, 
                               sizeof(TOKEN_PRIVILEGES), 
                               (PTOKEN_PRIVILEGES) NULL, 
                               (PDWORD) NULL) )
    { 
        _tprintf(L"AdjustTokenPrivileges error: %u", GetLastError() ); 
        return FALSE; 
    } 

    if( GetLastError() == ERROR_NOT_ALL_ASSIGNED )
    {
        _tprintf(L"The token does not have the specified privilege. ");
        return FALSE;
    } 

    return TRUE;
}

BOOL EjectDll(DWORD dwPID, LPCTSTR szDllName)
{
    BOOL bMore = FALSE, bFound = FALSE;
    HANDLE hSnapshot, hProcess, hThread;
    HMODULE hModule = NULL;
    MODULEENTRY32 me = { sizeof(me) };
    LPTHREAD_START_ROUTINE pThreadProc;

    // dwPID = notepad 进程ID
    // 使用TH32CS_SNAPMODULE 参数,获取加载到notepad进程的DLL名称
    hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID);

    bMore = Module32First(hSnapshot, &me);
    for( ; bMore ; bMore = Module32Next(hSnapshot, &me) )
    {
        if( !_tcsicmp((LPCTSTR)me.szModule, szDllName) || 
            !_tcsicmp((LPCTSTR)me.szExePath, szDllName) )
        {
            bFound = TRUE;
            break;
        }
    }

    if( !bFound )
    {
        CloseHandle(hSnapshot);
        return FALSE;
    }

    if ( !(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)) )
    {
        _tprintf(L"OpenProcess(%d) failed!!! [%d]", dwPID, GetLastError());
        return FALSE;
    }

    hModule = GetModuleHandle(L"kernel32.dll");
    pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hModule, "FreeLibrary");
    hThread = CreateRemoteThread(hProcess, NULL, 0, 
                                 pThreadProc, me.modBaseAddr, 
                                 0, NULL);
    WaitForSingleObject(hThread, INFINITE);

    CloseHandle(hThread);
    CloseHandle(hProcess);
    CloseHandle(hSnapshot);

    return TRUE;
}

int _tmain(int argc, TCHAR* argv[])
{
    DWORD dwPID = 0xFFFFFFFF;
 
    // find process
    dwPID = FindProcessID(DEF_PROC_NAME);
    if( dwPID == 0xFFFFFFFF )
    {
        _tprintf(L"There is no <%s> process!", DEF_PROC_NAME);
        return 1;
    }

    _tprintf(L"PID of \"%s\" is %d", DEF_PROC_NAME, dwPID);

    // change privilege(改变privilege)
    if( !SetPrivilege(SE_DEBUG_NAME, TRUE) )
        return 1;

    // eject dll
    if( EjectDll(dwPID, DEF_DLL_NAME) )
        _tprintf(L"EjectDll(%d, \"%s\") success!!!", dwPID, DEF_DLL_NAME);
    else
        _tprintf(L"EjectDll(%d, \"%s\") failed!!!", dwPID, DEF_DLL_NAME);

    return 0;
}

【windows代码注入教程】第三课 DLL卸载

【windows代码注入教程】第三课 DLL卸载
  获取进程中加载的DLL信息

【windows代码注入教程】第三课 DLL卸载

【windows代码注入教程】第三课 DLL卸载
  CreateToolHelp32Snapshot其中各个参数含义如下:
  dwFlags:指定了获取系统进程快照的类型;
  th32ProcessID:指向要获取进程快照的ID,获取系统内所有进程快照时是0;
  如果函数调用成功返回快照句柄,否则返回INVALID_HANDLE_VALUE。
  MODULEENTRY32结构体定义如下:
typedef struct tagMODULEENTRY32

{

DWORD dwSize;

DWORD th32ModuleID;

DWORD th32ProcessID;

DWORD GlblcntUsage;

DWORD ProccntUsage;

BYTE *modBaseAddr;

DWORD modBaseSize;

HMODULE hModule;

TCHAR szModule[MAX_PATH];

TCHAR szExePath[MAX_PATH];

} MODULEENTRY32, *PMODULEENTRY32, *LPMODULEENTRY32;
  DwSize 指定结构的长度,以字节为单位。在调用Module32First功能,设置这个成员SIZEOF(MODULEENTRY32)。如果你不初始化的dwSize,Module32First将失败。
  th32ModuleID 此成员已经不再被使用,通常被设置为1
  th32ProcessID 正在检查的进程标识符。这个成员的内容,可以使用Win32 API的元素
  GlblcntUsage 全局模块的使用计数,即模块的总载入次数。通常这一项是没有意义的,被设置为0xFFFF。
  ProccntUsage 全局模块的使用计数(与GlblcntUsage相同)。通常这一项也是没有意义的,被设置为0xFFFF。
  ModBaseAddr 模块的基址,在其所属的进程范围内。
  ModBaseSize 模块的大小,单位字节。
  HModule 所属进程的范围内,模块句柄。
  SzModule NULL结尾的字符串,其中包含模块名。
  SzExePath NULL结尾的字符串,其中包含的位置,或模块的路径。

【windows代码注入教程】第三课 DLL卸载

【windows代码注入教程】第三课 DLL卸载
  获取目标进程的句柄

【windows代码注入教程】第三课 DLL卸载

【windows代码注入教程】第三课 DLL卸载
  获取FreeLibrary()API地址

【windows代码注入教程】第三课 DLL卸载

【windows代码注入教程】第三课 DLL卸载
  在目标进程中运行线程

【windows代码注入教程】第三课 DLL卸载

【windows代码注入教程】第三课 DLL卸载

【windows代码注入教程】第三课 DLL卸载

【windows代码注入教程】第三课 DLL卸载

【windows代码注入教程】第三课 DLL卸载

【windows代码注入教程】第三课 DLL卸载
  下面进行注入实践
  首先把注入器,卸载器,要注入的dll放到同一文件夹中

【windows代码注入教程】第三课 DLL卸载

【windows代码注入教程】第三课 DLL卸载

【windows代码注入教程】第三课 DLL卸载

【windows代码注入教程】第三课 DLL卸载

【windows代码注入教程】第三课 DLL卸载

【windows代码注入教程】第三课 DLL卸载

【windows代码注入教程】第三课 DLL卸载

【windows代码注入教程】第三课 DLL卸载

【windows代码注入教程】第三课 DLL卸载

【windows代码注入教程】第三课 DLL卸载

【windows代码注入教程】第三课 DLL卸载

【windows代码注入教程】第三课 DLL卸载

【windows代码注入教程】第三课 DLL卸载

【windows代码注入教程】第三课 DLL卸载
  M开头的Dll中已经看不到我们注入的myhack.dll了

【windows代码注入教程】第三课 DLL卸载

【windows代码注入教程】第三课 DLL卸载
  局限性:
  使用FreeLibrary()的方法仅适用于卸载自己使用CreateRemoteThread强制注入的DLL文件,PE文件直接导入的DLL文件是无法在进程运行过程中卸载的。
  下节课讲解通过修改PE加载DLL,需要熟练掌握PE结构,没有学过PE结构的可以看我的手写PE系列教程。
            
温馨提示:
1.如果您喜欢这篇帖子,请给作者点赞评分,点赞会增加帖子的热度,评分会给作者加学币。(评分不会扣掉您的积分,系统每天都会重置您的评分额度)。
2.回复帖子不仅是对作者的认可,还可以获得学币奖励,请尊重他人的劳动成果,拒绝做伸手党!
3.发广告、灌水回复等违规行为一经发现直接禁言,如果本帖内容涉嫌违规,请点击论坛底部的举报反馈按钮,也可以在【投诉建议】板块发帖举报。
论坛交流群:672619046

    发表于 2020-9-1 18:14:43
    太给力了,这么多好东西!

    小黑屋|手机版|站务邮箱|学逆向论坛 ( 粤ICP备2021023307号 )|网站地图

    GMT+8, 2024-11-21 22:26 , Processed in 0.137764 second(s), 47 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表