Jump to content

Process + Thread + DLL Functions UDFs


Ascend4nt
 Share

Recommended Posts

Those are the Context functions I excluded (as I stated previously). I see no legit reason yet why registers or code pointers need to be modified, other than for hacking another process. Perhaps it could be useful for inspecting a Thread created by AutoIt or another process - to maybe see where the code is at. But then, debuggers are much better for that (IDA Pro Disassembler and Debugger, for example). AutoIt isn't really meant for that type of advanced stuff.

So, I still need convincing. Modifying registers of another thread doesn't make sense for any legitimate purpose. Modifying the code pointer, or whats on the stack is also another thing I can't find a good, meaningful purpose for either - other than altering the flow of execution of another process (which again wreaks of hacking).

I'm sorta torn about this though.. I've already put the functions in the Thread manipulation GUI as a placeholder. And I've been testing it for the purpose of making sure it works right. I guess I just need someone to say 'I've got a great [legitimate] use for it'! Maybe I could include just the Context-read functions in the next release.. maybe

Link to comment
Share on other sites

  • 9 months later...

Well, I've decided to fill out this massive beast with even more functionality. Context functions? Check. PEB, TEB/TIB structure reading? Check. List of drivers loaded? Check. Plus, improvements, fixes, etc.. I think this can be considered complete.

By the way - full PEB and TEB structure definitions are included in the given modules, both fully x64 compatible (thanks VMWare!).

6/8/2011:

