The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: oex on April 09, 2010, 11:23:37 PM

Title: Valid Memory Address
Post by: oex on April 09, 2010, 11:23:37 PM
So.... just wondering if there is a way to tell if an address in a register is a valid memory address ie say I have:

mov esi, chr$("Random String")

mov esi, alloc(10)
and then move a string to esi

Can I test that address in esi to see if it has a string in it and say print that string somehow without crashing the app? I know I might be able to use some error checking function I forget the name of but it seems crude, maybe there is a more obvious answer to this question....

Further is there a way to see if esi contains the allocated address ie

mov esi, alloc(10)
esi = true
inc esi
esi=FALSE
Title: Re: Valid Memory Address
Post by: dedndave on April 09, 2010, 11:26:42 PM
well - almost any location in memory will be zero terminated - - eventually   :P
you can use VirtualQuery/VirtualQueryEx to determine access rights
after that, you are writing a little proc to test for alphanumeric ASCII with punctuation - hard to set the rules for that, i guess

it would be easier to write the code so that a "no string" condition is a null terminator - then you can test for that condition
Title: Re: Valid Memory Address
Post by: redskull on April 09, 2010, 11:54:49 PM
The "standard" way would be to use a SEH frame based exception handler, but I'm from the school of thought that says a bad pointer is a bug in the code, and not something that can be "handled" as a matter of course.  Of course, SEH and things like IsBadReadPtr, VirtualQuery, etc, would only throw an access violation, and not a "non-ascii string" error.  You would have to test for that yourself.

