load and call DLL in another process

delphi package - easy access to kernel objects etc.
Ahell
Posts: 31
Joined: Mon Feb 07, 2011 4:54 pm

load and call DLL in another process

Post by Ahell »

Hello, Madshi! :wink:

My task is change window caption in Console application.

I think:
1. call this function from memory of another process, by using

Code: Select all

IProcess.ExecuteFunction
. But example of using this function in the help, misunderstood for me. Can you make very simple example for me, please? :blush:
2. load dll in memory of another process by using IProcess.LoadModule and them call same function by

Code: Select all

 IModule.GetProcAddress
. But a can't found example for this.

How I can complete this task? :crazy:
Ahell
Posts: 31
Joined: Mon Feb 07, 2011 4:54 pm

Re: load and call DLL in another process

Post by Ahell »

Help me, please :wink:
madshi
Site Admin
Posts: 10753
Joined: Sun Mar 21, 2004 5:25 pm

Re: load and call DLL in another process

Post by madshi »

For changing the window caption usually SendMessage(WM_SETTEXT) works just fine. Not sure if it also works for console windows, though.

Not sure what you want to know about IProcess.ExecuteFunction and IModule.GetProcAddress exactly?
Ahell
Posts: 31
Joined: Mon Feb 07, 2011 4:54 pm

Re: load and call DLL in another process

Post by Ahell »

madshi wrote:For changing the window caption usually SendMessage(WM_SETTEXT) works just fine. Not sure if it also works for console windows, though.

Not sure what you want to know about IProcess.ExecuteFunction and IModule.GetProcAddress exactly?
Console windows do not have a message handler windows.
and SendMessage does not always work.
Determine the console application window so as impossible as they all have a class ConsoleWindowClass.

At the moment I'm using just such a scheme:
Sleep (SleepTime);
AttachConsole (Pinfo.dwProcessId);
AppInfo.WindowHande: = GetConsoleWindow;
ShowWindow (AppInfo.WindowHande, SW_HIDE);
FreeConsole;

And it works, but again not always.

So I came up with another option. Load a DLL into the address space of another process also control the process through this DLL.
Program TrayIt, exactly what works! DLL is the Windows message handler and react like a normal gui application.

