远程线程调用 LoadLibrary 失败,错误为 87

发布于 2024-12-24 01:08:47 字数 1818 浏览 1 评论 0原文

我试图创建一个远程线程来加载我编写的 DLL,并从中运行一个函数。 DLL 工作正常(已检查),但由于某种原因,远程线程失败并且创建它的进程停止响应。

我使用 ollyDebug 尝试查看出了什么问题,我注意到两件事......

  1. 我的字符串(dll 名称和函数名称)已正确传递到远程线程线程
  2. 在 LoadLibrary 上失败,最后错误代码 87“ERROR_INVALID_PARAMETER”

我的最佳猜测不知何故,远程线程找不到 LoadLibrary (这是因为链接器是根据我的进程完成的吗???,只是猜测......)

我做错了什么?

这是远程函数的代码:

static DWORD WINAPI SetRemoteHook (DATA *data)
{
  HINSTANCE dll;
  HHOOK WINAPI hook;
  HOOK_PROC hookAdress;

  dll = LoadLibrary(data->dll);

  hookAdress = (HOOK_PROC) GetProcAddress(dll,data->func);
  if (hookAdress != NULL)
  {
    (hookAdress)(); 
  }
  return 1;
}

编辑:

这是我将内存分配给远程进程的部分:

typedef struct
{
    char* dll;
    char* func;
} DATA;

char* dllName = "C:\\Windows\\System32\\cptnhook.dll";  
char* funcName = "SetHook";
char* targetPrgm = "mspaint.exe";
Data lData;
lData.dll = (char*) VirtualAllocEx( explorer, 0, sizeof(char)*strlen(dllName), MEM_COMMIT, PAGE_READWRITE );
lData.func = (char*) VirtualAllocEx( explorer, 0, sizeof(char)*strlen(funcName), MEM_COMMIT, PAGE_READWRITE );
WriteProcessMemory( explorer, lData.func, funcName, sizeof(char)*strlen(funcName), &v );
WriteProcessMemory( explorer, lData.dll, dllName, sizeof(char)*strlen(dllName), &v );
rDataP = (DATA*) VirtualAllocEx( explorer, 0, sizeof(DATA), MEM_COMMIT, PAGE_READWRITE );
WriteProcessMemory( explorer, rDataP, &lData, sizeof(DATA), NULL );

编辑: 看起来问题是远程线程正在调用“垃圾”地址 而不是 LoadLibrary 基地址。是否有可能链接的 Visual studio 远程进程LoadLibrary地址错误?

编辑: 当我尝试运行与本地线程相同的代码时(我在 CreateRemoteThread 中使用当前进程的句柄),整个事情运行得很好。什么会导致这种情况?

我应该添加调用函数代码吗?它似乎正在尽其职责 代码正在远程线程中使用正确的参数执行...

代码是在 VS2010 下编译的。

data 是一个简单的结构,名称带有 char* 。 (因为在代码中明确编写字符串会导致指向我原始过程的指针)。

我做错了什么?

I am tring to create a Remote thread that will load a DLL I wrote, and run a function from it.
The DLL is working fine (Checked) but from some reason, the Remote thread fails and the proccess in which it was created stop responding.

I used ollyDebug to try and see what is going wrong and I noticed two things...

  1. My strings (dll name and function name) are passed to the remote thread correctly
  2. The thread fails on LoadLibrary with lasterror code 87 "ERROR_INVALID_PARAMETER"

My best guess is that somehow, The remote thread can't find LoadLibrary (Is this because the linker is done with repspect to my proccess???, Just a guess...)

What am I doing wrong?

This is the code to the remote function:

static DWORD WINAPI SetRemoteHook (DATA *data)
{
  HINSTANCE dll;
  HHOOK WINAPI hook;
  HOOK_PROC hookAdress;

  dll = LoadLibrary(data->dll);

  hookAdress = (HOOK_PROC) GetProcAddress(dll,data->func);
  if (hookAdress != NULL)
  {
    (hookAdress)(); 
  }
  return 1;
}

Edit:

This is the part in which I allocate the memory to the remote proccess:

typedef struct
{
    char* dll;
    char* func;
} DATA;

