[Discusión miscelánea] Un método de detección anti-trampas de C#

prefacio

Recientemente, al descompilar un juego de Unity, encontré una solicitud para agregar un mecanismo anti-trampas. Al principio, usaba el proceso Process en Internet para leer y operar. Después de muchos intentos, descubrí que los procesos similares a Cheat Engine y Speed ​​​​Wizard no podían encontrar el Nombre del proceso. Al mismo tiempo, según el método de lectura de Handle mencionado en Internet, probé el Handle de C# (realmente implementado usando Unity, pero la esencia sigue siendo C#) combinado con User32.dll para leer el Handle, pero desafortunadamente, todavía no pude encontrar el nombre del título leyendo el identificador, así que cambié a él. El método se describe a continuación.

当然,完全可能是因为我本人对于语言的了解不够透彻而导致的无法操作Handle的情况,在此还请大家多多包涵

forma seria

1. Determinar si el proceso ha comenzado leyendo la lista de procesos

De hecho, es obvio que el método anti-trampas más simple es monitorear si el programa de trampas está activado. Encontré el código C# relevante en Internet de la siguiente manera:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Diagnostics;
 
public class NewBehaviourScript : MonoBehaviour
{
    
    
  	......
    public void ReadProgramm()
    {
    
    
       Process[] ps = Process.GetProcesses();
       foreach(Process p in ps){
    
    
          string info = "";
          try
          {
    
    
              info = p.Id + "  " + p.ProcessName + "  " + p.MainWindowTitle + "  " + p.StartTime;
          }catch(Exception e){
    
    
              info = e.Message;
          }
          Console.WriteLine(info);
       }
    }
  ......
}

Desafortunadamente, tal vez debido a mis problemas técnicos, la lista de programas se puede obtener ya sea que se inicie en modo administrador o en modo no administrador, pero a menudo es imposible consultar otros procesos como CE y , o ProcessNamevacío MainWindowTitle. Entonces, en este caso, tuve que encontrar otra manera.

2. Lea el nombre de la ventana del programa a través de User32

Primero damos el código directamente.

//获取窗口标题
[DllImport("user32", SetLastError = true)]
private static extern int GetWindowText(
    IntPtr hWnd,//窗口句柄
    StringBuilder lpString,//标题
    int nMaxCount //最大值
);

//获取类的名字
[DllImport("user32.dll")]
private static extern int GetClassName(
    IntPtr hWnd,//句柄
    StringBuilder lpString, //类名
    int nMaxCount //最大值
);

Todavía es una pena que aquí siempre pienso que es mi problema técnico lo que causó que el nombre de la ventana de lectura y el nombre de la clase aún no detectaran el nombre de la ventana CE y algunas otras ventanas de programas de trampa, pero no sé cómo para aplicarlo. , así que me tengo que rendir, espero que todos los que saben me puedan enseñar.

una herejía

Dado que no puedo implementar los dos métodos anteriores, e incluso en algunos casos necesitamos obtener privilegios de administrador, ¿hay alguna manera que no requiera privilegios de administrador y pueda leerse fácilmente? creo que hay

Bajo el administrador de tareas de Windows, no es difícil encontrar que realmente podemos ver todos los procesos, nombres de procesos y nombres de ventanas, y esta lectura se puede leer a través de la línea de comando, y se puede leer la ID del programa tasklist. requieren privilegios de administrador en absoluto.

La teoría existe y comienza la práctica.

Entonces, el primer paso que debemos hacer es escribir un código que ejecute la línea de comando, usando C#un método de clase que a su vez llame a un proceso.

public void RunCmd(string cmd)
{
    
    
  	Process proc = new Process();
    proc.StartInfo.FileName = @"cmd.exe";
    proc.StartInfo.CreateNoWindow = true;//不显示程序窗口
    proc.StartInfo.UseShellExecute = false;//使用shell启动
    proc.StartInfo.RedirectStandardError = true;//重定向标准错误
    proc.StartInfo.RedirectStandardInput = true;//重定向标准输入
    proc.StartInfo.RedirectStandardOutput = true;//重定向标准输出
    proc.Start();
    proc.StandardInput.WriteLine(cmd);//标准输入,输入cmd命令
    proc.Close();
}

Entonces, obviamente, podemos obtener una salida a través de este programa, o establecer el valor de retorno de la función para stringobtener la salida estándar string outStr = proc.StandardOutput.ReadtoEnd();para que podamos returndevolver un resultado de salida. Luego divida los resultados de salida dividiendo y dividiendo la cadena para obtener la información de todos los programas en ejecución, y luego juzgue el ID y el nombre del programa para cerrar el programa (requiere privilegios de administrador), o cierre su propio programa (u otras medidas) para lograr el efecto

Epílogo

Habiendo dicho eso, creo que todavía es necesario entender User32.dllel contenido del contenido. Creo que esta es realmente la forma más útil. Creo que todavía es necesario entender y aprender. Pero también es interesante pensar en esta forma lateral de vez en cuando. Sin embargo, si tiene algún otro método, espero que me pueda enseñar, muchas gracias.

Supongo que te gusta

Origin blog.csdn.net/qq_19577209/article/details/118345982
Recomendado
Clasificación