C # simulate keyboard and mouse 2: Incorrect jump and memory View

Source: Internet
Author: User

The last time we used windows API and xml configuration to simulate the keyboard and mouse, we did not handle logical errors or exceptions in the simulation (for example, after the simulation is enabled, some forms or business logic errors of the current program do not need to be prompted, and the simulation program must exit normally to ensure data security .), In addition, the Label-like controls in the form cannot capture the form handle or traverse the sub-form handle to obtain the corresponding information. Therefore, after a period of research and rectification, the ErrorTo attribute and the Error node are added to some configuration nodes. When a logical Error or exception occurs, the nodes directly jump to the corresponding node to run the corresponding normal exit step.

I set the ErrorTo attribute to be set on all nodes, but if the child node does not exist, the setting of the parent node will be used. The configuration changes are as follows:

1 <Program Name = "kp" Value = "\ BIN \ kp.exe" ErrorTo = "No2"> SOFTWARE \ aerospace information \ counterfeit invoicing \ path </Program>

For the above changes, we need to modify the AbstractStep and make some changes to the default Init initialization method. The code changes are as follows:

1 /// <summary>

2 // Initialization

3 /// </summary>

4 // <param name = "step"> previous step </param>

5 // <param name = "node"> node </param>

6 public virtual void Init (AbstractStep step, XElement node)

7 {

8 // the original code is omitted

9 // Add code

10 this. ErrorTo = this. GetAttribute ("ErrorTo ");

11 if (string. IsNullOrEmpty (this. ErrorTo ))

12 {

13 this. ErrorTo = this. ParentStep. ErrorTo;

14}

15}

As for the newly added Error node, the main function is to configure a normal exit step, because we may open multiple forms, so we need to close them in sequence, or cancel the storage of some data. In addition to the main nodes, other sub-steps are the original configurations, which are roughly as follows:

1 <Error Name = "No1">

2 <Form Class = "TInvQueryForm" Caption = "select invoice number query">

3 <KeyBoard> {ESC} </KeyBoard>

4 <KeyBoard> {ESC} </KeyBoard>

5 <KeyBoard> {ESC} </KeyBoard>

6 <Form Class = "TMainForm" Caption = "">

7 <ClickTo>-5, 5 </ClickTo>

8 </Form>

9 <Form Class = "TFaceForm" Caption = "VAT anti-counterfeiting Tax Control System invoicing subsystem">

10 <ClickTo> 504,330 </ClickTo>

11 </Form>

12 </Form>

13 </Error>

When adding a node, you need to make some judgment on the XML parsing configuration. The changes are as follows:

  

1 /// <summary>

2 // obtain the subnode

3 /// </summary>

4 /// <param name = "parentStep"> step object of the parent node </param>

5 /// <param name = "childList"> subnode list </param>

6 /// <param name = "nowList"> List of subnode steps </param>

7 void GetChildStep (AbstractStep parentStep, IEnumerable <XElement> childList, IList <AbstractStep> nowList)

8 {

9 foreach (var node in childList)

10 {

11 if (node. Name. LocalName = "Error ")

12 {

13 var type = node. Attribute ("Name"). Value;

14 this. dicError [type] = new List <AbstractStep> ();

15 this. GetChildStep (parentStep, node. Elements (), this. dicError [type]);

16}

17 else

18 {

19 // the original code is omitted

20}

21}

22}

The basic configuration and resolution are almost the same, and the rest is about the modifications that need to be made during the internal operation. Because we need to handle logical errors and abnormal processes, it is relatively simple to handle exceptions. We only need to use Try in the Tick event of Timer... catch can be captured. If the logic is incorrect, it involves a wide range of aspects, such: the corresponding form handle cannot be captured, the retrieved handle value does not exist in the comparison data, and the handle is unavailable. Because we have set an enumeration to determine the status of the Step --- EnumStepState, therefore, we need to add two enumerated values, for example, LogicError and Exception, and then refer to the possible errors. Therefore, we need to modify the step of the derived class: fromStep, ChildStep, IfStep, EachStep, and ProgramStep.

FormStep: A logical error occurs when a form does not exist after the waiting time is exceeded.

ChildStep: similar to FormStep, the range is found in the subform of the form.

IfStep: This is complicated because If will trigger another simulation device. Therefore, we need to set the normal end of the If simulation device to the start of the original simulation device, and set the configuration of the original simulation device to the If simulation device.

EachStep: similar to IfStep, only the returned values in the cyclic step need to be returned with one more status for logical errors.

ProgramStep: determines the program to be started. If yes, the logic is incorrect.

At this point, we will almost modify the error. Next, we will use the capture memory method for values similar to Label. Because it is only a separate test, it has not been added to the original function. In this case, we need to use another windows api, kernel32.dll. The main api is as follows:

1 /// <summary>

2 // close the handle Resource

3 /// </summary>

4 /// <param name = "processWnd"> process form handle </param>

5 [DllImport ("kernel32.dll")]

6 public static extern void CloseHandle (IntPtr processWnd );

7

8 /// <summary>

9 // open the process handle Resource

10 /// </summary>

11 /// <param name = "wndDesiredAccess"> the form requires an access restriction. The maximum permission is 0x1F0FFF. </param>