The problem is that I don `t know how to call a function from the loaded DLL in the address space of another process, and pass it a parameter.

Or how to run my code in the address space of another process. Examples are described in the certificate are not entirely clear to me ...

Could you give some examples to meet the following of my code in the address space of another process? Or with a call to the DLL is loaded into the address space of another process ....
madshi
Site Admin
Posts: 10753
Joined: Sun Mar 21, 2004 5:25 pm

Re: load and call DLL in another process

Post by madshi »

The easiest solution would be to use madCodeHook. With InjectLibrary you can inject your dll into the other process. Then your dll could call CreateIpcQueue in the initialization section and your exe could then call SendIpcMessage to send a message to the dll. As a result your dll would call your IPC message callback function in which you could run some code and then return data to the exe.

Doing all of this with madKernel would be possible, too, but you'd need to do more work by yourself. E.g. you'd have to implement the whole inter process communication yourself. Btw, the "IProcess.ExecuteFunction" and "IProcess.LoadModule" functionality will need madDisAsm. If you don't have madExcept or madCodeHook installed, madKernel doesn't have access to madDisAsm. So you need to have madExcept or madCodeHook installed, otherwise IProcess.ExecuteFunction and IProcess.LoadModule will fail.
Ahell
Posts: 31
Joined: Mon Feb 07, 2011 4:54 pm

Re: load and call DLL in another process

Post by Ahell »

madshi wrote:The easiest solution would be to use madCodeHook. With InjectLibrary you can inject your dll into the other process. Then your dll could call CreateIpcQueue in the initialization section and your exe could then call SendIpcMessage to send a message to the dll. As a result your dll would call your IPC message callback function in which you could run some code and then return data to the exe.

Doing all of this with madKernel would be possible, too, but you'd need to do more work by yourself. E.g. you'd have to implement the whole inter process communication yourself. Btw, the "IProcess.ExecuteFunction" and "IProcess.LoadModule" functionality will need madDisAsm. If you don't have madExcept or madCodeHook installed, madKernel doesn't have access to madDisAsm. So you need to have madExcept or madCodeHook installed, otherwise IProcess.ExecuteFunction and IProcess.LoadModule will fail.
MadCollection(except MadCodeHook 3, becouse is are shareware product) are installed.

I have a DLL, with this code:

Code: Select all

library DLL;

type
    BOOL = LongBool;
    DWORD = LongWord;

function SetConsoleTitle(lpConsoleTitle: PChar): BOOL; stdcall; external 'kernel32.dll' name 'SetConsoleTitleA';
procedure FreeLibraryAndExitThread(hLibModule: HMODULE; dwExitCode: DWORD); stdcall; external 'kernel32.dll' name 'FreeLibraryAndExitThread';
function GetModuleHandle(lpModuleName: PChar): HMODULE; stdcall; external 'kernel32.dll' name 'GetModuleHandleA';

procedure SetWindowCaption(aNewCaption:PChar); stdcall;
begin
  SetConsoleTitle(aNewCaption);
  FreeLibraryAndExitThread(GetModuleHandle('myDLL.dll'), 0);
end;

exports
   SetWindowCaption;

begin
end.
Using madKernel.pas of madCallection. I want to load this DLL in another process, then call the function from the DLL "SetWindowCaption" and pass prametr type PChar in this function ..

How do I do?

I wrote the following code:

Code: Select all

procedure TForm1.Button1Click(Sender: TObject);
type
  TCallProc=procedure (aStr:PChar);
var
  dh:THandle;
  myProc:TCallProc;
begin
  with Process('Console.exe') do
  begin
    If IsStillRunning then
    begin
     @myProc:=LoadModule(ExtractFilePath(ParamStr(0))+'mydll.dll').GetProcAddress('SetWindowCaption');
     myProc('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!'); //raised exception class EAccesViolation at 0x0000000 to 0x00000000
    end;
  end;
But I can not understand why not get a pointer to a callback function IProcess ('Console.exe'). LodLibrary ('myDLL.dll'). GetProcAdderss ('SetWindowsCaption');

And there is an error of memory access to get a pointer (EAccesViolation)
madshi
Site Admin
Posts: 10753
Joined: Sun Mar 21, 2004 5:25 pm

Re: load and call DLL in another process

Post by madshi »

The dll is loaded in another process. The address you get by IModule.GetProcAddress is valid only in the other process, not in yours. So you can't simply call "myProc", because doing so would try to execute the dll's exported function in your own process. You need to execute the function in the other process, not in your own one.
Ahell
Posts: 31
Joined: Mon Feb 07, 2011 4:54 pm

Re: load and call DLL in another process

Post by Ahell »

madshi wrote:The dll is loaded in another process. The address you get by IModule.GetProcAddress is valid only in the other process, not in yours. So you can't simply call "myProc", because doing so would try to execute the dll's exported function in your own process. You need to execute the function in the other process, not in your own one.
If I get a function pointer to dll, which is located in another process, and I can not just call in its process (I need to call in another process), I use IProcess.ExecuteFunction and the pointer to point to dll exported function in a foreign process?

Or as something else?
madshi
Site Admin
Posts: 10753
Joined: Sun Mar 21, 2004 5:25 pm

Re: load and call DLL in another process

Post by madshi »

Yes, you could use IProcess.ExecuteFunction. Of course then your exported function must match the parameter and calling type required for IProcess.ExecuteFunction. Alternatively you could create some kind of inter process communication message queue in your dll and then send notifications to it by your exe. For that to work your hook dll would create a private thread in its DllMain function. The private thread could then e.g. create an invisible window and then go into an endless message loop (GetMessage, ...). Your exe could then search for that window (FindWindow) and send messages to it. In your hook dll's private thread's message loop you would get these messages and could then directly call the exported function. Actually you wouldn't even have to export it this way.
Ahell
Posts: 31
Joined: Mon Feb 07, 2011 4:54 pm

Re: load and call DLL in another process

Post by Ahell »

Strange, but I can not really get a pointer to the procedure in the dll, which is in another process.

and if you do not check for nil, I write that "the paramter is given is not true."

can I do something wrong? attach the source ...

Please, help me.
Attachments
src.zip
this is my test project and test console application
(27.27 KiB) Downloaded 764 times
madshi
Site Admin
Posts: 10753
Joined: Sun Mar 21, 2004 5:25 pm

Re: load and call DLL in another process

Post by madshi »

Ahell wrote:I can not really get a pointer to the procedure in the dll
I need more details than that. What do you get? A nil pointer or what?
Ahell
Posts: 31
Joined: Mon Feb 07, 2011 4:54 pm

Re: load and call DLL in another process

Post by Ahell »

Yes,
In a variable myProc not a pointer to a callback function from the DLL in another process ..
See screenshot
Безымянный.JPG
Безымянный.JPG (88.48 KiB) Viewed 26875 times
if assigned(Pointer) then Pointer is not nil.
madshi
Site Admin
Posts: 10753
Joined: Sun Mar 21, 2004 5:25 pm

Re: load and call DLL in another process

Post by madshi »

Please check "LoadModule(...).IsValid". Is the module valid?
Ahell
Posts: 31
Joined: Mon Feb 07, 2011 4:54 pm

Re: load and call DLL in another process

Post by Ahell »

hm, something wrorng with me or with my code :o
i wrote this code, but my dll.dll does not loaded in process....

Code: Select all

procedure TForm1.Button1Click(Sender: TObject);
type
  TCallProc = procedure(aNewCaption: PChar);
var
  myProc: TCallProc;
  s: PChar;
  b: Boolean;
  i: Integer;
begin
  with Process('Console.exe') do
  begin
    if IsStillRunning then
    begin
      if FileExists(ExtractFilePath(ParamStr(0)) + 'dll.dll') then
      begin
      ShowMessage('DLL.dll are exists!');  //condition is satisfied
      end else
      ShowMessage('DLL.dll not found!');

      if not LoadModule(ExtractFilePath(ParamStr(0)) + 'dll.dll', false).IsValid then
      begin
       ShowMessage('LoadModule is not valid!');    //condition is satisfied
      end;

      for i := 0 to Modules.ItemCount - 1 do
      begin
        if Modules.Items[i].FileName = 'dll.dll' then
        begin
          @myProc := Modules.Items[i].GetProcAddress('SetWindowCaption');
          b := Assigned(myProc);
          if b then
          begin
            s := PChar(Edit1.text);
            ExecuteFunction(@myProc, 1000, @s, Length(s));
          end;
        end;
      end;
    end;
  end;
end;
The dll.dll are exists, but LoadModule not worked. What is wrong? :o
madshi
Site Admin
Posts: 10753
Joined: Sun Mar 21, 2004 5:25 pm

Re: load and call DLL in another process

Post by madshi »

You do have madExcept installed, correct?

Are you sure you have enough privileges to inject the dll into the target process? Try running your exe as admin.
Post Reply