Cheat Engine Forum Index Cheat Engine
The Official Site of Cheat Engine
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 


.dll injection from Free Pascal

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> General programming
View previous topic :: View next topic  
Author Message
Luig
Cheater
Reputation: 0

Joined: 24 Sep 2010
Posts: 26

PostPosted: Wed Feb 23, 2011 8:39 pm    Post subject: .dll injection from Free Pascal Reply with quote

Alright, I finally created a working injectable .dll trainer in free pascal although it ended up being 11.8 mb in size. Now I want some way to inject the .dll from Free Pascal. The following code ends up in an access violation.

Code:
Function InjectDll(ProcessID: DWORD; LibraryName: String): Integer;
const
  MAX_LIBRARYNAME   =  MAX_PATH;
  MAX_FUNCTIONNAME  =  255;
  MIN_INSTRSIZE     =  5;
Type
  PLibRemote        =  ^TLibRemote;
  TLibRemote        =  packed record
     ProcessID:     DWORD;
     LibraryName:   Array [0..MAX_LIBRARYNAME] of Char;
     LibraryHandle: HMODULE;
  end;
var  hKernel:       HMODULE;
     hProcess:      THandle;
     hThread:       THandle;
     dwNull:        Cardinal;
     lpRemote:      PLibRemote;
     lpLibRemote:   PChar;


Begin
     // Set default result of (-1), which means the injection failed
     result:=(-1);
     // Check library name and version of OS we are running on
     if (Length(LibraryName) > 0) and ((GetVersion and $80000000) = 0)then
     begin
        Result := 2;
        // Attempt to open the process
        hProcess:=OpenProcess(PROCESS_VM_OPERATION, False, ProcessID);
        // Check process handle
        if (hProcess <> 0) then
        begin
           // Resource protection
           try
              Result:= 3;
              // Get module handle for kernel32
              hKernel:=GetModuleHandle('kernel32.dll');
              // Check handle
              if (hKernel <> 0) then
              begin
                Result := 4;
                 // Allocate memory in other process
                 lpLibRemote:=VirtualAllocEx(hProcess, nil, Succ(Length(LibraryName)), MEM_COMMIT, PAGE_READWRITE);
                 // Check memory pointer
                 if Assigned(lpLibRemote) then
                 begin
                    // Resource protection
                    try
                      Result := 5;
                       // Write the library name to the memory in other process
                       WriteProcessMemory(hProcess, lpLibRemote, PChar(LibraryName), Length(LibraryName), dwNull);
                       // Create the remote thread
                       hThread:=CreateRemoteThread(hProcess, nil, 0, GetProcAddress(hKernel, 'LoadLibraryA'), lpLibRemote, 0, dwNull);
                       // Check the thread handle
                       if (hThread <> 0) then
                       begin
                          // Resource protection
                          try
                             // Allocate a new remote injection record
                             lpRemote:=AllocMem(SizeOf(TLibRemote));
                             // Set process id
                             lpRemote^.ProcessID:=ProcessID;
                             // Copy library name
                             StrPLCopy(lpRemote^.LibraryName, LibraryName, MAX_LIBRARYNAME);
                             // Wait for the thread to complete
                             WaitForSingleObject(hThread, INFINITE);
                             // Fill in the library handle
                             GetExitCodeThread(hThread, DWORD(lpRemote^.LibraryHandle));
                             // Add to list
                             result:=1;
                          finally
                             // Close the thread handle
                             CloseHandle(hThread);
                          end;
                       end;
                    finally
                       // Free allocated memory
                       VirtualFree(lpLibRemote, 0, MEM_RELEASE);
                    end;
                 end;
              end;
           finally
              // Close the process handle
              CloseHandle(hProcess);
           end;
        end;
     end;
End;


Calling it like this:
Code:
procedure TForm1.Button2Click(Sender: TObject);
Var
   PID:DWORD;
   WHnd:THandle;
   Check:Integer;
begin
  Whnd := FindWindow(nil, 'Adobe Flash Player 9');
  GetWindowThreadProcessID(Whnd, @PID);
  Check := InjectDll(PID, ExtractFilePath(Application.ExeName + 'SpeedHack.dll'));
    ShowMessage('Successfully injected .dll');
    ShowMessage(IntToStr(Check));
end; 
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 471

Joined: 09 May 2003
Posts: 25856
Location: The netherlands

PostPosted: Wed Feb 23, 2011 8:45 pm    Post subject: Reply with quote

tip to cut down on the size:

project options->linking. Untick dsplay line numbers and tick "Strip symbols from executable"

as for the crash, where does the exception happen. Game or injector?
Anyhow,
Code:

Check := InjectDll(PID, ExtractFilePath(Application.ExeName + 'SpeedHack.dll'));

I'd change it to
Check := InjectDll(PID, ExtractFilePath(Application.ExeName) + 'SpeedHack.dll');


and I'd also add PROCESS_VM_WRITE PROCESS_VM_READ , PROCESS_CREATE_THREAD and PROCESS_QUERY_INFORMATION to openprocess

_________________
Do not ask me about online cheats. I don't know any and wont help finding them.

Like my help? Join me on Patreon so i can keep helping
Back to top
View user's profile Send private message MSN Messenger
Luig
Cheater
Reputation: 0

Joined: 24 Sep 2010
Posts: 26

PostPosted: Wed Feb 23, 2011 9:02 pm    Post subject: Reply with quote

Thanks for the quick reply Dark Byte and tips. This is my following code and I still get Access Violation.

Code:
procedure TForm1.Button2Click(Sender: TObject);
Var
   PID:DWORD;
   WHnd:THandle;
   Check:Integer;
begin
  Whnd := FindWindow(nil, 'Adobe Flash Player 9');
  GetWindowThreadProcessID(Whnd, @PID);
  Check := InjectDll(PID, ExtractFilePath(Application.ExeName) + 'SpeedHack.dll');
    ShowMessage('Successfully injected .dll');
    ShowMessage(IntToStr(Check));
end;

Function InjectDll(ProcessID: DWORD; LibraryName: String): Integer;
const
  MAX_LIBRARYNAME   =  MAX_PATH;
  MAX_FUNCTIONNAME  =  255;
  MIN_INSTRSIZE     =  5;
Type
  PLibRemote        =  ^TLibRemote;
  TLibRemote        =  packed record
     ProcessID:     DWORD;
     LibraryName:   Array [0..MAX_LIBRARYNAME] of Char;
     LibraryHandle: HMODULE;
  end;
var  hKernel:       HMODULE;
     hProcess:      THandle;
     hThread:       THandle;
     dwNull:        Cardinal;
     lpRemote:      PLibRemote;
     lpLibRemote:   PChar;


Begin
     // Set default result of (-1), which means the injection failed
     result:=(-1);
     // Check library name and version of OS we are running on
     if (Length(LibraryName) > 0) and ((GetVersion and $80000000) = 0)then
     begin
        Result := 2;
        // Attempt to open the process
        hProcess:=OpenProcess(PROCESS_VM_OPERATION+PROCESS_CREATE_THREAD+PROCESS_QUERY_INFORMATION , False, ProcessID);
        // Check process handle
        if (hProcess <> 0) then
        begin
           // Resource protection
           try
              Result:= 3;
              // Get module handle for kernel32
              hKernel:=GetModuleHandle('kernel32.dll');
              // Check handle
              if (hKernel <> 0) then
              begin
                Result := 4;
                 // Allocate memory in other process
                 lpLibRemote:=VirtualAllocEx(hProcess, nil, Succ(Length(LibraryName)), MEM_COMMIT, PAGE_READWRITE);
                 // Check memory pointer
                 if Assigned(lpLibRemote) then
                 begin
                    // Resource protection
                    try
                      Result := 5;
                       // Write the library name to the memory in other process
                       WriteProcessMemory(hProcess, lpLibRemote, PChar(LibraryName), Length(LibraryName), dwNull);
                       // Create the remote thread
                       hThread:=CreateRemoteThread(hProcess, nil, 0, GetProcAddress(hKernel, 'LoadLibraryA'), lpLibRemote, 0, dwNull);
                       // Check the thread handle
                       if (hThread <> 0) then
                       begin
                          // Resource protection
                          try
                             // Allocate a new remote injection record
                             lpRemote:=AllocMem(SizeOf(TLibRemote));
                             // Set process id
                             lpRemote^.ProcessID:=ProcessID;
                             // Copy library name
                             StrPLCopy(lpRemote^.LibraryName, LibraryName, MAX_LIBRARYNAME);
                             // Wait for the thread to complete
                             WaitForSingleObject(hThread, INFINITE);
                             // Fill in the library handle
                             GetExitCodeThread(hThread, DWORD(lpRemote^.LibraryHandle));
                             // Add to list
                             result:=1;
                          finally
                             // Close the thread handle
                             CloseHandle(hThread);
                          end;
                       end;
                    finally
                       // Free allocated memory
                       VirtualFree(lpLibRemote, 0, MEM_RELEASE);
                    end;
                 end;
              end;
           finally
              // Close the process handle
              CloseHandle(hProcess);
           end;
        end;
     end;
End;


According to msdn if I declare PROCESS_VM_OPERATION it allows the use of WriteProcessMemory and it doesn't crash, my injector just throws an access violation error.
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 471

