Entwickler-Ecke

Windows API - SpeedGear


SAiBOT - Fr 21.08.09 02:02
Titel: SpeedGear
Ich habe ein Tool names "SpeedGear" gefunden (http://www.softcows.com/speed_gear.htm) mit dem es möglich ist Prozesse zu verlangsamen/beschleunigen. Das will ich nun nachbauen :P .
Erst dachte ich es seien nur API Hooks, also habe ich mich rangemacht und habe folgende Funktionen gehookt:

Das funktioniert nun mit Ausnahme von wenigen Prozessen auch sehr gut!
Alle Ausnahme Prozesse mit denen ich rumprobiert habe, sind mit SpeedGear allerdings auch veränderbar!?

In der "whatsnew.txt" steht:
Zitat:
Version 5.0
[+] Enhanced speeder kernel arithmetic
[+] New "linearity-accelerate" technology


In der "tips.txt" steht:
Zitat:
Speed Gear only changes the CPU speed! ...


Dann habe ich bei Google noch diesen Text gefunden:
Zitat:
Speed Gear's working theory is brilliant: Speed Gear enters computer system ring 0, which is also known as Kernel Mode. Then changes the system time intermit. Once system time intermit is changed, all games' speed will be changed. For example: It cheats game thinks two seconds is only one second, so the characters in game will run twice fast.

Weiss jemand was genaueres ?

MfG


delfiphan - Fr 21.08.09 16:41

Die Zeit wird vom Kernel ständig nachgeführt. Ich denke mal das passiert bei einem (hardware) timer interrupt. Es gibt ein Chip, der in gewissen (konfigurierbaren) Intervallen dem Prozessor einen tick gibt. Dann wird dort ein Hardware Interrupt ausgelöst. Dort wird dann z.B. der Scheduler fürs Multitasking ausgeführt, welcher dafür sorgt, dass nach dem Beenden des Interrupts die Kontrolle ggf. an den nächsten Prozess geht.
Du kannst wohl also entweder das Intervall halbieren, oder die Zeit doppelt inkrementieren. Berücksichtigen musst du vermutlich auch noch, dass es alle x Minuten eine synchronisation mit der Hardware-Uhr gibt. Die Details auszuarbeiten wird wohl nicht so ganz einfach..


SAiBOT - Fr 21.08.09 17:24

Da die Änderungen nicht global auftreten, sondern Prozess spezifisch, gehe ich davon aus, dass des Rätsels Lösung irgendwo im Prozess-Objekt steckt?

zB. in einer vergleichbaren Struktur, wie dieser hier:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
_KERNEL_USER_TIMES = record
    CreateTime: LARGE_INTEGER;
    ExitTime: LARGE_INTEGER;
    KernelTime: LARGE_INTEGER;
    UserTime: LARGE_INTEGER;
  end;


Die abgefragt/geändert durch folgende Funktionen wird:
NtQueryInformationProcess/NtSetInformationProcess

:?!?:


delfiphan - Fr 21.08.09 17:31

Vielleicht reicht es ja für deine Zwecke, wenn du QueryPerformanceFrequency hookst (Edit: Ach so, das hast du schon gemacht).
Ich kann auch nur spekulieren.


SAiBOT - So 23.08.09 12:32

Mein Denkansatz war völlig falsch, dies ist der richtige Weg:

Per Treiber zB. WinIo¹ (Nur nötig ab Win2000, bis XP gibt es sogar noch API Funktionen dafür!) die I/O Ports des PIT's² ansteuert und den PIT so programmieren!

Wie genau das alles nun funktioniert... ich weiß es noch nicht :nixweiss:

Hier die I/O Ports:

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
-------------------------------------------------------------------------------
0040-005F ---- PIT (Programmable Interrupt Timer 8253, 8254)
  XT & AT uses 40-43 PS/2 uses 40, 42,43,44, 47

0040 r/w PIT counter 0, counter divisor (XT, AT, PS/2)
0041 r/w PIT counter 1, RAM refresh counter (XT, AT)
0042 r/w PIT counter 2, cassette & speaker (XT, AT, PS/2)

0043 r/w PIT mode port, control word register for counters 0-2
  bit 7-6 = 00 counter 0 select
    = 01 counter 1 select (not PS/2)
    = 10 counter 2 select
  bit 5-4 = 00 counter latch command
    = 01 read/write counter bits 0-7 only
    = 10 read/write counter bits 8-15 only
    = 11 read/write counter bits 0-7 first, then 8-15
  bit 3-1 = 000 mode 0 select
    = 001 mode 1 select - programmable one shot
    = x10 mode 2 select - rate generator
    = x11 mode 3 select - square wave generator
    = 100 mode 4 select - software triggered strobe
    = 101 mode 5 select - hardware triggered strobe
  bit 0 = 0 binary counter 16 bits
    = 1 BCD counter

0044 r/w PIT counter 3 (PS/2, EISA)
  used as fail-safe timer. generates an NMI on time out.
  for user generated NMI see at 0462.

0047 w PIT control word register counter 3 (PS/2, EISA)
  bit 7-6 = 00 counter 3 select
    = 01 reserved
    = 10 reserved
    = 11 reserved
  bit 5-4 = 00 counter latch command counter 3
    = 01 read/write counter bits 0-7 only
    = 1x reserved
  bit 3-0 = 00

0048 EISA
0049 8254 timer 2, not used (counter 1)
004A EISA programmable interval timer 2
004B EISA programmable interval timer 2
-------------------------------------------------------------------------------


Edit: @delfiphan: Deine Vermutung traf es ziemlich genau :zustimm:
_________________
1. The WinIo library allows 32-bit Windows applications to directly access I/O ports and physical memory. It bypasses Windows protection mechanisms by using a combination of a kernel-mode device driver and several low-level programming techniques.
(http://www.internals.com/utilities_main.htm)

2. Programmable Interrupt Timer.
(http://toasteros.web17.webbpro.de/sites/tutorials/PIT.pdf)
(http://www4.informatik.uni-erlangen.de/Lehre/WS07/V_BS//Uebungen/oostubs/web/aufgaben/aufgabe5/timer.shtml)


delfiphan - So 23.08.09 18:46

Codebeispiele: http://wiki.osdev.org/Programmable_Interval_Timer


SAiBOT - Fr 28.08.09 10:10

Ok ich habs, die PIT-Technik ist veraltet, aber wer sich dafür interessiert:


C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
#include "stdafx.h"
#include "ntport.h"

#define FREE_INT_NO 5

void Ring0()
{   //ÔÚWindows9xϽøÈëring0ºó½øÐеIJÙ×÷
   __asm
   {
      cli
      mov al,34h
      out 43h,al   //дÈë8253¿ØÖƼĴæÆ÷£¬ÉèÖÃд0ºÅ¶¨Ê±Æ÷
      mov ax,bx   
      out 40h,al   //д¶¨Ê±ÖµµÍλ
      mov al,ah
      out 40h,al   //д¶¨Ê±Öµ¸ßλ
      sti
      iretd;
   }
}

void SetClockNT(int freq)
{   //NTϵIJÙ×÷
   //ÕâÀïʹÓÃÁËNT Port¿â
   Outport(0x43,0x34);   //дÈë8253¿ØÖƼĴæÆ÷£¬ÉèÖÃд0ºÅ¶¨Ê±Æ÷
   Outport(0x40,freq&0xff);   //д¶¨Ê±ÖµµÍλ
   Outport(0x40,(freq>>8)&0xff);   //д¶¨Ê±Öµ¸ßλ
}

void SetClock9x(int freq)
{
   union Function_Pointer
   {
      void (*pointer)();
      char bytes[sizeof(void *)];
   }OldIntAddress,NewIntAddress;

   int IDTAddress;      //IDT±í»ùµØÖ·
   int IDTItemAddress;   //ÒªÐ޸ĵÄÖжÏÃÅËùÔÚµØÖ·
   char *Pointer;   //ÒªÐ޸ĵÄÖжÏÃÅËùÔÚµØÖ·£¬Ö¸ÕëÐÎʽ

   __asm
   {
      push eax
      sidt [esp-2]
      pop eax
      mov IDTAddress,eax   //µÃµ½IDT±í»ùµØÖ·
   }
   
   IDTItemAddress=FREE_INT_NO*8+IDTAddress;
   Pointer=(char *)IDTItemAddress;
   NewIntAddress.pointer=Ring0;
   
   OldIntAddress.bytes[0]=Pointer[0];
   OldIntAddress.bytes[1]=Pointer[1];
   OldIntAddress.bytes[2]=Pointer[6];
   OldIntAddress.bytes[3]=Pointer[7];   //±£´æ¾ÉµÄÖжÏÃÅ

   Pointer[0]=NewIntAddress.bytes[0];
   Pointer[1]=NewIntAddress.bytes[1];
   Pointer[6]=NewIntAddress.bytes[2];
   Pointer[7]=NewIntAddress.bytes[3]; //ÉèÖÃеÄÖжÏÃÅ
   
   __asm
   {
      mov ebx,freq
      int FREE_INT_NO         //²úÉúÖжϣ¬½øÈëring0
   }

   Pointer[0]=OldIntAddress.bytes[0];
   Pointer[1]=OldIntAddress.bytes[1];
   Pointer[6]=OldIntAddress.bytes[2];
   Pointer[7]=OldIntAddress.bytes[3];   //»Ö¸´¾ÉµÄÖжÏÃÅ
}


Eleganter ist es natürlich, das ganze nicht Systemweit zu machen, dafür sind spezielle QueryPerformanceCounter/GetTickCount Hooktechniken nötig!

Vielleicht release ich bald eine SpeedGear ebenwürdige Freeware :wave: