📄 cmd_trace.cpp
字号:
/*++
Copyright (c) 2005 Godness
Contact information:
mail: godness@omen.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:
cmd_trace.cpp
Abstract: Implements !TRACE, !TRCINIT, !TRCCODE extension commands.
See tracetut.txt for more detail
=============== e X T r e m e = t R a C e r = E n g i n e =================
Revision History of eXTreme tRaCer Engine:
Godness 01/08/2005
project was started ...finally!
Godness 20/08/2005
version 0.01
now it can trace simple condition such as "eax == 1"
Godness 29/08/2005
+ added logic condition "||" and "&&"
+ added support brackets (eax == 1 || ebx == 2) && (...)
+ added support register at right part of condition "eax == ax"
Godness 13/09/2005
version 0.02 beta
+ added support "Step over" and "Execute till return" commands
- fixed bugs
Godness 01/10/2005
Initial release
Godness 04/03/2006
+ added powerful posibility work with pointers such as *eax == 'string'
- fixed many bugs
===========================================================================
--*/
extern "C" {
#pragma warning ( push, 3 )
#include <ntddk.h>
#pragma warning ( pop )
}
#pragma warning ( disable: 4514 ) // unreferenced inline function has been removed
#include <windef.h>
#include <ntverp.h>
#include <stdio.h>
#include "keyboard.h"
#include "wdbgexts.h"
#include "softice.h"
#include "defs.h"
#include "tracer.h"
extern void help_TRACE(void);
extern void help_TRCINIT(void);
extern bool Compile(char *buffer);
extern char compiled_code[0x800];
extern int __cdecl CodeAnalyzer (CLIENT_STATE *pClientState);
extern char szGood[];
extern char szBad[];
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ULONG NumberOfTracedCommand = 0;
ULONG CountOfCommand = 0;
ULONG TracerCallBack = 0;
ULONG EipWhenPRET = 0xFFFFFFFF;
ULONG ReturnToMakePageIn = 0;
ULONG MakePageIn = 0;
ULONG SavedCR0 = 0;
ULONG CR3ForOurProcess = 0;
ULONG PreLastEIPValue = 0;
ULONG CurrentRing = 0;
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void ExecutePCommand(void);
void ExecutePRETCommand(void);
bool NeedToExecutePCommand(void);
bool si_atoi(PCSTR string, ULONG& value);
void FillClientStateStruct(CLIENT_STATE &client);
////////////////////////////////////////////////////////////////////////////
//
// TRACE
//
// Trace commands with condition
//
////////////////////////////////////////////////////////////////////////////
DECLARE_API(trace)
{
UNREFERENCED_PARAMETER(dwProcessor);
UNREFERENCED_PARAMETER(dwCurrentPc);
UNREFERENCED_PARAMETER(hCurrentThread);
UNREFERENCED_PARAMETER(hCurrentProcess);
CLIENT_STATE client;
if (*args == '*')
{
if (NumberOfTracedCommand > CountOfCommand)
{
__asm
{
mov eax, ClientRegs
push [eax + 0x24] //push eflags
push [eax + 0x28] //push cs
push [eax + 0x20] //push eip
push [eax + 0x00] //push eax
push [eax + 0x08] //push ecx
push [eax + 0x0C] //push edx
push [eax + 0x04] //push ebx
push [eax + 0x1C] //push esp
push [eax + 0x18] //push ebp
push [eax + 0x10] //push esi
push [eax + 0x14] //push edi
call offset compiled_code
add esp, 0x2C
mov args, eax
}
if (!args)
{
DbgPrint(szGood, CountOfCommand);
}
else if (++CountOfCommand == NumberOfTracedCommand)
{
DbgPrint(szBad);
}
else if (EipWhenPRET == -1 || !NeedToExecutePCommand())
{
FillClientStateStruct(client);
if (CodeAnalyzer(&client)) //in case when we start from instruction than need to be amulate
++CountOfCommand;
ClientRegs->EIP = client.eip; //restore in softice client's registers
if (ClientRegs->CS & 1)
ClientRegs->ESP = client.esp3;
//else ??? need to be corrent in CodeAnalizer for ring0
// ClientRegs->ESP = client.esp0;
if (CountOfCommand < NumberOfTracedCommand)
{
TracerCallBack = (ULONG)compiled_code;
si_Exec("T");
}
return;
}
else
{
ExecutePCommand();
return;
}
CountOfCommand = 0;
NumberOfTracedCommand = 0;
EipWhenPRET = (ULONG)(-1);
}
return;
}
CountOfCommand = 0;
EipWhenPRET = (ULONG)(-1);
if (si_atoi(args, NumberOfTracedCommand))
{
while (*args != 0 && *args != ' ') ++args;
while (*args == ' ') ++args;
}
if (*args == 0 || si_atoi(args, EipWhenPRET))
{
if (NumberOfTracedCommand)
{
//void *OldInt = GetInterruptHandler(0x6);
//if (&Int06Handler != OldInt)
//{
// OldInt6 = OldInt;
// SetInterruptHandler(0x6, &Int06Handler);
//}
//
//OldInt = GetInterruptHandler(0xD);
//if (&Int0DHandler != OldInt)
//{
// OldIntD = OldInt;
// SetInterruptHandler(0xD, &Int0DHandler);
//}
//
//OldInt = GetInterruptHandler(0x10);
//if (&Int10Handler != OldInt)
//{
// OldInt10 = OldInt;
// SetInterruptHandler(0x10, &Int10Handler);
//}
if (EipWhenPRET == -1 || !NeedToExecutePCommand())
{
PreLastEIPValue = ClientRegs->EIP;
CurrentRing = ClientRegs->CS & 3;
__asm
{
mov eax, CR3
mov CR3ForOurProcess, eax
}
FillClientStateStruct(client);
if (CodeAnalyzer(&client)) //in case when we start from instruction than need to be amulate
++CountOfCommand;
ClientRegs->EIP = client.eip; //restore in softice client's registers
if (ClientRegs->CS & 1)
ClientRegs->ESP = client.esp3;
//else ??? need to be corrent in CodeAnalizer for ring0
// ClientRegs->ESP = client.esp0;
if (CountOfCommand < NumberOfTracedCommand)
{
TracerCallBack = (ULONG)compiled_code;
si_Exec("T");
}
}
else
ExecutePCommand();
}
return;
}
help_TRACE();
return;
}
////////////////////////////////////////////////////////////////////////////
//
// TRCINIT
//
// Compile the tracer condition code
//
////////////////////////////////////////////////////////////////////////////
DECLARE_API(trcinit)
{
UNREFERENCED_PARAMETER(dwProcessor);
UNREFERENCED_PARAMETER(dwCurrentPc);
UNREFERENCED_PARAMETER(hCurrentThread);
UNREFERENCED_PARAMETER(hCurrentProcess);
short saved_fs;
__asm
{
mov ax, fs
mov saved_fs, ax
mov eax, 30h
mov fs, ax
}
if (Compile((char *)args))
{
DbgPrint("\n ------------ e X T r e m e - t R a C e r ------------\n");
DbgPrint("\n IS READY!\n");
DbgPrint("\n Enter the \"!trace\" command to see the blue screen ;-)\n");
DbgPrint(" -----------------------------------------------------\n\n");
}
else
{
DbgPrint("\n Error in tracer condition!\n\n");
help_TRCINIT();
}
__asm
{
mov ax, saved_fs
mov fs, ax
}
return;
}
////////////////////////////////////////////////////////////////////////////
//
// TRCCODE ...abstract
//
// Show the code that was compiled by TRCINIT function
//
////////////////////////////////////////////////////////////////////////////
DECLARE_API(trccode)
{
UNREFERENCED_PARAMETER(dwProcessor);
UNREFERENCED_PARAMETER(dwCurrentPc);
UNREFERENCED_PARAMETER(hCurrentThread);
UNREFERENCED_PARAMETER(hCurrentProcess);
UNREFERENCED_PARAMETER(args);
si_PutToKbdBufferChar('u');
si_PutToKbdBufferChar(' ');
for (int i = 7; i >= 0; i--)
{
char ch = (char)((int)compiled_code >> 4*i) & 0x0F;
if (ch < 0xA)
ch += 0x30;
else
ch += 0x37;
si_PutToKbdBufferChar(ch);
}
si_PutToKbdBufferChar(KBD_ENTER);
return;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
bool __declspec(naked) NeedToExecutePCommand(void)
{
__asm
{
mov eax, ClientRegs
mov eax, [eax + 20h]
cmp byte ptr [eax], 0xE8
je direct_call
cmp word ptr [eax], 0x15FF
jne false_exit
mov eax, [eax + 2]
mov eax, [eax]
jmp compare_eip
direct_call:
add eax, [eax + 1]
add eax, 5
compare_eip:
cmp eax, EipWhenPRET
jae true_exit
false_exit:
xor eax, eax
ret
true_exit:
mov al, 1
ret
}
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void ExecutePCommand(void)
{
si_Exec("P");
si_Exec("!TRACE *");
return;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void ExecutePRETCommand(void)
{
si_Exec("P RET");
si_Exec("!TRACE *");
return;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
bool si_atoi(PCSTR string, ULONG& value)
{
__asm
{
mov esi, string
call si_Expression2Integer
jb syntax_error
mov ebx, value
mov [ebx], eax
mov eax, 1
jmp exit
syntax_error:
mov eax, 0
exit:
}
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void FillClientStateStruct(CLIENT_STATE &client)
{
client.cs = ClientRegs->CS;
client.ds = ClientRegs->DS;
client.fs = ClientRegs->FS;
client.ss = ClientRegs->SS;
client.es = ClientRegs->ES;
client.eax = ClientRegs->EAX;
client.ebp = ClientRegs->EBP;
client.ebx = ClientRegs->EBX;
client.ecx = ClientRegs->ECX;
client.edx = ClientRegs->EDX;
client.edi = ClientRegs->EDI;
client.esi = ClientRegs->ESI;
client.eip = ClientRegs->EIP;
client.esp0 = ClientRegs->ESP; // ??? need to be correct
client.esp3 = ClientRegs->ESP; // ???
client.eflags = ClientRegs->EFLAGS;
return;
}
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -