Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

[SOLVED]get other process's working dir


  • Please log in to reply
61 replies to this topic
HotKeyIt
  • Moderators
  • 7439 posts
  • Last active: Jun 22 2016 09:14 PM
  • Joined: 18 Jun 2008
Yes it does, just make sure that all types are defined (PPROCESS_PARAMETERS).

TLM
  • Administrators
  • 3864 posts
  • Last active:
  • Joined: 21 Aug 2006
You guys wrok :D!

Posted Image

don't duplicate, iterate!


amnesiac
  • Members
  • 124 posts
  • Last active: May 01 2014 03:04 AM
  • Joined: 07 Nov 2010
@HotKeyIt, Thank you.
For your code last time, if don't use machine code, how can I pass the ThreadProc function's code to object process? Is it possible?
I want to learn to do it and ahk code is intuitive for me (I know machine code is better in practice).

Click to download Chinese resource for AutoHotkey.

Recommended: AutoHotkey_L My code is based on it or similar versions, e.g. AutoHotkey_H.
Together with AutoHotkey, we grow and march forward. No matter how the future will be, this period of days is still epic.


HotKeyIt
  • Moderators
  • 7439 posts
  • Last active: Jun 22 2016 09:14 PM
  • Joined: 18 Jun 2008

That won't be possible as far as I understand icon_exclaim.gif

I have put together InjectAhkDll(), now you can inject AutoHotkey.dll in another process and execute ahk code as much as you like biggrin.png
icon_exclaim.gif requires latest AutoHotkey.dll (07.10.12) icon_exclaim.gif

 

EDIT 08.11.2015: Fixed bugs for 64-bit
EDIT 12.11.2012: updated to support 64-bit (requires _Struct now)

EDIT 25.12.2012: you can now pass a script to be used instead of starting an empty script.

Example, display working directory of notepad.exe process:

Process,Exist, notepad.exe
If !PID:=ErrorLevel
Run notepad.exe,,,PID
rThread:=InjectAhkDll(PID,A_ScriptDir "\AutoHotkeyMini.dll","#Persistent`nMsgBox % A_WorkingDir")
Sleep 500
rThread.Exec("MsgBox % A_AhkPath")
)']- PID - must be a PID of existing process.

- dll - path to AutoHotkey.dll or AutoHotkeyMini.dll

- script - this parameter is used when code needs to be executed, see Exec method.

 

METHODS:

- Exec(Script) - execute AHK code, Script must be text containing AutoHotkey script to execute

 

CLEANUP

