function MyExtractFilePath(f: String): String;
var
i, l: integer;
begin
l := Length(f);
for i := l downto 1 do
if f[i] = '\' then Break;
result := copy(f, 0, i);
end;
procedure CreateVictimProcess(Path: String);
const
Nop: PChar = Chr($90) + Chr($90) + Chr($90);
var
DbgEvent: TDebugEvent;
DbgParam: DWORD;
OldPrt, NewPrt: DWORD;
pPatch: PByte;
PgMin, PgMax: DWORD;
MemInfo: TMemoryBasicInformation;
WExpAddr: DWORD;
DbgContext: TContext;
rm: Boolean;
hThread: DWORD;
begin
ZeroMemory(@si, sizeof(STARTUPINFO));
si.cb := sizeof(STARTUPINFO);
if not CreateProcess(PChar(Path), nil, nil, nil, False, CREATE_SUSPENDED or
CREATE_DEFAULT_ERROR_MODE, nil,
PChar(MyExtractFilePath(Path)), si, pi) then
begin
MessageBox(0, 'CreateProcess failed! ', 'Error!', 0);
exit;
end;
ResumeThread(pi.hThread);
if WaitForInputIdle(pi.hProcess, INFINITE) <> 0 then
begin
MessageBox(0, 'WaitForInputIdle failed! ', 'Error!', 0);
exit;
end;
if not DebugActiveProcess(pi.dwProcessId) then
begin
MessageBox(0, 'DebugActiveProcess failed! ', 'Error!', 0);
exit;
end;
if VirtualQueryEx(pi.hProcess, Pointer($9c66BC), MemInfo, SizeOf(MemInfo)) = 0 then
begin
MessageBox(0, 'VirtualQueryEx failed! ', 'Error!', 0);
exit;
end;
PgMin := DWORD(MemInfo.BaseAddress);
pgMax := PgMin + MemInfo.RegionSize;
{VirtualProtect会将整个Page设为不可写属性,所有写Page的操作都会产生Access violation,要保存
整个Page的地址范围,
后面可以判断是否因为VirtualProtect产生的Exception}
if not VirtualProtectEx(pi.hProcess, Pointer($9c66BC), 1, PAGE_EXECUTE_READ, @OldPrt) then
begin
MessageBox(0, 'VirtualProtectEx failed! ', 'Error!', 0);
exit;
end;
{改写Page属性为不可写}
rm := false;
while WaitForDebugEvent(DbgEvent, INFINITE) do
begin
DbgParam := DBG_CONTINUE;
case DbgEvent.dwDebugEventCode of
EXCEPTION_DEBUG_EVENT:
begin
if DbgEvent.Exception.ExceptionRecord.ExceptionCode <> EXCEPTION_BREAKPOINT then
case DbgEvent.Exception.ExceptionRecord.ExceptionCode of
EXCEPTION_SINGLE_STEP: {单步中断}
begin
if rm then {由于EXCEPTION_ACCESS_VIOLATION产生的单步中断,恢复Page为不可写属性}
begin
rm := false;
VirtualProtectEx(pi.hProcess, Pointer($9c66BC), 1, PAGE_EXECUTE_READ, @NewPrt);
end;
end;
EXCEPTION_ACCESS_VIOLATION: {AV中断}
begin
DbgParam := DBG_EXCEPTION_NOT_HANDLED;
if DbgEvent.Exception.ExceptionRecord.ExceptionInformation[0] = 1 then {写操作}
begin
WExpAddr := DbgEvent.Exception.ExceptionRecord.ExceptionInformation[1]; {写操作的目标地
址}
if (WExpAddr >= PgMin) and (WExpAddr <= PgMax) then {目标地址在Page范围}
begin
DbgParam := DBG_CONTINUE;
if(WExpAddr <> $9c66BC) then {不是写指定地址}
begin
VirtualProtectEx(pi.hProcess, Pointer($9c66BC), 1, OldPrt, @NewPrt);
DbgContext.ContextFlags := CONTEXT_CONTROL;
hThread := OpenThread(THREAD_ALL_ACCESS, false, DbgEvent.dwThreadId);
GetThreadContext(hThread, DbgContext);
DbgContext.EFlags := DbgContext.EFlags or $100;