Log in

View Full Version : Access violation


VeeDub
June 28th, 2006, 18:51
Hi,

I have an app that makes calls to GetSystemTimeAsFileTime. I thought as a useful exercise I would replace the call to the API with a call to separate routine where I set the registers to see if I could essentially manipulate the time that the app "see's" by managing the registers.

However even when I set all the registers to the same values, the app subsequently generates an access violation, so clearly there is something that I should be doing but am not.

Thanks

VW

naides
June 28th, 2006, 21:33
Quote:
[Originally Posted by VeeDub]. . . so clearly there is something that I should be doing but am not.

Thanks

VW


1. The first thing you should be doing is to post a concise but detailed and commented code snippet, so we can at lest guess what the problem might be. . .

2. One of he most frequent access violations when you directly modify/assemble code without the help of a compiler is an unbalanced stack: at the time of the ret(urn), the top of the stack contains something that is not the return address, so the program tries to "return" to some non existant or illegal area of memory.

3. Also, if you mix up what should be a pointer to a variable with the content value of a variable, it necessarily makes the program try to "read" or "write" to an illegal address, which in turn generates an access violation.

VeeDub
June 28th, 2006, 22:47
Quote:
[Originally Posted by naides]1. The first thing you should be doing is to post a concise but detailed and commented code snippet, so we can at lest guess what the problem might be. . .


Fair enough ... DOH

Original code ...

Code:

004516FB |. 50 PUSH EAX ; /pFileTime
004516FC |. FF15 50634900 CALL DWORD PTR DS:[<&KERNEL32.GetSyst>; \GetSystemTimeAsFileTime
00451702 |. 6A 01 PUSH 1


Modified code at original location ...

Code:

004516FB |. 50 PUSH EAX
004516FC |. E8 393B0400 CALL backup_m.0049523A
00451701 |. 90 NOP
00451702 |. 6A 01 PUSH 1


My code to maintain the register values ...
Code:

0049523A /$ B8 DA7BC501 MOV EAX,1C57BDA
0049523F |. B9 28FF1200 MOV ECX,12FF28
00495244 |. BA 82DDE907 MOV EDX,7E9DD82
00495249 |. BC 24FF1200 MOV ESP,12FF24
0049524E |. BF 00000000 MOV EDI,0
00495253 \. C3 RETN


I worked this out by running the app and comparing the register values when the API call was made and once it was removed. There are a couple of statements missing yet to set the Z & P flags, but I was modifying those flags in Olly so that - if I had done everything correctly - I expected the app to have all the right inputs.

My understanding is that GetSystemTimeAsFileTime loads it's value into EAX and this is the value that I was modifying with the routine. The remaining registers are being set to preserve the values of the other registers.



Quote:

2. One of he most frequent access violations when you directly modify/assemble code without the help of a compiler is an unbalanced stack: at the time of the ret(urn), the top of the stack contains something that is not the return address, so the program tries to "return" to some non existant or illegal area of memory.

3. Also, if you mix up what should be a pointer to a variable with the content value of a variable, it necessarily makes the program try to "read" or "write" to an illegal address, which in turn generates an access violation.


I am guessing that I have done one or two of the later, but hopefully once you've had a look at what I've done you might be able to see the problem and save me some time.

thanks

VW

TQN
June 28th, 2006, 23:08
Do not change EDI. It was reserved by Windows API. Your code change ESP, so stackpointer is wrong.

LLXX
June 29th, 2006, 00:36
Quote:
[Originally Posted by VeeDub]
Code:

00495249 |. BC 24FF1200 MOV ESP,12FF24
Your problem. Never arbitarily move the stack pointer somewhere.

Quote:
[Originally Posted by VeeDub]My understanding is that GetSystemTimeAsFileTime loads it's value into EAX
Your second problem.
Quote:
[Originally Posted by Win32APIref]The GetSystemTimeAsFileTime function obtains the current system date and time. The information is in Coordinated Universal Time (UTC) format.

VOID GetSystemTimeAsFileTime(

LPFILETIME lpSystemTimeAsFileTime // pointer to a file time structure
);
Parameters

lpSystemTimeAsFileTime

Pointer to a FILETIME structure to receive the current system date and time in UTC format.
...and FILETIME is just the fancy name for a qord "representing the number of 100-nanosecond intervals since January 1, 1601". So, here is a "fixed" GSTAFT implementation:
Code:
pop eax ; return addr
pop edx ; we'll use this
mov [edx], 01234567h
mov [edx+4], 89abcdefh
push eax
retn 4

Kayaker
June 29th, 2006, 00:36
Hi

You better check how the app *uses* the result of GetSystemTimeAsFileTime. According to the docs the function does *not* officially return a value. If you actually trace through the API, yes it does modify eax, edx and ecx, but depending on how the programmer sets up the next instructions, and the compiler itself, the returned values probably won't (or won't necessarily) be accessed directly from the registers but instead from the FILETIME structure pushed in the first place.