Joined: 09 May 2003
Posts: 25856
Location: The netherlands

PostPosted: Wed Feb 23, 2011 9:25 pm    Post subject: Reply with quote

the msdn on writeprocessmemory says :"The handle must have PROCESS_VM_WRITE and PROCESS_VM_OPERATION access to the process."

but again, what part is the access violation in? The target process or your app ?

anyhow, just set a breakpoint and step through the code to find out where it goes bad

_________________
Do not ask me about online cheats. I don't know any and wont help finding them.

Like my help? Join me on Patreon so i can keep helping
Back to top
View user's profile Send private message MSN Messenger
Luig
Cheater
Reputation: 0

Joined: 24 Sep 2010
Posts: 26

PostPosted: Sat Feb 26, 2011 12:44 am    Post subject: Reply with quote

Alright, I still can't get that function to work. The problem lies in writeprocessmemory. It just raises Access Violation. The interesting part is that this code:
Code:
procedure InjectDll3(PID: dword;  DLL: pChar);
var
  BytesWritten, hProcess, hThread, TID: Cardinal;
  Parameters: pointer;
  pThreadStartRoutine: Pointer;
begin
  hProcess := OpenProcess(PROCESS_ALL_ACCESS,  False,  PID);
  Parameters := VirtualAllocEx( hProcess, nil, Length(DLL), MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE);
  WriteProcessMemory(hProcess,Parameters,DLL,Length(DLL),BytesWritten);
  pThreadStartRoutine := GetProcAddress(GetModuleHandle('kernel32.dll'), 'LoadLibraryA');
  hThread := CreateRemoteThread(hProcess,  nil,  0,  pThreadStartRoutine,  Parameters,  0,  BytesWritten);
  CloseHandle(hProcess);
end;

can actually write to the process but this one causes the target process to crash. I just need a simple function I can use to inject a .dll into a target process. If someone could provide one that works in Free Pascal, that would be truly appreciated.
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 471

Joined: 09 May 2003
Posts: 25856
Location: The netherlands

PostPosted: Sat Feb 26, 2011 6:46 am    Post subject: Reply with quote

ce's dll injection obviously works, but I make use of a slightly more fail proof injector using auto assembler

as for this code:
1: try replacing length(dll) with length(dll+1) so the 0 terminator is written as well, just in case the memory is not zero'd on alloc (weird, but might happen if you use a selfwritten alloc)

2: the dll you pass has the FULL path ?


3: you are sure your dll and target process are 32-bit right ?

4: If you inject your dll with ce into the target process, does it crash then as well ?

_________________
Do not ask me about online cheats. I don't know any and wont help finding them.

Like my help? Join me on Patreon so i can keep helping
Back to top
View user's profile Send private message MSN Messenger
DeletedUser14087
I post too much
Reputation: 2

Joined: 21 Jun 2006
Posts: 3069

PostPosted: Sat Feb 26, 2011 10:26 am    Post subject: Reply with quote

You need SeDebugPrivilege privilege enabled, this is known for Pascal / Delphi.
Back to top
View user's profile Send private message
Luig
Cheater
Reputation: 0

Joined: 24 Sep 2010
Posts: 26

PostPosted: Sat Feb 26, 2011 11:46 am    Post subject: Reply with quote

I retrieved SEDebugPrivileges, tried the +1, I am sure both are 32 bit, I believe I am writing the whole path, I can inject just fine from AutoIt or CE. I still crash the target program when I use the function that can actually write to the memory. The other function still raises an exception at writeprocessmemory.
Back to top
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 471

Joined: 09 May 2003
Posts: 25856
Location: The netherlands

PostPosted: Sat Feb 26, 2011 6:26 pm    Post subject: Reply with quote

in the first function step through and see if you can find out why. (sounds like a nil pointer)

debug that other function as well and CONFIRM that the path of the dll is valid

Actually, just add this code at the beginning:
Code:

  if (not fileexists(dll)) or (pos(directoryseperator, dll)=0) then
    raise exception.create('The dll path is wrong');


also, i see a lot of your code is based on C code (especially the first routine)
remember that in pascal strings do NOT require \\ for directory seperators. so : c:\bla\mydll.dll and NOT c:\\bla\\mydll.dll

_________________
Do not ask me about online cheats. I don't know any and wont help finding them.

Like my help? Join me on Patreon so i can keep helping
Back to top
View user's profile Send private message MSN Messenger
Luig
Cheater
Reputation: 0

Joined: 24 Sep 2010
Posts: 26

PostPosted: Sat Feb 26, 2011 6:46 pm    Post subject: Reply with quote

I just did a showmessage(dll) and confirmed it passes the correct path. I've been trying to debug these functions to atleast get 1 of them to work. No such luck.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> General programming All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites