- 注册时间
- 2011-10-30
- 最后登录
- 1970-1-1
该用户从未签到
|
本帖最后由 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;
aWORD;
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[0].luid);
if bEnabled then
tp.Privileges[0].Attributes:= SE_PRIVILEGE_ENABLED
else
tp.Privileges[0].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[Length(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); //查找指定进程
if FProcessEntry32.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. |
|