Code:

void GetSystemTimeAsFileTime(
LPFILETIME lpSystemTimeAsFileTime
);

Parameters
lpSystemTimeAsFileTime
[out] Pointer to a FILETIME structure to receive the current system
date and time in UTC format.

Return Values
This function does not return a value.

typedef struct _FILETIME {
DWORD dwLowDateTime;
DWORD dwHighDateTime;
} FILETIME, *PFILETIME;



You'd probably be better to call GetSystemTimeAsFileTime yourself in your patch (using the same FILETIME buffer initially pushed) and modify the FILETIME fields directly before returning. If you're trying to for example fool the app into thinking it's a month earlier than it really is, then you should be able to subtract a constant value from (probably) the dwHighDateTime result, and it will be consistent whether you run it now or a year from now.

Again though, in your particular case directly modifying the registers *might* be the best course of action if the results are immediately used, but in theory that's *not* the way this particular function should be emulated or modified.

EDIT:I see LLXX and I both posted at the same GetSystemTimeAsFileTime, so part of the point is duplicated.

Kayaker

VeeDub
June 29th, 2006, 02:58
Quote:
[Originally Posted by Kayaker]
You'd probably be better to call GetSystemTimeAsFileTime yourself in your patch (using the same FILETIME buffer initially pushed) and modify the FILETIME fields directly before returning. If you're trying to for example fool the app into thinking it's a month earlier than it really is, then you should be able to subtract a constant value from (probably) the dwHighDateTime result, and it will be consistent whether you run it now or a year from now.

OK, I understand conceptually the point that both you & LLXX are making. Which means my initial attempt was way of base.

What I don't understand, is that EAX contains a value that points to an entry on the stack which holds a "pointer" to the FILETIME buffer. The value in that stack entry is 30000h.

Is this the 30000h a relative address - and if so, what's the base address? As far as I can tell the 30000h can't be an absolute address. I have looked at the API help and done a search on Google and I'm afraid I don't understand where the FILETIME buffer that I need to modify before I return to the mainline is stored.

BTW thanks to everyone for your responses, without this help I would be stuck.

VW

LLXX
June 29th, 2006, 04:33
Quote:
[Originally Posted by VeeDub]What I don't understand, is that EAX contains a value that points to an entry on the stack which holds a "pointer" to the FILETIME buffer. The value in that stack entry is 30000h.
No, there is only ONE indirection. The value on the stack *is* the address of the FILETIME qord. That address being 30000 may explain the access violations you've been experiencing...

VeeDub
June 29th, 2006, 05:56
Quote:
[Originally Posted by LLXX]That address being 30000 may explain the access violations you've been experiencing...

I think I should clarify, the app was producing access violations because my initial attempt at "preserving" the registers was in fact changing values that I should not have been touching. Since I stopped doing that, the app has been running fine, albeit with it's view of time unchanged as I have not yet been able to figure out how this pointer works.

Quote:
[Originally Posted by LLXX]No, there is only ONE indirection. The value on the stack *is* the address of the FILETIME qord.

Generally I have found the API help to be quite good, but unfortunately in this instance the documentation for this API call is not at all clear to me.

Here's one of the call's in the app:
Code:

0045856E |. 50 PUSH EAX ; /pFileTime
0045856F |. FF15 A0E34900 CALL DWORD PTR DS:[<&KERNEL32.GetSystemTimeAsFileTime>] ; \GetSystemTimeAsFileTime


Prior to call:
Code:

EAX = 0012FF28
0012FF28 = 00030000


After the call:
Code:

EAX = 01C69B67
00122F28 = F8E0C921


If I restart the app (say after about 2 mins), the values before the call will be the same.

After the call (second time):
Code:

EAX = 01C69B68
00122F28 = 46A71F07


If I restart the app again (third time): (after about another minute)
Code:

EAX = 01C69B68
00122F28 = 8BEA4F99



