做外挂小记(2)--接上C#篇
http://hi.baidu.com/859729391/blog/item/58a4f21285a43a876438dbfd.html
大家都知道C#对底层的支持是非常不好....但是我们还是可以通过一些方法来读PID
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;//我们可以通过此类来查找进程pid,比通过API的来的简单的许多.
using System.Management;
namespace ok
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
public class getpid//定义取得pid的类
{ public string pid;//为了省事,我直接声明一个公共字段了,当然你也可以写属性写构造啦!
System.Diagnostics.Process[] processes = Process.GetProcesses();
//获得当前所有进程列表 ,注意是个数组,除非你的电脑只有一个进程
foreach (Process a in processes) //遍历每一个进程 ,如果出错请声明一下a
{
if(a.ProcessName.ToString()=="xxx.exe")//如果进程名等于xxx.exe,可以用资源管理器查看
{
pid= a.Id.ToString();//就输出他的pid,这样就可以获得pid了
//当然Process a的属性还有很多,总之很强大,例如 a.MachineName.ToString();//获取关联进程机器名
// a.MainWindowTitle.ToString();//获取主窗口的窗口名
//红色部分可以任意替换,如果你不知道进程名,知道窗口名,就用a.MainWindowTitle.ToString()="记事本"
}
}
}
}
//这样,我们就获得了进程的pid了,下面我们来修改内存...还是得调用API..下面我们来写个内存读写类.
//呵呵,说来说去还是要用API
public class read_and_write//定义一个类,类名随便你写....我就通俗点了,直接用read_and_write
{
const uint PROCESS_ALL_ACCESS = 0x001F0FFF;
const uint KEYEVENTF_EXTENDEDKEY = 0x1;
const uint KEYEVENTF_KEYUP = 0x2;
const uint KBC_KEY_CMD = 0x64;
const uint KBC_KEY_DATA = 0x60;
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName );
//得到窗体句柄的函数,FindWindow函数用来返回符合指定的类名( ClassName )和窗口名( WindowTitle )的窗口句柄
[DllImport("user32.dll")]
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, IntPtr ProcessId);
//取得pid的一种函数,我们上面已经获得pid了,所以这里用不到了.
[DllImport("kernel32.dll")]
static extern bool ReadProcessMemory(uint hProcess, IntPtr lpBaseAddress,
IntPtr lpBuffer, uint nSize, ref uint lpNumberOfBytesRead);
//读取进程内存的函数,非常重要
[DllImport("kernel32.dll")]
static extern bool WriteProcessMemory(uint hProcess, IntPtr lpBaseAddress,
uint[] lpBuffer, uint nSize, ref uint lpNumberOfBytesWritten);
//写入进程内存函数,更重要
[DllImport("kernel32.dll")]
public static extern uint OpenProcess(uint dwDesiredAccess, bool bInheritHandle, int dwProcessId);
//得到目标进程句柄的函数
//上面是调用一些API函数,不用记,COPY就行了,不记得就百度一下
public void write(string pid,IntPtr address,int wordin)//定义写内存的方法
{
byte[] vBuffer = new byte[4];
IntPtr vBytesAddress = Marshal.UnsafeAddrOfPinnedArrayElement(vBuffer, 0); // 得到缓冲区的地址
uint hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, Convert.ToInt32(pid));
//这个大家很熟悉了..获得进程句柄,并且得到绝对控制权限,3个参数(绝对控制,总是false,pid注意是int类型)
uint[] PinballScoreWrite = new uint[] { Convert.ToUInt32(wordin) };//定义欲写入
//写入的值,,注意是个数组,不是数组能不能我也不清楚,你可以试试
WriteProcessMemory(hProcess, address, PinballScoreWrite, (uint)vBuffer.Length, ref hProcess);
//这个就是写入内存了,参数列表(进程句柄,地址(注意其类型),写入的值,长度,ref hProcess)
//注意最后一个参数是引用传递..可能可以填0.
CloseHandle(hProcess);//养成良好习惯,关闭句柄
}
public string read(string pid,IntPtr address,int wordin)//定义读内存的方法,既然是读就有返回值
{
byte[] vBuffer = new byte[4];
IntPtr vBytesAddress = Marshal.UnsafeAddrOfPinnedArrayElement(vBuffer, 0); // 同上
uint hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, Convert.ToInt32(pid));//同上
uint[] PinballScoreWrite = new uint[] { Convert.ToUInt32(wordin) };//同上
if(ReadProcessMemory(hProcess, address, PinballScoreWrite, (uint)vBuffer.Length, ref hProcess);)
//假如读的出,这是个bool型判断,就就是true,则执行
{
CloseHandle(hProcess);//关闭句柄
return Convert.Tostring( Marshal.ReadInt32(address));//返回address地址存放的值,就可以调用了
else//否则什么都不做,只关闭句柄
{
CloseHandle(hProcess);
}
}
}
}
//这样我们就可以调用了...小记(3)则写一个如何调用read_and_write的类..^ ^