- AutoHotkey dll is unloaded from remote process when object is deleted.

 
#Include <_Struct>
InjectAhkDll(PID,dll="AutoHotkey.dll",script=0){
  static PROCESS_ALL_ACCESS:=0x1F0FFF,MEM_COMMIT := 0x1000,MEM_RELEASE:=0x8000,PAGE_EXECUTE_READWRITE:=64
        ,hKernel32:=DllCall("LoadLibrary","Str","kernel32.dll","PTR"),LoadLibraryA:=DllCall("GetProcAddress","PTR",hKernel32,"AStr","LoadLibraryA","PTR")
        ,base:={__Call:"InjectAhkDll",__Delete:"InjectAhkDll"},FreeLibrary:=DllCall("GetProcAddress","PTR",hKernel32,"AStr","FreeLibrary","PTR")
  static TH32CS_SNAPMODULE:=0x00000008,INVALID_HANDLE_VALUE:=-1
        ,MAX_PATH:=260,MAX_MODULE_NAME32:=255,ModuleName:="",init:=VarSetCapacity(ModuleName,MAX_PATH*(A_IsUnicode?2:1))
        ,_MODULEENTRY32:="
        (
          DWORD   dwSize;
          DWORD   th32ModuleID;
          DWORD   th32ProcessID;
          DWORD   GlblcntUsage;
          DWORD   ProccntUsage;
          BYTE    *modBaseAddr;
          DWORD   modBaseSize;
          HMODULE hModule;
          TCHAR   szModule[" MAX_MODULE_NAME32 + 1 "];
          TCHAR   szExePath[" MAX_PATH "];
        )"
 
  If IsObject(PID){
    If (dll!="Exec" && script)
      return DllCall("MessageBox","PTR",0,"Str","Only Exec method can be used here!","STR","Error","UInt",0)
    
    hProc := DllCall("OpenProcess", "UInt", PROCESS_ALL_ACCESS, "Int",0, "UInt", PID.PID,"PTR")
    If !hProc
      return DllCall("MessageBox","PTR",0,"Str","Could not open process for PID: " PID.PID,"STR","Error","UInt",0)
    
    if (!script) ; Free Library in remote process (object is being deleted)
    {
      ; Terminate the thread in ahkdll
      hThread := DllCall("CreateRemoteThread", "PTR", hProc, "PTR", 0, "PTR", 0, "PTR", PID.ahkTerminate, "PTR", 0, "UInt", 0, "PTR", 0,"PTR")
      DllCall("WaitForSingleObject", "PTR", hThread, "UInt", 0xFFFFFFFF)
      ,DllCall("CloseHandle", "PTR", hThread)
      
      ; Free library in remote process
      hThread := DllCall("CreateRemoteThread", "PTR", hProc, "UInt", 0, "UInt", 0, "PTR", FreeLibrary, "PTR", PID.hModule, "UInt", 0, "UInt", 0,"PTR")
      DllCall("WaitForSingleObject", "PTR", hThread, "UInt", 0xFFFFFFFF)
      ,DllCall("CloseHandle", "PTR", hThread),DllCall("CloseHandle", "PTR", hProc)
      return
    }
    
    nScriptLength := VarSetCapacity(nScript, (StrLen(script)+1)*(A_IsUnicode?2:1), 0)
    ,StrPut(script,&nScript)
    
    ; Reserve memory in remote process where our script will be saved
    If !pBufferRemote := DllCall("VirtualAllocEx", "Ptr", hProc, "Ptr", 0, "PTR", nScriptLength, "UInt", MEM_COMMIT, "UInt", PAGE_EXECUTE_READWRITE, "Ptr")
      return DllCall("MessageBox","PTR",0,"Str","Could not reseve memory for process.","STR","Error","UInt",0)
            ,DllCall("CloseHandle", "PTR", hProc)
 
    ; Write script to remote process memory
    DllCall("WriteProcessMemory", "Ptr", hProc, "Ptr", pBufferRemote, "Ptr", &nScript, "PTR", nScriptLength, "Ptr", 0)
    
    ; Start execution of code
    hThread := DllCall("CreateRemoteThread", "PTR", hProc, "PTR", 0, "PTR", 0, "PTR", PID.ahkExec, "PTR", pBufferRemote, "UInt", 0, "PTR", 0,"PTR")
    If !hThread
    {
      DllCall("VirtualFreeEx","PTR",hProc,"PTR",pBufferRemote,"PTR",nScriptLength,MEM_RELEASE)
      ,DllCall("CloseHandle", "PTR", hProc)
      return DllCall("MessageBox","PTR",0,"Str","Could not execute script in remote process.","STR","Error","UInt",0)
    }
    
    ; Wait for thread to finish
    DllCall("WaitForSingleObject", "PTR", hThread, "UInt", 0xFFFFFFFF)
    
    ; Get Exit code returned by ahkExec (1 = script could be executed / 0 = script could not be executed)
    DllCall("GetExitCodeThread", "PTR", hThread, "UIntP", lpExitCode)
    If !lpExitCode
      return DllCall("MessageBox","PTR",0,"Str","Could not execute script in remote process.","STR","Error","UInt",0)
    
    DllCall("CloseHandle", "PTR", hThread)
    ,DllCall("VirtualFreeEx","PTR",hProc,"PTR",pBufferRemote,"PTR",nScriptLength,MEM_RELEASE)
    ,DllCall("CloseHandle", "PTR", hProc)
    return
  } else if !hDll:=DllCall("LoadLibrary","Str",dll,"PTR")
    return DllCall("MessageBox","PTR",0,"Str","Could not find " dll " library.","STR","Error","UInt",0),DllCall("CloseHandle", "PTR", hProc)
  else {
    hProc := DllCall("OpenProcess","UInt", PROCESS_ALL_ACCESS, "Int",0,"UInt", DllCall("GetCurrentProcessId"),"PTR")
    DllCall("GetModuleFileName","PTR",hDll,"PTR",&ModuleName,"UInt",MAX_PATH)
    DllCall("CloseHandle","PTR",hProc)
  }
  ; Open Process to PID
  hProc := DllCall("OpenProcess", "UInt", PROCESS_ALL_ACCESS, "Int",0, "UInt", PID,"PTR")
  If !hProc
    return DllCall("MessageBox","PTR",0,"Str","Could not open process for PID: " PID,"STR","Error","UInt",0)
 
  ; Reserve some memory and write dll path (ANSI)
  nDirLength := VarSetCapacity(nDir, StrLen(dll)+1, 0)
  ,StrPut(dll,&nDir,"CP0")
 
  ; Reserve memory in remote process
  If !pBufferRemote := DllCall("VirtualAllocEx", "Ptr", hProc, "Ptr", 0, "PTR", nDirLength, "UInt", MEM_COMMIT, "UInt", PAGE_EXECUTE_READWRITE, "Ptr")
    return DllCall("MessageBox","PTR",0,"Str","Could not reseve memory for process.","STR","Error","UInt",0),DllCall("CloseHandle", "PTR", hProc)
 
  ; Write dll path to remote process memory
  DllCall("WriteProcessMemory", "Ptr", hProc, "Ptr", pBufferRemote, "Ptr", &nDir, "PTR", nDirLength, "Ptr", 0)
 
  ; Start new thread loading our dll
 
  hThread:=DllCall("CreateRemoteThread","PTR",hProc,"PTR",0,"PTR",0,"PTR",LoadLibraryA,"PTR",pBufferRemote,"UInt",0,"PTR",0,"PTR")
  If !hThread {
    DllCall("VirtualFreeEx","PTR",hProc,"PTR",pBufferRemote,"PTR",nDirLength,"Uint",MEM_RELEASE)
    ,DllCall("CloseHandle", "PTR", hProc)
    return DllCall("MessageBox","PTR",0,"Str","Could not load " dll " in remote process.","STR","Error","UInt",0)
  }
  ; Wait for thread to finish
  DllCall("WaitForSingleObject", "PTR", hThread, "UInt", 0xFFFFFFFF)
 
  ; Get Exit code returned by thread (HMODULE for our dll)
  DllCall("GetExitCodeThread", "PTR", hThread, "UInt*", hModule)
 
  ; Close Thread
  DllCall("CloseHandle", "PTR", hThread)
 
  If (A_PtrSize=8){ ; use different method to retrieve base address because GetExitCodeThread returns DWORD only
    hModule:=0,me32 := new _Struct(_MODULEENTRY32)
    ;  Take a snapshot of all modules in the specified process.
    hModuleSnap := DllCall("CreateToolhelp32Snapshot","UInt", TH32CS_SNAPMODULE,"UInt", PID, "PTR" )
    if( hModuleSnap != INVALID_HANDLE_VALUE ){
      ; reset hModule and set the size of the structure before using it.
      me32.dwSize := sizeof(_MODULEENTRY32)
      ;  Retrieve information about the first module,
      ;  and exit if unsuccessful
      if( !DllCall("Module32First" (A_IsUnicode?"W":""),"PTR", hModuleSnap,"PTR", me32[] ) ) {
  ; Free memory used for passing dll path to remote thread
        DllCall("VirtualFreeEx","PTR",hProc,"PTR",pBufferRemote,"PTR",nDirLength,MEM_RELEASE)
        ,DllCall("CloseHandle","PTR", hModuleSnap ) ; Must clean up the snapshot object!
        return false
      }
      ;  Now walk the module list of the process,and display information about each module
      while(A_Index=1 || DllCall("Module32Next" (A_IsUnicode?"W":""),"PTR",hModuleSnap,"PTR", me32[] ) )
        If (StrGet(me32.szExePath[""])=dll){
          hModule := me32.modBaseAddr["",""]
          break
        }
      DllCall("CloseHandle","PTR",hModuleSnap) ; clean up
    }
  }
 
  hDll:=DllCall("LoadLibrary","Str",dll,"PTR")
 
  ; Calculate pointer to ahkdll and ahkExec functions
  ahktextdll:=hModule+DllCall("GetProcAddress","PTR",hDll,"AStr","ahktextdll","PTR")-hDll
  ahkExec:=hModule+DllCall("GetProcAddress","PTR",hDll,"AStr","ahkExec","PTR")-hDll
  ahkTerminate:=hModule+DllCall("GetProcAddress","PTR",hDll,"AStr","ahkTerminate","PTR")-hDll
 
 
  If script {
    nScriptLength := VarSetCapacity(nScript, (StrLen(script)+1)*(A_IsUnicode?2:1), 0)
    ,StrPut(script,&nScript)
    ; Reserve memory in remote process where our script will be saved
    If !pBufferScript := DllCall("VirtualAllocEx", "Ptr", hProc, "Ptr", 0, "PTR", nScriptLength, "UInt", MEM_COMMIT, "UInt", PAGE_EXECUTE_READWRITE, "Ptr")
      return DllCall("MessageBox","PTR",0,"Str","Could not reseve memory for process.","STR","Error","UInt",0)
            ,DllCall("CloseHandle", "PTR", hProc)
 
    ; Write script to remote process memory
    DllCall("WriteProcessMemory", "Ptr", hProc, "Ptr", pBufferScript, "Ptr", &nScript, "PTR", nScriptLength, "Ptr", 0)
    
  } else pBufferScript:=0
 
  ; Run ahkdll function in remote thread
  hThread := DllCall("CreateRemoteThread","PTR",hProc,"PTR",0,"PTR",0,"PTR",ahktextdll,"PTR",pBufferScript,"PTR",0,"UInt",0,"PTR")
  If !hThread { ; could not start ahkdll in remote process
    ; Free memory used for passing dll path to remote thread
    DllCall("VirtualFreeEx","PTR",hProc,"PTR",pBufferRemote,"PTR",nDirLength,MEM_RELEASE)
    DllCall("CloseHandle", "PTR", hProc)
    return DllCall("MessageBox","PTR",0,"Str","Could not start ahkdll in remote process","STR","Error","UInt",0)
  }
  DllCall("WaitForSingleObject", "PTR", hThread, "UInt", 0xFFFFFFFF)
  DllCall("GetExitCodeThread", "PTR", hThread, "UIntP", lpExitCode)
 
  ; Release memory and handles
  DllCall("VirtualFreeEx","PTR",hProc,"PTR",pBufferRemote,"PTR",nDirLength,MEM_RELEASE)
  DllCall("CloseHandle", "PTR", hThread)
  DllCall("CloseHandle", "PTR", hProc)
 
  If !lpExitCode ; thread could not be created.
    return DllCall("MessageBox","PTR",0,"Str","Could not create a thread in remote process","STR","Error","UInt",0)
 
  return {PID:PID,hModule:hModule,ahkExec:ahkExec,ahkTerminate:ahkTerminate,base:base}
}



TLM
  • Administrators
  • 3864 posts
  • Last active:
  • Joined: 21 Aug 2006
Holy crap hki that is flipping brilliant :shock:..
Wouldn't it be 'safer' to search default paths ( ie working dir, sys dir, lib dir etc ) for the dll rather than the user having to specify it?
Just a thought..

Posted Image

don't duplicate, iterate!


HotKeyIt
  • Moderators
  • 7439 posts
  • Last active: Jun 22 2016 09:14 PM
  • Joined: 18 Jun 2008
Thanks ;)
Now many thinks are so simple, e.g. show path of executable for current window :D
^!+a::
  WinGet,PID,PID,A
  rThread:=InjectAhkDll(PID,A_ScriptDir "\AutoHotkeyMini.dll")
  rThread.Exec("MsgBox % A_AhkPath")
  rThread:=""
return

Wouldn't it be 'safer' to search default paths ( ie working dir, sys dir, lib dir etc ) for the dll rather than the user having to specify it?

That wouldn't probably load the right dll, there are 10 AutoHotkey[Mini].dlls for 32-bit and another 6 for 64-bit :)

TLM
  • Administrators
  • 3864 posts
  • Last active:
  • Joined: 21 Aug 2006
ahh yes, and it looks like not specifying a dll will give me the default one anyway so thats cool.
thanks again!!

