Manko Posted January 23, 2009 Share Posted January 23, 2009 (edited) Hi! I don't like WMI. It's slow and it only works if the WMI-server can run.I use this func in my security-app "ModHelper", here: http://www.autoitscript.com/forum/index.php?showtopic=84939I need to be able to suspend processes so they can't get up to no good... WMI doesn't work if you suspend it... It works on XP sp3 and Vista Home. Hope you will try on others. (pre NT will not work.)(The structures involved are not publicly disclosed (?) by Microsoft, likely so they can change them whenever they feel like it...)Thanks to wraithdu for borrowing his GetDebugPrivilege, and also for suggestions!Also check out his great variant using remote thread execution, further down! expandcollapse popup#include <WinAPI.au3> ; _GetPrivilege_SEDEBUG() uses this include. My function needs none. #include <array.au3> ; Needed to display array in example. Not needed by Func. #RequireAdmin ; Reported to be of use on Vista, getting more info from protected processes... ; ############# Needed Constants ################### Global Const $PROCESS_VM_READ=0x10 Global Const $PROCESS_QUERY_INFORMATION = 0x400 ; ############ Example code ####################### _GetPrivilege_SEDEBUG() ; I need this for tricky processes. Not needed for most... $list=ProcessList() Redim $list[ubound($list,1)][3] for $i=1 to ubound($list,1)-1 $list[$i][2]=_WinAPI_GetCommandLineFromPID($list[$i][1]) Next _ArrayDisplay($list) Exit ; ############################################### ; ############ Here be func! #################### Func _WinAPI_GetCommandLineFromPID($PID) $ret1=DllCall("kernel32.dll", 'int', 'OpenProcess', 'int', $PROCESS_VM_READ+$PROCESS_QUERY_INFORMATION, 'int', False, 'int', $PID) $tag_PROCESS_BASIC_INFORMATION = "int ExitStatus;" & _ "ptr PebBaseAddress;" & _ "ptr AffinityMask;" & _ "ptr BasePriority;" & _ "ulong UniqueProcessId;" & _ "ulong InheritedFromUniqueProcessId;" $PBI=DllStructCreate($tag_PROCESS_BASIC_INFORMATION) DllCall("ntdll.dll", "int", "ZwQueryInformationProcess", "hwnd", $ret1[0], "int", 0, "ptr", DllStructGetPtr($PBI), "int", _ DllStructGetSize($PBI), "int",0) $dw=DllStructCreate("ptr") DllCall("kernel32.dll", "int", "ReadProcessMemory", "hwnd", $ret1[0], _ "ptr", DllStructGetData($PBI,2)+0x10, _ ; PebBaseAddress+16 bytes <-- ptr _PROCESS_PARAMETERS "ptr", DllStructGetPtr($dw), "int", 4, "ptr", 0) $unicode_string = DllStructCreate("ushort Length;ushort MaxLength;ptr String") DllCall("kernel32.dll", "int", "ReadProcessMemory", "hwnd", $ret1[0], _ "ptr", DllStructGetData($dw, 1)+0x40, _ ; _PROCESS_PARAMETERS+64 bytes <-- ptr CommandLine Offset (UNICODE_STRING struct) - Win XP / Vista. "ptr", DllStructGetPtr($unicode_string), "int", DllStructGetSize($unicode_string), "ptr", 0) $ret=DllCall("kernel32.dll", "int", "ReadProcessMemory", "hwnd", $ret1[0], _ "ptr", DllStructGetData($unicode_string, "String"), _ ; <-- ptr Commandline Unicode String "wstr", 0, "int", DllStructGetData($unicode_string, "Length") + 2, "int*", 0) ; read Length + terminating NULL (2 bytes in unicode) DllCall("kernel32.dll", 'int', 'CloseHandle', "hwnd", $ret1[0]) If $ret[5] Then Return $ret[3] ; If bytes returned, return commandline... Return "" ; Getting empty string is correct behaviour when there is no commandline to be had... EndFunc ; ####################### Below Func is Part of example - Needed to get commandline from more processes. ############ ; ####################### Thanks for this function, wraithdu! (Didn't know it was your.) :) ######################### Func _GetPrivilege_SEDEBUG() Local $tagLUIDANDATTRIB = "int64 Luid;dword Attributes" Local $count = 1 Local $tagTOKENPRIVILEGES = "dword PrivilegeCount;byte LUIDandATTRIB[" & $count * 12 & "]" ; count of LUID structs * sizeof LUID struct Local $TOKEN_ADJUST_PRIVILEGES = 0x20 Local $call = DllCall("advapi32.dll", "int", "OpenProcessToken", "ptr", _WinAPI_GetCurrentProcess(), "dword", $TOKEN_ADJUST_PRIVILEGES, "ptr*", "") Local $hToken = $call[3] $call = DllCall("advapi32.dll", "int", "LookupPrivilegeValue", "str", Chr(0), "str", "SeDebugPrivilege", "int64*", "") ;msgbox(0,"",$call[3] & " " & _WinAPI_GetLastErrorMessage()) Local $iLuid = $call[3] Local $TP = DllStructCreate($tagTOKENPRIVILEGES) Local $LUID = DllStructCreate($tagLUIDANDATTRIB, DllStructGetPtr($TP, "LUIDandATTRIB")) DllStructSetData($TP, "PrivilegeCount", $count) DllStructSetData($LUID, "Luid", $iLuid) DllStructSetData($LUID, "Attributes", $SE_PRIVILEGE_ENABLED) $call = DllCall("advapi32.dll", "int", "AdjustTokenPrivileges", "ptr", $hToken, "int", 0, "ptr", DllStructGetPtr($TP), "dword", 0, "ptr", Chr(0), "ptr", Chr(0)) Return ($call[0] <> 0) ; $call[0] <> 0 is success EndFunc ;==>_GetPrivilege_SEDEBUGtrancexx fixed 64-bit support and fleshed out structs.expandcollapse popupFunc _WinAPI_GetCommandLineFromPID($iPID) Local $aCall = DllCall("kernel32.dll", "handle", "OpenProcess", _ "dword", 1040, _ ; PROCESS_VM_READ | PROCESS_QUERY_INFORMATION "bool", 0, _ "dword", $iPID) If @error Or Not $aCall[0] Then Return SetError(1, 0, "") EndIf Local $hProcess = $aCall[0] Local $tPROCESS_BASIC_INFORMATION = DllStructCreate("dword_ptr ExitStatus;" & _ "ptr PebBaseAddress;" & _ "dword_ptr AffinityMask;" & _ "dword_ptr BasePriority;" & _ "dword_ptr UniqueProcessId;" & _ "dword_ptr InheritedFromUniqueProcessId") $aCall = DllCall("ntdll.dll", "int", "NtQueryInformationProcess", _ "handle", $hProcess, _ "dword", 0, _ ; ProcessBasicInformation "ptr", DllStructGetPtr($tPROCESS_BASIC_INFORMATION), _ "dword", DllStructGetSize($tPROCESS_BASIC_INFORMATION), _ "dword*", 0) If @error Then DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $hProcess) Return SetError(2, 0, "") EndIf Local $tPEB = DllStructCreate("byte InheritedAddressSpace;" & _ "byte ReadImageFileExecOptions;" & _ "byte BeingDebugged;" & _ "byte Spare;" & _ "ptr Mutant;" & _ "ptr ImageBaseAddress;" & _ "ptr LoaderData;" & _ "ptr ProcessParameters;" & _ "ptr SubSystemData;" & _ "ptr ProcessHeap;" & _ "ptr FastPebLock;" & _ "ptr FastPebLockRoutine;" & _ "ptr FastPebUnlockRoutine;" & _ "dword EnvironmentUpdateCount;" & _ "ptr KernelCallbackTable;" & _ "ptr EventLogSection;" & _ "ptr EventLog;" & _ "ptr FreeList;" & _ "dword TlsExpansionCounter;" & _ "ptr TlsBitmap;" & _ "dword TlsBitmapBits[2];" & _ "ptr ReadOnlySharedMemoryBase;" & _ "ptr ReadOnlySharedMemoryHeap;" & _ "ptr ReadOnlyStaticServerData;" & _ "ptr AnsiCodePageData;" & _ "ptr OemCodePageData;" & _ "ptr UnicodeCaseTableData;" & _ "dword NumberOfProcessors;" & _ "dword NtGlobalFlag;" & _ "ubyte Spare2[4];" & _ "int64 CriticalSectionTimeout;" & _ "dword HeapSegmentReserve;" & _ "dword HeapSegmentCommit;" & _ "dword HeapDeCommitTotalFreeThreshold;" & _ "dword HeapDeCommitFreeBlockThreshold;" & _ "dword NumberOfHeaps;" & _ "dword MaximumNumberOfHeaps;" & _ "ptr ProcessHeaps;" & _ "ptr GdiSharedHandleTable;" & _ "ptr ProcessStarterHelper;" & _ "ptr GdiDCAttributeList;" & _ "ptr LoaderLock;" & _ "dword OSMajorVersion;" & _ "dword OSMinorVersion;" & _ "dword OSBuildNumber;" & _ "dword OSPlatformId;" & _ "dword ImageSubSystem;" & _ "dword ImageSubSystemMajorVersion;" & _ "dword ImageSubSystemMinorVersion;" & _ "dword GdiHandleBuffer[34];" & _ "dword PostProcessInitRoutine;" & _ "dword TlsExpansionBitmap;" & _ "byte TlsExpansionBitmapBits[128];" & _ "dword SessionId") $aCall = DllCall("kernel32.dll", "bool", "ReadProcessMemory", _ "ptr", $hProcess, _ "ptr", DllStructGetData($tPROCESS_BASIC_INFORMATION, "PebBaseAddress"), _ "ptr", DllStructGetPtr($tPEB), _ "dword", DllStructGetSize($tPEB), _ "dword*", 0) If @error Or Not $aCall[0] Then DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $hProcess) Return SetError(3, 0, "") EndIf Local $tPROCESS_PARAMETERS = DllStructCreate("dword AllocationSize;" & _ "dword ActualSize;" & _ "dword Flags;" & _ "dword Unknown1;" & _ "word LengthUnknown2;" & _ "word MaxLengthUnknown2;" & _ "ptr Unknown2;" & _ "handle InputHandle;" & _ "handle OutputHandle;" & _ "handle ErrorHandle;" & _ "word LengthCurrentDirectory;" & _ "word MaxLengthCurrentDirectory;" & _ "ptr CurrentDirectory;" & _ "handle CurrentDirectoryHandle;" & _ "word LengthSearchPaths;" & _ "word MaxLengthSearchPaths;" & _ "ptr SearchPaths;" & _ "word LengthApplicationName;" & _ "word MaxLengthApplicationName;" & _ "ptr ApplicationName;" & _ "word LengthCommandLine;" & _ "word MaxLengthCommandLine;" & _ "ptr CommandLine;" & _ "ptr EnvironmentBlock;" & _ "dword Unknown[9];" & _ "word LengthUnknown3;" & _ "word MaxLengthUnknown3;" & _ "ptr Unknown3;" & _ "word LengthUnknown4;" & _ "word MaxLengthUnknown4;" & _ "ptr Unknown4;" & _ "word LengthUnknown5;" & _ "word MaxLengthUnknown5;" & _ "ptr Unknown5;") $aCall = DllCall("kernel32.dll", "bool", "ReadProcessMemory", _ "ptr", $hProcess, _ "ptr", DllStructGetData($tPEB, "ProcessParameters"), _ "ptr", DllStructGetPtr($tPROCESS_PARAMETERS), _ "dword", DllStructGetSize($tPROCESS_PARAMETERS), _ "dword*", 0) If @error Or Not $aCall[0] Then DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $hProcess) Return SetError(4, 0, "") EndIf $aCall = DllCall("kernel32.dll", "bool", "ReadProcessMemory", _ "ptr", $hProcess, _ "ptr", DllStructGetData($tPROCESS_PARAMETERS, "CommandLine"), _ "wstr", "", _ "dword", DllStructGetData($tPROCESS_PARAMETERS, "MaxLengthCommandLine"), _ "dword*", 0) If @error Or Not $aCall[0] Then DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $hProcess) Return SetError(5, 0, "") EndIf DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $hProcess) Return $aCall[3] EndFunc/Manko [EDIT: trancexx corrections!] Edited March 11, 2010 by Manko Zohar 1 Yes i rush things! (I sorta do small bursts inbetween doing nothing.) Things I have rushed and reRushed:* ProDLLer - Process manager - Unload viri modules (dll) and moore...* _WinAPI_ProcessListOWNER_WTS() - Get Processes owner list...* _WinAPI_GetCommandLineFromPID() - Get commandline of target process...* _WinAPI_ThreadsnProcesses() Much info if expanded - optional Indented "Parent/Child"-style Processlist. Moore to come... eventually... Link to comment Share on other sites More sharing options...
trancexx Posted January 23, 2009 Share Posted January 23, 2009 Nice, nice, nice... ♡♡♡ . eMyvnE Link to comment Share on other sites More sharing options...
UEZ Posted January 23, 2009 Share Posted January 23, 2009 Nice work Manko and very useful. THANKS! UEZ Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ Link to comment Share on other sites More sharing options...
GreenCan Posted January 23, 2009 Share Posted January 23, 2009 Nicely done UEZ. Your udf seems to find process paths that Alzo Process Management doesn't find and sometimes V.V. Interesting. Thanks for sharing, GreenCan Contributions CheckUpdate - SelfUpdating script ------- Self updating script Dynamic input validation ------------------- Use a Input masks can make your life easier and Validation can be as simple MsgBox with CountDown ------------------- MsgBox with visual countdown Display Multiline text cells in ListView ---- Example of pop-up or ToolTip for multiline text items in ListView Presentation Manager ---------------------- Program to display and refresh different Border-less GUI's on a Display (large screen TV) USB Drive Tools ------------------------------ Tool to help you with your USB drive management Input Period udf ------------------------------ GUI for a period input Excel ColorPicker ---------------------------- Color pickup tool will allow you to select a color from the standard Excel color palette Excel Chart UDF ----------------------------- Collaboration project with water GetDateInString ------------------------------ Find date/time in a string using a date format notation like DD Mon YYYY hh:mm TaskListAllDetailed --------------------------- List All Scheduled Tasks Computer Info --------------------------------- A collection of information for helpdesk Shared memory Demo ----------------------- Demo: Two applications communicate with each other through means of a memory share (using Nomad function, 32bit only) Universal Date Format Conversion -------- Universal date converter from your PC local date format to any format Disable Windows DetailsPane -------------- Disable Windows Explorer Details Pane Oracle SQL Report Generator ------------- Oracle Report generator using SQL SQLite Report Generator ------------------- SQLite Report generator using SQL SQLite ListView and BLOB demo ---------- Demo: shows how binary (image) objects can be recognized natively in a database BLOB field DSN-Less Database connection demo --- Demo: ActiveX Data Objects DSN-Less Database access Animated animals ----------------------------- Fun: Moving animated objects Perforated image in GUI --------------------- Fun: Perforate your image with image objects UEZ's Perforator major update ------------- Fun: Pro version of Perforator by UEZ Visual Crop Tool (GUI) ----------------------- Easy to use Visual Image Crop tool Visual Image effect (GUI) -------------------- Visually apply effects on an image Link to comment Share on other sites More sharing options...
Paulchen Posted January 23, 2009 Share Posted January 23, 2009 Nice work. Note:When you start this program with #RequireAdmin you get also information over the process with higher integritylevel Link to comment Share on other sites More sharing options...
UEZ Posted January 23, 2009 Share Posted January 23, 2009 Nicely done UEZ.Your udf seems to find process paths that Alzo Process Management doesn't find and sometimes V.V. Interesting.Thanks for sharing,GreenCanThe credits must go to Manko not to me UEZ Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ Link to comment Share on other sites More sharing options...
Manko Posted January 23, 2009 Author Share Posted January 23, 2009 (edited) The credits must go to Manko not to me UEZThanks UEZ, and all of you!Paulchen: Is that in Vista??! Never new "#RequireAdmin" did anything but stop code from running if you're not admin. Can't wait to try it on Vista! Or did you mean I forgot to mention that running in admin would reveal more commandlines on xp? Never thought of that... Always in admin. Always doing stuff that require it... If you have Vista, can you confirm this? (That "#RequireAdmin" gives access to more commandlines.)Can't get to a vista system before Sunday./Manko Edited January 23, 2009 by Manko Yes i rush things! (I sorta do small bursts inbetween doing nothing.) Things I have rushed and reRushed:* ProDLLer - Process manager - Unload viri modules (dll) and moore...* _WinAPI_ProcessListOWNER_WTS() - Get Processes owner list...* _WinAPI_GetCommandLineFromPID() - Get commandline of target process...* _WinAPI_ThreadsnProcesses() Much info if expanded - optional Indented "Parent/Child"-style Processlist. Moore to come... eventually... Link to comment Share on other sites More sharing options...
wraithdu Posted January 23, 2009 Share Posted January 23, 2009 I'll check this out tonight. In my little app I use WMI for the commandline. It would be nice to not have to use it. One other option is to inject a small DLL that calls the GetCommandLine function and returns the info to your app. Link to comment Share on other sites More sharing options...
wraithdu Posted January 23, 2009 Share Posted January 23, 2009 (edited) Vista Ultimate SP1 32-bit Alrighty, good function! Few things - 1) #RequireAdmin would be useful for users with UAC enabled only. I'm not sure if getting SEDEBUG will work without this on UAC systems. UAC or not, in Vista SEDEBUG is REQUIRED to get info from system processes. 2) ReadProcessMemory() will always read the specified number of bytes, assuming you're not trying to read outside of the process's address space. So it will return either 0 or 1024, so testing $ret[5]>2 is kinda pointless. Rather - If Not @error And $ret[5] Then Return $ret[3]oÝ÷ Ûpèm~àzÛh Z,xv§vWêk¡Ç¬³*.ßÛÞ¢§yÝ÷jëh×6DllCall("kernel32.dll", "int", "CloseHandle", "ptr", $ret1[0]) I get the same results as the WMI version, so that's good. Only other suggestion would be to credit the authors of functions you've borrowed in your source Edited January 23, 2009 by wraithdu Link to comment Share on other sites More sharing options...
Manko Posted January 24, 2009 Author Share Posted January 24, 2009 Vista Ultimate SP1 32-bit Alrighty, good function! Few things - 1) #RequireAdmin would be useful for users with UAC enabled only. I'm not sure if getting SEDEBUG will work without this on UAC systems. UAC or not, in Vista SEDEBUG is REQUIRED to get info from system processes. 2) ReadProcessMemory() will always read the specified number of bytes, assuming you're not trying to read outside of the process's address space. So it will return either 0 or 1024, so testing $ret[5]>2 is kinda pointless. Rather - If Not @error And $ret[5] Then Return $ret[3]oÝ÷ Ûpèm~àzÛh Z,xv§vWêk¡Ç¬³*.ßÛÞ¢§yÝ÷jëh×6DllCall("kernel32.dll", "int", "CloseHandle", "ptr", $ret1[0]) I get the same results as the WMI version, so that's good. Only other suggestion would be to credit the authors of functions you've borrowed in your source Thanks for being a sport about me borrowing your "GetDebugPrivilege" Func! (Didn't know it was yours, I promise!) (Bad excuse! Coulda checked.) 1. I'm putting it in there. Hope this helps yall getting this commandlines on Vista! 2. Another good sugestion. 3. Yeah! You are SO right! Thanks for the borrowed Func! Before I realised that you didn't mean anything in my "UDF", I was going to make a smartass remark about thanking Microsoft for their APIs and structs... Glad I only thought that, and didn't post it on this board... .. . . . . /Manko Yes i rush things! (I sorta do small bursts inbetween doing nothing.) Things I have rushed and reRushed:* ProDLLer - Process manager - Unload viri modules (dll) and moore...* _WinAPI_ProcessListOWNER_WTS() - Get Processes owner list...* _WinAPI_GetCommandLineFromPID() - Get commandline of target process...* _WinAPI_ThreadsnProcesses() Much info if expanded - optional Indented "Parent/Child"-style Processlist. Moore to come... eventually... Link to comment Share on other sites More sharing options...
wraithdu Posted January 24, 2009 Share Posted January 24, 2009 No problem. Keep up the good work (this one and ModHelper)! I think I'm going to do up a small C++ example and give it to the author of Daphne process explorer, since he seems to be having problems getting commandlines in Vista. All credit to you for the method! Link to comment Share on other sites More sharing options...
wraithdu Posted January 25, 2009 Share Posted January 25, 2009 (edited) After doing the C++ version of this, I have a minor update to your function. The commandline is stored as a UNICODE_STRING structure so it's better to read the given length of the string instead of a generic 1024 bytes. If for some reason the full 1024 bytes is not accessible by the ReadProcessMemory function, then the function fails and reads nothing. By reading the actual length of the string, we avoid this potential problem. To do this, we back up the second ReadProcessMemory call by 4 bytes to the beginning of the UNICODE_STRING struct, and read 8 bytes, the size of the struct. Func _GetCommandLineFromPID($PID) $ret1=DllCall("kernel32.dll", 'int', 'OpenProcess', 'int', $PROCESS_VM_READ+$PROCESS_QUERY_INFORMATION, 'int', False, 'int', $PID) $tag_PROCESS_BASIC_INFORMATION = "int ExitStatus;" & _ "ptr PebBaseAddress;" & _ "ptr AffinityMask;" & _ "ptr BasePriority;" & _ "ulong UniqueProcessId;" & _ "ulong InheritedFromUniqueProcessId;" $PBI=DllStructCreate($tag_PROCESS_BASIC_INFORMATION) DllCall("ntdll.dll", "int", "ZwQueryInformationProcess", "hwnd", $ret1[0], "int", 0, "ptr", DllStructGetPtr($PBI), "int", _ DllStructGetSize($PBI), "int",0) $dw=DllStructCreate("ptr") DllCall("kernel32.dll", "int", "ReadProcessMemory", "hwnd", $ret1[0], _ "ptr", DllStructGetData($PBI,2)+0x10, _ ; PebBaseAddress+16 bytes <-- ptr _PROCESS_PARAMETERS "ptr", DllStructGetPtr($dw), "int", 4, "ptr", 0) $unicode_string = DllStructCreate("ushort Length;ushort MaxLength;ptr String") DllCall("kernel32.dll", "int", "ReadProcessMemory", "hwnd", $ret1[0], _ "ptr", DllStructGetData($dw, 1)+0x40, _ ; _PROCESS_PARAMETERS+64 bytes <-- ptr CommandLine Offset (UNICODE_STRING struct) - Win XP / Vista. "ptr", DllStructGetPtr($unicode_string), "int", DllStructGetSize($unicode_string), "ptr", 0) $ret=DllCall("kernel32.dll", "int", "ReadProcessMemory", "hwnd", $ret1[0], _ "ptr", DllStructGetData($unicode_string, "String"), _ ; <-- ptr Commandline Unicode String "wstr", 0, "int", DllStructGetData($unicode_string, "Length") + 2, "int*", 0) ; read Length + terminating NULL (2 bytes in unicode) DllCall("kernel32.dll", 'int', 'CloseHandle', "hwnd", $ret1[0]) If $ret[5] Then Return $ret[3] ; If bytes returned, return commandline... Return "" ; Getting empty string is correct behaviour when there is no commandline to be had... EndFunc ; ...or if we're not allowed for some reason.... vista... Edited January 25, 2009 by wraithdu Link to comment Share on other sites More sharing options...
Manko Posted January 25, 2009 Author Share Posted January 25, 2009 (edited) Thanks, wraithdu! I must admit, I had not grasped the UNICODE_STRING struct. Ushort... That explains things... Yes, that is exactly the way to go. (When one knows to get that info... I rushed things as usual...) Will update! btw, please relay the mentioned authors response! /Manko Edited January 25, 2009 by Manko Yes i rush things! (I sorta do small bursts inbetween doing nothing.) Things I have rushed and reRushed:* ProDLLer - Process manager - Unload viri modules (dll) and moore...* _WinAPI_ProcessListOWNER_WTS() - Get Processes owner list...* _WinAPI_GetCommandLineFromPID() - Get commandline of target process...* _WinAPI_ThreadsnProcesses() Much info if expanded - optional Indented "Parent/Child"-style Processlist. Moore to come... eventually... Link to comment Share on other sites More sharing options...
wraithdu Posted January 25, 2009 Share Posted January 25, 2009 I will when I get one. He seems to visit his board fairly infrequently. Here's the thread -http://forum.drk.com.ar/viewtopic.php?f=10...=27&start=0 Link to comment Share on other sites More sharing options...
wraithdu Posted February 10, 2009 Share Posted February 10, 2009 I was doing some research regarding remote thread execution for ModuleSpy, and came up with this option for getting the commandline. It creates a thread in the target process which calls the GetCommandLine() function, then retrieves the pointer and reads the memory. There are 2 different functions for creating the remote threads depending if you're using Vista/2008 or not. The reasons are noted in the comments. expandcollapse popup#AutoIt3Wrapper_Change2CUI=y #include <WinAPI.au3> _GetPrivilege_SEDEBUG() $ISVISTA = (@OSVersion == "WIN_VISTA") Or (@OSVersion == "WIN_2008") $pGetCommandLineW = _GetProcAddress(_WinAPI_GetModuleHandle("kernel32.dll"), "GetCommandLineW") $pExitThread = _GetProcAddress(_WinAPI_GetModuleHandle("kernel32.dll"), "ExitThread") $szCmdLine = DllStructCreate("wchar[520]") If $pGetCommandLineW Then $aList = ProcessList() For $i = 1 To $aList[0][0] $hProc = _GetProcHandle($aList[$i][1]) ConsoleWrite("-------------------" & @CRLF) ConsoleWrite("PID: " & $aList[$i][1] & @CRLF & "hProc: " & $hProc & @CRLF) If $hProc Then If $ISVISTA Then $hThread = NtCreateThreadEx($hProc, $pGetCommandLineW, 0) Else $hThread = CreateRemoteThread($hProc, $pGetCommandLineW, 0) EndIf ConsoleWrite("hThread: " & $hThread & @CRLF) If $hThread Then _WinAPI_WaitForSingleObject($hThread) ; wait for thread to finish ; get thread return value, which is the ptr to commandline string $ret = DllCall("kernel32.dll", "int", "GetExitCodeThread", "ptr", $hThread, "dword*", 0) $pszCmdLine = Ptr($ret[2]) ConsoleWrite("pszCmdLine: " & $pszCmdLine & @CRLF) _WinAPI_CloseHandle($hThread) ; close thread handle If $pszCmdLine Then ; read the commandline from the remote process $ret = DllCall("kernel32.dll", "int", "ReadProcessMemory", "ptr", $hProc, "ptr", $pszCmdLine, "ptr", DllStructGetPtr($szCmdLine), _ "ulong", DllStructGetSize($szCmdLine), "ulong*", 0) If $ret[5] Then ConsoleWrite("CmdLine: " & DllStructGetData($szCmdLine, 1) & @CRLF) EndIf EndIf EndIf _WinAPI_CloseHandle($hProc) EndIf Next EndIf If @Compiled Then MsgBox(0, "GetCommandLineW", "Done.") Func NtCreateThreadEx($hProcess, $pCode, $pParameter) ; this is a largely undocumented function, so don't ask what the structure is...I don't know either :) Local $return = 0 Local $tagUNKNOWN = "ulong Length;ulong Unknown1;ulong Unknown2;ptr Unknown3;ulong Unknown4;ulong Unknown5;ulong Unknown6;ptr Unknown7;ulong Unknown8" Local $dw0 = DllStructCreate("dword") Local $dw1 = DllStructCreate("dword") DllStructSetData($dw0, 1, 0) DllStructSetData($dw1, 1, 0) Local $buffer = DllStructCreate($tagUNKNOWN) DllStructSetData($buffer, 1, DllStructGetSize($buffer)) DllStructSetData($buffer, 2, 0x10003) DllStructSetData($buffer, 3, 0x8) DllStructSetData($buffer, 4, DllStructGetPtr($dw1)) DllStructSetData($buffer, 5, 0) DllStructSetData($buffer, 6, 0x10004) DllStructSetData($buffer, 7, 4) DllStructSetData($buffer, 8, DllStructGetPtr($dw0)) DllStructSetData($buffer, 9, 0) ; create the remote thread ; NtCreateThreadEx is only availale in Vista+ and allows creating threads in sessions other than the calling app's ; this is necessary versus XP, because a good portion of Vista's processes run in a different session Local $ret = DllCall("ntdll.dll", "dword", "NtCreateThreadEx", "ptr*", 0, "dword", 0x1FFFFF, "ptr", 0, "ptr", $hProcess, "ptr", $pCode, "ptr", $pParameter, _ "int", 0, "dword", 0, "dword", 0, "dword", 0, "ptr", DllStructGetPtr($buffer)) If $ret[1] Then $return = $ret[1] Return $return EndFunc Func CreateRemoteThread($hProcess, $pCode, $pParameter) Local $return = 0 ; create remote thread ; CreateRemoteThread cannot create threads in processes that are not in the calling app's session ; however in XP, pretty much everything runs in the same session, so we're OK using this function Local $ret = DllCall("kernel32.dll", "ptr", "CreateRemoteThread", "ptr", $hProcess, "ptr", 0, "uint", 0, "ptr", $pCode, "ptr", $pParameter, "dword", 0, "ptr", 0) If $ret[0] Then $return = $ret[0] Return $return EndFunc ; this is another option that allows us to create remote threads in other sessions in XP ; however the return value of our thread is lost (which may be very important, such as the return from LoadLibrary or GetCommandLine) Func RtlCreateUserThread($hProcess, $pCode, $pParameter) Local $return = 0 ; create a suspended thread at kernel32!ExitThread Local $ret = DllCall("ntdll.dll", "dword", "RtlCreateUserThread", "ptr", $hProcess, "ptr", 0, "int", 1, "ulong", 0, "ulong*", 0, "ulong*", 0, _ "ptr", $pExitThread, "dword*", 0, "ptr*", 0, "ptr*", 0) If $ret[9] Then ; schedule an asynchronous procedure call (APC) at the code to be executed DllCall("ntdll.dll", "dword", "NtQueueApcThread", "ptr", $ret[9], "ptr", $pCode, "ptr", $pParameter, "ptr", 0, "ulong", 0) ; resume the thread, executing the APC DllCall("kernel32.dll", "dword", "ResumeThread", "ptr", $ret[9]) $return = $ret[9] EndIf ; NOTE: the return value of the APC is lost Return $return EndFunc Func _GetProcAddress($module, $function) Local $call = DllCall("kernel32.dll", "ptr", "GetProcAddress", "ptr", $module, "str", $function) Return $call[0] EndFunc Func _GetProcHandle($process) Local $hProcess = 0 Local $PERMISSION = BitOR(0x0002, 0x0400, 0x0008, 0x0010, 0x0020) ; CREATE_THREAD, QUERY_INFORMATION, VM_OPERATION, VM_READ, VM_WRITE If IsInt($process) Then If $process > 0 Then Local $ret = DllCall("kernel32.dll", "ptr", "OpenProcess", "dword", $PERMISSION, "int", 0, "dword", $process) If $ret[0] Then $hProcess = $ret[0] EndIf EndIf EndIf Return $hProcess EndFunc Func _GetPrivilege_SEDEBUG() Local $tagLUIDANDATTRIB = "int64 Luid;dword Attributes" Local $count = 1 Local $tagTOKENPRIVILEGES = "dword PrivilegeCount;byte LUIDandATTRIB[" & $count * 12 & "]" ; count of LUID structs * sizeof LUID struct Local $TOKEN_ADJUST_PRIVILEGES = 0x20 Local $call = DllCall("advapi32.dll", "int", "OpenProcessToken", "ptr", _WinAPI_GetCurrentProcess(), "dword", $TOKEN_ADJUST_PRIVILEGES, "ptr*", "") Local $hToken = $call[3] $call = DllCall("advapi32.dll", "int", "LookupPrivilegeValue", "str", Chr(0), "str", "SeDebugPrivilege", "int64*", "") Local $iLuid = $call[3] Local $TP = DllStructCreate($tagTOKENPRIVILEGES) Local $LUID = DllStructCreate($tagLUIDANDATTRIB, DllStructGetPtr($TP, "LUIDandATTRIB")) DllStructSetData($TP, "PrivilegeCount", $count) DllStructSetData($LUID, "Luid", $iLuid) DllStructSetData($LUID, "Attributes", $SE_PRIVILEGE_ENABLED) $call = DllCall("advapi32.dll", "int", "AdjustTokenPrivileges", "ptr", $hToken, "int", 0, "ptr", DllStructGetPtr($TP), "dword", 0, "ptr", Chr(0), "ptr", Chr(0)) Return ($call[0] <> 0) ; $call[0] <> 0 is success EndFunc ;==>_GetPrivilege_SEDEBUG Link to comment Share on other sites More sharing options...
Manko Posted February 10, 2009 Author Share Posted February 10, 2009 I was doing some research regarding remote thread execution for ModuleSpy, and came up with this option for getting the commandline. It creates a thread in the target process which calls the GetCommandLine() function, then retrieves the pointer and reads the memory.Hi, wraithdu!Great work!Remote thread execution... Brings back memories from my reversing days...Thanks for posting in my thread! /Manko Yes i rush things! (I sorta do small bursts inbetween doing nothing.) Things I have rushed and reRushed:* ProDLLer - Process manager - Unload viri modules (dll) and moore...* _WinAPI_ProcessListOWNER_WTS() - Get Processes owner list...* _WinAPI_GetCommandLineFromPID() - Get commandline of target process...* _WinAPI_ThreadsnProcesses() Much info if expanded - optional Indented "Parent/Child"-style Processlist. Moore to come... eventually... Link to comment Share on other sites More sharing options...
rexx Posted March 9, 2010 Share Posted March 9, 2010 (edited) Hi, I found this is not working under x64. I tried to make some modifications but still not working. Maybe it's the problem of the PEB structure. http://msdn.microsoft.com/en-us/library/aa813706(VS.85).aspx But I don't know how to fix it. Any idea? Func _WinAPI_GetCommandLineFromPID($PID) Local $ret1 = DllCall("kernel32.dll", 'handle', 'OpenProcess', 'dword', $PROCESS_VM_READ+$PROCESS_QUERY_INFORMATION, 'bool', False, 'dword', $PID) Local $tag_PROCESS_BASIC_INFORMATION = "int ExitStatus;" & _ "ptr PebBaseAddress;" & _ "ptr AffinityMask;" & _ "ptr BasePriority;" & _ "ulong_ptr UniqueProcessId;" & _ "ulong InheritedFromUniqueProcessId;" Local $PBI=DllStructCreate($tag_PROCESS_BASIC_INFORMATION) DllCall("ntdll.dll", "int", "ZwQueryInformationProcess", "hwnd", $ret1[0], "int", 0, "ptr", DllStructGetPtr($PBI), "int", _ DllStructGetSize($PBI), "int",0) Local $dw=DllStructCreate("ptr") DllCall("kernel32.dll", "bool", "ReadProcessMemory", "handle", $ret1[0], _ "ptr", DllStructGetData($PBI,2)+0x10, _ ; PebBaseAddress+16 bytes <-- ptr _PROCESS_PARAMETERS "ptr", DllStructGetPtr($dw), "ulong_ptr", 4, "ulong_ptr*", 0) Local $unicode_string = DllStructCreate("ushort Length;ushort MaxLength;ptr String") DllCall("kernel32.dll", "bool", "ReadProcessMemory", "handle", $ret1[0], _ "ptr", DllStructGetData($dw, 1)+0x40, _ ; _PROCESS_PARAMETERS+64 bytes <-- ptr CommandLine Offset (UNICODE_STRING struct) - Win XP / Vista. "ptr", DllStructGetPtr($unicode_string), "ulong_ptr", DllStructGetSize($unicode_string), "ulong_ptr*", 0) Local $ret = DllCall("kernel32.dll", "int", "ReadProcessMemory", "handle", $ret1[0], _ "ptr", DllStructGetData($unicode_string, "String"), _ ; <-- ptr Commandline Unicode String "wstr", 0, "ulong_ptr", DllStructGetData($unicode_string, "Length") + 2, "ulong_ptr*", 0) ; read Length + terminating NULL (2 bytes in unicode) DllCall("kernel32.dll", 'int', 'CloseHandle', "hwnd", $ret1[0]) If $ret[5] Then Return $ret[3] ; If bytes returned, return commandline... Return "" ; Getting empty string is correct behaviour when there is no commandline to be had... EndFunc Edited March 9, 2010 by rexx Link to comment Share on other sites More sharing options...
trancexx Posted March 9, 2010 Share Posted March 9, 2010 (edited) That's because of the coding style Manko uses (check his profile). That's not bad, usually it's efficient enough. That function should look something like this: expandcollapse popupFunc _WinAPI_GetCommandLineFromPID($iPID) Local $aCall = DllCall("kernel32.dll", "handle", "OpenProcess", _ "dword", 1040, _ ; PROCESS_VM_READ | PROCESS_QUERY_INFORMATION "bool", 0, _ "dword", $iPID) If @error Or Not $aCall[0] Then Return SetError(1, 0, "") EndIf Local $hProcess = $aCall[0] Local $tPROCESS_BASIC_INFORMATION = DllStructCreate("dword_ptr ExitStatus;" & _ "ptr PebBaseAddress;" & _ "dword_ptr AffinityMask;" & _ "dword_ptr BasePriority;" & _ "dword_ptr UniqueProcessId;" & _ "dword_ptr InheritedFromUniqueProcessId") $aCall = DllCall("ntdll.dll", "int", "NtQueryInformationProcess", _ "handle", $hProcess, _ "dword", 0, _ ; ProcessBasicInformation "ptr", DllStructGetPtr($tPROCESS_BASIC_INFORMATION), _ "dword", DllStructGetSize($tPROCESS_BASIC_INFORMATION), _ "dword*", 0) If @error Then DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $hProcess) Return SetError(2, 0, "") EndIf Local $tPEB = DllStructCreate("byte InheritedAddressSpace;" & _ "byte ReadImageFileExecOptions;" & _ "byte BeingDebugged;" & _ "byte Spare;" & _ "ptr Mutant;" & _ "ptr ImageBaseAddress;" & _ "ptr LoaderData;" & _ "ptr ProcessParameters;" & _ "ptr SubSystemData;" & _ "ptr ProcessHeap;" & _ "ptr FastPebLock;" & _ "ptr FastPebLockRoutine;" & _ "ptr FastPebUnlockRoutine;" & _ "dword EnvironmentUpdateCount;" & _ "ptr KernelCallbackTable;" & _ "ptr EventLogSection;" & _ "ptr EventLog;" & _ "ptr FreeList;" & _ "dword TlsExpansionCounter;" & _ "ptr TlsBitmap;" & _ "dword TlsBitmapBits[2];" & _ "ptr ReadOnlySharedMemoryBase;" & _ "ptr ReadOnlySharedMemoryHeap;" & _ "ptr ReadOnlyStaticServerData;" & _ "ptr AnsiCodePageData;" & _ "ptr OemCodePageData;" & _ "ptr UnicodeCaseTableData;" & _ "dword NumberOfProcessors;" & _ "dword NtGlobalFlag;" & _ "ubyte Spare2[4];" & _ "int64 CriticalSectionTimeout;" & _ "dword HeapSegmentReserve;" & _ "dword HeapSegmentCommit;" & _ "dword HeapDeCommitTotalFreeThreshold;" & _ "dword HeapDeCommitFreeBlockThreshold;" & _ "dword NumberOfHeaps;" & _ "dword MaximumNumberOfHeaps;" & _ "ptr ProcessHeaps;" & _ "ptr GdiSharedHandleTable;" & _ "ptr ProcessStarterHelper;" & _ "ptr GdiDCAttributeList;" & _ "ptr LoaderLock;" & _ "dword OSMajorVersion;" & _ "dword OSMinorVersion;" & _ "dword OSBuildNumber;" & _ "dword OSPlatformId;" & _ "dword ImageSubSystem;" & _ "dword ImageSubSystemMajorVersion;" & _ "dword ImageSubSystemMinorVersion;" & _ "dword GdiHandleBuffer[34];" & _ "dword PostProcessInitRoutine;" & _ "dword TlsExpansionBitmap;" & _ "byte TlsExpansionBitmapBits[128];" & _ "dword SessionId") $aCall = DllCall("kernel32.dll", "bool", "ReadProcessMemory", _ "ptr", $hProcess, _ "ptr", DllStructGetData($tPROCESS_BASIC_INFORMATION, "PebBaseAddress"), _ "ptr", DllStructGetPtr($tPEB), _ "dword", DllStructGetSize($tPEB), _ "dword*", 0) If @error Or Not $aCall[0] Then DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $hProcess) Return SetError(3, 0, "") EndIf Local $tPROCESS_PARAMETERS = DllStructCreate("dword AllocationSize;" & _ "dword ActualSize;" & _ "dword Flags;" & _ "dword Unknown1;" & _ "word LengthUnknown2;" & _ "word MaxLengthUnknown2;" & _ "ptr Unknown2;" & _ "handle InputHandle;" & _ "handle OutputHandle;" & _ "handle ErrorHandle;" & _ "word LengthCurrentDirectory;" & _ "word MaxLengthCurrentDirectory;" & _ "ptr CurrentDirectory;" & _ "handle CurrentDirectoryHandle;" & _ "word LengthSearchPaths;" & _ "word MaxLengthSearchPaths;" & _ "ptr SearchPaths;" & _ "word LengthApplicationName;" & _ "word MaxLengthApplicationName;" & _ "ptr ApplicationName;" & _ "word LengthCommandLine;" & _ "word MaxLengthCommandLine;" & _ "ptr CommandLine;" & _ "ptr EnvironmentBlock;" & _ "dword Unknown[9];" & _ "word LengthUnknown3;" & _ "word MaxLengthUnknown3;" & _ "ptr Unknown3;" & _ "word LengthUnknown4;" & _ "word MaxLengthUnknown4;" & _ "ptr Unknown4;" & _ "word LengthUnknown5;" & _ "word MaxLengthUnknown5;" & _ "ptr Unknown5;") $aCall = DllCall("kernel32.dll", "bool", "ReadProcessMemory", _ "ptr", $hProcess, _ "ptr", DllStructGetData($tPEB, "ProcessParameters"), _ "ptr", DllStructGetPtr($tPROCESS_PARAMETERS), _ "dword", DllStructGetSize($tPROCESS_PARAMETERS), _ "dword*", 0) If @error Or Not $aCall[0] Then DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $hProcess) Return SetError(4, 0, "") EndIf $aCall = DllCall("kernel32.dll", "bool", "ReadProcessMemory", _ "ptr", $hProcess, _ "ptr", DllStructGetData($tPROCESS_PARAMETERS, "CommandLine"), _ "wstr", "", _ "dword", DllStructGetData($tPROCESS_PARAMETERS, "MaxLengthCommandLine"), _ "dword*", 0) If @error Or Not $aCall[0] Then DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $hProcess) Return SetError(5, 0, "") EndIf DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $hProcess) Return $aCall[3] EndFunc Obviously now you can use it to get other informations also. You just have to pick what you want from $tPROCESS_PARAMETERS structure. Test it. I know it works as 32bit. To make it bullet-proof someone with experience with these structures might help. edit: But maybe it's bullet-proof already. Edited March 9, 2010 by trancexx ♡♡♡ . eMyvnE Link to comment Share on other sites More sharing options...
rexx Posted March 10, 2010 Share Posted March 10, 2010 Thanks! Works fine both 32 and 64 bit. Link to comment Share on other sites More sharing options...
Manko Posted March 11, 2010 Author Share Posted March 11, 2010 Thanks, trancexx, for tidying up my code...Didn't know autoit did this for us... Haven't analysed your corrections, but am i correct in assuming "ptr" gets retranslated to 64 bits in 64-bit systems?Thanks also for contributing more fleshed-out structs!/Manko Yes i rush things! (I sorta do small bursts inbetween doing nothing.) Things I have rushed and reRushed:* ProDLLer - Process manager - Unload viri modules (dll) and moore...* _WinAPI_ProcessListOWNER_WTS() - Get Processes owner list...* _WinAPI_GetCommandLineFromPID() - Get commandline of target process...* _WinAPI_ThreadsnProcesses() Much info if expanded - optional Indented "Parent/Child"-style Processlist. Moore to come... eventually... Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now