Key Counter

A open source key stroke counter for windows

EDIT: An upgrade.
The name for the program is currently, Keycounter. Hosted in my repository. Written in C++. I use g++ to compile it. Here is the compiled binaries. Keycumcounter only count the total keystroke+mouse clicks, but save log in a human readable way.

The program count every keystroke, mouse clicks and how far the mouse have moved(in pixels, rounded). Save the data each hour as a human-not-readable text file.
Why would it be useful if it's not human-readable(unless you have a hash table of Virtual-Key Codes and read HEX like decimals)? Because the data are suppose to be analyzed by some other program. I might write one, or not. For example, write a script with php that analyze the data and store it in a mysql database. Then someone can use Google Chart API to plot the data in some way.

The file structure is so easy, anyone can make use of it.
Example structure:

2009,2,28,14,1|3A,DE|16,FF|334,

Structure of the file:
Each line is a entry. Values separated by a comma.
Year, Month, Date, Hour, Rest of the data
The time is UTC time.

The rest of the data are keystroke counts, stored as a string represent a hex value.
1|3A means the 0x01 key(which is a mouse click) was stroked 58 times. Everything according to the Virtual-Key Codes.
There is a special one don't have anything to do Virtual-Key Code. That's FF. FF|334 means the mouse have moved a total distance of 820 pixels(a very rough estimate).

Note, sum of every keystroke count doesn't mean the total keystroke you have done. For example. The left ctrl count as 2 separate keystrokes. A left keyboard stroke and a left ctrl stroke.

Features:

  • Low CPU usage. 0% on my EEEPC 1000H.
  • Theoretically, the key capture rate is 100%. In practice, might be 99.9999999%
  • Low memory usage. Well it's not that low, over 1MB.
  • Portable log file

Credits:

Alternatives:
Whatpulse, Keystroke Counter Tool by Tim Koschützki, KeyCounter by skwire and KeyCounter.

Source. If you can't be bothered to check the repository.

#include <cstdio>
#include <ctime>
#include <cstdlib>
#include <windows.h>
 
typedef short (*KeyState)(int);
unsigned int a[256];
int z[4];
//This is from http://bbs.emath.ac.cn/viewthread.php?tid=1207&page=6&fromuid=310#pid16108
//by  gxqcn, http://emath.ac.cn
unsigned long isqrt( unsigned long n ){
    unsigned long t;
    unsigned long ret = 0;
 
    #define SQRT_CORE(x)        \
        t = ret + (1UL<<(x));   \
        ret >>= 1;              \
        if ( n >= t )           \
        {                       \
            n -= t;             \
            ret += (1UL<<(x));  \
        }
 
    SQRT_CORE(30);
    SQRT_CORE(28);
    SQRT_CORE(26);
    SQRT_CORE(24);
    SQRT_CORE(22);
    SQRT_CORE(20);
    SQRT_CORE(18);
    SQRT_CORE(16);
    SQRT_CORE(14);
    SQRT_CORE(12);
    SQRT_CORE(10);
    SQRT_CORE(8);
    SQRT_CORE(6);
    SQRT_CORE(4);
    SQRT_CORE(2);
    SQRT_CORE(0);
 
    #undef SQRT_CORE
 
    return ret;
}
inline int press(int i){
	return (GetAsyncKeyState(i) & 0x8000);
}
void savetmp(void){
	int i=0;
	if(a[0]!=0){
		FILE * pFile;
		pFile = fopen ("tmp.txt","w");
		if(pFile!=NULL){
			fprintf(pFile,"%d %d %d %d ",z[3],z[2],z[1],z[0]);
			for(i=1;i<256;i++){
				if(a[i]!=0){
					fprintf(pFile,"%d %d ",i,a[i]);
				}
			}
			fclose (pFile);
	  }
	}
}
inline void savelog(void){
	if(a[0]!=0 || a[255]>0){
		FILE * pFile;
		pFile = fopen ("log.txt","a");
		if(pFile!=NULL){
			fprintf(pFile,"%d,%d,%d,%d,",z[3]+1900,z[2]+1,z[1],z[0]);
			for(int i=1;i<256;i++){
				if(a[i]!=0){
					fprintf(pFile,"%X|%X,",i,a[i]);
				}
			}
			fprintf(pFile,"\n");
			fclose (pFile);
	  }
	}
 
};
inline void readtmp(void){
	FILE * pFile;
	pFile = fopen ("tmp.txt","r");
	time_t rawtime;
	tm* ptm;
	time(&rawtime);
	ptm = gmtime(&rawtime);
	int i=0;
	if (pFile!=NULL){
		fscanf (pFile, "%d %d %d %d", &z[3],&z[2],&z[1],&z[0]);
		while (!feof(pFile)) {
			  fscanf(pFile, "%d", &i);
			  fscanf(pFile, "%d", &a[i]);
		}
		a[0] = 1;
		fclose (pFile);
		if(z[0] != ptm->tm_hour || z[1] != ptm->tm_mday
		|| z[2] != ptm->tm_mon || z[3] != ptm->tm_year){
			savelog();
			z[0] = ptm->tm_hour;
			z[1] = ptm->tm_mday;
			z[2] = ptm->tm_mon;
			z[3] = ptm->tm_year;
			for(int i=0;i<256;++i) a[i]=0;
		}
	}else{
		z[0] = ptm->tm_hour;
		z[1] = ptm->tm_mday;
		z[2] = ptm->tm_mon;
		z[3] = ptm->tm_year;
	}
};
 
int main(int argc, char * argv[]){
	POINT pt;
	GetCursorPos(&pt);
	const int stime =40; 
	int i=0,o,clx=pt.x,cly=pt.y;
	//initialize variables
	bool b[256];
	for(i=0;i<256;++i){a[i]=0;b[i]=false;}
	//Read tmp file
	readtmp();
	//ini time
	time_t rawtime;
	tm * ptm;
 
	atexit(savetmp);
	while(1){
		//Save log if hour is different
		time(&rawtime);
		ptm = gmtime(&rawtime);
		if(z[0] != ptm->tm_hour){
			savelog();
			z[0] = ptm->tm_hour;
			z[1] = ptm->tm_mday;
			z[2] = ptm->tm_mon;
			z[3] = ptm->tm_year;
			for(i=0;i<256;++i) a[i]=0;
		}
 
		//keystorke counter
		for(i=1;i<255;++i){
			o = press(i);
			if(!b[i] && o){
				b[i]=true;
			}else if(b[i] && o==0){
				b[i]=false;
				++a[i];
				++a[0];
				//std::cout<<i<<"-";
			}
		}
		//mouse distant tracker
		GetCursorPos(&pt);
		clx -= pt.x;
		cly -= pt.y;
		a[255]+=isqrt((unsigned int)(clx*clx+cly*cly));
		clx=pt.x;
		cly=pt.y;
		Sleep(stime);
	}
   return 0;
}
Honey Pot that kill bots