615 lines
14 KiB
C
615 lines
14 KiB
C
#include <precomp.h>
|
|
#pragma hdrstop
|
|
|
|
BOOL
|
|
WINAPI
|
|
ReadProcessMem(
|
|
HANDLE hProcess,
|
|
LPVOID lpBaseAddress,
|
|
LPVOID lpBuffer,
|
|
DWORD nSize,
|
|
LPDWORD lpNumberOfBytesRead
|
|
)
|
|
{
|
|
if ( fWinDbg ) {
|
|
return (*ReadProcessMemWinDbg)( (DWORD)lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesRead );
|
|
} else {
|
|
return ReadProcessMemory( hProcess, lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesRead );
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
WriteProcessMem(
|
|
HANDLE hProcess,
|
|
LPVOID lpBaseAddress,
|
|
LPVOID lpBuffer,
|
|
DWORD nSize,
|
|
LPDWORD lpNumberOfBytesWritten
|
|
)
|
|
{
|
|
if ( fWinDbg ) {
|
|
return (*WriteProcessMemWinDbg)( (DWORD)lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesWritten );
|
|
} else {
|
|
return WriteProcessMemory( hProcess, lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesWritten );
|
|
}
|
|
|
|
}
|
|
|
|
#ifndef i386
|
|
|
|
ULONG
|
|
GetRegValue(
|
|
NT_CPU_REG reg,
|
|
BOOL bInNano,
|
|
ULONG UMask
|
|
)
|
|
|
|
{
|
|
if (bInNano) {
|
|
|
|
return(ReadDword(reg.nano_reg));
|
|
|
|
} else if (UMask & reg.universe_8bit_mask) {
|
|
|
|
return (ReadDword(reg.saved_reg) & 0xFFFFFF00 |
|
|
ReadDword(reg.reg) & 0xFF);
|
|
|
|
} else if (UMask & reg.universe_16bit_mask) {
|
|
|
|
return (ReadDword(reg.saved_reg) & 0xFFFF0000 |
|
|
ReadDword(reg.reg) & 0xFFFF);
|
|
|
|
} else {
|
|
|
|
return (ReadDword(reg.reg));
|
|
|
|
}
|
|
}
|
|
|
|
ULONG
|
|
GetEspValue(
|
|
NT_CPU_INFO nt_cpu_info,
|
|
BOOL bInNano
|
|
)
|
|
|
|
{
|
|
if (bInNano) {
|
|
|
|
return (ReadDword(nt_cpu_info.nano_esp));
|
|
|
|
} else {
|
|
|
|
if (ReadDword(nt_cpu_info.stack_is_big)) {
|
|
|
|
return (ReadDword(nt_cpu_info.host_sp) -
|
|
ReadDword(nt_cpu_info.ss_base));
|
|
|
|
} else {
|
|
|
|
return (ReadDword(nt_cpu_info.esp_sanctuary) & 0xFFFF0000 |
|
|
(ReadDword(nt_cpu_info.host_sp) -
|
|
ReadDword(nt_cpu_info.ss_base) & 0xFFFF));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
int
|
|
GetContext(
|
|
VDMCONTEXT* lpContext
|
|
) {
|
|
#ifndef i386 //
|
|
int mode;
|
|
ULONG pTmp;
|
|
NT_CPU_INFO nt_cpu_info;
|
|
BOOL b;
|
|
BOOL bInNano;
|
|
ULONG UMask;
|
|
|
|
pTmp = (ULONG)EXPRESSION("ntvdm!nt_cpu_info");
|
|
|
|
if ( pTmp ) {
|
|
b = ReadProcessMem( hCurrentProcess,
|
|
(LPVOID) pTmp,
|
|
(LPVOID) &nt_cpu_info,
|
|
sizeof(NT_CPU_INFO),
|
|
NULL );
|
|
if ( !b ) {
|
|
PRINTF("Could not read IntelRegisters context out of process\n");
|
|
return( -1 );
|
|
}
|
|
|
|
bInNano = ReadDword((ULONG) nt_cpu_info.in_nano_cpu);
|
|
UMask = ReadDword((ULONG) nt_cpu_info.universe);
|
|
|
|
lpContext->Eax = GetRegValue(nt_cpu_info.eax, bInNano, UMask);
|
|
lpContext->Ecx = GetRegValue(nt_cpu_info.ecx, bInNano, UMask);
|
|
lpContext->Edx = GetRegValue(nt_cpu_info.edx, bInNano, UMask);
|
|
lpContext->Ebx = GetRegValue(nt_cpu_info.ebx, bInNano, UMask);
|
|
lpContext->Ebp = GetRegValue(nt_cpu_info.ebp, bInNano, UMask);
|
|
lpContext->Esi = GetRegValue(nt_cpu_info.esi, bInNano, UMask);
|
|
lpContext->Edi = GetRegValue(nt_cpu_info.edi, bInNano, UMask);
|
|
|
|
lpContext->Esp = GetEspValue(nt_cpu_info, bInNano);
|
|
lpContext->EFlags = ReadDword(nt_cpu_info.flags);
|
|
lpContext->Eip = ReadDword(nt_cpu_info.eip);
|
|
|
|
lpContext->SegEs = ReadWord(nt_cpu_info.es);
|
|
lpContext->SegCs = ReadWord(nt_cpu_info.cs);
|
|
lpContext->SegSs = ReadWord(nt_cpu_info.ss);
|
|
lpContext->SegDs = ReadWord(nt_cpu_info.ds);
|
|
lpContext->SegFs = ReadWord(nt_cpu_info.fs);
|
|
lpContext->SegGs = ReadWord(nt_cpu_info.gs);
|
|
|
|
|
|
} else {
|
|
|
|
PRINTF("Could not find the symbol 'ntvdm!nt_cpu_info'\n");
|
|
return( -1 );
|
|
}
|
|
|
|
if ( !(ReadDword(nt_cpu_info.cr0) & 1) ) {
|
|
mode = V86_MODE;
|
|
} else {
|
|
mode = PROT_MODE;
|
|
}
|
|
return( mode );
|
|
|
|
#else //
|
|
|
|
NTSTATUS rc;
|
|
BOOL b;
|
|
ULONG EFlags;
|
|
WORD cs;
|
|
int mode;
|
|
ULONG lpVdmTib;
|
|
|
|
lpContext->ContextFlags = CONTEXT_FULL;
|
|
rc = NtGetContextThread( hCurrentThread,
|
|
lpContext );
|
|
if ( NT_ERROR(rc) ) {
|
|
PRINTF( "bde.k: Could not get current threads context - status = %08lX\n", rc );
|
|
return( -1 );
|
|
}
|
|
/*
|
|
** Get the 16-bit registers from the context
|
|
*/
|
|
cs = (WORD)lpContext->SegCs;
|
|
EFlags = lpContext->EFlags;
|
|
|
|
if ( EFlags & V86_BITS ) {
|
|
/*
|
|
** V86 Mode
|
|
*/
|
|
mode = V86_MODE;
|
|
} else {
|
|
if ( (cs & RPL_MASK) != KGDT_R3_CODE ) {
|
|
mode = PROT_MODE;
|
|
} else {
|
|
/*
|
|
** We are in flat 32-bit address space!
|
|
*/
|
|
lpVdmTib = (ULONG)EXPRESSION("ntvdm!VdmTib");
|
|
if ( !lpVdmTib ) {
|
|
PRINTF("Could not find the symbol 'VdmTib'\n");
|
|
return( -1 );
|
|
}
|
|
b = ReadProcessMem( hCurrentProcess,
|
|
(LPVOID) (lpVdmTib +
|
|
FIELD_OFFSET(VDM_TIB,VdmContext)),
|
|
lpContext,
|
|
sizeof(VDMCONTEXT),
|
|
NULL );
|
|
if ( !b ) {
|
|
PRINTF("Could not read IntelRegisters context out of process\n");
|
|
return( -1 );
|
|
}
|
|
EFlags = lpContext->EFlags;
|
|
if ( EFlags & V86_BITS ) {
|
|
mode = V86_MODE;
|
|
} else {
|
|
mode = PROT_MODE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return( mode );
|
|
#endif
|
|
}
|
|
|
|
ULONG
|
|
GetIntelBase(
|
|
VOID
|
|
)
|
|
{
|
|
#ifndef i386
|
|
ULONG IntelBase;
|
|
BOOL b;
|
|
|
|
IntelBase = (ULONG)EXPRESSION("ntvdm!Start_of_M_area");
|
|
if ( IntelBase ) {
|
|
b = ReadProcessMem( hCurrentProcess,
|
|
(LPVOID) IntelBase, &IntelBase,
|
|
sizeof(ULONG), NULL );
|
|
if ( !b ) {
|
|
PRINTF("Could not read symbol 'ntvdm!Start_of_M_area\n");
|
|
return(0);
|
|
}
|
|
|
|
} else {
|
|
PRINTF("Could not find the symbol 'ntvdm!Start_of_M_area'\n");
|
|
}
|
|
|
|
return(IntelBase);
|
|
#else
|
|
return(0);
|
|
#endif
|
|
}
|
|
|
|
DWORD read_dword(
|
|
ULONG lpAddress,
|
|
BOOL bSafe
|
|
) {
|
|
BOOL b;
|
|
DWORD dword;
|
|
|
|
b = ReadProcessMem(
|
|
hCurrentProcess,
|
|
(LPVOID)lpAddress,
|
|
&dword,
|
|
sizeof(dword),
|
|
NULL
|
|
);
|
|
if ( !b ) {
|
|
if ( !bSafe ) {
|
|
PRINTF("Failure reading dword at memory location %08lX\n", lpAddress );
|
|
}
|
|
return( 0 );
|
|
}
|
|
return( dword );
|
|
}
|
|
|
|
WORD read_word(
|
|
ULONG lpAddress,
|
|
BOOL bSafe
|
|
) {
|
|
BOOL b;
|
|
WORD word;
|
|
|
|
b = ReadProcessMem(
|
|
hCurrentProcess,
|
|
(LPVOID)lpAddress,
|
|
&word,
|
|
sizeof(word),
|
|
NULL
|
|
);
|
|
if ( !b ) {
|
|
if ( !bSafe ) {
|
|
PRINTF("Failure reading word at memory location %08lX\n", lpAddress );
|
|
}
|
|
return( 0 );
|
|
}
|
|
return( word );
|
|
}
|
|
|
|
BYTE read_byte(
|
|
ULONG lpAddress,
|
|
BOOL bSafe
|
|
) {
|
|
BOOL b;
|
|
BYTE byte;
|
|
|
|
b = ReadProcessMem(
|
|
hCurrentProcess,
|
|
(LPVOID)lpAddress,
|
|
&byte,
|
|
sizeof(byte),
|
|
NULL
|
|
);
|
|
if ( !b ) {
|
|
if ( !bSafe ) {
|
|
PRINTF("Failure reading byte at memory location %08lX\n", lpAddress );
|
|
}
|
|
return( 0 );
|
|
}
|
|
return( byte );
|
|
}
|
|
|
|
BOOL read_gnode(
|
|
ULONG lpAddress,
|
|
PGNODE p,
|
|
BOOL bSafe
|
|
) {
|
|
BOOL b;
|
|
|
|
b = ReadProcessMem(
|
|
hCurrentProcess,
|
|
(LPVOID)lpAddress,
|
|
p,
|
|
sizeof(*p),
|
|
NULL
|
|
);
|
|
if ( !b ) {
|
|
if ( !bSafe ) {
|
|
PRINTF("Failure reading word at memory location %08lX\n", lpAddress );
|
|
}
|
|
return( 0 );
|
|
}
|
|
return( TRUE );
|
|
}
|
|
|
|
BOOL read_gnode32(
|
|
ULONG lpAddress,
|
|
PGNODE32 p,
|
|
BOOL bSafe
|
|
) {
|
|
BOOL b;
|
|
|
|
b = ReadProcessMem(
|
|
hCurrentProcess,
|
|
(LPVOID)lpAddress,
|
|
p,
|
|
sizeof(*p),
|
|
NULL
|
|
);
|
|
if ( !b ) {
|
|
if ( !bSafe ) {
|
|
PRINTF("Failure reading word at memory location %08lX\n", lpAddress );
|
|
}
|
|
return( 0 );
|
|
}
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
BOOL GetDescriptorData(
|
|
WORD selector,
|
|
LPVDMLDT_ENTRY pdte
|
|
)
|
|
{
|
|
#ifdef i386
|
|
NTSTATUS rc;
|
|
DESCRIPTOR_TABLE_ENTRY dte;
|
|
dte.Selector = selector;
|
|
rc = NtQueryInformationThread( hCurrentThread,
|
|
ThreadDescriptorTableEntry,
|
|
&dte,
|
|
sizeof(DESCRIPTOR_TABLE_ENTRY),
|
|
NULL );
|
|
if ( NT_ERROR(rc) ) {
|
|
return( FALSE );
|
|
}
|
|
pdte->HighWord = dte.Descriptor.HighWord;
|
|
pdte->BaseLow = dte.Descriptor.BaseLow;
|
|
pdte->LimitLow = dte.Descriptor.LimitLow;
|
|
return (TRUE);
|
|
#else
|
|
PVOID LdtAddress;
|
|
NTSTATUS Status;
|
|
ULONG BytesRead;
|
|
selector &= ~(SELECTOR_LDT | SELECTOR_RPL);
|
|
|
|
//
|
|
// Get address of Ldt
|
|
//
|
|
|
|
LdtAddress = (PVOID)EXPRESSION("ntvdm!Ldt");
|
|
|
|
Status = ReadProcessMem(
|
|
hCurrentProcess,
|
|
LdtAddress,
|
|
&LdtAddress,
|
|
sizeof(ULONG),
|
|
&BytesRead
|
|
);
|
|
|
|
if ((!Status) || (BytesRead != sizeof(ULONG))) {
|
|
return FALSE;
|
|
}
|
|
|
|
(PUCHAR)LdtAddress += selector;
|
|
|
|
Status = ReadProcessMem(
|
|
hCurrentProcess,
|
|
LdtAddress,
|
|
pdte,
|
|
sizeof(VDMLDT_ENTRY),
|
|
&BytesRead
|
|
);
|
|
return TRUE;
|
|
#endif
|
|
}
|
|
|
|
ULONG GetInfoFromSelector(
|
|
WORD selector,
|
|
int mode,
|
|
SELECTORINFO *si
|
|
) {
|
|
|
|
ULONG base;
|
|
ULONG type;
|
|
#ifdef i386
|
|
BYTE byte;
|
|
BOOL b;
|
|
#endif
|
|
VDMLDT_ENTRY dte;
|
|
|
|
switch( mode ) {
|
|
case V86_MODE:
|
|
base = (ULONG)selector << 4;
|
|
if ( si ) {
|
|
si->Limit = 0xFFFFL;
|
|
si->bCode = FALSE;
|
|
}
|
|
break;
|
|
case PROT_MODE:
|
|
|
|
#ifdef i386
|
|
if ( (selector & 0xFF78) < KGDT_LDT ) {
|
|
return( (ULONG)-1 );
|
|
}
|
|
#endif
|
|
|
|
if ( !GetDescriptorData(selector, &dte) ) {
|
|
return( (ULONG)-1 );
|
|
}
|
|
|
|
base = ((ULONG)dte.HighWord.Bytes.BaseHi << 24)
|
|
+ ((ULONG)dte.HighWord.Bytes.BaseMid << 16)
|
|
+ ((ULONG)dte.BaseLow);
|
|
|
|
if ( si ) {
|
|
si->Limit = (ULONG)dte.LimitLow
|
|
+ ((ULONG)dte.HighWord.Bits.LimitHi << 16);
|
|
|
|
if ( dte.HighWord.Bits.Granularity ) {
|
|
si->Limit <<= 12;
|
|
si->Limit += 0xFFF;
|
|
}
|
|
si->Base = base;
|
|
|
|
type = dte.HighWord.Bits.Type;
|
|
|
|
si->bSystem = !(BOOL) (type & 0x10);
|
|
|
|
if (!si->bSystem) {
|
|
si->bCode = (BOOL) (type & 8);
|
|
}
|
|
si->bAccessed = (BOOL) (type & 1);
|
|
si->bWrite = (BOOL) (type & 2);
|
|
if (si->bCode) {
|
|
si->bWrite = !si->bWrite;
|
|
|
|
}
|
|
si->bPresent = (BOOL) dte.HighWord.Bits.Pres;
|
|
si->bBig = (BOOL) dte.HighWord.Bits.Default_Big;
|
|
|
|
}
|
|
|
|
if ( base == 0 ) {
|
|
return( (ULONG)-1 );
|
|
}
|
|
|
|
#ifdef i386
|
|
b = ReadProcessMem(
|
|
hCurrentProcess,
|
|
(LPVOID)base,
|
|
&byte,
|
|
sizeof(byte),
|
|
NULL
|
|
);
|
|
if ( !b ) {
|
|
return( (ULONG)-1 );
|
|
}
|
|
#endif
|
|
break;
|
|
|
|
case FLAT_MODE:
|
|
PRINTF("Unsupported determination of base address in flat mode\n");
|
|
base = 0;
|
|
break;
|
|
}
|
|
|
|
return( base );
|
|
}
|
|
|
|
|
|
//****************************************************************************
|
|
//
|
|
// Command line parsing routines
|
|
//
|
|
//****************************************************************************
|
|
BOOL
|
|
SkipToNextWhiteSpace(
|
|
VOID
|
|
)
|
|
{
|
|
char ch;
|
|
while ( (ch = *lpArgumentString) != '\0' ) {
|
|
if ( ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n' ) {
|
|
return TRUE;
|
|
}
|
|
lpArgumentString++;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
GetNextToken(
|
|
VOID
|
|
)
|
|
{
|
|
char ch;
|
|
|
|
while ( (ch = *lpArgumentString) != '\0' ) {
|
|
if ( ch != ' ' && ch != '\t' && ch != '\r' && ch != '\n' ) {
|
|
return TRUE;
|
|
}
|
|
lpArgumentString++;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
ParseIntelAddress(
|
|
int *pMode,
|
|
WORD *pSelector,
|
|
PULONG pOffset
|
|
)
|
|
|
|
{
|
|
char sel_text[128], off_text[128];
|
|
char *colon;
|
|
char *mode_prefix;
|
|
|
|
colon = strchr( lpArgumentString, ':' );
|
|
if ( colon == NULL ) {
|
|
PRINTF("Please specify an address in the form 'seg:offset'\n");
|
|
return FALSE;
|
|
}
|
|
|
|
mode_prefix = strchr( lpArgumentString, '&' );
|
|
if ( mode_prefix == NULL ) {
|
|
|
|
mode_prefix = strchr( lpArgumentString, '#' );
|
|
if ( mode_prefix != NULL ) {
|
|
|
|
if ( mode_prefix != lpArgumentString ) {
|
|
PRINTF("Address must have '&' symbol as the first character\n");
|
|
return FALSE;
|
|
}
|
|
|
|
*pMode = PROT_MODE;
|
|
lpArgumentString = mode_prefix+1;
|
|
}
|
|
|
|
} else {
|
|
|
|
if ( mode_prefix != lpArgumentString ) {
|
|
PRINTF("Address must have '#' symbol as the first character\n");
|
|
return FALSE;
|
|
}
|
|
*pMode = V86_MODE;
|
|
lpArgumentString = mode_prefix+1;
|
|
|
|
}
|
|
|
|
*colon = '\0';
|
|
strcpy( sel_text, lpArgumentString );
|
|
*colon = ':';
|
|
strcpy( off_text, colon+1 );
|
|
*pSelector = (WORD) EXPRESSION( sel_text );
|
|
*pOffset = (ULONG) EXPRESSION( off_text );
|
|
|
|
SkipToNextWhiteSpace();
|
|
|
|
return TRUE;
|
|
}
|