Jump to content
Tuts 4 You

Timer Replacer (Visual C++)


CodeExplorer

Recommended Posts

CodeExplorer

Time in milliseconds of a timer:
time1 = when timer started
time1 = when timer proc ended

time1=9182437
time2=9182437

time1=9182452

The difference is big: 15 ms!

I know that 1 millisecond is much for computer performance!
I've tested some code and the time in ms was not even 1 ms.

uElapse [in]
    Type: UINT
    The time-out value, in milliseconds.
    If uElapse is less than USER_TIMER_MINIMUM (0x0000000A), the timeout is set to USER_TIMER_MINIMUM.
    If uElapse is greater than USER_TIMER_MAXIMUM (0x7FFFFFFF), the timeout is set to USER_TIMER_MAXIMUM.

I need something much better then a timer!

 

Link to comment
CodeExplorer

I found an easy solution: just create a thread with a loop:
 

Quote

DWORD   dwThreadId;
HANDLE hThread = CreateThread(
            NULL,                   // default security attributes
            0,                      // use default stack size  
            MyThreadFunction,       // thread function name
            NULL,          // argument to thread function
            0,                      // use default creation flags
            &dwThreadId);   // returns the thread identifier

Quote

DWORD WINAPI MyThreadFunction( LPVOID lpParam )
{
while (true)
{

// code here

}

return 0;
}

 

 

Link to comment
CodeExplorer

I'm building an allocation API hoocker: will save ESP when API starts on DWORD 1 and EAX when the API ends on DWORD 2,
both DWORDs should be checked in a loop, SetTimer minimum value is of 0x0000000A miliseconds which is way to much for performance.
I want a fast loop.
 

Link to comment
CodeExplorer
5 hours ago, VirtualPuppet said:

If you want to be very performance aware, using rdtsc.

I found some great articles about rdtsc:
https://msdn.microsoft.com/en-us/library/twchhe95.aspx
https://helloacm.com/the-rdtsc-performance-timer-written-in-c/
I don't need time performance measurement, for that GetTickCount would do the trick;
if the difference is less then 1 (ms) all is ok.
So far the CreateThread on a loop seems to be the fastest solution!

 

Edited by CodeExplorer
Link to comment

Keep in mind if you loop endlessly like that without any sleep/wait, you are going to cause the CPU usage of your process to spike really high.

Link to comment
CodeExplorer
3 hours ago, atom0s said:

Keep in mind if you loop endlessly like that without any sleep/wait, you are going to cause the CPU usage of your process to spike really high.

When no Sleep at all CPU was somewhere around 25% and that crap won't work.
CPU usage 6% with some Sleep,
Why when I use: Sleep(5);
when I measure the difference the ms difference is 10 and even more?
The program won't work without Sleep at all since will report same value multiple times!
 

Link to comment

Whatever you're doing, you're doing it wrong.
If your code runs every millisecond (and it takes 1 millisecond to run), there just isn't enough time/resources to run anything else on that CPU core.

 

As for your question, the answer is in MSDN:

Quote

After the sleep interval has passed, the thread is ready to run. ... Note that a ready thread is not guaranteed to run immediately. Consequently, the thread may not run until some time after the sleep interval elapses. For more information, see Scheduling Priorities.

 

Link to comment
CodeExplorer

Sleep is very weird:

DWORD time1 = GetTickCount();
Sleep(5);
DWORD time2 = GetTickCount();

time1 = 0x008a0159
time2 = 0x008a0159

How is that possible?
And sometimes the difference is more then 5 ms.
I expect more accuracy!

Quote

If your code runs every millisecond (and it takes 1 millisecond to run), there just isn't enough time/resources to run anything else on that CPU core. 

When I don't use Sleep: 25% of CPU when the program is running is not much I think! I would (even) say that the program doesn't use enough CPU resources.
But in the end I have to use Sleep!
 

Quote


If your code runs every millisecond (and it takes 1 millisecond to run)

That is not even possible!
 

Link to comment

25% of CPU is exactly 1 core of the 4-core CPU you have. :) 

Read the MSDN article I linked earlier, it also explains why sometimes thread will sleep less than expected. And some suggestions how to work around it.

 

But in the end, I really think you should go back to drawing board and find another way to do whatever you're trying to do. 

Link to comment
CodeExplorer
CodeExplorer

I've thought that there is something wrong with my program: actually is just "slow"
over an Asprotect unpackme with all options enabled.
It takes ~8 minutes to trace that sheet. The get speed is slower directly proportional with number of (allocations) Apis called!
But when you try to build an trace script for Olly for tracing Apis I would say that my tracer is ok.
 

Link to comment

GetTickCount is not a timer you should use to benchmark differences like that. Also, Windows rounds sleeps up to 10 in most cases due to CPU timing. So values between 1-10 are generally going to give the result of 10 regardless. 

If you want to accurately test the time between the two values you showed above, use a lower level clock like the CPU timer etc.

Link to comment
CodeExplorer
Quote

GetTickCount is not a timer you should use to benchmark differences like that.