char* dllName = "C:\\Windows\\System32\\cptnhook.dll";  
char* funcName = "SetHook";
char* targetPrgm = "mspaint.exe";
Data lData;
lData.dll = (char*) VirtualAllocEx( explorer, 0, sizeof(char)*strlen(dllName), MEM_COMMIT, PAGE_READWRITE );
lData.func = (char*) VirtualAllocEx( explorer, 0, sizeof(char)*strlen(funcName), MEM_COMMIT, PAGE_READWRITE );
WriteProcessMemory( explorer, lData.func, funcName, sizeof(char)*strlen(funcName), &v );
WriteProcessMemory( explorer, lData.dll, dllName, sizeof(char)*strlen(dllName), &v );
rDataP = (DATA*) VirtualAllocEx( explorer, 0, sizeof(DATA), MEM_COMMIT, PAGE_READWRITE );
WriteProcessMemory( explorer, rDataP, &lData, sizeof(DATA), NULL );

Edit:
It looks like the problem is that the remote thread is calling a "garbage" address
instead of LoadLibrary base address. Is there a possibily Visual studio linked
the remote proccess LoadLibrary address wrong?

Edit:
when I try to run the same exact code as a local thread (I use a handle to the current procces in CreateRemoteThread) the entire thing works just fine. What can cause this?

Should I add the calling function code? It seems to be doing its job as
the code is being executed in the remote thread with the correct parameters...

The code is compiled under VS2010.

data is a simple struct with char* 's to the names. (As explicetly writing the strings in code would lead to pointers to my original proccess).

What am I doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

奈何桥上唱咆哮 2024-12-31 01:08:47

失败并显示 ERROR_INVALID_PARAMETER 表示传递的参数存在问题。

因此,应该查看 data->dll,它代表唯一有问题的参数。

它在这里初始化:

lData.dll = VirtualAllocEx(explorer, 0, sizeof(char) * (strlen(dllName) + 1), MEM_COMMIT, PAGE_READWRITE);

所以让我们添加一个检查是否分配引用的内存应该存储到lData.dll中,确实成功了。

if (!lData.dll) {
  // do some error logging/handling/whatsoever
}

完成此操作后,您可能会发现所实现的调用失败,因为(来自 MSDN 的 VirtualAllocEx() 的逐字记录):

如果您尝试提交尚未提交的页面,则该函数将失败
预订的。生成的错误代码为 ERROR_INVALID_ADDRESS。

因此,您可能想按照建议修改相关调用的第四个参数(再次逐字来自 MSDN):

要一步保留并提交页面,请使用以下命令调用 VirtualAllocEx
MEM_COMMIT | MEM_RESERVE。

PS:对分配lData.func的调用重复此练习。 ;-)

Failing with ERROR_INVALID_PARAMETER indicates that there is a problem with the parameters passed.

So one should look at data->dll which represents the only parameter in question.

It is initialised here:

lData.dll = VirtualAllocEx(explorer, 0, sizeof(char) * (strlen(dllName) + 1), MEM_COMMIT, PAGE_READWRITE);

So let's add a check whether the allocation of the memory which's reference should be store into lData.dll really succeded.

if (!lData.dll) {
  // do some error logging/handling/whatsoever
}

Having done so, you might have detected that the call as implemented failed because (verbatim from MSDN for VirtualAllocEx()):

The function fails if you attempt to commit a page that has not been
reserved. The resulting error code is ERROR_INVALID_ADDRESS.

So you might like to modifiy the fourth parameter of the call in question as recommended (again verbatim from MSDN):

To reserve and commit pages in one step, call VirtualAllocEx with
MEM_COMMIT | MEM_RESERVE.

PS: Repeat this exercise for the call to allocate lData.func. ;-)

过气美图社 2024-12-31 01:08:47

LoadLibrary 实际上可能是 LoadLibraryW 的别名(取决于项目设置),这是 Unicode 版本。每当您使用带有“char”字符串而不是“TCHAR”的 Windows API 时,您应该显式使用 ANSI 版本名称。这将防止在编写代码时出现调试麻烦,并且在将来项目转向 Unicode 时,您或其他人也能避免出现调试麻烦。

因此,除了解决可怕的未终止字符串问题之外,请确保使用:

LoadLibraryA(data->dll);

It's possible that LoadLibrary is actually aliasing LoadLibraryW (depending on project settings), which is the Unicode version. Whenever you use the Windows API with "char" strings instead of "TCHAR", you should explicitly use ANSI version names. This will prevent debugging hassles when the code is written, and also in the future for you or somebody else in case the project ever flips to Unicode.

So, in addition to fixing that horrible unterminated string problem, make sure to use:

LoadLibraryA(data->dll);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文