hapi 发表于 2011-11-18 07:33:07

【转】读写其他进程内存技术

本帖最后由 hapi 于 2011-11-25 12:05 编辑

最近看了篇文章,关于读写其他进程内存的技巧,感觉有可取之处,贴出来共勉之!

众所周知,在win32中,每个应用程序都可“看见”4GB的线性地址空间,其中最开始的4MB和最后的2GB由操作系统保留,剩下的不足2GB的空间是应用程序的私有空间。具体分配原则是:(从高到低)0xFFFFFFFF~0xC0000000的1GB用于Vxd,存储器管理和文件系统,0xBFFFFFFF~0x80000000的1GB用于共享的win32Dll,存储器映像文件和共享存储区,0x7FFFFFFF~0x00400000为每个应用程序的私有空间,0x00300000~0x00001000位MS—DOS和win16应用程序,0x00000FFF~0x00000000为防止使用空指针而保留的4096字节。所以,我们通常用LordPe查看到的基地址大都是00400000。下面的程序例子是读取其他进程内存的例子,其中读取的数据放到lpBuffer中,写数据时将读取的lpBuffer中的数据原样写入,因为一不小心就可能挂掉被访问的进程。我就是这么想的,能挂掉最好,想通过在这种方法结束360tray.exe的进程,结果是失败了。代码贴出来做个记录吧!代码中的EnabledDebugPrivilege和KillTask是我自己后来为了结束其他进程而加入的。程序运行后会自行结束360的主动防御进程。其他地方做了注释! 注意在uses里加上 Tlhelp32;在测试的时候发现不提升权限,很多系统进程的内存没法访问,后来就加上了提升权限的功能。

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Mask,Tlhelp32;

type
TForm1 = class(TForm)
    ComboBox1: TComboBox;
    Memo1: TMemo;
    Label1: TLabel;
    MaskEdit1: TMaskEdit;
    MaskEdit2: TMaskEdit;
    Label2: TLabel;
    Label3: TLabel;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
private
    { Private declarations }
public
    { Public declarations }

    FSnapShotHandle: THandle;
    Function GetProcessID(var List : TStringList; FileName: string = ''): TProcessEntry32;
end;

var
Form1: TForm1;

implementation


{$R *.dfm}
function EnabledDebugPrivilege(const bEnabled:Boolean):Boolean;    //提升权限
var
hToken:Thandle;
tp:TOKEN_PRIVILEGES;
a:DWORD;
const SE_DEBUG_NAME = 'SeDebugPrivilege';
begin
Result:=False;
if (OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,hToken)) then
begin
tp.PrivilegeCount:=1;
LookupPrivilegeValue(nil,SE_DEBUG_NAME,tp.Privileges.luid);
if bEnabled then
tp.Privileges.Attributes:= SE_PRIVILEGE_ENABLED
else
tp.Privileges.Attributes:=0;
a:=0;
AdjustTokenPrivileges(hToken,false,tp,sizeof(tp),nil,a);
Result:= GetLastError = Error_SUCCESS;
closehandle(hToken);
end;
end;

function KillTask(ExeFileName: string): integer;//结束指定进程
const
PROCESS_TERMINATE = $0001;
var
ContinueLoop: BOOL;
FSnapshotHandle: THandle;
FProcessEntry32: TProcessEntry32;
begin
result := 0;

