📄 tracer.cpp
字号:
/*++
Copyright (c) 2002 Sten
Contact information:
mail: stenri@mail.ru
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Module Name:
tracer.cpp
Abstract: Very simple tracer engine. It's only purpose is trace the instruction that
caused break point on range exception so that break point can be restored after
instruction execution.
Revision History:
Godness 01/09/2005
Adapted for eXTreme tRaCer engine
Sten 11/12/2002
Initial release
--*/
extern "C"{
#pragma warning ( push, 3 )
#include <ntddk.h>
#pragma warning ( pop )
}
#pragma warning ( disable: 4514 ) // unreferenced inline function has been removed
#include "defs.h"
#include "ntoskrnl.h"
#include "softice.h"
#include "keyboard.h"
#include "undoc.h"
#include "bpr.h"
#include "tracer.h"
///////////////////////////////////////////////////////////////////////
// External definitions
///////////////////////////////////////////////////////////////////////
extern void ExecutePCommand(void);
extern void ExecutePRETCommand(void);
extern ULONG NumberOfTracedCommand;
extern ULONG CountOfCommand;
extern ULONG TracerCallBack;
extern ULONG EipWhenPRET;
extern ULONG ReturnToMakePageIn;
extern ULONG MakePageIn;
extern ULONG SavedCR0;
extern ULONG CR3ForOurProcess;
extern ULONG PreLastEIPValue;
extern ULONG CurrentRing;
void* CheckAddressAndMakePageIn(void *address);
void* GetUserHandler(void);
///////////////////////////////////////////////////////////////////////
// Globals
///////////////////////////////////////////////////////////////////////
void *OldInterruptStack;
char NewInterruptStack[0x1000];
int InTraceMode = 0;
int HideTFflag = 0;
int EipWait = 0;
int SystemInt1 = 0;
int DRDebugException = 0;
int DRSavedHandler = 0;
char DRSavedByte = 0;
void* UserHandler = 0;
void* UserAddress = 0;
int EmulatePOPFD = 0;
char Int0Installed = 1;
void *OldInt0 = 0;
void *OldInt1 = 0; // Old int1 handler
void *OldInt6 = 0;
void *OldIntD = 0;
void *OldInt10 = 0;
char szBad[] = "Traced through given number of instructions - no trace condition has been met...\n";
char szGood[] = "One of the trace conditions is met! %d commands has been traced...\n";
char szFPUInst[] = "FPU exception occured at address %08X\n";
char szInt3Inst[] = "INT3 instruction has been met at address %08X\n";
char szException[] = "Exception instruction has been met at address %08X\n";
char szInvalidInst[] = "Invalid instruction has been met at address %08X\n";
char szTraceStoped[] = "Tracing has been stopped! %d commands has been traced...\n";
char szZeroDivision[] = "Division on ZERO occured at address %08X\n";
int __cdecl CodeAnalyzer (CLIENT_STATE *pClientState)
{
#define CHANGE_ESP3_VALUE(UserRegister) \
pClientState->esp3 = UserRegister; \
pClientState->eip += 2; \
return 1;
if (!CheckAddressAndMakePageIn((void *)(pClientState->eip + 0))) return 0;
if (!CheckAddressAndMakePageIn((void *)(pClientState->eip + 1))) return 0;
if (*(PUCHAR)(pClientState->eip + 0) == 0x8B)
{
switch (*(PUCHAR)(pClientState->eip + 1))
{
case 0xE0: CHANGE_ESP3_VALUE(pClientState->eax); // emulate mov esp, eax
case 0xE1: CHANGE_ESP3_VALUE(pClientState->ecx); // -//- mov esp, ecx
case 0xE2: CHANGE_ESP3_VALUE(pClientState->edx); // ...
case 0xE3: CHANGE_ESP3_VALUE(pClientState->ebx);
case 0xE4: CHANGE_ESP3_VALUE(pClientState->esp3);
case 0xE5: CHANGE_ESP3_VALUE(pClientState->ebp);
case 0xE6: CHANGE_ESP3_VALUE(pClientState->esi);
case 0xE7: CHANGE_ESP3_VALUE(pClientState->edi);
}
}
if (*(PUCHAR)(pClientState->eip + 0) == 0x9C) // if pushfd command was met
{ // need to remove TF flag from stack
EipWait = pClientState->eip + 1;
HideTFflag = 1;
return 0;
}
if (*(PUCHAR)(pClientState->eip + 0) == 0x9D) // if popfd command was met
{
if (!CheckAddressAndMakePageIn((void *)(pClientState->esp3))) return 0;
if (*(PULONG)pClientState->esp3 & 0x100)
{
if ((UserHandler = GetUserHandler()) == 0) return 0;
UserAddress = (void *)pClientState->eip;
DWORD cr0 = EnableWrite();
*(PUCHAR)pClientState->eip = 0xCC;
SetCR0(cr0);
EmulatePOPFD = 1;
return 0;
}
}
return 0;
}
///////////////////////////////////////////////////////////////////////
//
// Int 00 handler
//
///////////////////////////////////////////////////////////////////////
void __declspec(naked) Int00Handler(void)
{
__asm
{
cmp cs:[TracerCallBack], 0
je next_handler
pushad
push fs
push ds
push es
mov eax, 30h
mov fs, ax
mov eax, 23h
mov ds, ax
mov es, ax
push dword ptr [esp + 0x2C]
push offset szZeroDivision
call DbgPrint
add esp, 8
pop es
pop ds
pop fs
popad
next_handler:
jmp cs:[OldInt0]
}
}
///////////////////////////////////////////////////////////////////////
//
// Int 01 handler
//
///////////////////////////////////////////////////////////////////////
void __declspec(naked) Int01Handler(void)
{
__asm
{
cmp cs:[MakePageIn], 0
je not_make_pagein
jmp cs:[ReturnToMakePageIn] //return to CheckAndMakePageIn function
not_make_pagein:
cmp cs:[TracerCallBack], 0
je do_not_trace
push ds
push eax
mov eax, 23h
mov ds, ax
mov eax, esp
add eax, 8
mov OldInterruptStack, eax // save original stack pointer
pop eax
mov esp, offset NewInterruptStack + 0x1000 - 0x10
pushad
push fs
mov esi, OldInterruptStack
push dword ptr [esi - 4] // save original ds value
push es
mov eax, 30h
mov fs, ax
mov eax, 23h
mov es, ax
mov al, byte ptr [esi + 4]
and al, 3
cmp al, byte ptr [CurrentRing]
je ring_value_not_change
pop es // if ring value was suddenly changed
pop ds // the some other int1 interrupt occured
pop fs // so we need to pass this way for today...
popad
mov esp, OldInterruptStack
iretd
ring_value_not_change:
cld
mov ecx, 5
test al, 3 // check in CS value last two bits
jnz copy_stack // copy interrupt stack to new arrea
mov ecx, 3 // it's need for MakePageIn function
copy_stack:
mov edi, offset NewInterruptStack + 0x1000 - 0x10
repnz movsd
cmp HideTFflag, 0 // remove TF flag when pushfd command was met
jz emulate_popfd
mov HideTFflag, 0
mov eax, OldInterruptStack // get original interrupt stack pointer
mov edx, dword ptr [eax]
cmp edx, EipWait // check current eip value
jne emulate_popfd
mov eax, dword ptr [eax + 0xC] // get esp ring 3 pointer
push eax
call CheckAddressAndMakePageIn
or eax, eax
jz emulate_popfd
and dword ptr [eax], not 100h
emulate_popfd:
cmp EmulatePOPFD, 0 // need to correct exception params in stack
jz tracer_call_back // for emulate popfd instruction
mov EmulatePOPFD, 0
mov eax, dword ptr [esp + 0x2C] // if user eip value == user's exception handler
cmp eax, UserHandler
jnz tracer_call_back
mov eax, dword ptr [esp + 0x38]
push eax
call CheckAddressAndMakePageIn
or eax, eax
jz tracer_call_back
mov eax, dword ptr [eax + 4] // get pointer to ExceptionCode in _EXCEPTION_RECORD *ExceptionRecord
push eax
call CheckAddressAndMakePageIn
or eax, eax
jz tracer_call_back
mov dword ptr [eax], 0x80000004 // STATUS_SINGLE_STEP exception
call EnableWrite
mov ebx, eax
mov eax, UserAddress
mov byte ptr [eax], 0x9D // patch user code back
push ebx
call SetCR0
tracer_call_back:
call TracerCallBack
or eax, eax
jnz good_message
mov eax, CountOfCommand
inc eax
mov CountOfCommand, eax
cmp eax, NumberOfTracedCommand
jae bad_message
mov eax, DR6 // check if DR registers was
test al, 0Fh // cause of interrupt
jz not_debug_breakpoint
cmp CurrentRing, 3 // ring0 context not support yet...
jne not_debug_breakpoint
call GetUserHandler // in this way we must transfer
or eax, eax // control to system handler
jz dr_exception_bad
push eax
call CheckAddressAndMakePageIn
or eax, eax
jz dr_exception_bad
push eax
call EnableWrite
mov ebx, eax
pop eax
mov dl, byte ptr [eax]
mov DRSavedHandler, eax
mov DRSavedByte, dl
mov byte ptr [eax], 0xCC
push ebx
call SetCR0
mov eax, si_OldIntTable
mov eax, [eax + 4]
mov SystemInt1, eax
mov DRDebugException, 1
dr_exception_bad:
pop es
pop ds
pop fs
popad
mov esp, OldInterruptStack
or dword ptr [esp + 8], 100h
jmp cs:[SystemInt1] // transfer control to system handler
not_debug_breakpoint:
push esp
call CodeAnalyzer
add esp, 4
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -