Log in

View Full Version : time trials


qweasdzxc
April 13th, 2003, 16:26
I have looked far and wide, but still haven't found anything describing this problem.

I am trying to kill a timer in my target. I have killed a nag screen and the 30 day limit so far, But when you execute the prog you are limited to 4 minutes of runtime...

I have looked for settimer, killtimer, getsystemtime, and ofcourse the milliseconds (240000), and the HEX equivalent (3A980)... I have also set a break for the 4 minute nag screen, but I got trapped in USER32.dll

The timer does not use the system time. I can start the app, then change my system time and the app always runs for 4 minutes.

My guess is that the app sets it's own independant timer, I have no experience with that yet. Can someone point me to a good tutorial? or offer any relevant advice?

Ida reports that the app is coded in C++, Is there a trick with some C++ library that I'm missing?

Manko
April 13th, 2003, 17:16
You tried gettickcount?

And about the time... No smart coder would use exactly 4 mins, since it will be easy to find. (Though I agree, this is quite common... So coders are not that smart, then... :P)

There are many other apis to get time too...

Hope someone will help you with the question about timers.

/Manko

qweasdzxc
April 13th, 2003, 18:35
No, I haven't tried Gettickcount. didn't know about it...
I know I need to read more, but I don't feel like I learn by reading, I like to learn by hands on methods, this way what I learn seems to stick around a little better.

I have a feeling that I am right ontop of the section I need to be in, I keep narrowing down and I have a couple of screens of interesting code. I have identified the VU Meter in the app, and I have a jmp out of that code into a rather large loop with SEVERAL calls. I am close, but I still cant see it. I can't find anything I recognize from any tuts I've read.

I have timed this with a stopwatch, it is 4 minutes!! I wasn't too suprised by that,

I will check for a reference to Gettickcount in Wdasm and see what I come up with.

Thanks!!

qweasdzxc
April 13th, 2003, 22:24
I didn't find Gettickcount...

I think it might be time to try a different debugger.... Or maybe put this to the side for now, I've been stuck on it for almost a month.

dELTA
April 14th, 2003, 07:49
A generic trick that might sometimes work surprisingly good in these situations is to search for the constant of the time limit. In your case I would try to search the entire deadlisting for the constant 240 (4 minutes in seconds) and 240000 (4 minutes in milliseconds). Check the code around the places where they will possibly occur. If you see a compare with these constants, try to track the compared data backwards and you might very well end up at the time-sample function (not that you would really need it once you have found the location of the compare, but anyway, for academical interest ).

This is the reason why "clever programmers" might choose a constant that is a little bit off (e.g. 240345 milliseconds, or 239 seconds), like Manko mentions above.

dELTA

disavowed
April 14th, 2003, 09:23
why not make a program to keep readprocessmemory'ing your app's process space, take a snapshot every few seconds, and then compare the snapshots to see what area of memory has a variable that keeps incrementing

there might even be some game trainers out there that do this automatically

banshee
April 14th, 2003, 09:45
Just a thought:
There is rdtsc command that return number of ticks since your PC started. You can use it combined with processor MHz information to determine how much time lasted since the last call. (Think API GetTickCount uses that command) Try to search for that command in your disassembly listing.

tgodd
April 14th, 2003, 11:11
It could be possible that they are accessing the Clock using direct IO via a device driver.

I have seen many an exe with an embedded driver which they load to do direct IO, then unload when finished.

Just a small possibility.

Regards,

tgodd

nikolatesla20
April 14th, 2003, 12:48
Another thing - did you only check the Imports for GetTickCount or did you also check strings table? Because it could be a dynamic import.

If you are using SI, another thing you could do is set a Breakpoint on a window message. You'll have to grab the softice manual to know what I'm talking about ...if you installed D.S 2.7 you will have that.

Anyway, get the window's handle and then do a breakpoint on WM_TIMER and see if anything comes thru or not...

It could be that any DLL that the program uses could actually do the counting, etc, etc.. so if it's using DLLs look at those too.


-nt20

Iwarez
April 14th, 2003, 14:44
Don't know about you but I'am getting interested in which program you try to get to work.

qweasdzxc
April 14th, 2003, 18:05
I have been using Ollydbg since I cant get softice to run on my machine. (problem with video card + drivers) I tried to search the dead listing I got from Wdasm and I finally found settimer, and Killtimer. Why wouldn't they show up in Olly?

The program is GuitarFX 2.6 .... it is a true demo prog. I found a reference to a serial number, just no place to input one in the demo.
This demo is limited by the number of days, time limit of effects processing, time limit of recording, you can't import wave files for playback during record, and ofcourse nag screens.

It looks like USER32.dll is keeping track of time, I guess I finally caught a break here!

Thanks everyone.

Kilby
April 15th, 2003, 06:38
Please excuse me if I appear to critisize as that is not the intention.

You folks are really going about this the hard way

I blame this on the fact that reversing these days is almost completely baised around breakpointing on API calls, unpacking, and finding where the serial number is compared.

ATM you are guessing which API is used and attempting to work from there, disavowed is on the right track but reinventing the wheel

You are curently suggesting bruteforce, this is acceptable, but wernt computers built to do the bruteforce work for us humans

Go and find yourself a nice game training tool (gamehack being one of them), and use that to find the counter. Let your PC do the work ! From there you can find the right piece of code easily.

It's lazy, easy and saves a lot of wasted effort when you can put the effort into something else more deserving.

If I appear patronising then I apologise, but I feel that the breadth of knowledge in todays scene is starting to constrict.

So much time is spent thinking about how things are done via the OS, between unpacking, decryption and the like.

Simplicity works learn to use it.

Try to lose thinking about the complexity of modern operating systems, think about what you want to do, then hit the right piece of code first time.

I think I will put somthing into the off topic section about this as I think there is quaite a lot to say about this.

Regards,

Kilby...

dELTA
April 15th, 2003, 07:08
I'm sorry to say this after your long lecture and everything Kilby , but in my opinion it is most likely that there is no "counter" at all. There simply isn't a good reason why it would be saved.

My guess is a timer procedure looking something like this:

Code:

//This is the only data saved in the data segment
int calculated_limit_time; //This will never be changed,
//only calculated once at program startup

//This is the checking procedure
void TimerProc(void)
{
if (sample_time() > calculated_limit_time)
{
exit_program_or_whatever();
}
}

This means that the sampled time will be at the best saved on the stack (also possibly only in a register), which means you can never find it with a mem-compare-tool program.

Or even easier, the timer itself might be set to 4 minutes, and then just call exit_program_or_whatever() immediately in the TimerProc. In neither of the cases there will be any data so perform "differential analysis" on.

Also, in my opinion trying to figure out the workings of the program is always better than bruteforcing it. Bruteforcing only works for certain stupid protections, while "guessing" (or rather concluding/zenning) will always work. This also makes you smarter and more experienced each time, which in turn makes it even easier to predict the workings of the next program.

dELTA

tgodd
April 15th, 2003, 08:16
Extremely well put delta.

I'm in agreement with everything you have outlined.

Having a deep understanding of how these things work
is essential to reverse engineering.

If you are using a tools which do most of the work for you, then
you are not truely reversing.

It is one thing to use the tools, when you understand how these things work.
It is completely something else when you rely on those tools, due to a lack of understanding of how things work.

I always suggest to Windoz "experts", whom I have been aquainted with, to learn Doz to expand on there abilities and understanding of the OS.

This is simply put, "Getting your hands dirty".

You can not fix a car if you are afraid, or incapable of touching an oily nut or bolt.

Get down and dirty folks.

Regards,

tgodd

Kilby
April 15th, 2003, 10:02
This is split into two replys.

This is the civil and measured, as was the maposting it is in reply to

Delta:

No lecture intended just wanted to say that it can be much easier when you apply lessons elsewhere. Even if you are unsuccessful, atleast there is something to remove from the list of possibles.

As you say it depends on how it is implemented.

All too often things are implemented badly and timers are very prone to this (you would be surprised to see the number of apps that do exactly this).

I most certainly am not zen like (I wish I was but I'm way too up tight), but a couple of minutes testing for holes & general stupidity yields many dividends.

Learning to ignore the spurious noise within windoze enables you to discover what is really happening. Though possibly I just suffer from a low bordom threshold.

BTW: The most likely way for me to have a go at such a timer is:

1: Check what timer apis are in the import table

2: Check for counters

3: Log calls to getprocaddress for that task to see if anything is resolved at runtime (write a logger for this).

4: Use an API logger to log what timer calls are used by the app in question (write your own for this too).

5: Start monitoring any suspect memory addresses of API calls

6: How it exits (thats always useful)

It's sorting the wheat from the chaff, and only takes a couple of minutes and can save hours of wasted effort.
To me the bruteforce method is sticking breakpoints on every time related API and waiting for the right call, then nopping the following conditional jmp

I work from one side (excluding things) and other people work from the other end looking for things to include it's all personal pereference.

I simply feel that too much of what people call reversing in windoze is purely hoping to bpx on the right API. I have in the past made 1000s of calls to particular APIs just to annoy the people who rely on this technique. It really is funny

Anyway I hope you understand where I am coming from.

Kilby...

Kilby
April 15th, 2003, 10:05
Second post.

Now I feel that I must be less reserved and civil.

The following is not supposed to be a flame and it is a bit off topic, but I feel that it is nessicary if you feel it isn't then thats fine.

If my original posting came across as arrogant, then I must state that wasn't the intention, possibly the posting in the off topic section may clear things up.

However I do feel that I am responding to arrogance, at least partialy directed towards me, I may be misreading it, or perhaps English is not the native tongue of tgodd, but I still feel that I must respond.

tgodd:

I thought, reversing is using whatever tools you have at your disposal, sometimes it's off the shelf, sometimes it's home grown, sometimes the tool is your mind.

Computers where built to remove repedative operations, and I dunno about anybody else but searching for the right bit of code can in fact be repeditive.

Once you find the guilty party then it's time to exercise your creativity to do something about it (I hate NOPs with a vengance).

So it's OK to use SICE (robbed no doubt), or ollydebug but not to use something that looks for changed values ?

oh dear ! I seem to have got it all wrong sorry !

Please be careful in what you say and how you say it, there is always somebody out there with a longer list than you and they may have know considerably more than you assume.

So how low down and dirty should one get ?

Windoze:
Hate it, but it's there and I have done way enough to comment within it to comment.

Dos:
Been there seen it done it, didn't bother with the Tshirt.
Redirected calls to mscdex and int 21
Long before sice was in the background, remember int 13
Game trainers, tsr's many apps and .sys files tweaked and rewritten

Amiga Dos:
Turn off the OS and hit the hardware directly.
Custom disc loaders, unpacking, 1KB demos
Code optimization for psygnosis developers
Using the blitter to help multiply complex numbers
DTMF decoder
Where is that T Shirt

Atari ST:
Where are those unpackers & disk loaders.
Oh theyr'e under the T shirt

Z80, 6502 and 6809 8 bit home machines.
Where are thise custom tape and disk load/save routines
The network driver for the BBC micro
The home designed & built samplers, network interfaces modems, parallel & rs232 ports, etc.
Mains ring networking.
Wrote own assemblers and debugging roms
T Shirts wheren't invented then.

6800 single board computer.
No assembler (hand assembled)
100 bytes of ram, hex keypad, 7 seg led display.
The only way to save your code was in a notebook using a pen.
Played tunes in an AM radio using interfearence from the machine, by using times loops

Hmmm what about building registers on a breadboard using NAND gates.

I think I still have the furs we cavemen wore in those days.

Anyway you can stop clapping your flippers like a demented seal that wants a fish from delta.

Possibly I have misread your post, but I doubt it.

Kilby...

tgodd
April 15th, 2003, 12:08
I did not mean for my response to be offensive.

As for The list you gave on your experiences.
Yes I have been there and done that also.
The 80's were a wonderful time.


DEC PDP-11's
RadShack Mod 1, 3, and coco
Osbourne
Amiga
Pet

I still know all the CP/M fast keycodes.

I've been there also.

What does one do when the tool does not give him what he wishes for?

Pray?

Give me a break.
My suggestion was in fact the most rudimentary.
All requests for the time MUST do IO to the device.

You find the IO you can backtrack to anywhere.

Do you disagree with this logic?

Tools are useless without source or at least an understanding of how they work.

For praying will not yield much with respect to results.
The more one knows of inner workings, the less likely the project will be handed over to somebody of greater knowledge.

I do did not in previous messages try to be arrogant.

And correct me if I am wrong, but it sounds to me as though you discount the fact that you have had these past experiences.
Could somebody relatively speaking "new" to this stuff, not benefit from knowing how these things work.

It's sick to see people having to kiss feet to get answers from people who do have this inner workings knowkledge.

And as far as Breadboarding descrete gates, I would recommend anybody try it.

Imagine how clean peoples code would be if they knew
boolean algebra, and understood Karneu maps.
I know I proly misspelled Karneu, but this is not a spelling 'B'.


I am sorry for coming across so agressively, but your message DID warrant a defense.

regards,

tgodd

nikolatesla20
April 15th, 2003, 13:03
"In my day, I hacked the AND gate by crossing the wire directly to the +5V line..and I LIKED IT!"

And I suppose both of you had to walk uphill both ways to the lab?


LOL


-nt20

tgodd
April 15th, 2003, 13:16
Bwahahahaha

Stumbling, every step of the way.
Go to be that the knees hurt!!!

tgodd

dELTA
April 15th, 2003, 13:23

Not to mention that most of the time we were completely out of NAND gates, and had to build all our logic by only using OR gates.

Kilby
April 16th, 2003, 12:57
Well I'm glad that we all have that sorted out then.

(it wasn't your io post I was replying to BTW)


regards,
Kilby...

cRk
April 18th, 2003, 01:36
i was able to get some info. and practice on this target, actually thanks to a cracker called realisty i was able to get the right places where the limit message comes and the cmp involved on this.... but there's one problem.. the program is crashing with a bluescreen after skeeping this limit.. it looks like i'm missing something or maybe this can't be cracked? because we're missing part of the Code... remember this is a demo....... did you handle to finish it and is working??.. if you want i can paste my research on this here.. just let me know.

Manko
April 18th, 2003, 02:54
Hi!

Your thinking is slightly off. If it works during the timelimit, ofcourse it will work after, if you patch it right.

He is using something to trick you, no doubt...
...or maybe...

How did you patch it?
And have you looked into the proc, or the instructions
that create the values that are being compared?
Maybe he sets some things up...
Maybe you left the result... and he is using it later?

/Manko

dELTA
April 18th, 2003, 08:05
A bluescreen after a patch is typically either a deliberate integrity check by the programmer (which can in that case be removed too), or a bad patch (which can in that case be rethinked and redone in a better and more correct way ).

dELTA

Kilby
April 18th, 2003, 15:48
This comes back to understanding the code.

90% of the time a simple nop or jmp patch will do the job.

However every now and then the author will look for such changes, leaving a couple of choices.

1: Subvert the original protection in a suitably discreet place

2: Patch all the authors checks

/Hint on

My preferred option is 1.
eg if there is a call to the protection routine, set the appropiate flag at the start of the routine then return early, authors seldom check for patches at the start of a subroutine, usually they check the last few bytes.

/hints_off

Kilby...

qweasdzxc
April 18th, 2003, 19:10
cRK, I haven't really had time this week, been busy at work. I was planning on going to a party tonight, but work blew that, So, I am going to try this again!

JMI
April 18th, 2003, 19:36
Haven't played around with this program, but know that there is a partially working crack floating around out there for this version. The person who wrote the crack says that the 4 minute time limit is connected in some way to an "overflow of the level meters," which suggests a possible buffer. He suggests that the only way to prevent it from "overflowing" and stopping the program is starting and stopping the level meters.

Now I'm not suggesting that anyone use a ready made crack for this program, because you won't learn anything by doing that (and he didn't "solve" this problem any), but his "observation/suggestion" does seem to indicate a good potential point for analysis of the code. Maybe it's not an "overflow" or maybe it is, but it certainly suggests that this might be a very good place to begin the search for the elusive "timer." This is also reported as a truely crippled demo without the code for "input function," which is the only true way to "protect" demo software, but it still can provide a good object for study of the protection system.

Regards.

qweasdzxc
April 18th, 2003, 19:53
You can turn the VU level meter off... I know that if you pause execution of the program code while the levels are on, you can step right into the level meters! you find a loop... at somepoint a condition is met and you jump into the normal program code, and eventually back into the meters. (didn't spend too much time on this part). By pausing with the meter levels off, you drop into the normal program code and it seems to contain the important code. I'm still looking.

disavowed
April 18th, 2003, 22:01
well, i finally decided to take a look at this for myself

i tracked down where the messagebox was coming from, although that wasn't particularly useful. i then decided to look for one of those programs i had mentioned for making game trainers. after 5 minutes of searching with google, i found this, which suited my needs perfectly: http://www.gw32.de/english.html

it allows you to search for changing values in memory. quite simply, i just watched for areas of memory that kept increasing. the only address of memory like this in the process's address space is: 0x55C7D8 (gamewiz32 will say 0x55C7D9... close enough)

so, we take a look at 0x55C7D8 with ida. lo and behold, it's initialized to 0 when the thread starts, and it's constantly updated and checked in sub_419690. setting some wise breakpoints with olly lead me to figure out that the '5' in:
Code:
.text:00419719 cmp dword_55C7D4, 5

is actually the number of minutes allowed + 1. setting it to 1 will cause it timeout immediately. setting it to 2 will cause it to timeout after 1 minute, whereas originally the 5 causes it to timeout after 4 minutes. anyway, chaning
Code:
.text:00419720 jl short loc_419773

to an unconditional 'jmp' instead of a conditional 'jl' gets rid of the timeout.

disavowed
April 18th, 2003, 22:06
heh, evidently that causes an eventual overflow. the solution would probably be to just prevent the counter from incrementing. i'll leave that as an exercise for the reader, now that you know what sub_ to look in

qweasdzxc
April 18th, 2003, 22:13
Disavowed, I agree with you that the memory dump/compair is the easy way to do this, I have been trying to trace the code, and figure it out for myself, the hard way, (so I can better understand the OS, and what protection schemes really do, plus learn some more assembly). According to your post, I am in the right area of code though. ....

JMI
April 18th, 2003, 22:21
qweasdzxc:

Let me encourage you to maintain that attitude. Learning to understand the Code is the essence of what you need to advance your skills at RCE. Patching without knowledge is not a learning experience you can generally apply on other software. If you improve your level of understanding, you will be able to carry this forward when you begin to examine your next target.

Regards.

cRk
April 19th, 2003, 00:43
Guitar FX BOX 2.6

:0041A384 C1E005 shl eax, 05 <-- 05? maybe 4.59 Min.
:0041A387 03C2 add eax, edx
:0041A389 F6401001 test [eax+10], 01 <-- press Start
:0041A38D 7428 je 0041A3B7
:0041A38F 8B0DC8C75500 mov ecx, dword ptr [0055C7C8]
:0041A395 E876FBFFFF call 00419F10 <-- continue process
:0041A39A A1C8C75500 mov eax, dword ptr [0055C7C8]
:0041A39F 40 inc eax
:0041A3A0 99 cdq

once we're on 00419F10 there's alot of piece of code which i think
it handles the sounds process... please correct me anytime if i'm
mistaken.. i'm here to learn more and correct my mistakes...

continuing..

check a little the big piece code.. and go down until you get to

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0041A0AD(C), :0041A0DB(U), :0041A124(U), :0041A16A(U)
|
:0041A17D 8B4DF8 mov ecx, dword ptr [ebp-08]
:0041A180 E80BF5FFFF call 00419690 <- let's go here

on 00419690 continue reading the sound process and there alittle cmp
which compares a virtual (rva) location with 05 which mean our target
dosen't read 4 minutes exactly as it says.. i think it reads 4.59 minutes... go to 00419690 and read a little until you see this:

:00419713 890DD4C75500 mov dword ptr [0055C7D4], ecx

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004196F6(C)
|
:00419719 833DD4C7550005 cmp dword ptr [0055C7D4], 00000005 <<-- compare minutes here
:00419720 7C51 jl 00419773 <-- if 5 minutes passed jumps-|
:00419722 C705506D550001000000 mov dword ptr [00556D50], 00000001 |
:0041972C 833D6CC7550000 cmp dword ptr [0055C76C], 00000000 |
:00419733 740D je 00419742 |
:00419735 8B0D94C75500 mov ecx, dword ptr [0055C794] |
:0041973B E8E02DFFFF call 0040C520 |
:00419740 EB12 jmp 00419754 |
|
* Referenced by a (U)nconditional or (C)onditional Jump at Address: |
|:00419733(C) |
| |
:00419742 8B1588645500 mov edx, dword ptr [00556488] |
:00419748 8B02 mov eax, dword ptr [edx] |
:0041974A 8B0D88645500 mov ecx, dword ptr [00556488] |
:00419750 51 push ecx |
:00419751 FF5048 call [eax+48] |
|
* Referenced by a (U)nconditional or (C)onditional Jump at Address: |
|:00419740(U) |
| |
:00419754 8B1518C75500 mov edx, dword ptr [0055C718] <----------- jumps here
:0041975A 8955EC mov dword ptr [ebp-14], edx
:0041975D 6A00 push 00000000
:0041975F 6A00 push 00000000
:00419761 6865040000 push 00000465
:00419766 8B45EC mov eax, dword ptr [ebp-14]
:00419769 8B481C mov ecx, dword ptr [eax+1C]
:0041976C 51 push ecx

* Reference To: USER32.PostMessageA, Ord:01DEh
|
:0041976D FF15D0D44400 Call dword ptr [0044D4D0] <-- our nag message comes here

if we make jmp on 00419720 you'll note if won't give any nag and will keep working but somehow it will stop and you'll note the level meter will stop and will give you a bluescreen fatal error after 2 or 3 more minutes , the system says to pressed any key and bye bye program.. i wonder if there's still another check for this maybe a cmp? because i also have tried all time related possible solutions and still not luck

the only possible compare i found for this is the above one but i guess there's something more
somewhere... i'll hope i'm missing something. another thing is that the nag about the 4 minutes limit looks like a messageboxa.. if you do bpx messageboxa sice will break when the 4.. minutes are over.. the messageboxa comes from 0041FF74 i don't see there any cmp or way to skip it it looks that first call USER32.PostMessageA while tracing a little just before the limit is over
and exactly the message comes from 0041976D then the messageboxa shows up .

i got this code where the messageboxa comes from :

:0041FF6D 8D05C0E94100 lea eax, dword ptr [0041E9C0] <-- read here, there's a C3 only
:0041FF73 50 push eax
:0041FF74 FF2538545500 jmp dword ptr [00555438] <<--- Messageboxa here
:0041FF7A 5F pop edi
:0041FF7B 5E pop esi
:0041FF7C 5B pop ebx
:0041FF7D 8BE5 mov esp, ebp
:0041FF7F 5D pop ebp
:0041FF80 C20800 ret 0008

to skip the nag message i did change push (55) for C3 at the begin of that piece of code on
0041FEB0, but it won't make any change.. it only remove the messageboxa

if i increment value on cmp dword ptr [0055C7D4], 00000005 for
cmp dword ptr [0055C7D4], 00000009 i guess it should read 9 = minutes in this case ?

while tracing alittle bit more.. while the program process the sounds looks it read locations
between 0041BFDC & 0041BED7 there's a loop and i think that maybe there's the function where it stops the sound processing. "i'm not sure" i wonder what exactly KERNEL32.SleepEx does
because there are many references about it there..

is there a way to make it loop so we won't have to press manually start each time 4 minutes has passed ? like simule we have pressed "Start" after 4 minutes has passed. any ideas which bpx should i set to catch where exactly the sound processing stops?.. you can note it when the level meter stops responding.. that's a good sign. i tried closehandle but nothing happends.

Any tips, complaints or possible help is welcome to resolve the time limit mistery of this program.

qweasdzxc
April 19th, 2003, 06:54
The SleepEx function causes the current thread to enter a wait state until the specified interval of time has passed, or until an I/O completion callback function is called.

This function is available only in the Win32 API.

DWORD SleepEx(

DWORD dwTimeout, // time-out interval in milliseconds
BOOL fAlertable // early completion flag
);

Parameters

dwTimeout

Specifies the time, in milliseconds, that the delay is to occur. A value of zero causes the function to return immediately. A value of INFINITE causes an infinite delay.

fAlertable

Specifies whether the function may terminate early due to an I/O completion callback function. If fAlertable is FALSE, the function does not return until the time-out period has elapsed. If an I/O completion callback occurs, the function does not return and the I/O completion function is not executed.
If fAlertable is TRUE and the thread that called this function is the same thread that called the extended I/O function (
ReadFileEx or WriteFileEx), the function returns when either the time-out period has elapsed or when an I/O completion callback function occurs. If an I/O completion callback occurs, the I/O completion function is executed.


its a fancy wait command... IN this program I think it has to do mainly with sound latency, the coder probably used this for faster code, while still being able to pause a thread...

almos
April 20th, 2003, 08:16
It is easy to get THAT counter:

004196EF cmp dword ptr [0055C7D8], 00000000
004196F6 jne 00419719
004196F8 mov edx, dword ptr [0055C7D4] ;get minutes
004196FE mov eax, dword ptr [0055C7D4] ;ditto
00419703 mov dword ptr [4*edx+00554364], eax ;store it elsewhere...
0041970A mov ecx, dword ptr [0055C7D4]
00419710 add ecx, 00000001 ;increment minutes!!!
00419713 mov dword ptr [0055C7D4], ecx
00419719 cmp dword ptr [0055C7D4], 00000005 ;cmp time with limit
00419720 jl 00419773 ;not yet 4+1, continue
...
shortly after comes the routine to increase minutes:

00419773 mov ecx, dword ptr [0055C7D8] ;
00419779 add ecx, dword ptr [ebp-18] ;x80
0041977C mov eax, dword ptr [0045CCFC] ;22050 (Hz?)
00419781 cdq
00419782 and edx, 0000007F
00419785 add eax, edx
00419787 mov esi, eax
00419789 sar esi, 07
0041978C imul esi, 0000003C ;60 (second)
0041978F shl esi, 07
00419792 mov eax, ecx
00419794 cdq
00419795 idiv esi ;when edx=0, 1 min elapsed!
00419797 mov dword ptr [0055C7D8], edx ; <<<

Thus, by putting 0 into edx/[55C7D8] a few times, one can trigger the '4 mins limit reached' condition, rather than physicaly waiting out the 4 minutes So it's possible to make it 'faster', but unfortunately won't work the opposite way - 'fixing' this counter (say by changing the increment to 0 at 419710) later still results in a blue screen.
How it does that, I still don't know, but I doubt if uses any patch/integrity check. I reckon rather it is some buffer or stack overrun causes the blue screen.

A time check not necessarily requires a windows timer. For example, with a sound sample rate of 22050 Hz, when processed say 11025 samples then 11025/22050 = 0.5 second has elapsed. One can just count how many times were sound buffers filled... etc. and derive the duration. In fact, there are quite a few other 'counters' (using floating pont numbers) related to sound processing. Yet, I feel the solution is not with those FP values. How do I reckon?

Previously I eliminated all limitations from 2 older (2,1, 2.5) versions, but when tried the usual fixes on this version (maybe in July last year) failed with the 4 mins limit. If there is no another 'time check' then sure has some 'screw-it-up' routine. It may be just writing memory/buffers eg. [offset+counter x constant] which eventually kills Windoze, unless stopped in good time (bit over 5 mins). This surprise is surely absent from the older versions. Since the major difference is in multithread use in v2.6, I guess that's the suspicious part to deserve extra attention. For example, there is another (faster) 'counter' at [0055C7EC], related both to the common minute counter and also to thread activation.

In any case, this is a real bitch, a good protection.

qweasdzxc
April 20th, 2003, 09:13
Almos,

Your right about making the timer faster, I managed to get the 4 minute nag in about 30 seconds of runtime!! But I didn't manage to slow it down yet.

I suspect that there is a second check elsewhere. I have found several references to killtimer since I decided to use Wdasm to look at the code. I set breakpoints on two of them and let the app run out the 4 min. I didn't hit either brp. I also checked the 20 second recording limit with the same brp's, and failed to break on either. So, I am going to back trace the code to see what calls the two killtimer's. I have a feeling that it will be a second "security" timer.

tgodd
April 20th, 2003, 09:55
I have personally written code which requires that the counter continue to count.

If the counter is stalled or advanced the program crashes.

Do not always rely on being able to stop or advance the counter.

The values will be referenced more than likely within another
thread.

You may want to focus there!!

Just a point to take into consideration.

regards,

tgodd

cRk
April 20th, 2003, 10:50
i got the idea.... this program always read the system time.. because how it knows 4 minutes has passed? sure is reading system time clock somehow.. if we reverse this to fool it and skip reading the system time clock.. this is just a suggestion.. btw i think all wee need is to find the right place to patch , i would not consider this a good protection.. other thing it is possible the code to process the sound it's done to stop right away after 4 minutes and there's now way back, no loop or C3. so forcing it to continue it will just crash.. why bluescreen? maybe takes too much memory,while doing nothing after 4 minutes "Not sure". or maybe we're missing the part of this code where the program could have a loop to keep processing. it is possible it has an internal counter that counts appart from the system clock?.. i don't think this is done with killtimer.. SICE will break right away before the little nag..in this case don't break anywhere..

qweasdzxc
April 26th, 2003, 10:46
Tgodd might be right.. the program does setup a new thread after startup. And I do think there is a second counter somewhere. I set olly for just in time debugging, to check the program crash after 4 minutes and when I broke, I was dumped into a real mess. instructions overlapping blocks, unknown commands, and illegal procedures.

Crk you might want to look at getsystemtime as filetime, this just occured to me. I will check on that too. But you can start the program and get into the 4 minute loop, then change the system time with out the nag appearing. At any rate, I've been too busy to look at it much.