12 /// <param name = "bInheritHandle"> whether to inherit the processing? </param>

13 /// <param name = "processId"> process ID </param>

14 /// <returns> </returns>

15 [DllImportAttribute ("kernel32.dll", EntryPoint = "OpenProcess")]

16 public static extern IntPtr OpenProcess (int dwDesiredAccess, bool bInheritHandle, int processId );

17

18 /// <summary>

19 // read the value of the memory specified by the process into the buffer zone

20 /// </summary>

21 /// <param name = "processWnd"> process form handle </param>

22 /// <param name = "addressWnd"> memory address handle </param>

23 // <param name = "bufferWnd"> buffer address handle </param>

24 /// <param name = "bufferSize"> buffer size </param>

25 /// <param name = "bufferReadWnd"> handle of the number of bytes read by the buffer </param>

26 /// <returns> </returns>

27 [DllImportAttribute ("kernel32.dll", EntryPoint = "ReadProcessMemory")]

28 public static extern bool ReadProcessMemory (IntPtr processWnd, IntPtr addressWnd, IntPtr bufferWnd, int bufferSize, IntPtr bufferReadWnd );

29

30 /// <summary>

31 // write the value to the memory specified by the Process

32 /// </summary>

33 // <param name = "processWnd"> process form handle </param>

34 /// <param name = "addressWnd"> memory address handle </param>

35 /// <param name = "values"> value array </param>

36 /// <param name = "bufferSize"> buffer size </param>

37 // <param name = "bufferWriteWnd"> handle of the number of bytes written to the buffer </param>

38 /// <returns> </returns>

39 [DllImportAttribute ("kernel32.dll", EntryPoint = "WriteProcessMemory")]

40 public static extern bool WriteProcessMemory (IntPtr processWnd, IntPtr addressWnd, int [] values, int bufferSize, IntPtr bufferWriteWnd );

In addition, we need to use our own methods, because I personally prefer to use the extension method, so there will be more extension methods. The Code is as follows:

1 /// <summary>

2 // obtain the process based on the process name

3 /// </summary>

4 // <param name = "name"> process name </param>

5 /// <returns> </returns>

6 public static Process GetProcessByName (string name)

7 {

8 Process process = null;

9 try

10 {

11 Process [] processes = Process. GetProcessesByName (name );

12 process = processes [0];

13}

14 catch (Exception)

15 {

16 throw new Exception (string. Format ("the process name does not exist {0 }. ", Name ));

17}

18 return process;

19}

20

21 /// <summary>

22 // obtain the process based on the process title

23 /// </summary>

24 // <param name = "title"> process title </param>

25 /// <returns> </returns>

26 public static Process GetProcessByTitle (string title)

27 {

28 Process process = null;

29 try

30 {

31 Process [] processes = Process. GetProcesses ();

32 foreach (var p in processes)

33 {

34 if (p. MainWindowTitle. IndexOf (title )! =-1)

35 {

36 process = p;

37}

38}

39}

40 catch (Exception)

41 {

42 throw new Exception (string. Format ("the process title does not exist: {0 }. ", Title ));

43}

44 return process;

45}

46

47 -------------------------------------------------- Extension Method ----------------------------------------------

48 /// <summary>

49 // read the memory value of the process

50 /// </summary>

51 // <param name = "p"> Process </param>

52 // <param name = "address"> memory address </param>

53 // <returns> </returns>

54 public static int ReadProcessMemoryValue (this Process p, int address)

55 {

56 // set the buffer, open the process handle resource, read the memory, and close the Process Handle Resource

57 byte [] buffer = new byte [4];

58 IntPtr byteAddress = Marshal. UnsafeAddrOfPinnedArrayElement (buffer, 0 );

59 IntPtr processWnd = Memory. OpenProcess (0x1F0FFF, false, p. Id );

60 Memory. ReadProcessMemory (processWnd, (IntPtr) address, byteAddress, 4, IntPtr. Zero );

61 Memory. CloseHandle (processWnd );

62 return Marshal. ReadInt32 (byteAddress );

63}

64

65 // <summary>

66 // write the value to the memory specified by the Process

67 /// </summary>

68 // <param name = "baseAddress"> </param>

69 // <param name = "processName"> </param>

70 // <param name = "value"> </param>

71 public static void WriteProcessMemoryValue (this Process p, int address, int value)

72 {

73 // open the process handle resource, write the value to the specified memory address, and release the Process Handle Resource

74 IntPtr processWnd = Memory. OpenProcess (0x1F0FFF, false, p. Id); // 0x1F0FFF maximum permission

75 Memory. WriteProcessMemory (processWnd, (IntPtr) address, new int [] {value}, 4, IntPtr. Zero );

76 Memory. CloseHandle (processWnd );

77}

After we have the method, we also need to use a tool to help-CheatEngine, which can help us filter the required values and find the memory address. The Code is as follows:

1 var p = memory.getprocpolicytitle(this.txt ProcessTitle. Text );

2 var address = 0x014C14DC;

3 var value = p. ReadProcessMemoryValue (address );

Because of the time, there are not many learnings. It's almost time to come. Thank you. I was very sorry because I forgot to provide the source code last time. This time I made up the code and wrote it poorly. I'm sorry, haha. Source code here! <------ Remember to download

Author ahl5esoft

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.