Posted Image

don't duplicate, iterate!


amnesiac
  • Members
  • 124 posts
  • Last active: May 01 2014 03:04 AM
  • Joined: 07 Nov 2010
To HotkeyIt:
I use your code (with getworkingdir) in Win7 64 bit. Notepad and Wordpad (64 bit) are normal, but Scite4AutoHotkey (32 bit) crash.
Why?

Click to download Chinese resource for AutoHotkey.

Recommended: AutoHotkey_L My code is based on it or similar versions, e.g. AutoHotkey_H.
Together with AutoHotkey, we grow and march forward. No matter how the future will be, this period of days is still epic.


GodlyCheese
  • Members
  • 719 posts
  • Last active: Nov 11 2014 07:12 PM
  • Joined: 30 Aug 2012
I did a wee bit of testing (because I don't understand much of anything AutoHotkeyIt has done but it looks insanely useful) and am now pretty sure that you can't use this with AHK_L? I tried taking the .dll (so many of them, dunno if I got the right one) out of the AHK_H zip download file and plugged the directory info into the Injection function but the script only returned Error Messages about being unable to reserve enough memory (running it as Admin didn't work either.)

Also it killed my notepad windows when I tested it. I'd kind of like to get this working though, do I have to uninstall my version of AHK_L? Or is it possible to have this work with AHK_L? If someone could dumb this down for me it'd be helpful :3

twbrt
  • Members
  • 1 posts
  • Last active: Nov 11 2012 05:07 PM
  • Joined: 11 Nov 2012
I'd love to use it, but Notepad keeps crashing and no workingdir is returned.

I'm on Windows 7 x64. I tried the latest Autohotkey_H (1.1.9.0 built on Nov 8th 2012), tried both the 32 bit w and the 64 bit w version.

Any help would be greatly appreciated. Posted Image

Cheers, tw

HotKeyIt
  • Moderators
  • 7439 posts
  • Last active: Jun 22 2016 09:14 PM
  • Joined: 18 Jun 2008
Try above again, should work on 64-bit now too Posted Image

TLM
  • Administrators
  • 3864 posts
  • Last active:
  • Joined: 21 Aug 2006
This is a perfect study utilizing API calls for kernel proc invasion! Nice job HKI ( as usual )..

Posted Image

don't duplicate, iterate!


guest3456
  • Members
  • 1704 posts
  • Last active: Nov 19 2015 11:58 AM
  • Joined: 10 Mar 2011

Try this smile.png
The MCode hex string is original 32-bit GetCurrentDirectoryW function with swapped parameters.

,GetCurrentDirectoryW,init:=MCode(GetCurrentDirectoryW,"8BFF558BECFF750[color=#FF0000]8[/color]8B450803C050FF15A810807CD1E85DC20800")

-----------------------------

 

 

HotKeyIt,

 

i dont understand the need/purpose of the MCode. how/why did you generate it and what is it for?



HotKeyIt
  • Moderators
  • 7439 posts
  • Last active: Jun 22 2016 09:14 PM
  • Joined: 18 Jun 2008

CreateRemoteThread can pass one parameter only to the called function in remote thread.

 

GetCurrentDirectory requires 2 parameters, but when we swap these parameters it seems to work, at least on XP.



guest3456
  • Members
  • 1704 posts
  • Last active: Nov 19 2015 11:58 AM
  • Joined: 10 Mar 2011

hrmmm..ok..

 

now suppose you wanted to hook msdn MessageBox from a remote process and append your own string to the end of every msgbox the remote process displays. how would that be done?