FSnapshotHandle := CreateToolhelp32Snapshot
    ( := Sizeof(FProcessEntry32);
ContinueLoop := Process32First(FSnapshotHandle,
    FProcessEntry32);

while integer(ContinueLoop) <> 0 do
begin
    if ((UpperCase(ExtractFileName(FProcessEntry32.szExeFile)) =
      UpperCase(ExeFileName))
      or (UpperCase(FProcessEntry32.szExeFile) =
      UpperCase(ExeFileName))) then
      Result := Integer(TerminateProcess(OpenProcess(
      PROCESS_TERMINATE, BOOL(0),
      FProcessEntry32.th32ProcessID), 0));
    Co op := Process32Next(FSnapshotHandle,
      FProcessEntry32);
end;
CloseHandle(FSnapshotHandle);
end;

Function HexToInt(HexStr: String):Int64;
var
Retvar : Int64;
i: Byte;
begin
HexStr := UpperCase(HexStr);
if HexStr = 'H' then
Delete(HexStr,Length(HexStr),1);
Retvar := 0;
for i := 1 to Length(HexStr) do
begin
   Retvar := Retvar shl 4;
   if HexStr in ['0'..'9'] then
    Retvar := Retvar + (Byte(HexStr) - 48)
   else
    if HexStr in ['A'..'F'] then
       (Byte(HexStr) - 55)
    else
   begin
      Retvar := 0;
      Break;
      end;
   end;
Result := Retvar;
end;


procedure TForm1.Button1Click(Sender: TObject);
var
FProcessEntry32 : TProcessEntry32;
ProcessID : Integer;
ProcessHandle : THandle;
lpBuffer : Pchar;
nSize : DWORD;
lpNumberOfBytes : DWORD;
i : Integer;
addr : DWORD;
s : String;
List :; //内存状态的结构,返回内存状态
dwOldProtect : DWORD;

begin
if Combobox1.ItemIndex = -1 then exit;
List := TStringList.Create;
FProcessEntry32 := GetProcessID(list,Combobox1.text); //查找指定进程
ifFProcessEntry32.th32ProcessID = 0 then exit;
ProcessID := FProcessEntry32.th32ProcessID;
Memo1.Lines.Clear;
Memo1.Lines.Add('Process ID : '+IntToHex(FProcessEntry32.th32ProcessID,8));
Memo1.Lines.Add('File Name : '+ FProcessEntry32.szExeFile);
ProcessHandle := OpenProcess(PROCESS_ALL_ACCESS,false,ProcessID); //以所有存取权打开进程
Memo1.Lines.Add('Process Handle : '+ inttohex(ProcessHandle,8));
Memo1.Lines.Add('虚拟内存中的数据:');
addr:=.Text) - addr +1;//长度
if HexToInt(MaskEdit2.Text)> addr then   //如果输入的起始,结束地址有效
begin
   lpBuffer := AllocMem(nSize);
   //开始读取其他进程的数据
   if (not ReadProcessMemory(ProcessHandle,Pointer(addr),lpBuffer,nSize,lpNumberOfBytes)) or (nSize<>lpNumberOfBytes) then
    begin             //被读进程句柄读的起始地址存放数据缓冲区读取字节数返回实际读取字节数
   showmessage('读取数据出错,可能是指定地址不存在');
   exit;
    end;
   s :='';
   for i := 0 to nSize -1 do
   begin
    S := s +(i=nSize -1) then    //每16字节分行显示
   begin
      Memo1.Lines.Add(s);
      s:='';
   end;
    end;         //进程句柄   内存区域有地址内存状态       结构长度
VirtualQueryEx(ProcessHandle,Pointer(addr),mbi_thunk, sizeof(TMemoryBasicInformation)); //取得内存状态
                     //进程句柄   指向改变首地址 大小    新的访问属性         当前访问属性
   VirtualProtectEx(ProcessHandle,Pointer(addr),nSize,PAGE_EXECUTE_READWRITE,mbi_thunk.Protect);//修改内存属性
   if(not WriteProcessMemory(ProcessHandle, Pointer(addr), lpBuffer, nSize, lpNumberOfBytes))
         then
   begin
      showmessage('写数据出错,可能是该地址不允许写。如果该处不是Rom,可以通过Ring0或其它特权写该内存。');
   end;
   VirtualProtectEx(ProcessHandle,Pointer(addr), nSize, mbi_thunk.Protect,dwOldProtect); //恢复内存属性
   FreeMem(lpBuffer, nSize);
end;
CloseHandle(ProcessHandle);    //关闭句柄,释放内存
List.free;
end;
//获取全部进程的名字
Function Tform1.GetProcessID(var List : TStringList; FileName: string = ''):TProcessEntry32;
var
Ret: BOOL;
s: string;
FProcessEntry32: TProcessEntry32;
begin
FSnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); //创建进程快照
FProcessEntry32.dwSize := Sizeof(FProcessEntry32);//初始化结构大小
Ret := Proces2First(FSnapshotHandle, FProcessEntry32); //取第一个进程
while Ret do
begin
    s := ExtractFileName(FProcessEntry32.szExeFile);
    if (FileName = '') then//如果filename为空,则列出全部进程
    begin
      List.Add(Pchar(s));
    end
    else if (AnsiCompareText(Trim(s),Trim(FileName))=0) and (FileName <> '') then
    begin
      List.Add(Pchar(s));
      result := FProcessEntry32;
      break;
    end;
    Ret := Process32Next(FSnapshotHandle, FProcessEntry32); //取下一进程

end;
//循环枚举出系统所有进程
CloseHandle(FSnapshotHandle);
end;

procedure TForm1.FormCreate(Sender: TObject);
var
List: TStringList;
i: integer;
begin
EnabledDebugPrivilege(true);    //提升权限
if KillTask('zhudongfangyu.exe') =1 then
showmessage('Ok!')
else showmessage('failed');
Combobox1.clear;
List := TStringList.Create;
GetProcessID(List);
for i := 0 to List.Count - 1 do
begin
    Combobox1.items.add(Trim(List.strings));
end;
List.Free;
Combobox1.itemindex := 0;
end;

end.
页: [1]
查看完整版本: 【转】读写其他进程内存技术