Page 1 of 1

Simple: 'DLL injection'

Posted: Sun May 31, 2009 9:38 pm
by hipy001
Injecting a DLL into Another Process's

Code: Select all

Procedure InjectLibA(dwProcessId.l, pszLibFile$)
  hProcess.l
  hThread.l
  lzLibFileRemote.l
  lSize.l
  endSize.l
  lsThreadRtn.l
  
  hProcess = OpenProcess_(#PROCESS_QUERY_INFORMATION | #PROCESS_CREATE_THREAD | #PROCESS_VM_OPERATION | #PROCESS_VM_WRITE, 0, dwProcessId)
  
  If hProcess = 0 : Goto ErrHandle : EndIf
  lSize = 1 + Len(pszLibFile$)
  endSize = lSize
  
  lzLibFileRemote = VirtualAllocEx_(hProcess, #Null, endSize, #MEM_COMMIT, #PAGE_READWRITE)
  
  If lzLibFileRemote = 0 : Goto ErrHandle : EndIf
  
  If (WriteProcessMemory_(hProcess, lzLibFileRemote, pszLibFile$, endSize, #Null) = 0) : Goto ErrHandle : EndIf
  
  OpenLibrary(0, "Kernel32.dll") : lsThreadRtn = GetFunction(0, "LoadLibraryA") : CloseLibrary(0)
  
  If lsThreadRtn = 0 : Goto ErrHandle : EndIf
  
  hThread = CreateRemoteThread_(hProcess, #Null, #Null, lsThreadRtn, lzLibFileRemote, #Null, #Null)
  
  If (hThread = 0) : Goto ErrHandle : EndIf
  
  WaitForSingleObject_(hThread, #INFINITE)
  
  If lzLibFileRemote<>0
    VirtualFreeEx_(hProcess, lzLibFileRemote, 0, #MEM_RELEASE)
    MessageRequester("Hi", "Hi", 0)
  EndIf
  End
  
  ErrHandle:
      CloseHandle_(hThread)
      CloseHandle_(hProcess)
EndProcedure

InjectLibA('PiD - > ' 3680, "C:\test.dll")

Posted: Mon Jun 01, 2009 12:05 am
by cas
Is there any practical use of this?

Re: Simple: 'DLL injection'

Posted: Mon Jun 01, 2009 3:32 am
by PB
Got an example on what you'd use this for?

Posted: Mon Jun 01, 2009 4:02 am
by pdwyer
Read the contents of a pwd textbox! :P

Just the example sited by wikipedia

http://en.wikipedia.org/wiki/DLL_injection

I think this breaks on Vista and above anyway due to Address Space Layout Randomization or (ASLR)

Posted: Mon Jun 01, 2009 12:23 pm
by SFSxOI
nah, it works in Vista but just not in all cases.

Posted: Mon Jun 01, 2009 1:25 pm
by pdwyer
sounds reliable :P

Posted: Mon Jun 01, 2009 2:57 pm
by hipy001
works And Windows 7.

Posted: Mon Jun 01, 2009 5:07 pm
by SFSxOI
you injecting into games?

Posted: Sun Jun 21, 2009 1:23 pm
by SFSxOI
Below is code for a simple utility .dll injector i've been playing with. The injection portion is the simple injection code presented by hipy001 in this thread with a few minor changes and the addition of code for getting the PID for use in the injection code from hipy001.

Works in Vista 32 bit. I've only tested with non-native windows processes which are running with admin permissions. I have not tested with x64 or XP, and although I have Windows 7 installed on another drive i've not tested with Windows 7.

Code: Select all

Prototype.i PFNCreateToolhelp32Snapshot(dwFlags.i, th32ProcessID.i) ;
Prototype.b PFNProcess32First(hSnapshot.i, *lppe.PROCESSENTRY32) ;
Prototype.b PFNProcess32Next(hSnapshot.i, *lppe.PROCESSENTRY32) ;

Procedure GetPidByName(p_name$) 
    Protected hDLL.i, process_name$ 
    Protected PEntry.PROCESSENTRY32, hTool32.i 
    Protected pCreateToolhelp32Snapshot.PFNCreateToolhelp32Snapshot 
    Protected pProcess32First.PFNProcess32First 
    Protected pProcess32Next.PFNProcess32Next 
    Protected pid.i 
    
    hDLL = OpenLibrary(#PB_Any,"kernel32.dll") 
    
    If hDLL 
        pCreateToolhelp32Snapshot = GetFunction(hDLL,"CreateToolhelp32Snapshot") 
        pProcess32First = GetFunction(hDLL,"Process32First") 
        pProcess32Next = GetFunction(hDLL,"Process32Next") 
    Else 
        ProcedureReturn 0 
    EndIf 
    
    PEntry\dwSize = SizeOf(PROCESSENTRY32) 
    hTool32 = pCreateToolhelp32Snapshot(#TH32CS_SNAPPROCESS, 0) 
    pProcess32First(hTool32, @PEntry) 
    process_name$ = Space(#MAX_PATH) 
    CopyMemory(@PEntry\szExeFile,@process_name$,#MAX_PATH) 
    
    If  UCase(process_name$) = UCase(p_name$) 
        ProcedureReturn PEntry\th32ProcessID 
    EndIf 
    
    While pProcess32Next(hTool32, @PEntry) > 0 
        process_name$ = Space(#MAX_PATH) 
        CopyMemory(@PEntry\szExeFile,@process_name$,#MAX_PATH) 
        
        If  UCase(process_name$) = UCase(p_name$) 
            ProcedureReturn PEntry\th32ProcessID 
        EndIf 
    
    Wend 
    
    CloseLibrary(hDLL) 
    
    ProcedureReturn 0 
EndProcedure

Procedure InjectLibA(dwProcessId.i, pszLibFile$) 
  hProcess.i 
  hThread.i 
  lzLibFileRemote.i 
  lSize.i 
  endSize.i 
  lsThreadRtn.i 
  
  hProcess = OpenProcess_(#PROCESS_QUERY_INFORMATION | #PROCESS_CREATE_THREAD | #PROCESS_VM_OPERATION | #PROCESS_VM_WRITE, 0, dwProcessId) 
  
  If hProcess = 0 : Goto ErrHandle : EndIf 
  lSize = 1 + Len(pszLibFile$) 
  endSize = lSize 
  
  lzLibFileRemote = VirtualAllocEx_(hProcess, #Null, endSize, #MEM_COMMIT, #PAGE_READWRITE) 
  
  If lzLibFileRemote = 0 : Goto ErrHandle : EndIf 
  
  If (WriteProcessMemory_(hProcess, lzLibFileRemote, pszLibFile$, endSize, #Null) = 0) : Goto ErrHandle : EndIf 
  
  OpenLibrary(0, "Kernel32.dll") : lsThreadRtn = GetFunction(0, "LoadLibraryA") : CloseLibrary(0) 
  
  If lsThreadRtn = 0 : Goto ErrHandle : EndIf 
  
  hThread = CreateRemoteThread_(hProcess, #Null, #Null, lsThreadRtn, lzLibFileRemote, #Null, #Null) 
  
  If (hThread = 0) : Goto ErrHandle : EndIf 
  
  WaitForSingleObject_(hThread, #INFINITE) 
  
  If lzLibFileRemote<>0 
    VirtualFreeEx_(hProcess, lzLibFileRemote, 0, #MEM_RELEASE) 
    MessageRequester("Inject Status", "Injection Suceeded", 0)
    Else
    VirtualFreeEx_(hProcess, lzLibFileRemote, 0, #MEM_RELEASE) 
    MessageRequester("Inject Status", "Injection Failed !!!", 0)
  EndIf 
  End 
  
  ErrHandle: 
      CloseHandle_(hThread) 
      CloseHandle_(hProcess) 
EndProcedure

Input_proc$ = InputRequester("Simple DLL injector", "Please enter target process name (.exe):", "") ;enter process name i.e...notepad.exe
val_pid.i = GetPidByName(Input_proc$)
Delay(10)
File_dll$ = OpenFileRequester("Choose .dll file to inject", "C:\", "DLL File (*.dll)|*.dll;*.dll", 0)
Delay(10)
InjectLibA(val_pid, File_dll$)
Maybe adding something to browse and select the running process instead of manually entering a process .exe name would make it more user friendly but this is OK just to play around with. And...if you wanted to use Srod's fine COMate you can get the PID (and other information about the process). I used the above because its been sort of one of my staples...but here is a COMate version for use with the injector code:

Code: Select all

XIncludeFile "COMate.pbi"

Procedure Proces_Now(p_name$)

Define.COMateObject objWMIService, objProcess
colProcessList.COMateEnumObject
strComputer.s = "."

objWMIService = COMate_GetObject("winmgmts:{impersonationLevel=impersonate}!\\" + strComputer + "\root\cimv2")
If objWMIService
  colProcessList = objWMIService\CreateEnumeration("ExecQuery('Select * from Win32_Process')")
  
  If colProcessList
    objProcess = colProcessList\GetNextObject()
    While objProcess
    
    Process_name$ = objProcess\GetStringProperty("Name")
    Process_Id$ = Str(objProcess\GetIntegerProperty("ProcessId"))
    Process_handle$ = Str(objProcess\GetIntegerProperty("Handle"))
    Executable_Path$ = objProcess\GetStringProperty("ExecutablePath")
        
    If  UCase(Process_name$) = UCase(p_name$)
    Process_name_PID.i = Val(Process_Id$)  
    EndIf
        
      objProcess\Release()
      objProcess = colProcessList\GetNextObject()
    Wend
    colProcessList\Release()
  EndIf
  objWMIService\Release()
Else
  MessageRequester("Error", "ProcInfo")
EndIf

ProcedureReturn Process_name_PID

EndProcedure

Procedure InjectLibA(dwProcessId.i, pszLibFile$) 
  hProcess.i 
  hThread.i 
  lzLibFileRemote.i 
  lSize.i 
  endSize.i 
  lsThreadRtn.i 
  
  hProcess = OpenProcess_(#PROCESS_QUERY_INFORMATION | #PROCESS_CREATE_THREAD | #PROCESS_VM_OPERATION | #PROCESS_VM_WRITE, 0, dwProcessId) 
  
  If hProcess = 0 : Goto ErrHandle : EndIf 
  lSize = 1 + Len(pszLibFile$) 
  endSize = lSize 
  
  lzLibFileRemote = VirtualAllocEx_(hProcess, #Null, endSize, #MEM_COMMIT, #PAGE_READWRITE) 
  
  If lzLibFileRemote = 0 : Goto ErrHandle : EndIf 
  
  If (WriteProcessMemory_(hProcess, lzLibFileRemote, pszLibFile$, endSize, #Null) = 0) : Goto ErrHandle : EndIf 
  
  OpenLibrary(0, "Kernel32.dll") : lsThreadRtn = GetFunction(0, "LoadLibraryA") : CloseLibrary(0) 
  
  If lsThreadRtn = 0 : Goto ErrHandle : EndIf 
  
  hThread = CreateRemoteThread_(hProcess, #Null, #Null, lsThreadRtn, lzLibFileRemote, #Null, #Null) 
  
  If (hThread = 0) : Goto ErrHandle : EndIf 
  
  WaitForSingleObject_(hThread, #INFINITE) 
  
  If lzLibFileRemote<>0 
    VirtualFreeEx_(hProcess, lzLibFileRemote, 0, #MEM_RELEASE) 
    MessageRequester("Inject Status", "Injection Suceeded", 0)
    Else
    VirtualFreeEx_(hProcess, lzLibFileRemote, 0, #MEM_RELEASE) 
    MessageRequester("Inject Status", "Injection Failed !!!", 0)
  EndIf 
  End 
  
  ErrHandle: 
      CloseHandle_(hThread) 
      CloseHandle_(hProcess) 
EndProcedure

Input_proc$ = InputRequester("Simple Utility Injector", "Please enter target process name (.exe):", "")
val_pid.i = Proces_Now(Input_proc$)
Delay(10)
File_dll$ = OpenFileRequester("Choose .dll file to inject", "C:\", "DLL File (*.dll)|*.dll;*.dll", 0)
Delay(10)
InjectLibA(val_pid, File_dll$)
I'm going to use COMate in a more advanced version of an injector tool.

Re: Simple: 'DLL injection'

Posted: Sun Jun 28, 2009 3:57 pm
by Michael Vogel
PB wrote:Got an example on what you'd use this for?
Would this routine allow to do the following:

I have an old windows game named Civ2 which uses obviously the PeekMessageA function for checking messages. The result is a high CPU load for the whole time, the game is played.

What about doing a hack to inject(?) a modified PeekMessageA routine which does not use that high amount of CPU load into the civ2.exe?

Thanks,
Michael

Re: Simple: 'DLL injection'

Posted: Sun Jun 28, 2009 4:34 pm
by SFSxOI
Michael Vogel wrote:
PB wrote:Got an example on what you'd use this for?
Would this routine allow to do the following:

I have an old windows game named Civ2 which uses obviously the PeekMessageA function for checking messages. The result is a high CPU load for the whole time, the game is played.

What about doing a hack to inject(?) a modified PeekMessageA routine which does not use that high amount of CPU load into the civ2.exe?

Thanks,
Michael
Yep, you can do that. I borrowed a game from a friend who's out of town right now to experiment with this on, Call of Duty 4, and I injected a game cheat I found on the 'net just to see if everything would work and if it was possible to do 'modifications' to things, worked like a charm. I even created a small dll that toggles a memory location in the game and turns the mini-map on and off. So i'm sure you could do your PeekMessageA thing if you simply found the memory location of it and bypassed by NOop'ong it out and then directing to your own.

Re: Simple: 'DLL injection'

Posted: Sun Jun 28, 2009 11:08 pm
by Michael Vogel
SFSxOI wrote:[...]So i'm sure you could do your PeekMessageA thing if you simply found the memory location of it and bypassed by NOop'ong it out and then directing to your own.[...]
Oooh :shock:
I've to search the memory for the opcode? :evil: Sounds not that easy for me, I thought it acts like catching a certain call :oops:

So this is the first "solution", which works fine - maybe there's also a way to replace the CPUThrottle.dll by a Purebasic made one (I have no idea what's inside the dll which I have downloaded from the internet :evil:)

Code: Select all

PID.i=GetPidByName("ntvdm.exe")
If PID
	InjectLibA(PID,"CPUThrottle.dll")
Else
	MessageRequester("Achtung!","CIV does not run!")
EndIf
Michael

Posted: Mon Jun 29, 2009 7:41 pm
by SFSxOI
Very basically from the way I understand it, leading to the way I did it experimentally; you NO'op the one function (PeekMessageA in your case) by placing the NOOP code 90's in the command line then you have a jump to your function and when the function use is finished it returns back to where the main program picks up again originally where it would have continued if the PeekMessageA was still in place . Or....you replace the original function with a jump to your routine so the original function is bypassed and do it all again. Or....I guess that if you just did not want the PeekMessageA to work at all you could just NOOP it and leave it at that.

I don't really do games myself and had just borrowed the COD 4 to have something else to experiment with. But while searching around for ways to do this I came across this > http://www.codeproject.com/KB/cpp/codecave.aspx < which explains it all pretty much using something called Code Caves. And also this one > http://www.codeproject.com/KB/cpp/funccaller.aspx

Re: Simple: 'DLL injection'

Posted: Thu Jun 15, 2017 9:52 pm
by Lunasole
Here is some update of @SFSxOI utility (slightly modified for unicode support + few "cosmetic" changes).
I wondered if it will work on Win7 or newer, but it worked fine :mrgreen:

Code: Select all

EnableExplicit

Procedure GetPidByName(p_name$) 
	Protected process_name$ 
	Protected PEntry.PROCESSENTRY32
	Protected hTool32, pid
	
	PEntry\dwSize = SizeOf(PROCESSENTRY32) 
	hTool32 = CreateToolhelp32Snapshot_(#TH32CS_SNAPPROCESS, 0) 
	p_name$ = UCase(p_name$) 
	
	Process32First_(hTool32, @PEntry) 
	process_name$ = Space(#MAX_PATH) 
	CopyMemory(@PEntry\szExeFile,@process_name$,#MAX_PATH) 
	
	If UCase(process_name$) = p_name$
		pid = PEntry\th32ProcessID 
	Else
		While Process32Next_(hTool32, @PEntry) > 0 
			process_name$ = Space(#MAX_PATH) 
			CopyMemory(@PEntry\szExeFile,@process_name$,#MAX_PATH) 
			If UCase(process_name$) = p_name$
				pid = PEntry\th32ProcessID
				Break
			EndIf 
		Wend     
	EndIf 
	CloseHandle_(hTool32)
	
	ProcedureReturn pid
EndProcedure

; This one injects library to a target process
; Both DLL and process must be unicode
; For ASCII: change LoadLibraryW > LoadLibraryA, and modify strings related to pszLibFile$
Procedure InjectLibW(dwProcessId, pszLibFile$) 
	Protected hProcess, hThread, lzLibFileRemote, endSize, lsThreadRtn
	
	hProcess = OpenProcess_(#PROCESS_QUERY_INFORMATION | #PROCESS_CREATE_THREAD | #PROCESS_VM_OPERATION | #PROCESS_VM_WRITE, 0, dwProcessId) 
	
	If hProcess = 0 : Goto ErrHandle : EndIf 
	endSize = 1 + StringByteLength(pszLibFile$) 
	
	lzLibFileRemote = VirtualAllocEx_(hProcess, #Null, endSize, #MEM_COMMIT, #PAGE_READWRITE) 
	
	If lzLibFileRemote = 0 : Goto ErrHandle : EndIf 
	
	If (WriteProcessMemory_(hProcess, lzLibFileRemote, pszLibFile$, endSize, #Null) = 0) : Goto ErrHandle : EndIf 
	
	OpenLibrary(0, "Kernel32.dll") : lsThreadRtn = GetFunction(0, "LoadLibraryW") : CloseLibrary(0) 
	
	If lsThreadRtn = 0 : Goto ErrHandle : EndIf 
	
	hThread = CreateRemoteThread_(hProcess, #Null, #Null, lsThreadRtn, lzLibFileRemote, #Null, #Null) 
	
	If (hThread = 0) : Goto ErrHandle : EndIf 
	
	WaitForSingleObject_(hThread, #INFINITE) 
	
	If lzLibFileRemote<>0 
		VirtualFreeEx_(hProcess, lzLibFileRemote, 0, #MEM_RELEASE) 
		MessageRequester("Inject Status", "Injection Suceeded", 0)
	Else
		VirtualFreeEx_(hProcess, lzLibFileRemote, 0, #MEM_RELEASE) 
		MessageRequester("Inject Status", "Injection Failed !!!", 0)
	EndIf 
	End 
	
	ErrHandle: 
	CloseHandle_(hThread) 
	CloseHandle_(hProcess) 
EndProcedure


;------------------------------------
Define Input_proc$ = InputRequester("Simple DLL injector", "Please enter target process name (.exe):", "") ;enter process name i.e...notepad.exe
Define val_pid = GetPidByName(Input_proc$)
Define File_dll$

Delay(10)
If val_pid
	File_dll$ = OpenFileRequester("Choose .dll file to inject", "C:\", "DLL File (*.dll)|*.dll;*.dll", 0)
	Delay(10)
	InjectLibW(val_pid, File_dll$)
Else
	MessageRequester("Inject Status", "val_pid = 0", 0)
EndIf

Re: Simple: 'DLL injection'

Posted: Fri Jun 23, 2017 3:24 am
by Opcode
Lunasole wrote:Here is some update of @SFSxOI utility (slightly modified for unicode support + few "cosmetic" changes).
I wondered if it will work on Win7 or newer, but it worked fine :mrgreen:

Code: Select all

- snip -
Works fine on Windows 10 x64 with PB 5.31 in both unicode and ascii with a simple compiler if statement. Here's my quick tidy and edit with a few improvements.

Code: Select all

EnableExplicit

Procedure GetPidByName(pName.s)
  
  Protected.s processName.s = Space(#MAX_PATH)
  Protected pEntry.PROCESSENTRY32
  Protected.i hTool32, pId
  
  pEntry\dwSize = SizeOf(PROCESSENTRY32)
  hTool32 = CreateToolhelp32Snapshot_(#TH32CS_SNAPPROCESS, 0)
  pName = UCase(pName)
  
  Process32First_(hTool32, @pEntry)
  CopyMemory(@pEntry\szExeFile, @processName, #MAX_PATH)
  
  If UCase(processName) = pName
    pId = pEntry\th32ProcessID
  Else
    While Process32Next_(hTool32, @pEntry) > 0
      CopyMemory(@pEntry\szExeFile, @processName, #MAX_PATH)
      If UCase(processName) = pName
        pId = PEntry\th32ProcessID
        Break
      EndIf
    Wend
  EndIf
  
  CloseHandle_(hTool32)
  
  ProcedureReturn pId
  
EndProcedure

; Inject Library To A Target Process
; Both DLL And Process Must Be Unicode
; For ASCII: Change LoadLibraryW > LoadLibraryA And Modify Strings Related To pszLibFile
Procedure LoadLibrary(dwProcessId.i, pszLibFile.s)
  
  Protected.i hProcess, hThread, lzLibFileRemote, endSize, lsThreadRtn
  
  hProcess = OpenProcess_(#PROCESS_QUERY_INFORMATION | #PROCESS_CREATE_THREAD | #PROCESS_VM_OPERATION | #PROCESS_VM_WRITE, 0, dwProcessId)
  
  If hProcess = 0 : Goto ErrHandle : EndIf
  endSize = 1 + StringByteLength(pszLibFile)
  
  lzLibFileRemote = VirtualAllocEx_(hProcess, #Null, endSize, #MEM_COMMIT, #PAGE_READWRITE)
  
  If lzLibFileRemote = 0 : Goto ErrHandle : EndIf
  
  If WriteProcessMemory_(hProcess, lzLibFileRemote, pszLibFile, endSize, #Null) = 0 : Goto ErrHandle : EndIf
  
  CompilerIf #PB_Compiler_Unicode
    OpenLibrary(0, "Kernel32.dll") : lsThreadRtn = GetFunction(0, "LoadLibraryW") : CloseLibrary(0) 
  CompilerElse
    OpenLibrary(0, "Kernel32.dll") : lsThreadRtn = GetFunction(0, "LoadLibraryA") : CloseLibrary(0) 
  CompilerEndIf
  
  If lsThreadRtn = 0 : Goto ErrHandle : EndIf
  
  hThread = CreateRemoteThread_(hProcess, #Null, #Null, lsThreadRtn, lzLibFileRemote, #Null, #Null)
  
  If hThread = 0 : Goto ErrHandle : EndIf
  
  WaitForSingleObject_(hThread, #INFINITE)
  
  If lzLibFileRemote <> 0 
    VirtualFreeEx_(hProcess, lzLibFileRemote, 0, #MEM_RELEASE)
    MessageRequester("Inject Status", "Injection Suceeded!", #MB_ICONINFORMATION)
  Else
    VirtualFreeEx_(hProcess, lzLibFileRemote, 0, #MEM_RELEASE)
    MessageRequester("Inject Status", "Injection Failed!", #MB_ICONERROR)
  EndIf
  End
  
  ErrHandle:
  CloseHandle_(hThread)
  CloseHandle_(hProcess)
  
EndProcedure

; ----- Main Program -----

CompilerIf #PB_Compiler_IsMainFile
  
  Define.s nDLL, procName = InputRequester("Simple DLL Injector", "Enter Target Process Name (*.exe):", "")
  Define.i pId = GetPidByName(procName)
  
  If pId
    nDLL = OpenFileRequester("Choose DLL File To Inject", "C:\", "DLL File (*.dll)|*.dll;*.dll", 0)
    LoadLibrary(pId, nDLL)
  Else
    MessageRequester("Error", "Process ID Not Found!", #MB_ICONERROR)
  EndIf
  
CompilerEndIf