New:

  • _ProcessUDGetPEB.au3, _ThreadUDGetTEB.au3 -> both return fully filled out Structures for PEB or TEB
  • _ThreadContext.au3 - yes, I decided to add it in. There's some usefulness from a debug/inspection standpoint
  • _DriverList.au3 - Returns information about drivers loaded by the O/S (which don't show up in process lists!)
Added:
  • _ProcessesWinList() - multiple processes with the same name? This will get all the windows (_ProcessListFunctions UDF)
  • Functions for new modules: _ProcessUDGetPEB, _ThreadUDGetTEB, _ThreadGetContext, _ThreadGetWow64Context,

    _ThreadSetContext, _ThreadSetWow64Context, _DriverList

  • New examples: ProcessMemoryReducer.au3, DriverList.au3, DLLInjectionExample (stripped out of the _DLLInjection UDF)
  • Support modules for the GUI's
Changed:
  • Most 'List' functions now allow an 'everything that does NOT match criteria' flag [+8] (excludes matches)
  • Misc. tweaks in certain UDF's: slimmed code, pointers to Process memory can be numerical/string,
  • 'Test' GUI's - 'System' process is now allowed (though good luck getting much information on it). Also, new functions added, some minor fixes & tweaks.
Fixed:
  • _ProcessWinList() - 'Alt-Tab'-only windows was returning some 'non-Alt-tab' windows
  • _RemoteMsgBox() - Proper cleanup if error
Link to comment
Share on other sites

This is a lot of UDFs for 1 topic-- Although I guess they are all pretty similar in way.

Anyways, given your experience with threads/processes and memory-- Have you ever considered giving a crack at multithreading/multiprocessing within autoit? Figured you might be the best guy for the job.

Link to comment
Share on other sites

There are 2, no 3* examples in my code of creating additional threads - either in this process or in another. Admittedly, the examples are relatively simple, but it shows that it can be done. The problem is that it must be done with binary code.

As for AutoIt script 'code', AutoIt only interprets this code on one thread. If you know about Adlib, DLLCallback, and Keyboard/Mouse Hooking code (look around the forum for those), you'll find out soon enough that when AutoIt gets interrupted by one of those methods, it will stop interpreting the main script code (wherever it was at), and interpret from the place it was interrupted from (until it returns). So its impossible in native script code.

Binary code is the only way you'll get another thread going, and that means getting your hands dirty. I had created a multithreading UDF a while back (lost in the Examples forum somewhere), but it got very little interest because most people don't know how to use it, or expect it to create native script code threads.

As for multiprocessing - that's as simple as running another process. If you need to communicate between the two scripts, Inter-process Communication (IPC) is a common covered topic on the forums (or inter-script communication). This would be the suggested method for having a 'helper' script run on the side. There are a number of unique methods for updating one script from another, though the most common is using WM_COPYDATA messages.

Also, I'm not the only one who's created threads - monoceres, trancexx (her popular UDF, for example), and I believe ward have all created threads. See some links in in the now-defunct_RemoteThreadX UDF thread for more leads.

Still, the number of people that know how to create, run, and execute machine code (via CallWindowProc, CreateThread or CreateRemoteThread) is limited, as is the need for creating threads in a single-threaded script interpreter language. Multiprocessing will achieve what most people want to do - you just need to learn IPC methods, and you're set.

*edit: There are actually 3 examples, if you count the DLLInjection code.

*edit2: Clarified some things and added some links for those that are interested.

Edited by Ascend4nt
Link to comment
Share on other sites

There are 3* examples in my code of creating additional threads - either in this process or in another. Admittedly, the examples are relatively simple, but it shows that it can be done. The problem is that it must be done with binary code.

As for AutoIt script 'code', AutoIt only interprets this code on one thread. If you know about Adlib, DLLCallback, and Keyboard/Mouse Hooking code (look around the forum for those), you'll find out soon enough that when AutoIt gets interrupted by one of those methods, it will stop interpreting the main script code (wherever it was at), and interpret from the place it was interrupted from (until it returns). So its impossible in native script code.

Binary code is the only way you'll get another thread going, and that means getting your hands dirty. I had created a multithreading UDF a while back (lost in the Examples forum somewhere), but it got very little interest because most people don't know how to use it, or expect it to create native script code threads.

As for multiprocessing - that's as simple as running another process. If you need to communicate between the two scripts, Interprocess Communication (IPC) is a common covered topic on the forums (or interscript communication). This would be the suggested method for having a 'helper' script run on the side. There are a number of unique methods for updating one script from another, though the most common is using WM_COPYDATA messages.

also, I'm not the only one who's created threads - trancexx's GIF animation uses threads, for example. (Still, I recommend the easier route - multiprocessing)

*edit: there are actually 3 examples, if you count the DLLInjection code

Ohh, Yeah I figured any type of multithreading would be complex and over complicated for AutoIT purposes unless recompiled for support for it. I never knew you made a UDF for it and a search brings me to "_RemoteThreadX" but I see you removed it as explained on your autoit site.

I thought maybe you had a crack at multiprocessing UDF's. The one I use currently is ChildProc ().

He has examples using WM_COPYDATA but the fastest way is he uses Environment variables. A very simple demo of what he does (more or less) is here:

#include <Debug.au3>
Global Const $STDIO_INHERIT_PARENT = 0x10

_DebugSetup ("Debug Window", false, 2)
CheckIfChild()

_DebugOut("Hello, I am the parent");

EnvSet("ChildProc", "0x" & Hex(StringToBinary("Child")))

$iPid = Run(FileGetShortName(@AutoItExe) & ' "' & @ScriptFullPath & '"', @WorkingDir, default, $STDIO_INHERIT_PARENT )


Func Child()
    _DebugOut("Hello, I am the child");
EndFunc


Func CheckIfChild()
    $sCmd = EnvGet("ChildProc")
    If StringLeft($sCmd, 2) = "0x" Then
        $sCmd = BinaryToString($sCmd)
        Call($sCmd)

        If @error And Not @Compiled Then MsgBox(16, "ChildProc Error", "Unable to Call: " & $sCmd)
        Exit
    EndIf
EndFunc

However he uses functions like ProcessExists and such in his UDF, and because of it I think performance takes a hit. To counterbalance that I am going to take a crack at it mixing his idea for EnvVars, and having persistnant child processes (to avoid the slowdown of creating/destroying processes) that get fed variables/data thanks to CoCreates ideas for sending variables via STDIN/STDOUT: for the internal process functions I hope to use some parts of your UDF.

Thought maybe if you had any logic/advise for me on the way you would personally approach multiprocessing.

Link to comment
Share on other sites

If WM_COPYDATA is too slow for you, there's also direct process-memory writing. I'm sure I've heard of someone using that before. The concept is pretty simple: just allocate memory using either DLLStructCreate or a Memory allocation function (Heap,Global, or Virtual). Then you'd need to at least send a message (WM_COPYDATA or another) to the other script with the memory address. I know there's a number of other methods employed, but besides sending messages, writing to memory might be the fastest and most flexible.

Edit: Some Wikipedia links on Inter-process communication (IPC) methods and specifically related to this post, Shared memory

Edited by Ascend4nt
Link to comment
Share on other sites

  • 3 months later...

Can Someone help with _ProcessMemoryReadSimple

I have the folowing code

$struct = "int color;int position;char var[128]"
$Structure=DllStructCreate($struct)
DllStructSetData($Structure,"color",$BackgroundColor) ; sets the value of color at $BackgroundColor
DllStructSetData($Structure,"position",$CornerPosition) ; sets the value of corner position
$Pointer1 = DllStructGetPtr($Structure,"color") ; Returns the pointer to the color
$Pointer2 = DllStructGetPtr($Structure,"position") ; Returns the pointer to the position

and I am trying to read this way with no luck.

Read_Memory($PID, $Pointer1, 136, "int")
Func Read_Memory($_PID, $_Pointer, $iNumBytes, $_VarType = "int")
; This function will read a value in memory, allocated by the calling application ToolbarAG.exe
Local $DllHandle = _ProcessOpen($_PID, 0x0010) ; Open the memory allocated by the PID from the calling application
Local $Data = _ProcessMemoryReadSimple($DllHandle, $_Pointer, $iNumBytes, $_VarType) ; read value passed by the mother application
$error = @Error ; just check if any error reading the memory
_ProcessCloseHandle($DllHandle) ; Close the Handle
If $error > 1 Then
Return ""
Else
Return $Data
EndIf
EndFunc ;==>Read_Memory

Can someone give his lights?

Edited by mailro
Link to comment
Share on other sites

'int' isn't 136 bytes long, it's 4. If you want to read 136 bytes, you'll need to read it into a struct

Link to comment
Share on other sites

While you don't actually need to use _ProcessMemoryRead/Write functions for memory within the same process that is running (you can read it with simple DLLStruct* functions in this case), here's what works for your example:

$struct = "int color;int position;char var[128]"
$Structure=DllStructCreate($struct)
DllStructSetData($Structure,"color",22)
DllStructSetData($Structure,"position",44)
$Pointer1 = DllStructGetPtr($Structure,"color")
$Pointer2 = DllStructGetPtr($Structure,"position")

$hProcess=_ProcessOpen(@AutoItPID,0x10)    ; Get a Process Handle with PROCESS_VM_READ access
$vValue=_ProcessMemoryReadSimple($hProcess,$Pointer1,4,'int')
_ProcessCloseHandle($hProcess)

ConsoleWrite("$vValue="&$vValue&@CRLF)

Console output:

$vValue=22

Link to comment
Share on other sites

It is not the same process. There are 2 different processes. The one creates the structure and passes to the second the pointers and his pid and the second tries to read from that pointers. It is the following example trying to be written with your functions.

Edited by mailro
Link to comment
Share on other sites

What the heck - for people using NomadMemory still, I've attached a special version of NomadMemory to the 1st post. Its untested but should work the way the old one did. (see the UDF for documentation on the missing functions and their replacements)

Edited by Ascend4nt
Link to comment
Share on other sites

Thanks!! It did the trick. It seems it is working ok. And it works as x64 too that I wanted.

They only think that was not and working is when you also use the function below to trace the times. When it is called no more data is being exchanged between mother and child.

Do you have any idea why? if not its ok. I will search for another way to trace the times

Thanks again for helping. You rule :graduated:

Func _dbg($msg = "NotFound")
Global $Pass
$Pass += 1
$Pass = String($Pass)
$PID = String(@AutoItPID)
If $msg = "NotFound" Then
  DllCall("kernel32.dll", "none", "OutputDebugString", "str", $PID & " Pass: " & $Pass)
Else
  DllCall("kernel32.dll", "none", "OutputDebugString", "str", $msg)
EndIf
EndFunc   ;==>_dbg
Link to comment
Share on other sites

Change that to 'OutputDebugStringA' (or 'OutputDebugStringW' with a 'wstr' parameter). Otherwise it causes a system error (check with _WinAPI_GetLastErrorMessage()). But yah, that's got nothing to do with this thread, and I have no idea why it would cause communication to fail. Try posting on the 'Shared memory variables demo' thread instead, if that still causes an issue. Or heck, maybe send the debug info to ConsoleWrite..

Link to comment
Share on other sites

  • 2 months later...

Ascend4nt what's ThreadCreate() is going to do?

Is it going to allow us to have MultiThreading like C++ or C# in AutoIt?

If yes, can you show me a simple example? Maybe something like this:

Func MainThread()
For $i = 1 To 10
  ToolTip($i, 10, 10, "Main Thread")
  Sleep(500)
Next
EndFunc
Func SecondThread()
For $i = 1 To 10
  TrayTip("Second Thread", $i, 1)
  Sleep(1000)
Next
EndFunc

Can we have each of this functions as a separated Thread and run both of them at once? I mean this 2 Loops running in same time.

Maybe i completely didn't understand your CreateThread() functionality, in this case just ignore my post.

Best Regards.

Edited by D4RKON3
Link to comment
Share on other sites

D4RKON3,

First question has been answered already - see Basically, don't bother using _ThreadCreate().

As for the ProcessMemoryReducer UDF, that simply calls 'EmptyWorkingSet' once for the processes you choose. It's usefulness is somewhat debated (search the forums), but in certain cases where a process is relatively dormant, it can be used without much worry about excess disk swapping.

Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...