My gut feel is that EAX contains the pointer to FILETIME as the other values are too volatile.

But if EAX does contain the pointer, how do you interpret the value? - it is not a memory address.

VW

Kayaker
June 29th, 2006, 09:51
Quote:

My gut feel is that EAX contains the pointer to FILETIME as the other values are too volatile.


Actually 00122F28 itself is the pointer to the start of a FILETIME structure which is being allocated to the stack.

typedef struct _FILETIME {
DWORD dwLowDateTime;
DWORD dwHighDateTime;
} FILETIME, *PFILETIME;

On return,
00122F28 = dwLowDateTime
00122F2C = dwHighDateTime

Completely ignore the fact for the moment that these returned values *also* end up in eax (dwHighDateTime) and edx(dwLowDateTime).

Quote:
But if EAX does contain the pointer, how do you interpret the value? - it is not a memory address.

"The information is in Coordinated Universal Time (UTC) format."

Your next step is researching how to interpret this format...

blabberer
June 29th, 2006, 11:31
i was wondering and looked at disassembly

and in fact the function uses eax and edx and then save them back to FileTime

Code:


7C8017E5 GetSystemTimeAsFileTime MOV EDI,EDI
7C8017E7 PUSH EBP
7C8017E8 MOV EBP,ESP
7C8017EA MOV EAX,DWORD PTR DS:[7FFE0018]
7C8017EF MOV EDX,DWORD PTR DS:[7FFE0014]
7C8017F5 CMP EAX,DWORD PTR DS:[7FFE001C]
7C8017FB JNZ SHORT kernel32.7C8017EA
7C8017FD MOV ECX,DWORD PTR SS:[EBP+8]
7C801800 MOV DWORD PTR DS:[ECX],EDX
7C801802 MOV DWORD PTR DS:[ECX+4],EAX
7C801805 POP EBP
7C801806 RETN 4


so one can sneakily check registers too if they want

Code:

7FFE0000 <tickcountlow> 002BAD9B
7FFE0004 <tickcountmultiplier> 0FA00000
7FFE0008 <interrupttime 3 dwords> 2306AACA
7FFE000C 00000068
7FFE0010 00000068
7FFE0014 <system time 3 dwords> 30885FA2
7FFE0018 01C69B96
7FFE001C 01C69B96
7FFE0020 <time zone bias 3 dwords> E647C400
7FFE0024 FFFFFFD1
7FFE0028 FFFFFFD1
7FFE002C 014C014C
7FFE0030 <ntsystemroot [260]> 003A0043

naides
June 29th, 2006, 11:34
I we had heed the the Rationalists during the french revolution and to Poincare at the turn of the century,
Time would be expressed in decimal units, and the Coordinated Universal Time (UTC) format would be self evident and meaningful

Now You will need to call to an specific API, or do a lot of cumbersome date calculations to turn that quad number into a year:month:day:hour:minute:second:tenth of sencond time coordinate

JMI
June 29th, 2006, 14:32
You mean IF you hadn't "lost your head" during the French Revolution! When there's no bread, don't tell them to eat cake!

Now join me in a rousing rendition of La Marseillais!

Aux armes citoyens!
Formez vos bataillons,
Marchons, marchons!
Qu'un sang impur
Abreuve nos sillons.

aux le barricades!



Regards,

Silkut
June 29th, 2006, 15:28
Wow JMI connais La Marseillaise

</offtopic>

JMI
June 29th, 2006, 16:28
Naturellement, pas chacun ?

Once I knew it in Vietnamese! But that's another story.

<,/further offtopic>

VeeDub
June 30th, 2006, 18:25
Quote:
[Originally Posted by Kayaker]
On return,
00122F28 = dwLowDateTime
00122F2C = dwHighDateTime


Hi Kayaker,

Thanks for this explanation, when I re-read the API help, it now makes sense when it refers to pointers.

Quote:

Your next step is researching how to interpret this format...

Actually I don't think that is going to be necessary. I can set the computer clock to a time value that will send the app to "goodboy". So if I understand this correctly I ought to be able to:

- change the computer clock
- run the app, make a note of the values in 00122F28 & 00122F2C
- modify the app to call my own routine, where I:
- call the API
- replace the values on the stack with the previously noted values
- return to app

I will be very interested to see if this actually works and even if it doesn't, I have learned a few things so this hasn't been a wasted exercise.

thanks again

VW