-r
Title: Re: Valid Memory Address
Post by: hutch-- on April 09, 2010, 11:59:25 PM
Dave's suggestion is easy enough to do if you don't mind a 2 step process for strings, allocate an array of empty pointers then for each string allocate that memory and place the pointer to it in the first array. If the pointer is zero there is no string else the value is the address of the string.
Title: Re: Valid Memory Address
Post by: dedndave on April 10, 2010, 12:38:27 AM
well, that wasn't what i was thinking, but i guess that'd work too
i was thinking a null string - first byte = 0
Title: Re: Valid Memory Address
Post by: qWord on April 10, 2010, 12:57:33 AM
oex,
the question is not how to detect bad pointers, it is why you get bad pointers.   :U
What got in my mind seeing this topic:The wrong way to determine the size of a buffer (http://blogs.msdn.com/oldnewthing/archive/2010/01/20/9950638.aspx) :toothy

regards, qWord
Title: Re: Valid Memory Address
Post by: oex on April 10, 2010, 01:07:41 AM
Quote from: hutch-- on April 09, 2010, 11:59:25 PM
Dave's suggestion is easy enough to do if you don't mind a 2 step process for strings, allocate an array of empty pointers then for each string allocate that memory and place the pointer to it in the first array. If the pointer is zero there is no string else the value is the address of the string.

Yeah I was trying to avoid this allocation of an array assuming windows must have analysis functions.... I have used this method in the past especially in my debugging functionality however I have always left strings out as a seperate 'object type' that I keep track of in my head :lol. Usually they are kinda important to keep an eye on as are the functions that receive sz....

Looking at the situation again now I kinda prefer the idea (at least in my debugger not my actual apps) of forward looking at the memory to determine it's properties and displaying as required rather than logging as I go....

I think SetUnhandledExceptionFilter was the boxing glove function I was thinking of before to pick up this pin, a hazy memory of past usage in a forum download so the functions above have been most illuminating.... Though IsBadReadPtr users might want to check the M$ page "IsBadXxxPtr should really be called CrashProgramRandomly" http://msdn.microsoft.com/en-us/library/aa366713(VS.85).aspx :lol
Title: Re: Valid Memory Address
Post by: oex on April 10, 2010, 01:11:34 AM
Quote from: qWord on April 10, 2010, 12:57:33 AM
oex,
the question is not how to detect bad pointers, it is why you get bad pointers.   :U
What got in my mind seeing this topic:The wrong way to determine the size of a buffer (http://blogs.msdn.com/oldnewthing/archive/2010/01/20/9950638.aspx) :toothy

regards, qWord

:P My code is flawless :lol I dont get them I just want to write code that analises without my input in my debugger.... Obviously on the offchance an error should occur (maybe through act of god or something similarly unlikely) the debugger doesnt know what data is coming up next so to be able to read and analyse the memory could be rather usefull
Title: Re: Valid Memory Address
Post by: oex on April 10, 2010, 01:19:00 AM
ie my breakpoint function might display:

EAX: -1                  FF FF FF FF            
EBX: 1                   01 00 00 00        ☺
ECX: 1244892             DC FE 12 00        ▄■↕
EDX: 2089870612          14 E5 90 7C        ¶σÉ|

if eax were a pointer to a string it would be nice to also print maybe the first 20 chars of that string....

I dont use Olly and the like
Title: Re: Valid Memory Address
Post by: clive on April 10, 2010, 04:58:45 AM
Quote from: redskull
The "standard" way would be to use a SEH frame based exception handler, but I'm from the school of thought that says a bad pointer is a bug in the code, and not something that can be "handled" as a matter of course.

Indeed, if I'm doing something that might cause the processor to fault, SEH is the way to go. Especially if the alternative is a pretty blue screen.

case IOCTL_MONKEY_PUT_MSR:
{
ULONG Param[3];

if (inLength < (sizeof(ULONG) * 3))
{
Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;

break;
}

RtlCopyMemory(Param, ioBuffer, (sizeof(ULONG) * 3));

try
{
_asm
{
mov ecx,Param[0]
mov eax,Param[4]
mov edx,Param[8]
wrmsr
}
}

except(EXCEPTION_EXECUTE_HANDLER)
{
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
}

break;
}


And I'm from the school that does things in C when it is simpler, easier and appropriate.

-Clive
Title: Re: Valid Memory Address
Post by: jj2007 on April 10, 2010, 08:02:30 AM
Quote from: redskull on April 09, 2010, 11:54:49 PM
I'm from the school of thought that says a bad pointer is a bug in the code, and not something that can be "handled" as a matter of course.  Of course, SEH and things like IsBadReadPtr, VirtualQuery, etc

Yes, let it crash. Olly is your friend. In my library, I use IsBadPtr in exactly one situation: Just before the "Fatal error" MessageBox followed by ExitProcess, and only to test if the additional info string is valid.
Title: Re: Valid Memory Address
Post by: Ghandi on April 10, 2010, 10:16:03 AM
I thought that memory allocation functions returned a NULL value on failure, that is a simple check you could perform.


mov esi,alloc(10)
test esi,esi
  jz alloc_failure

;ESI contains allocated memory

;Don't forget to free the memory when finished with it.

alloc_failure:

Icezelion also shows setting up a SEH to catch any errors when taking the e_lfanew member of the speculated DOS header, i can't recall the exact tutorial(s) which contain this but it wouldn't hurt to flick through them and see what i mean. If you set up the SEH and then attempt accessing the buffer (after checking it even exists first) and if your SEH is triggered you can display appropriate error message before cleanup and exit of routine/application.


HR,
Ghandi
Title: Re: Valid Memory Address
Post by: clive on April 10, 2010, 12:33:51 PM
Indeed, testing values like 0x0000000 and 0xFFFFFFFF, etc would represent a cheap initial test. You could also look to see if they fall within the scope of the executables static image, or belonged to the process.

I think the initial question was more one about registers with random/arbitrary contents.

When touching user space memory (from some arbitrary context) in kernel space, I used some thing along the lines of this.

Mdl = IoAllocateMdl(Addr, Length, FALSE, FALSE, NULL);

if (Mdl)
{
MmProbeAndLockPages(Mdl, KernelMode, IoModifyAccess);

VirtAddr = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);

if (VirtAddr)
{
Success = TRUE;
}
else
{
MmUnlockPages(Mdl);

IoFreeMdl(Mdl);

Mdl = NULL;
}
}


This kind of thing worked well, especially if you wanted to maintain access to the memory and the user space context changed to some other process along the way. The basic function is to create a "window" into the user space, at an address the kernel can always access. One or more of the tests will fail along the way if the address is not accessible by the users process.

-Clive