Function GetInfoTable(ATableType:dword):Pointer;
var
mSize: dword;
mPtr: pointer;
St: NTStatus;
begin
Result := nil;
mSize := $4000;
repeat
mPtr := VirtualAlloc(nil, mSize, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE);
if mPtr = nil then Exit;
St := ZwQuerySystemInformation(ATableType, mPtr, mSize, nil);
if St = STATUS_INFO_LENGTH_MISMATCH then
begin
VirtualFree(mPtr, 0, MEM_RELEASE);
mSize := mSize * 2;
end;
until St <> STATUS_INFO_LENGTH_MISMATCH;
if St = STATUS_SUCCESS
then Result := mPtr
else VirtualFree(mPtr, 0, MEM_RELEASE);
end;
function iOpenProcess(ProcessId:DWORD):DWORD;
var
HandlesInfo: PSYSTEM_HANDLE_INFORMATION_EX;
ClientID:TClientID;
pbi:_PROCESS_BASIC_INFORMATION;
oa:TObjectAttributes;
hProcessCur,hProcessToDup,hProcessToRet:DWORD;
Ret:DWORD;
I:Integer;
begin
SetPrivilege('SE_DEBUG',TRUE);
Result:=0;
FillChar(oa,SizeOf(TObjectAttributes),0);
FillChar(ClientID,SizeOf(TClientID),0);
oa.Length:=SizeOf(TObjectAttributes);
for I:=0 to HandlesInfo^.NumberOfHandles do
begin
If (HandlesInfo^.Information.ObjectTypeNumber=5) Then //OB_TYPE_PROCESS
ClientID.UniqueProcess:=HandlesInfo^.Information.ProcessId;
If ZwDuplicateObject(hProcessToDup,HandlesInfo^.Information.Handle,GetCurrentProcess,@hProcessCur,PROCESS_ALL_ACCESS,0,$4)=STATUS_SUCCESS then
If ZwQueryInformationProcess(hProcessCur,ProcessBasicInformation,@pbi,Sizeof(_PROCESS_BASIC_INFORMATION),@Ret)=STATUS_SUCCESS then
If (pbi.UniqueProcessId=ProcessId) Then
If ZwDuplicateObject(hProcessToDup,HandlesInfo^.Information.Handle,GetCurrentProcess,@hProcessToRet,PROCESS_ALL_ACCESS,0,$4)=STATUS_SUCCESS then
begin
Result:=hProcessToRet;
Break;
end;
end;
if hProcessCur>0 then ZwClose(hProcessCur);
if hProcessToDup>0 then ZwClose(hProcessToDup);
VirtualFree(HandlesInfo,0,MEM_RELEASE);
SetPrivilege('SE_DEBUG',FALSE);
end;
if (KeGetCurrentIrql()!=PASSIVE_LEVEL) return STATUS_PASSIVE_LEVEL_REQUIRED;
RtlZeroMemory(&mi,sizeof(mi));
if (!NT_SUCCESS(status=MapKernelImage(&mi,&dwKernelBase))) return status;
RtlZeroMemory(&idmi,sizeof(idmi));
RtlInitUnicodeString(&NtdllName, L"\\SystemRoot\\System32\\ntdll.dll");
if (!NT_SUCCESS(status=MapPeImage(&idmi,&NtdllName))) return status;
try {
for (i=0;Import.szName;i++){
Import.dwAddress=0;
switch (Import.dwType) {
case IMPORT_BY_NAME:
if (!(Import.dwAddress=GetProcRva(mi.hModule,Import.szName))) {
#ifdef DEBUG
DbgPrint("GetRealAddress(): Failed to get %s rva!\n",Import.szName);
#endif
}
break;
case IMPORT_BY_RVA:
Import.dwAddress=(DWORD)Import.szName;
break;
case IMPORT_BY_ADDRESS:
Import.dwAddress=(DWORD)Import.szName-dwKernelBase;
break;
case IMPORT_BY_SERVICE_ID:
// do not search this rva if it has been already found
if (!KiServiceTable_RVA) {
if (!(KiServiceTable_RVA=FindKiServiceTable(mi.hModule))) {
#ifdef DEBUG
DbgPrint("GetRealAddress(): Failed to get KiServiceTable RVA!\n");
#endif
break;
}
}
KiServiceTable=(PDWORD)(KiServiceTable_RVA+mi.hModule);
Import.dwAddress=KiServiceTable[(DWORD)Import.szName]-mi.dwImageBase;
break;
case IMPORT_BY_SERVICE_NAME:
if (!KiServiceTable_RVA){
if (!(KiServiceTable_RVA=FindKiServiceTable(mi.hModule))) break;
}
Import.dwId=GetIdForName(idmi.hModule,Import.szName);
KiServiceTable=(PDWORD)(KiServiceTable_RVA+mi.hModule);
Import.dwAddress=KiServiceTable[Import.dwId]-mi.dwImageBase;
break;
default:
break;
} //Case End
if (Import.dwId==0){
if (!KiServiceTable_RVA)
KiServiceTable_RVA=FindKiServiceTable(mi.hModule);
KiServiceTable=(PDWORD)(KiServiceTable_RVA+mi.hModule);
for (j=0;KiServiceTable[j];j++){if (Import.dwAddress==KiServiceTable[j]-mi.dwImageBase){Import.dwId=j;break;}}
}
Import.dwAddress=dwKernelBase+Import.dwAddress;
}
}except(EXCEPTION_EXECUTE_HANDLER){
return STATUS_ADD_FUNCTION_FAILED;
}
fp:THandle;
hThread:DWORD;
begin
FillChar(Regs,SizeOf(CONTEXT),0);
dwW2iThreadId:=0;
dwW2iProcessId:=0;
hW2iProcess:=0;
hW2iThread:=0;
fp:=0;
hW2iWnd:=FindWindow(WINDOW_CLASS, nil);
if( hW2iWnd>0) then dwW2iThreadId:=GetWindowThreadProcessId(hW2iWnd,@dwW2iProcessId);
if (dwW2iProcessId>0) then hW2iProcess:=OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwW2iProcessId);
if (hW2iProcess>0) then hW2iThread:=OpenThread(THREAD_ALL_ACCESS, FALSE, dwW2iThreadId);
if (hW2iThread>0) then
if DebugActiveProcess(dwW2iProcessId) then
begin
while(TRUE) do
begin
if (WaitForDebugEvent(DebugEv,10)) then
begin
dwContinueStatus:=DBG_EXCEPTION_NOT_HANDLED;
Case DebugEv.dwDebugEventCode of
EXCEPTION_DEBUG_EVENT:
begin
if(DWORD(DebugEv.Exception.ExceptionRecord.ExceptionAddress)=CHECKPOINT_ADDR) then
begin
hThread:=OpenThread(THREAD_ALL_ACCESS, FALSE, DebugEv.dwThreadId);
SuspendThread(hThread);
//非常简单的判断, 应该为枚举代码段地址,或者对每个正常的调用地址作判断
if dwCallRet>$00A87000 then
begin
WriteLn('发现外部调用!');
// 随便做点什么吧
end else begin
Regs.Esp:=Regs.Esp+$c; // add esp,0c
SetThreadContext(hThread,Regs);
end;
ResumeThread(hThread);
CloseHandle(hThread);
end;
dwContinueStatus:=DBG_CONTINUE;
end;
EXIT_PROCESS_DEBUG_EVENT:
begin
ExitProcess(0);
end;
end;
ContinueDebugEvent(DebugEv.dwProcessId, DebugEv.dwThreadId, dwContinueStatus);
end;
end;
end
else WriteLn('附加到进程失败!');