在远程线程中,如何调用参数包含指针的函数?
我想使用代码注入来调用 SHFileOperation
。我的代码在调用 simple 时工作正常 类似于 user32.dll
中的 MessageBox
的功能,但在从 shell32.dll> 调用
ShFileOperation
时则不会。
我将发布我认为有问题的代码部分。我知道问题出在结构实现中。
这是 RemoteInfo 值的图像:
http://www.freeimagehosting.net/uploads/219d79fc30。 jpg
//Structure type LPSHFILEOPSTRUCT = ^SHFILEOPSTRUCT; SHFILEOPSTRUCT = packed record Wnd: HWND; wFunc: UINT; pFrom: PAnsiChar; pTo: PAnsiChar; fFlags: FILEOP_FLAGS; fAnyOperationsAborted: BOOL; hNameMappings: Pointer; lpszProgressTitle: PAnsiChar; end; //Remote Info type TRemoteInfo = record LoadLibrary: function(lpLibFileName: PChar): HMODULE; stdcall; GetProcAddress: function(hModule: HMODULE; lpProcName: LPCSTR): FARPROC; stdcall; shf: SHFILEOPSTRUCT; ; Kernel32: array[0..20] of Char; shell32: array[0..20] of Char; SHFileOperationA: array[0..20] of Char; Fromlpbuff: array[0..20] of char; //Source path Tolpbuff: array[0..20] of Char; //Des Path end; //Initialize .... ZeroMemory(@RemoteInfo, SizeOf(RemoteInfo)); RemoteInfo.shf.Wnd := 0; RemoteInfo.shf.wFunc := FO_COPY; RemoteInfo.shf.pFrom := @remoteInfo.Fromlpbuff; RemoteInfo.shf.pto := @remoteInfo.tolpbuff; lstrcpy(RemoteInfo.shf.pFrom, 'e:\1.jpg' + #0#0); lstrcpy(RemoteInfo.shf.pto, 'f:\1.jpg' + #0#0); RemoteInfo.shf.fFlags := FOF_ALLOWUNDO; RemoteInfo.shf.fAnyOperationsAborted := false; ....
I want to call SHFileOperation
using code injection. My code works fine while calling simple
functions like MessageBox
from user32.dll
, but won't while calling ShFileOperation
from shell32.dll
.
I'll post the part of the code that I think has the problem. I know the problem is in the struct implementation.
Here is the image of RemoteInfo value:
http://www.freeimagehosting.net/uploads/219d79fc30.jpg
//Structure type LPSHFILEOPSTRUCT = ^SHFILEOPSTRUCT; SHFILEOPSTRUCT = packed record Wnd: HWND; wFunc: UINT; pFrom: PAnsiChar; pTo: PAnsiChar; fFlags: FILEOP_FLAGS; fAnyOperationsAborted: BOOL; hNameMappings: Pointer; lpszProgressTitle: PAnsiChar; end; //Remote Info type TRemoteInfo = record LoadLibrary: function(lpLibFileName: PChar): HMODULE; stdcall; GetProcAddress: function(hModule: HMODULE; lpProcName: LPCSTR): FARPROC; stdcall; shf: SHFILEOPSTRUCT; ; Kernel32: array[0..20] of Char; shell32: array[0..20] of Char; SHFileOperationA: array[0..20] of Char; Fromlpbuff: array[0..20] of char; //Source path Tolpbuff: array[0..20] of Char; //Des Path end; //Initialize .... ZeroMemory(@RemoteInfo, SizeOf(RemoteInfo)); RemoteInfo.shf.Wnd := 0; RemoteInfo.shf.wFunc := FO_COPY; RemoteInfo.shf.pFrom := @remoteInfo.Fromlpbuff; RemoteInfo.shf.pto := @remoteInfo.tolpbuff; lstrcpy(RemoteInfo.shf.pFrom, 'e:\1.jpg' + #0#0); lstrcpy(RemoteInfo.shf.pto, 'f:\1.jpg' + #0#0); RemoteInfo.shf.fFlags := FOF_ALLOWUNDO; RemoteInfo.shf.fAnyOperationsAborted := false; ....
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这段代码中最直接的问题是您在记录中存储了指向字符串参数的指针。这些指针是您的主进程中的地址;它们在目标进程中无效。您应该将这些值存储在记录中的固定大小数组中,就像您已经对模块和函数名称所做的那样。然后初始化远程函数内的指针字段。
但你确实让事情变得比需要的更加复杂。您根本不需要在远程函数中使用
GetProcAddress
。将整个函数放入 DLL 中。在那里你可以调用任何你想要的函数,Delphi 链接器和操作系统加载器将确保它们都可以在运行时调用。您也不需要使用 VirtualAllocEx 分配所有变量;您可以在 DLL 函数中使用普通的局部变量。在程序的整个过程中,您将使用
CreateRemoteThread
三次。第一次是注入对 LoadLibrary 的调用,以将 DLL 放入目标进程的地址空间。第二次是调用注入的函数,第三次是在完成后调用FreeLibrary
。棘手的部分是在目标进程中找到注入函数的地址。 Alexey Kurakin 关于 Code Project 的文章 演示了如何为此,您可以在自己的进程中查找该函数的相对地址,并将该偏移量应用到远程进程以确定要传递给第二次调用 CreateRemoteThread 的参数>。最后,不需要自己声明
ShFileOperation
的支持记录。 Delphi 已经在 ShellAPI 单元中为您声明了它们。在那里您还可以找到所需的各种标志的命名常量,例如fo_Copy
而不是$0002
。The immediate problem in this code is that you're storing pointers to the string parameters in your record. Those pointers are addresses in your main process; they are not valid in the target process. You should store those values in fixed-size arrays in your record, just like you're already doing with the module and function names. Then initialize the pointer fields inside the remote function.
But you're really making it more complicated than it needs to be. You don't need to use
GetProcAddress
in the remote function at all. Put you entire function in a DLL. There you can call whatever functions you want, and the Delphi linker and the OS loader will ensure that they're all available to call at run time. You also don't need to allocate all your variables withVirtualAllocEx
; you can use ordinary local variables in your DLL function.You'll use
CreateRemoteThread
three times over the course of your program. The first time is to inject a call toLoadLibrary
to get your DLL into the target process's address space. The second time is to invoke your injected function, and the third time is to callFreeLibrary
after you're finished. The tricky part is finding the address of your injected function in the target process. Alexey Kurakin's article on Code Project demonstrates how to do that by finding the relative address of the function in your own process, and the applying that offset to the remote process to determine the argument to pass to your second call toCreateRemoteThread
.Finally, there's no need to declare the support records for
ShFileOperation
yourself. Delphi already declares them for you in the ShellAPI unit. There you'll also find the named constants for the various flags you need, likefo_Copy
instead of$0002
.