C++ FreeLibrary未取消挂钩DLL

C++ FreeLibrary未取消挂钩DLL,c++,winapi,dll,hook,createremotethread,C++,Winapi,Dll,Hook,Createremotethread,我正在尝试将DLL挂接到记事本进程上,然后将其取消挂接。钩住后,只要用户单击“另存为”,DLL就会使记事本创建一个隐藏文件(此代码未显示)。当脱钩时,情况不应该如此 然而,由于某种原因,虽然我收到了“DLL从进程中取消挂钩”的消息,但DLL仍然没有从记事本进程中取消挂钩,我知道这一点,因为记事本仍然会在不应该这样做的情况下创建附加文件 返回值whatsover上没有错误消息(至少据我所知没有),因此我删除了大多数返回值检查 钩住 HANDLE hThread; char * pid = argv

我正在尝试将DLL挂接到记事本进程上,然后将其取消挂接。钩住后,只要用户单击“另存为”,DLL就会使记事本创建一个隐藏文件(此代码未显示)。当脱钩时,情况不应该如此

然而,由于某种原因,虽然我收到了“DLL从进程中取消挂钩”的消息,但DLL仍然没有从记事本进程中取消挂钩,我知道这一点,因为记事本仍然会在不应该这样做的情况下创建附加文件

返回值whatsover上没有错误消息(至少据我所知没有),因此我删除了大多数返回值检查

钩住

HANDLE hThread;
char * pid = argv[1];
DWORD user_pid = atoi(pid);
LPCSTR Dllpath = "C:\\Users\\xxx\\Desktop....\\MyDll.dll"
LPVOID pDllPath; // Address in remote process where Dllpath will be copied to.
HMODULE hKernel32 = GetModuleHandle("Kernel32");

HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, user_pid);

char * command = argv[2];

if (strcmp(command,"hook") == 0){

    SIZE_T bytesWritten = 0;

    //Allocate memory to target process, and write dll to the allocated memory.
    pDllPath = VirtualAllocEx(hProcess, NULL,strlen(DllPath)+1, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);

    // Write DLL hook name
    WriteProcessMemory(hProcess, pDllPath, (LPCVOID)DllPath, strlen(Dllpath)+1,&bytesWritten);

    // Load Dll to remote process
    hThread = CreateRemoteThread(hProcess, NULL,0,(LPTHREAD_START_ROUTINE)GetProcAddress(hKernel32, "LoadLibraryA"), pDllPath,0,NULL);

    WaitForSingleObject(hThread, INFINITE);

    //Clean up
   CloseHandle(hThread);
   VirtualFreeEx(hProcess, pDllPath, strlen(DllPath+1, MEM_RELEASE);

else if (strcmp(command,"unhook")==0){
    InlineUnhook(); //Call unhook inside the dll itself
}

}
取消挂钩(在dll内部)


这是因为上面的
InlineUnhook
调用调用的是加载到注入进程中的dll副本,而不是目标进程中的副本。

您的注入器直接调用
InlineUnhook()
,因此它将作用于注入进程中加载的dll实例,而不是挂接进程

freelLibraryAndExitThread()
CreateRemoteThread()
不兼容,因此不能像使用
LoadLibraryA()
那样使用远程线程直接调用它

在DLL本身内部,它不需要为自己调用
OpenProcess()
LoadLibrary()
、或
CreateRemoteThread()
。DLL可以像任何其他本地函数一样,直接调用
FreeLibraryAndExitThread()

HINSTANCE hThisInst;

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
{
    hThisInst = hinstDLL;
    ...
    return 1;
}

void __stdcall InlineUnhook()
{
    FreeLibraryAndExitThread(hThisInst, 0);
}
您的注入器必须使用远程线程在挂接进程的上下文中调用
InlineUnhook()
,而不是直接调用它。这意味着您需要:

  • 从DLL导出
    InlineUnhook()

  • 在挂钩进程中查找加载的DLL的地址。如果您的DLL是32位加载到32位目标进程中,则当调用
    LoadLibraryA()
    完成
    CreateRemoteThread()
    时,可以从
    GetExitCodeThread()
    获取该地址。否则,您必须在以后查找加载的地址,例如通过
    EnumProcessModules()
    CreateToolhelp32Snapshot(TH32CS\u SNAPMODULE)

  • 在钩住的进程中查找导出的
    InlineUnhook()
    的地址。在注入器内使用
    LoadLibrary()
    GetProcAddress()
    计算DLL内
    InlineUnhook()
    的偏移量,然后将该偏移量应用于挂接进程内加载的DLL的地址

  • 使用
    CreateRemoteThread()
    在该计算地址调用
    InlineUnhook()
    。您必须更改
    InlineUnhook()
    的签名才能与
    CreateRemoteThread()
    兼容,例如:


@takeru如果您想使用
freebrary()
而不是
InlineUnhook()
,那么是的,这将起作用(按原样使用
dll\u base\u addr
,而不从中减去
unhook\u func\u addr
)。如果您想改用
InlineUnhook()
,则可以自己使用
unhook\u func\u addr
,而不将其传递给
FreeLibrary()
,但查找该地址需要几个步骤,正如我在answer@takeru不,它更像是
CreateRemoteThread(hProcess,NULL,0,(LPTHREAD\u START\u例程)取消挂钩功能地址,空,0,空)其中
unhook_func_addr
的计算方式类似于
dll_base_addr+offset
,其中
offset
的计算方式类似于
lib=LoadLibrary(“dll”);偏移量=(UINT_PTR)GetProcAddress(lib,“InlineUnhook”)-(UINT_PTR)lib请不要污损您的问题。一旦您在此网站上提出问题,您的问题及其代码将根据您在加入该网站时同意的服务条款成为该网站的财产。@takeru(再次)回滚。原始问题的答案已发布,编辑后将变得毫无意义。不要那样做。正如有人告诉你的,你不能删除/污损你的问题。不过,您可以将您的姓名从中删除,请参见
HINSTANCE hThisInst;

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
{
    hThisInst = hinstDLL;
    ...
    return 1;
}

void __stdcall InlineUnhook()
{
    FreeLibraryAndExitThread(hThisInst, 0);
}
DWORD __stdcall InlineUnhook(LPVOID)
{
    FreeLibraryAndExitThread(hThisInst, 0);
    return 1;
}