代码拉取完成,页面将自动刷新
unit frmEditHistoryUnit;
{$mode delphi}
interface
uses
{$ifdef darwin}
macport,
{$endif}
{$ifdef windows}
windows,
{$endif}
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs,
StdCtrls, ComCtrls, ExtCtrls, Menus, NewKernelHandler, syncobjs,
symbolhandler, lua, lauxlib, lualib, betterControls;
type
{ TfrmEditHistory }
TfrmEditHistory = class(TForm)
Button1: TButton;
cbLogWrites: TCheckBox;
edtMaxWriteLogSize: TEdit;
wlImageList: TImageList;
Label1: TLabel;
lvWriteLog: TListView;
miUndo: TMenuItem;
Panel1: TPanel;
PopupMenu1: TPopupMenu;
Timer1: TTimer;
procedure Button1Click(Sender: TObject);
procedure cbLogWritesChange(Sender: TObject);
procedure edtMaxWriteLogSizeChange(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure lvWriteLogDblClick(Sender: TObject);
procedure miUndoClick(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
private
{ private declarations }
public
{ public declarations }
procedure refreshWriteLogView;
end;
TWriteLogEntry=class
public
id: integer;
address: ptruint;
originalsize: dword;
originalbytes: pbyte;
newsize: dword;
newbytes: pbyte;
destructor destroy; override;
end;
var
frmEditHistory: TfrmEditHistory;
logWrites: boolean=false;
procedure addWriteLogEntryToList(wle: TWriteLogEntry);
procedure setMaxWriteLogSize(size: integer);
procedure clearWriteLog;
procedure undoLastWrite;
procedure initializeLuaWriteLog;
function hasAddressBeenChanged(address: ptruint): boolean;
function hasAddressBeenChangedRange(startaddress, stopaddress: ptruint): boolean;
procedure undowrite(address: ptruint); overload;
implementation
{$R *.lfm}
uses MemoryBrowserFormUnit, ProcessHandlerUnit, globals, luahandler, LuaClass,
LuaByteTable, LuaObject, maps;
var
nextid: integer;
writelog: TList; //for a sorted list in the order it got changed
writelogmap: TMap; //for an address lookup to see if an address has been changed (holds every single byte)
writelogcs: TCriticalSection;
maxwritelogsize: integer=250;
{ TfrmEditHistory }
destructor TWriteLogEntry.destroy;
begin
if originalbytes<>nil then
FreeMemAndNil(originalbytes);
if newbytes<>nil then
FreeMemAndNil(newbytes);
inherited destroy;
end;
procedure removeBytesFromWriteLogMap(wle: TWriteLogEntry);
var
i: integer;
data: TObject;
a: ptruint;
oldwle: TWriteLogEntry;
begin
for i:=0 to wle.newsize-1 do
begin
a:=wle.address+i;
if writelogmap.GetData(a,data) then
begin
if data is TWriteLogEntry then //no list
writelogmap.Delete(a)
else //tlist
begin
tlist(data).Remove(wle);
if tlist(data).Count=1 then //no list needed anymore
begin
oldwle:=TWriteLogEntry(tlist(data)[0]);
tlist(data).free;
writelogmap.SetData(a,oldwle);
end;
end;
end;
end;
end;
procedure eraseWriteLogEntry(i: integer);
var wle: TWriteLogEntry;
begin
writelogcs.Enter;
try
if i<writelog.count then
begin
wle:=writelog[i];
writelog.Delete(i);
removeBytesFromWriteLogMap(wle);
wle.free;
end;
finally
writelogcs.Leave;
end;
end;
procedure clearWriteLog;
begin
while writelog.Count>0 do
eraseWriteLogEntry(writelog.count-1);
writelogmap.Clear; //should be empty already
end;
procedure addBytesToWriteLogMap(wle: TWriteLogEntry);
var
i: integer;
data: TObject;
newlist: TList;
a: ptruint;
begin
for i:=0 to wle.newsize-1 do
begin
a:=wle.address+i;
if writelogmap.GetData(a,data) then
begin
if data is TWriteLogEntry then
begin
//change the old entry to a list
newlist:=tlist.create;
newlist.add(data); //old entry first in the list
newlist.add(wle); //and now the new one
writelogmap.SetData(a, newlist);
end
else //tlist
tlist(data).Add(wle);
end
else
writelogmap.Add(a,wle);
end;
end;
procedure addWriteLogEntryToList(wle: TWriteLogEntry);
begin
wle.id:=nextid;
inc(nextid);
writelogcs.Enter;
try
if writelog.Count>maxwritelogsize then
eraseWriteLogEntry(0);
writelog.Add(wle);
addBytesToWriteLogMap(wle);
finally
writelogcs.leave;
end;
if (MainThreadID=GetCurrentThreadId) and (frmEditHistory<>nil) and (not frmEditHistory.Timer1.Enabled) then
frmEditHistory.Timer1.Enabled:=true;
end;
procedure setMaxWriteLogSize(size: integer);
begin
maxwritelogsize:=size;
while writelog.count>maxwritelogsize do
eraseWriteLogEntry(0);
end;
procedure undowriteInternal(id: integer); overload;
var i: integer;
wle: TWriteLogEntry;
x: ptruint;
oldprot: dword;
oldLogWrites: boolean;
vpe: boolean;
begin
writelogcs.enter;
try
for i:=0 to writelog.count-1 do
begin
wle:=TWriteLogEntry(writelog[i]);
if wle.id=id then
begin
vpe:=(SkipVirtualProtectEx=false) and VirtualProtectEx(processhandle, pointer(wle.address), wle.originalsize, PAGE_EXECUTE_READWRITE, oldprot);
oldLogWrites:=logWrites;
logWrites:=false;
WriteProcessMemory(processhandle, pointer(wle.address), wle.originalbytes, wle.originalsize, x);
logWrites:=oldLogWrites;
if vpe then VirtualProtectEx(processhandle, pointer(wle.address), wle.originalsize, oldprot, oldprot);
eraseWriteLogEntry(i);
break;
end;
end;
finally
writelogcs.leave;
end;
if frmEditHistory<>nil then
frmEditHistory.refreshWriteLogView;
end;
procedure undowrite(address: ptruint); overload;
var
data: TObject;
list: TList absolute data;
begin
if writelogmap.GetData(address, data) then
begin
if data is TWriteLogEntry then
undowriteInternal(TWriteLogEntry(data).id)
else
undowriteInternal(TWriteLogEntry(list[list.Count-1]).id);
end;
end;
procedure undoLastWrite;
begin
writelogcs.enter;
try
if writelog.Count>0 then
undowriteInternal(TWriteLogEntry(writelog[writelog.count-1]).id);
finally
writelogcs.leave;
end;
end;
procedure TfrmEditHistory.refreshWriteLogView;
var
i,j: integer;
wle: TWriteLogEntry;
e: tlistitem;
s: string;
selectedids: TIntegerSet;
mainselectedid: integer;
begin
if lvWriteLog.itemindex<>-1 then
mainselectedid:=integer(ptruint(lvWriteLog.items[lvWriteLog.ItemIndex].Data))
else
mainselectedid:=-1;
selectedids:=[];
for i:=0 to lvWriteLog.Items.Count-1 do
if lvWriteLog.Items[i].Selected then
selectedids:=selectedids+[integer(ptruint(lvWriteLog.Items[i].data))];
lvwritelog.BeginUpdate;
lvWriteLog.Clear;
writelogcs.enter;
try
for i:=0 to writelog.Count-1 do
begin
wle:=writelog[i];
e:=lvwritelog.Items.Add;
e.Caption:=symhandler.getNameFromAddress(wle.address);
s:='';
for j:=0 to wle.originalsize-1 do
s:=s+inttohex(wle.originalbytes[j],2)+' ';
e.SubItems.add(s);
s:='';
for j:=0 to wle.newsize-1 do
s:=s+inttohex(wle.newbytes[j],2)+' ';
e.SubItems.add(s);
e.Data:=pointer(wle);
end;
finally
writelogcs.leave;
end;
for i:=0 to lvwritelog.items.count-1 do
begin
if uintptr(lvWriteLog.Items[i].data) in selectedids then
lvWriteLog.Items[i].selected:=true;
if (mainselectedid<>-1) and (uintptr(lvWriteLog.Items[i].data)=mainselectedid) then
lvWriteLog.ItemIndex:=i;
end;
lvWriteLog.EndUpdate;
end;
procedure TfrmEditHistory.Button1Click(Sender: TObject);
begin
refreshWriteLogView;
end;
procedure TfrmEditHistory.cbLogWritesChange(Sender: TObject);
begin
logwrites:=cbLogWrites.checked;
end;
procedure TfrmEditHistory.edtMaxWriteLogSizeChange(Sender: TObject);
var v: integer;
begin
try
setMaxWriteLogSize(StrToInt(edtMaxWriteLogSize.text));
except
end;
end;
procedure TfrmEditHistory.FormShow(Sender: TObject);
begin
cbLogWrites.Checked:=logWrites;
edtMaxWriteLogSize.text:=inttostr(maxwritelogsize);
end;
procedure TfrmEditHistory.lvWriteLogDblClick(Sender: TObject);
begin
if lvWriteLog.Selected<>nil then
MemoryBrowser.disassemblerview.SelectedAddress:=symhandler.getAddressFromName(lvWriteLog.Selected.Caption);
end;
procedure TfrmEditHistory.miUndoClick(Sender: TObject);
var i: integer;
begin
for i:=lvWriteLog.items.count-1 downto 0 do
begin
if lvWriteLog.Items[i].Selected then
undowrite(TWriteLogEntry(lvWriteLog.Items[i].Data).address);
end;
end;
procedure TfrmEditHistory.Timer1Timer(Sender: TObject);
begin
timer1.enabled:=false;
refreshWriteLogView;
end;
//--------------------Lua-----------------
type
TWriteLog=class
private
function getWriteLogStatus: boolean;
procedure setWriteLogStatus(status: boolean);
function getWriteLogSize: integer;
procedure setWriteLogSize(size: integer);
public
published
property status: boolean read getWriteLogStatus write setWriteLogStatus;
property logsize: integer read getWriteLogSize write setWriteLogSize;
end;
var _writelog: TWriteLog;
function TWriteLog.getWriteLogStatus: boolean;
begin
result:=logWrites;
end;
procedure TWriteLog.setWriteLogStatus(status: boolean);
begin
logWrites:=status;
end;
function TWriteLog.getWriteLogSize: integer;
begin
result:=maxwritelogsize;
end;
procedure TWriteLog.setWriteLogSize(size: integer);
begin
maxwritelogsize:=size;
end;
function lua_getWriteLog(L:PLua_state): integer; cdecl;
begin
if _writelog=nil then
_writelog:=TWritelog.create;
luaclass_newClass(L,_writelog);
result:=1;
end;
function writelog_getLog(L:PLua_state): integer; cdecl;
var
wle: TWriteLogEntry;
i: integer;
begin
writelogcs.enter;
try
lua_newtable(L);
for i:=0 to writelog.count-1 do
begin
lua_pushinteger(L,i);
lua_newtable(L);
wle:=TWriteLogEntry(writelog[i]);
lua_pushstring(L, 'address');
lua_pushinteger(L, wle.address);
lua_settable(L,-3);
lua_pushstring(L, 'original');
CreateByteTableFromPointer(L, pbytearray(wle.originalbytes), wle.originalsize);
lua_settable(L,-3);
lua_pushstring(L, 'new');
CreateByteTableFromPointer(L, pbytearray(wle.newbytes), wle.newsize);
lua_settable(L,-3);
lua_settable(L,-3);
end;
result:=1;
finally
writelogcs.leave;
end;
end;
procedure writelog_addMetaData(L: PLua_state; metatable: integer; userdata: integer );
begin
object_addMetaData(L, metatable, userdata);
luaclass_addClassFunctionToTable(L, metatable, userdata, 'getLog', writelog_getLog);
end;
procedure initializeLuaWriteLog;
begin
luaclass_register(TWriteLog, writelog_addMetaData);
lua_register(LuaVM, 'getWriteLog', lua_getWriteLog);
end;
function hasAddressBeenChanged(address: ptruint): boolean;
begin
if logwrites then
result:=writelogmap.HasId(address)
else
result:=false;
end;
function hasAddressBeenChangedRange(startaddress, stopaddress: ptruint): boolean;
var i: integer;
startb: ptruint;
stopb: ptruint;
wle: TWriteLogEntry;
begin
if stopaddress-startaddress<writelog.count*4 then
begin
while startaddress<stopaddress do
begin
if hasAddressBeenChanged(startaddress) then
exit(true);
inc(startaddress);
end;
end
else
begin
//search the list
for i:=0 to writelog.count-1 do
begin
wle:=TWriteLogEntry(writelog[i]);
startb:=wle.address;
stopb:=wle.address+wle.newsize;
if ((startaddress < stopb) and (startb < stopaddress)) then
exit(true);
end;
end;
result:=false;
end;
initialization
writelog:=TList.create;
writelogmap:=TMap.Create(itsPtrSize, sizeof(TObject));
writelogcs:=TCriticalSection.create;
finalization
while writelog.count>0 do
eraseWriteLogEntry(writelog.count-1);
writelog.free;
writelogcs.free;
end.
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。