I know that GetTickCount is not a timer, GetTickCount just returns number of ms passed,
I think for my needs GetTickCount did the trick.

the "Sleep(5);" should Sleep for at last 5 ms not like it does sometimes for 0 ms!
That Sleep for 0 is a shit I have to fix!

 

Link to comment
CodeExplorer

I made a solution:

void CriticalTimeSleep(int ms)
{
DWORD time1 = GetTickCount();
DWORD time2 = 0;

do
{
Sleep(ms);
time2 = GetTickCount();
}
while ((time2-time1)<ms);

}

CriticalTimeSleep(10);
I've called that after I've read each dword (they are two dwords to read).

On the loop I've called only Sleep(1),
I don't know exactly what to do in main loop!!!
 

Quote

So values between 1-10 are generally going to give the result of 10 regardless.

It would be great if that would be the case, but sometimes the Sleep time is 0!
 

Link to comment
CodeExplorer

Some new info: I use Sleep(1) in main loop: sometime it takes 4 minutes, sometime 8 minutes, sometimes it takes 12 minutes: same Asprotect unpackme
I tend to think that it is because of the random Sleep time of Sleep(1).

I've found these resources:
https://stackoverflow.com/questions/1616392/why-does-an-empty-loop-use-so-much-processor-time
https://stackoverflow.com/questions/175882/whats-the-algorithm-behind-sleep
https://social.msdn.microsoft.com/Forums/vstudio/en-US/facc2b57-9a27-4049-bb32-ef093fbf4c29/threadsleep1-sleeps-for-156-ms?forum=clr

So to sum up my problem: how do to make it Sleep only some milliseconds:
I don't want very high CPU usage but neither low performance like it is when I use Sleep(1) ,
I'm looking for a sort of compromise!
 

Link to comment
  • 2 weeks later...
CodeExplorer

Thank you guys for all your help.
Still working at that alocation Api logger.
I won't use that CriticalTimeSleep any more.
I found a better solution:
 

ContinueExecution(place);

while (ReadProcessMemory(G_ProcHandle,(LPVOID)((unsigned int)place),keeper,4, &BytesRead)&&
(keeper[0]!=0||keeper[1]!=0||keeper[2]!=0||keeper[3]!=0))  // until we have something there!
{
unsigned int stack_pointer2 = ((keeper[3]<<24)|(keeper[2]<<16)|(keeper[1]<<8)|(keeper[0]));
Sleep(1);
}

In my Asm API hooks somewhere near the end dword ptr[place] is set to 0
Much faster and much better.
But I also wanna attach Olly debugger to traced process,
I noticed some strange: CC  INT3

 

Quote

777E0EA8    6A 0C               PUSH 0xC
777E0EAA    68 98BE7677         PUSH 0x7776BE98
777E0EAF    E8 A8D0F8FF         CALL 7776DF5C                            ; ntdll_1.7776DF5C
777E0EB4    33DB                XOR EBX,EBX
777E0EB6    53                  PUSH EBX
777E0EB7    6A 01               PUSH 0x1
777E0EB9    8D45 E7             LEA EAX,DWORD PTR SS:[EBP-0x19]
777E0EBC    50                  PUSH EAX
777E0EBD    6A 11               PUSH 0x11
777E0EBF    6A FE               PUSH -0x2
777E0EC1    5E                  POP ESI
777E0EC2    56                  PUSH ESI
777E0EC3    E8 50EDF7FF         CALL 7775FC18                            ; ntdll_1.ZwQueryInformationThread
777E0EC8    3BC3                CMP EAX,EBX
777E0ECA    7C 1C               JL SHORT 777E0EE8                        ; ntdll_1.777E0EE8
777E0ECC    385D E7             CMP BYTE PTR SS:[EBP-0x19],BL
777E0ECF    75 17               JNZ SHORT 777E0EE8                       ; ntdll_1.777E0EE8
777E0ED1    895D FC             MOV DWORD PTR SS:[EBP-0x4],EBX
777E0ED4    CC                  INT3
777E0ED5    8975 FC             MOV DWORD PTR SS:[EBP-0x4],ESI
777E0ED8    EB 0E               JMP SHORT 777E0EE8                       ; ntdll_1.777E0EE8
777E0EDA    33C0                XOR EAX,EAX
777E0EDC    40                  INC EAX
777E0EDD    C3                  RETN
777E0EDE    8B65 E8             MOV ESP,DWORD PTR SS:[EBP-0x18]
777E0EE1    C745 FC FEFFFFFF    MOV DWORD PTR SS:[EBP-0x4],-0x2
777E0EE8    E8 B4D0F8FF         CALL 7776DFA1                            ; ntdll_1.7776DFA1
777E0EED    C3                  RETN
777E0EEE    90                  NOP

00320000    CC                  INT3
00320001    68 7F237977         PUSH 0x7779237F
00320006    C3                  RETN

After the traced program crushes!
Any idea how to handle such stuff? And any idea why those things happens?
 

Edited by CodeExplorer
Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...