is it possible to change chat text color ?
i tried to search but i didn't find anything.
i tried to search but i didn't find anything.
I wrote code to do it a long time ago. The first way I did it was to perform client edits via WriteProcessMemory through a secondary program. That would work for all chat types except for All Chat right now due to how the client code is setup.Quote:
is it possible to change chat text color ?
i tried to search but i didn't find anything.
007A37C7 . 8078 04 00 CMP BYTE PTR DS:[EAX+4],0 007A37CB .^ 0F84 B2FEFFFF JE sro_clie.007A3683 007A37D1 > BD FEFF9FFF MOV EBP,FF9FFFFE ; Case A of switch 007A37B3 007A37D6 . EB 34 JMP SHORT sro_clie.007A380C 007A37D8 > BD 00FFFFFF MOV EBP,-100 ; Case 6 of switch 007A37B3 007A37DD . EB 2D JMP SHORT sro_clie.007A380C 007A37DF > BD C3AEFFFF MOV EBP,FFFFAEC3 ; Cases 3,7 of switch 007A37B3 007A37E4 . EB 26 JMP SHORT sro_clie.007A380C 007A37E6 > BD 41B5FFFF MOV EBP,FFFFB541 ; Case 5 of switch 007A37B3 007A37EB . EB 1F JMP SHORT sro_clie.007A380C 007A37ED > BD 73F5C2FF MOV EBP,FFC2F573 ; Case B of switch 007A37B3 007A37F2 . EB 18 JMP SHORT sro_clie.007A380C 007A37F4 > BD D0FF9AFF MOV EBP,FF9AFFD0 ; Case 4 of switch 007A37B3 007A37F9 . EB 11 JMP SHORT sro_clie.007A380C 007A37FB > BD F8ADDBFF MOV EBP,FFDBADF8 ; Case D of switch 007A37B3 007A3800 . EB 0A JMP SHORT sro_clie.007A380C 007A3802 > BD FFC764FF MOV EBP,FF64C7FF ; Case 10 of switch 007A37B3 007A3807 . EB 03 JMP SHORT sro_clie.007A380C 007A3809 > 83CD FF OR EBP,FFFFFFFF ; Default case of switch 007A37B3 007A380C > B8 07000000 MOV EAX,7
#include "cProcess.h"
#include <windows.h>
#include <math.h>
#include <stdio.h>
#include <fstream>
#include <sstream>
// Main program window
HWND hwnd = 0;
// Array of addresses to make for easier access
unsigned long addrs[6];
unsigned long defs[6];
unsigned long curs[6];
HWND hwnds[6];
HWND preview[6];
// Whisper
HWND lblWhisper = 0;
HWND editWhisper = 0;
HWND btnDefWhisper = 0;
unsigned long addrWhisper = 0x7A37D1;
unsigned long defColorWhisper = 0xFF9FFFFE;
// Global
HWND lblGlobal = 0;
HWND editGlobal = 0;
HWND btnDefGlobal = 0;
unsigned long addrGlobal = 0x7A37D8;
unsigned long defColorGlobal = 0xFFFFFF00;
// Notice
HWND lblNotice = 0;
HWND editNotice = 0;
HWND btnDefNotice = 0;
unsigned long addrNotice = 0x7A37DF;
unsigned long defColorNotice = 0xFFFFAEC3;
// Guild
HWND lblGuild = 0;
HWND editGuild = 0;
HWND btnDefGuild = 0;
unsigned long addrGuild = 0x7A37E6;
unsigned long defColorGuild = 0xFFFFB541;
// Union
HWND lblUnion = 0;
HWND editUnion = 0;
HWND btnDefUnion = 0;
unsigned long addrUnion = 0x7A37ED;
unsigned long defColorUnion = 0xFFC2F573;
// Party
HWND lblParty = 0;
HWND editParty = 0;
HWND btnDefParty = 0;
unsigned long addrParty = 0x7A37F4;
unsigned long defColorParty = 0xFF9AFFD0;
// Set chat color button
HWND btnColorize = 0;
HWND btnPerm = 0;
// Get the current color a chat type
HWND btnGetWhisper = 0;
HWND btnGetGlobal = 0;
HWND btnGetNotice = 0;
HWND btnGetGuild = 0;
HWND btnGetUnion = 0;
HWND btnGetParty = 0;
HWND btnGetAll = 0;
// Defines for the button messages
#define BTN_DEF_COLOR_WHISPER 1
#define BTN_DEF_COLOR_GLOBAL 2
#define BTN_DEF_COLOR_NOTICE 3
#define BTN_DEF_COLOR_GUILD 4
#define BTN_DEF_COLOR_UNION 5
#define BTN_DEF_COLOR_PARTY 6
#define BTN_DEF_COLOR_ALL 7
#define BTN_COLORIZE_ON 8
#define BTN_COLORIZE_GET 9
#define BTN_PREVIEW_COLOR_WHSIPER 11
#define BTN_PREVIEW_COLOR_GLOBAL 12
#define BTN_PREVIEW_COLOR_NOTICE 13
#define BTN_PREVIEW_COLOR_GUILD 14
#define BTN_PREVIEW_COLOR_UNION 15
#define BTN_PREVIEW_COLOR_PARTY 16
#define BTN_PREVIEW_COLOR_ALL 17
#define BTN_GET_COLOR_WHISPER 18
#define BTN_GET_COLOR_GLOBAL 19
#define BTN_GET_COLOR_NOTICE 20
#define BTN_GET_COLOR_GUILD 21
#define BTN_GET_COLOR_UNION 22
#define BTN_GET_COLOR_PARTY 23
#define BTN_GET_COLOR_ALL 24
// cProcess class object used to make working with processes a lot easier ;)
cProcess sro;
unsigned long CaptionToHex(HWND h)
{
// Store the actual hex string
unsigned char data[5] = {0};
// Store the ascii-hex string
char temp[32] = {0};
// The alpha should be FF, opaque (don't think font supports alpha)
temp[0] = 'F';
temp[1] = 'F';
// Get the desired window's color
GetWindowText(h, temp + 2, 7);
// Store the final value
int value = 0;
// We have to reverse the digits for hex form
int index = 3;
// Loop though all tuples of characters
for(int y = 0; y < 8; y += 2)
{
int tuple1 = 15, tuple2 = 15;
// Store current character
unsigned char cur = temp[y];
// If it's A - F, convert it to 10 - 15
if(cur >= 'A' && cur <= 'F')
tuple1 = cur - 'A' + 10;
// If it's 0 - 9, convert it to 0 - 9
else if(cur >= '0' && cur <= '9')
tuple1 = cur - '0';
// Store current character
cur = temp[y + 1];
// If it's A - F, convert it to 10 - 15
if(cur >= 'A' && cur <= 'F')
tuple2 = cur - 'A' + 10;
// If it's 0 - 9, convert it to 0 - 9
else if(cur >= '0' && cur <= '9')
tuple2 = cur - '0';
// Convert the two numbers into a unsigned character
value = tuple2 + 16 * tuple1;
// Store the final color value for this color component
data[index--] = value;
}
// Store a pointer of the final color value as a unsigned long
unsigned long* ptr = (unsigned long*)data;
return *ptr;
}
void DrawColorPreview(HDC hdc, int x, int y, unsigned long color)
{
color = color & 0x00FFFFFF;
HBRUSH NewBrush = CreateSolidBrush(RGB(GetBValue(color),GetGValue(color),GetRValue(color)));
SelectObject(hdc, NewBrush);
Rectangle(hdc, x, y, x + 18, y + 18);
DeleteObject(NewBrush);
}
// Get the current chat colors
void GetCurrentChatColors(int x)
{
// Array to hold the data
unsigned char buffer[5] = {0};
// Read in the memory location
if(!sro.ReadArray(addrs[x], buffer, 5))
{
MessageBox(hwnd, "Memory address could not be read.", "Fatal Error", MB_OK | MB_ICONERROR);
return;
}
char temp[256] = {0};
// Store the color components into the array
_snprintf(temp, 255, "%.2X%.2X%.2X", buffer[3], buffer[2], buffer[1]);
// Write the entire RGB color string to the edit box
SetWindowText(hwnds[x], temp);
}
void GeneratePreview(HWND btn, int button)
{
curs[button] = CaptionToHex(btn);
RECT r;
r.left = 284;
r.right = r.left + 18;
r.top = 10 + button * 30;
r.bottom = r.top + 18;
InvalidateRect(hwnd, &r, true);
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT Ps;
HDC hdc;
switch(msg)
{
case WM_PAINT:
{
hdc = BeginPaint(hwnd, &Ps);
for(int x = 0; x < 6; ++x)
DrawColorPreview(hdc, 284, 10 + x * 30, curs[x]);
EndPaint(hwnd, &Ps);
}
break;
case WM_COMMAND:
{
if(LOWORD(wParam) == BTN_COLORIZE_ON)
{
// Loop though all chat colors
for(int x = 0; x < 6; ++x)
{
int ptr = CaptionToHex(hwnds[x]);
// Write the color value to memory
sro.Write(addrs[x] + 1, ptr);
}
}
else if(LOWORD(wParam) >= BTN_GET_COLOR_WHISPER && LOWORD(wParam) <= BTN_GET_COLOR_ALL)
{
int button = LOWORD(wParam) - BTN_GET_COLOR_WHISPER;
GetCurrentChatColors(button);
GeneratePreview(hwnds[button], button);
}
else if(LOWORD(wParam) >= BTN_DEF_COLOR_WHISPER && LOWORD(wParam) <= BTN_DEF_COLOR_ALL)
{
// Save the real button #
int button = LOWORD(wParam) - 1;
// Buffer to hold the default value
char temp[256] = {0};
// Save the default value to the buffer
sprintf(temp, "%X", defs[button]);
// Write the default value to the window
SetWindowText(hwnds[button], temp + 2);
GeneratePreview(hwnds[button], button);
}
else if(LOWORD(wParam) >= BTN_PREVIEW_COLOR_WHSIPER && LOWORD(wParam) <= LOWORD(wParam))
{
int button = LOWORD(wParam) - BTN_PREVIEW_COLOR_WHSIPER;
GeneratePreview(hwnds[button], button);
}
}
break;
case WM_CLOSE:
{
DestroyWindow(hwnd);
}
break;
case WM_DESTROY:
{
PostQuitMessage(0);
}
break;
default:
{
return DefWindowProc(hwnd, msg, wParam, lParam);
}
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc = {0};
MSG msg = {0};
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = GetModuleHandle(0);
wc.hIcon = LoadIcon(NULL, MAKEINTRESOURCE(101));
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+6);
wc.lpszMenuName = NULL;
wc.lpszClassName = "SROChatColor";
wc.hIconSm = (HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(101), IMAGE_ICON, 16, 16, 0);;
// Win32 stuff to create the program
if(!RegisterClassEx(&wc))
{
MessageBox(NULL, "Window Registration Failed!", "Error!", MB_ICONERROR | MB_OK);
return 0;
}
// Create main window
hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, "SROChatColor", "Silkroad Chat Color - By: Drew Benton", WS_OVERLAPPEDWINDOW ^ WS_MAXIMIZEBOX ^ WS_THICKFRAME, CW_USEDEFAULT, CW_USEDEFAULT, 480, 290, NULL, NULL, hInstance, NULL);
if(hwnd == NULL)
{
MessageBox(NULL, "Window Creation Failed!", "Error!", MB_ICONERROR | MB_OK);
return 0;
}
// Try to open the sro client
if(!sro.Open("sro_client.exe"))
{
MessageBox(0, "Cannot find your sro_client.exe", "Error!", MB_ICONERROR | MB_OK);
return -1;
}
// Store the addresses
addrs[0] = addrWhisper;
addrs[1] = addrGlobal;
addrs[2] = addrNotice;
addrs[3] = addrGuild;
addrs[4] = addrUnion;
addrs[5] = addrParty;
//addrs[6] = addrAll;
// Store default colors
defs[0] = defColorWhisper;
defs[1] = defColorGlobal;
defs[2] = defColorNotice;
defs[3] = defColorGuild;
defs[4] = defColorUnion;
defs[5] = defColorParty;
//defs[6] = defColorAll;
// Store defaults
for(int x = 0; x < 6; ++x)
curs[x] = defs[x];
// Coords of controls
int X = 0; int Y = 0; int W = 0; int H = 0;
// Whisper
X = 10; Y = 10; W = 125; H = 20;
lblWhisper = CreateWindowEx(0, "STATIC", "Whisper Chat: ", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, NULL, NULL, 0);
X = 110;
editWhisper = CreateWindowEx(0, "EDIT", "", WS_CHILD | WS_VISIBLE | WS_BORDER, X, Y, W, H, hwnd, NULL, NULL, 0);
X = 312; W = 70;
btnDefWhisper = CreateWindowEx(0, "BUTTON", "Default", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_DEF_COLOR_WHISPER, NULL, 0);
X = 392;
btnGetWhisper = CreateWindowEx(0, "BUTTON", "Current", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_GET_COLOR_WHISPER, NULL, 0);
X = 250; W = 24;
preview[0] = CreateWindowEx(0, "BUTTON", "?", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_PREVIEW_COLOR_WHSIPER, NULL, 0);
// Global
X = 10; Y = 40; W = 125; H = 20;
lblGlobal = CreateWindowEx(0, "STATIC", "Global Chat: ", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, NULL, NULL, 0);
X = 110;
editGlobal = CreateWindowEx(0, "EDIT", "", WS_CHILD | WS_VISIBLE | WS_BORDER, X, Y, W, H, hwnd, NULL, NULL, 0);
X = 312; W = 70;
btnDefWhisper = CreateWindowEx(0, "BUTTON", "Default", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_DEF_COLOR_GLOBAL, NULL, 0);
X = 392;
btnGetGlobal = CreateWindowEx(0, "BUTTON", "Current", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_GET_COLOR_GLOBAL, NULL, 0);
X = 250; W = 24;
preview[1] = CreateWindowEx(0, "BUTTON", "?", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_PREVIEW_COLOR_GLOBAL, NULL, 0);
// Notice
X = 10; Y = 70; W = 125; H = 20;
lblNotice = CreateWindowEx(0, "STATIC", "Notice Chat: ", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, NULL, NULL, 0);
X = 110;
editNotice = CreateWindowEx(0, "EDIT", "", WS_CHILD | WS_VISIBLE | WS_BORDER, X, Y, W, H, hwnd, NULL, NULL, 0);
X = 312; W = 70;
btnDefNotice = CreateWindowEx(0, "BUTTON", "Default", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_DEF_COLOR_NOTICE, NULL, 0);
X = 392;
btnGetNotice = CreateWindowEx(0, "BUTTON", "Current", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_GET_COLOR_NOTICE, NULL, 0);
X = 250; W = 24;
preview[2] = CreateWindowEx(0, "BUTTON", "?", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_PREVIEW_COLOR_NOTICE, NULL, 0);
// Guild
X = 10; Y = 100; W = 125; H = 20;
lblGuild = CreateWindowEx(0, "STATIC", "Guild Chat: ", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, NULL, NULL, 0);
X = 110;
editGuild = CreateWindowEx(0, "EDIT", "", WS_CHILD | WS_VISIBLE | WS_BORDER, X, Y, W, H, hwnd, NULL, NULL, 0);
X = 312; W = 70;
btnDefGuild = CreateWindowEx(0, "BUTTON", "Default", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_DEF_COLOR_GUILD, NULL, 0);
X = 392;
btnGetGuild = CreateWindowEx(0, "BUTTON", "Current", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_GET_COLOR_GUILD, NULL, 0);
X = 250; W = 24;
preview[3] = CreateWindowEx(0, "BUTTON", "?", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_PREVIEW_COLOR_GUILD, NULL, 0);
// Union
X = 10; Y = 130; W = 125; H = 20;
lblUnion = CreateWindowEx(0, "STATIC", "Union Chat: ", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, NULL, NULL, 0);
X = 110;
editUnion = CreateWindowEx(0, "EDIT", "", WS_CHILD | WS_VISIBLE | WS_BORDER, X, Y, W, H, hwnd, NULL, NULL, 0);
X = 312; W = 70;
btnDefUnion = CreateWindowEx(0, "BUTTON", "Default", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_DEF_COLOR_UNION, NULL, 0);
X = 392;
btnGetUnion = CreateWindowEx(0, "BUTTON", "Current", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_GET_COLOR_UNION, NULL, 0);
X = 250; W = 24;
preview[4] = CreateWindowEx(0, "BUTTON", "?", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_PREVIEW_COLOR_UNION, NULL, 0);
// Party
X = 10; Y = 160; W = 125; H = 20;
lblParty = CreateWindowEx(0, "STATIC", "Party Chat: ", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, NULL, NULL, 0);
X = 110;
editParty = CreateWindowEx(0, "EDIT", "", WS_CHILD | WS_VISIBLE | WS_BORDER, X, Y, W, H, hwnd, NULL, NULL, 0);
X = 312; W = 70;
btnDefParty = CreateWindowEx(0, "BUTTON", "Default", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_DEF_COLOR_PARTY, NULL, 0);
X = 392;
btnGetParty = CreateWindowEx(0, "BUTTON", "Current", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_GET_COLOR_PARTY, NULL, 0);
X = 250; W = 24;
preview[5] = CreateWindowEx(0, "BUTTON", "?", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_PREVIEW_COLOR_PARTY, NULL, 0);
// Set chat color button
X = 312; Y = 220; W = 150; H = 30;
btnColorize = CreateWindowEx(0, "BUTTON", "Change Chat Colors!", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_COLORIZE_ON, NULL, 0);
// Store the edit handles to make life easier
hwnds[0] = editWhisper;
hwnds[1] = editGlobal;
hwnds[2] = editNotice;
hwnds[3] = editGuild;
hwnds[4] = editUnion;
hwnds[5] = editParty;
//hwnds[6] = editAll;
// Start the program out by getting the current colors stored in memory
for(int x = 0; x < 6; ++x)
GetCurrentChatColors(x);
// Reactivate this program
SetForegroundWindow(hwnd);
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while(msg.message != WM_QUIT)
{
if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
WaitMessage();
}
}
return 0;
}
/*****************************************************************************/ /* cProcess /* By; Drew Benton /* /* This class was written to make working with processes a lot easier. With /* this class, the user will be able to open a process and read from memory /* or write to memory. It is designed with simplicty and ease of use in mind. /* If you have any questions or comments e-mail me at [Only registered and activated users can see links. Click Here To Register...] /* /******************************************************************************/ #ifndef CPROCESS_H_ #define CPROCESS_H_ #include <windows.h> #include <tlhelp32.h> #include <string> // Display the current error to the user via a message box void ShowError(LPTSTR lpszFunction); // The callback function used for processing HWNDs BOOL CALLBACK enumCallbackFunc(HWND hwnd, LPARAM lparam); class cProcess { public: // The process entry for the process PROCESSENTRY32 pe32; // Handle to the process HANDLE handle; // One of the HWNDs associated with the process HWND hwnd; public: /******************************************************************************************/ // MEMBER FUNCTIONS REFERENCE // /******************************************************************************************/ /* // This is the constructor for the cProcess class. /* cProcess(); /* // This is the destructor for the cProcess class. /* ~cProcess(); /* /* // This function will open the desired executable's process. /* bool Open( /* const std::string& exeName, /* bool lookForWindow = true, /* DWORD dwDesiredAccess = PROCESS_ALL_ACCESS, /* BOOL bInhereitHandle = FALSE); /* /* // This function will close the opened process. /* void Close(); /* /* // This function will read exactly 'one' unit of the passed datatype specified. /* template <class type> /* bool Read( /* unsigned long address, /* type& buffer); /* /* // This function will read exactly sizeOfBuffer units of the /* // passed datatype specified or until 'stopValue' is read. /* template <class type> /* bool ReadArray( /* unsigned long address, /* type* buffer, /* int sizeOfBuffer, /* type stopValue); /* /* // This function will read exactly sizeOfBuffer units of the passed datatype specified. /* template <class type> /* bool ReadArray( /* unsigned long address, /* type* buffer, /* int sizeOfBuffer); /* /* // This function will write the passed variable to memory. /* template <class type> /* bool Write( /* unsigned long address, /* type& buffer); /* /* // This function will write the buffer of passed datatype /* // specified into the memory address specificed. /* template <class type> /* bool WriteArray( /* unsigned long address, /* type* buffer, /* int sizeOfBuffer); /*****************************************************************************************/ /******************************************************************************************/ // MEMBER FUNCTION IMPLEMENTATIONS // /******************************************************************************************/ /**************************************************************************/ /* Function: cProcess */ /* */ /* Description: This is the constructor for the cProcess class. */ /* */ /* Return Type: None */ /* */ /* Parameters: None */ /**************************************************************************/ cProcess::cProcess() { // Simply clear all the memory of our variables handle = 0; hwnd = 0; ZeroMemory(&pe32, sizeof(PROCESSENTRY32)); // This is a must in Win32 for this struct! pe32.dwSize = sizeof(PROCESSENTRY32); } /**************************************************************************/ /* Function: cProcess */ /* */ /* Description: This is the destructor for the cProcess class. */ /* */ /* Return Type: None */ /* */ /* Parameters: None */ /**************************************************************************/ cProcess::~cProcess() { // Call the Close function on object destruction Close(); } /**************************************************************************/ /* Function: Open */ /* */ /* Description: This function will open the desired executable's process.*/ /* Since there could be many processes with the same executable, a */ /* feature exsits to help the user select the correct window. The hwnd is*/ /* activated and the user replies to a message box as to if it is correct*/ /* */ /* Return Type: bool: true = success, false = failure */ /* */ /* Parameters: */ /* const string& exeName - This parameter is the executable file of */ /* the process we with to open. */ /* bool lookForWindow - Should the class find the main HWND */ /* [Default: true] */ /* DWORD dwDesiredAccess - This is the optional desired access flag */ /* used to open the process. */ /* [Default: PROCESS_ALL_ACCESS] */ /* BOOL bInhereitHandle - This is the optional desired flag used to */ /* open the process */ /* [Default: FALSE] */ /**************************************************************************/ bool Open(const std::string& exeName, bool lookForWindow = true, DWORD dwDesiredAccess = PROCESS_ALL_ACCESS, BOOL bInhereitHandle = FALSE) { /****************************************/ /* First see if we can find the process */ /****************************************/ // Used to get our process snapshot HANDLE hProcessSnap = 0; // Current operating status bool status = false; // First wee if we can get a snapshot of all processes if((hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)) == INVALID_HANDLE_VALUE) { // If we cant, return false for failure return false; } // If we were able to get the snapshot, call the Close function in case this particular // Process object was already opened. Close(); // Retrieve the information about the first process encountered in the system snapshot if(Process32First(hProcessSnap, &pe32)) { // Now get ready to loop though all of the processes do { // First check to see if the exe file name matches the one we are looking for if(std::string(pe32.szExeFile) == exeName) { // If we should find the window for this process if(lookForWindow) { // Now we call the enumCallbackFunc in order to find the // main HWND associated with the process. Note that a process could // have more than one HWND, so this library just gets the first. We // pass 'this' current object to the function in order to be able to // assign the HWND back to this class object. EnumWindows(enumCallbackFunc, (LPARAM)this); // If the hwnd is not null, then we have found the main window and // no longer need to continue this loop if(hwnd) { status = true; } } else { // Otherwise if there is no window being looked for, // we take the first process we find status = true; } } } // For our do-while we will loop while the HWND was not found and we have another process to check while(!status && Process32Next(hProcessSnap, &pe32)); } else { // If we reach this part there was a major error because Process32First has failed ShowError("cProcess::Open - Process32First"); return false; } // Once we get here, we no longer need the snapshot because we looked though all the processes CloseHandle(hProcessSnap); // Now, we will check if we found the process or not. We set status to true above to indicate if we did if(!status) { return false; } /****************************************/ /* If we found it, now we can open it */ /****************************************/ // Now we will try to open the process and store it handle = OpenProcess(dwDesiredAccess, bInhereitHandle, pe32.th32ProcessID); if(!handle) { // If we reach this part there was a problem because we could not open our process ShowError("cProcess::Open - OpenProcess"); return false; } // If we get here, we have found our process and hwnd and are ready to use the clas object! return true; } /**************************************************************************/ /* Function: Close */ /* */ /* Description: This function will close the opened process. */ /* */ /* Return Type: None */ /* */ /* Parameters: None */ /**************************************************************************/ void Close() { // First we will want to see if the handle we have is valid and close it if(handle && CloseHandle(handle) != 0) { handle = 0; } // Next just clear out our variables ZeroMemory(&pe32, sizeof(PROCESSENTRY32)); pe32.dwSize = sizeof(PROCESSENTRY32); hwnd = 0; } /**************************************************************************/ /* Function: Read */ /* */ /* Description: This function will read exactly 'one' unit of the passed */ /* datatype specified. */ /* */ /* Return Type: bool: true = success, false = failure */ /* */ /* Parameters: */ /* unsigned long address - The address of the memory to read. */ /* type& buffer - The variable to store the read memory to. */ /**************************************************************************/ template <class type> bool Read(unsigned long address, type& buffer) { // Holds the number of bytes read SIZE_T read = 0; // Try to read the memory and if there was a problem, show the error if(!ReadProcessMemory(handle, (LPCVOID)address, (LPVOID)&buffer, sizeof(type), &read)) { ShowError("cProcess::Read - ReadProcessMemory"); return false; } // Success! buffer now contains the memory read. return true; } /**************************************************************************/ /* Function: ReadArray */ /* */ /* Description: This function will read exactly sizeOfBuffer units of the*/ /* passed datatype specified or until 'stopValue' is read. */ /* */ /* Return Type: bool: true = success, false = failure */ /* */ /* Parameters: */ /* unsigned long address - The address of the memory to read. */ /* type* buffer - The array of variables to store the read memory to.*/ /* int sizeOfBuffer - The number of elements the array has space for */ /* type stopValue - The value to signal to stop reading memory if */ /* the number of elements read is smaller than */ /* sizeOfBuffer. */ /**************************************************************************/ template <class type> bool ReadArray(unsigned long address, type* buffer, int sizeOfBuffer, type stopValue) { // Holds the number of bytes read SIZE_T read = 0; // Precalcuate and store the size of the data type being used SIZE_T dataSize = sizeof(type); // Loop though all of the elements in the array and fill them in for(int x = 0; x < sizeOfBuffer; ++x) { // Try to read the memory and if there was a problem, show the error if(!ReadProcessMemory(handle, (LPCVOID)(address + (dataSize * x)), (LPVOID)&buffer[x], dataSize, &read)) { ShowError("cProcess::ReadArray - ReadProcessMemory"); // We shouldn't try to continue return false; } // Check to see if the current value read in is our stop value, if so, we are done if(buffer[x] == stopValue) { // Success! return true; } } // Success! return true; } /**************************************************************************/ /* Function: ReadArray */ /* */ /* Description: This function will read exactly sizeOfBuffer units of the*/ /* passed datatype specified. */ /* */ /* Return Type: bool: true = success, false = failure */ /* */ /* Parameters: */ /* unsigned long address - The address of the memory to read. */ /* type* buffer - The array of variables to store the read memory to.*/ /* int sizeOfBuffer - The number of elements the array has space for.*/ /**************************************************************************/ template <class type> bool ReadArray(unsigned long address, type* buffer, int sizeOfBuffer) { // Holds the number of bytes read SIZE_T read = 0; // Precalcuate and store the size of the data type being used SIZE_T dataSize = sizeof(type); // Loop though all of the elements in the array and fill them in for(int x = 0; x < sizeOfBuffer; ++x) { // Try to read the memory and if there was a problem, show the error if(!ReadProcessMemory(handle, (LPCVOID)(address + (dataSize * x)), (LPVOID)&buffer[x], dataSize, &read)) { return false; } } // Success! return true; } /**************************************************************************/ /* Function: Write */ /* */ /* Description: This function will write the passed variable to memory. */ /* */ /* Return Type: bool: true = success, false = failure */ /* */ /* Parameters: */ /* unsigned long address - The address of the memory to read. */ /* type& buffer - The variable to store in memory. */ /**************************************************************************/ template <class type> bool Write(unsigned long address, type& buffer) { // Holds the number of bytes written SIZE_T write = 0; // Try to write the memory and if there was a problem, show the error and return a failure if(!WriteProcessMemory(handle, (LPVOID)address, (LPVOID)&buffer, sizeof(type), &write)) { ShowError("cProcess::Write - WriteProcessMemory"); return false; } // Success! return true; } /**************************************************************************/ /* Function: WriteArray */ /* */ /* Description: This function will write the buffer of passed datatype */ /* specified into the memory address specificed. */ /* */ /* Return Type: bool: true = success, false = failure */ /* */ /* Parameters: */ /* unsigned long address - The address of the memory to read. */ /* type* buffer - The array of variables to write into memory. */ /* int sizeOfBuffer - The number of elements the array has. */ /**************************************************************************/ template <class type> bool WriteArray(unsigned long address, type* buffer, int sizeOfBuffer) { // Holds the number of bytes written SIZE_T write = 0; // Precalcuate and store the size of the data type being used SIZE_T dataSize = sizeof(type); // Loop though all of the elements in the array and fill memory with them for(int x = 0; x < sizeOfBuffer; ++x) { // Try to write the memory and if there was a problem, show the error if(!WriteProcessMemory(handle, (LPVOID)(address + (dataSize * x)), (LPVOID)&buffer[x], dataSize, &write)) { ShowError("cProcess::WriteArray - WriteProcessMemory"); // We shouldn't try to continue return false; } } // Success! return true; } }; // Taken and modified from a MSDN example, it will present a messagebox // to the user with the current error. Dont worry about this function. void ShowError(LPTSTR lpszFunction) { LPVOID lpMsgBuf; LPVOID lpDisplayBuf; DWORD dw = GetLastError(); FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL ); lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, (lstrlen((LPCTSTR)lpMsgBuf)+lstrlen((LPCTSTR)lpszFunction)+40)*sizeof(TCHAR)); wsprintf((LPTSTR)lpDisplayBuf, TEXT("%s failed with error %d: %s"), lpszFunction, dw, lpMsgBuf); MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK | MB_ICONERROR); LocalFree(lpMsgBuf); LocalFree(lpDisplayBuf); } // This function is the callback function used for EnumWindows BOOL CALLBACK enumCallbackFunc(HWND hwnd, LPARAM lparam) { // Since we passed the cProcess object we are working on, first retrieve it cProcess* process = (cProcess*)lparam; // Holds the process id of the window we are looking at DWORD pid = 0; // Get the process id GetWindowThreadProcessId(hwnd, &pid); // If the cProcess object's id equals the windows id if(process->pe32.th32ProcessID == pid) { // Store the active window HWND active = ::GetForegroundWindow(); // Bring the window we are looking at to the top SetForegroundWindow(hwnd); // Check with the user as to if this is the right window if(MessageBox(hwnd, "Was the correct window activated?", "Desired Window?", MB_ICONQUESTION | MB_YESNO) == IDYES) { // If so, save the hwnd to the class object process->hwnd = hwnd; // Restore the old foreground window SetForegroundWindow(active); // Return false so we do not call this function anymore, we are done return FALSE; } else { // Otherwise simply restore the old foreground window SetForegroundWindow(active); } } // Return true to keep on going though windows return TRUE; } #endif
Quote:
I wrote code to do it a long time ago. The first way I did it was to perform client edits via WriteProcessMemory through a secondary program. That would work for all chat types except for All Chat right now due to how the client code is setup.
The second method I used was to create a codecave in the client to process the chat color logic. You can get the current chat type and then specify a custom color for it. That is much easier to work with, but requires the use of a loader and injected DLL. You could use my guides to do it though but I'm not going to myself.
Here's the code in the latest 205 client that has to deal with chat colors.
You should be able to follow the colors in a graphics program that allows you to use hex/decimal for RGB. The colors are stored backwards in memory so FEFF9FFF is color (ARGB) FF 9F FF FE, or the color for whisper chat.Code:007A37C7 . 8078 04 00 CMP BYTE PTR DS:[EAX+4],0 007A37CB .^ 0F84 B2FEFFFF JE sro_clie.007A3683 007A37D1 > BD FEFF9FFF MOV EBP,FF9FFFFE ; Case A of switch 007A37B3 007A37D6 . EB 34 JMP SHORT sro_clie.007A380C 007A37D8 > BD 00FFFFFF MOV EBP,-100 ; Case 6 of switch 007A37B3 007A37DD . EB 2D JMP SHORT sro_clie.007A380C 007A37DF > BD C3AEFFFF MOV EBP,FFFFAEC3 ; Cases 3,7 of switch 007A37B3 007A37E4 . EB 26 JMP SHORT sro_clie.007A380C 007A37E6 > BD 41B5FFFF MOV EBP,FFFFB541 ; Case 5 of switch 007A37B3 007A37EB . EB 1F JMP SHORT sro_clie.007A380C 007A37ED > BD 73F5C2FF MOV EBP,FFC2F573 ; Case B of switch 007A37B3 007A37F2 . EB 18 JMP SHORT sro_clie.007A380C 007A37F4 > BD D0FF9AFF MOV EBP,FF9AFFD0 ; Case 4 of switch 007A37B3 007A37F9 . EB 11 JMP SHORT sro_clie.007A380C 007A37FB > BD F8ADDBFF MOV EBP,FFDBADF8 ; Case D of switch 007A37B3 007A3800 . EB 0A JMP SHORT sro_clie.007A380C 007A3802 > BD FFC764FF MOV EBP,FF64C7FF ; Case 10 of switch 007A37B3 007A3807 . EB 03 JMP SHORT sro_clie.007A380C 007A3809 > 83CD FF OR EBP,FFFFFFFF ; Default case of switch 007A37B3 007A380C > B8 07000000 MOV EAX,7
Here's the updated code to the project I wrote back in Feb. 07. The concept is pretty simple. Just write out the new hex values for the colors in the Silkroad process. You need to be running the program in Administrator in Vista/Win7 as well.
SilkroadChatColor.cpp
cProcess.hCode:#include "cProcess.h" #include <windows.h> #include <math.h> #include <stdio.h> #include <fstream> #include <sstream> // Main program window HWND hwnd = 0; // Array of addresses to make for easier access unsigned long addrs[6]; unsigned long defs[6]; unsigned long curs[6]; HWND hwnds[6]; HWND preview[6]; // Whisper HWND lblWhisper = 0; HWND editWhisper = 0; HWND btnDefWhisper = 0; unsigned long addrWhisper = 0x7A37D1; unsigned long defColorWhisper = 0xFF9FFFFE; // Global HWND lblGlobal = 0; HWND editGlobal = 0; HWND btnDefGlobal = 0; unsigned long addrGlobal = 0x7A37D8; unsigned long defColorGlobal = 0xFFFFFF00; // Notice HWND lblNotice = 0; HWND editNotice = 0; HWND btnDefNotice = 0; unsigned long addrNotice = 0x7A37DF; unsigned long defColorNotice = 0xFFFFAEC3; // Guild HWND lblGuild = 0; HWND editGuild = 0; HWND btnDefGuild = 0; unsigned long addrGuild = 0x7A37E6; unsigned long defColorGuild = 0xFFFFB541; // Union HWND lblUnion = 0; HWND editUnion = 0; HWND btnDefUnion = 0; unsigned long addrUnion = 0x7A37ED; unsigned long defColorUnion = 0xFFC2F573; // Party HWND lblParty = 0; HWND editParty = 0; HWND btnDefParty = 0; unsigned long addrParty = 0x7A37F4; unsigned long defColorParty = 0xFF9AFFD0; // Set chat color button HWND btnColorize = 0; HWND btnPerm = 0; // Get the current color a chat type HWND btnGetWhisper = 0; HWND btnGetGlobal = 0; HWND btnGetNotice = 0; HWND btnGetGuild = 0; HWND btnGetUnion = 0; HWND btnGetParty = 0; HWND btnGetAll = 0; // Defines for the button messages #define BTN_DEF_COLOR_WHISPER 1 #define BTN_DEF_COLOR_GLOBAL 2 #define BTN_DEF_COLOR_NOTICE 3 #define BTN_DEF_COLOR_GUILD 4 #define BTN_DEF_COLOR_UNION 5 #define BTN_DEF_COLOR_PARTY 6 #define BTN_DEF_COLOR_ALL 7 #define BTN_COLORIZE_ON 8 #define BTN_COLORIZE_GET 9 #define BTN_PREVIEW_COLOR_WHSIPER 11 #define BTN_PREVIEW_COLOR_GLOBAL 12 #define BTN_PREVIEW_COLOR_NOTICE 13 #define BTN_PREVIEW_COLOR_GUILD 14 #define BTN_PREVIEW_COLOR_UNION 15 #define BTN_PREVIEW_COLOR_PARTY 16 #define BTN_PREVIEW_COLOR_ALL 17 #define BTN_GET_COLOR_WHISPER 18 #define BTN_GET_COLOR_GLOBAL 19 #define BTN_GET_COLOR_NOTICE 20 #define BTN_GET_COLOR_GUILD 21 #define BTN_GET_COLOR_UNION 22 #define BTN_GET_COLOR_PARTY 23 #define BTN_GET_COLOR_ALL 24 // cProcess class object used to make working with processes a lot easier ;) cProcess sro; unsigned long CaptionToHex(HWND h) { // Store the actual hex string unsigned char data[5] = {0}; // Store the ascii-hex string char temp[32] = {0}; // The alpha should be FF, opaque (don't think font supports alpha) temp[0] = 'F'; temp[1] = 'F'; // Get the desired window's color GetWindowText(h, temp + 2, 7); // Store the final value int value = 0; // We have to reverse the digits for hex form int index = 3; // Loop though all tuples of characters for(int y = 0; y < 8; y += 2) { int tuple1 = 15, tuple2 = 15; // Store current character unsigned char cur = temp[y]; // If it's A - F, convert it to 10 - 15 if(cur >= 'A' && cur <= 'F') tuple1 = cur - 'A' + 10; // If it's 0 - 9, convert it to 0 - 9 else if(cur >= '0' && cur <= '9') tuple1 = cur - '0'; // Store current character cur = temp[y + 1]; // If it's A - F, convert it to 10 - 15 if(cur >= 'A' && cur <= 'F') tuple2 = cur - 'A' + 10; // If it's 0 - 9, convert it to 0 - 9 else if(cur >= '0' && cur <= '9') tuple2 = cur - '0'; // Convert the two numbers into a unsigned character value = tuple2 + 16 * tuple1; // Store the final color value for this color component data[index--] = value; } // Store a pointer of the final color value as a unsigned long unsigned long* ptr = (unsigned long*)data; return *ptr; } void DrawColorPreview(HDC hdc, int x, int y, unsigned long color) { color = color & 0x00FFFFFF; HBRUSH NewBrush = CreateSolidBrush(RGB(GetBValue(color),GetGValue(color),GetRValue(color))); SelectObject(hdc, NewBrush); Rectangle(hdc, x, y, x + 18, y + 18); DeleteObject(NewBrush); } // Get the current chat colors void GetCurrentChatColors(int x) { // Array to hold the data unsigned char buffer[5] = {0}; // Read in the memory location if(!sro.ReadArray(addrs[x], buffer, 5)) { MessageBox(hwnd, "Memory address could not be read.", "Fatal Error", MB_OK | MB_ICONERROR); return; } char temp[256] = {0}; // Store the color components into the array _snprintf(temp, 255, "%.2X%.2X%.2X", buffer[3], buffer[2], buffer[1]); // Write the entire RGB color string to the edit box SetWindowText(hwnds[x], temp); } void GeneratePreview(HWND btn, int button) { curs[button] = CaptionToHex(btn); RECT r; r.left = 284; r.right = r.left + 18; r.top = 10 + button * 30; r.bottom = r.top + 18; InvalidateRect(hwnd, &r, true); } LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT Ps; HDC hdc; switch(msg) { case WM_PAINT: { hdc = BeginPaint(hwnd, &Ps); for(int x = 0; x < 6; ++x) DrawColorPreview(hdc, 284, 10 + x * 30, curs[x]); EndPaint(hwnd, &Ps); } break; case WM_COMMAND: { if(LOWORD(wParam) == BTN_COLORIZE_ON) { // Loop though all chat colors for(int x = 0; x < 6; ++x) { int ptr = CaptionToHex(hwnds[x]); // Write the color value to memory sro.Write(addrs[x] + 1, ptr); } } else if(LOWORD(wParam) >= BTN_GET_COLOR_WHISPER && LOWORD(wParam) <= BTN_GET_COLOR_ALL) { int button = LOWORD(wParam) - BTN_GET_COLOR_WHISPER; GetCurrentChatColors(button); GeneratePreview(hwnds[button], button); } else if(LOWORD(wParam) >= BTN_DEF_COLOR_WHISPER && LOWORD(wParam) <= BTN_DEF_COLOR_ALL) { // Save the real button # int button = LOWORD(wParam) - 1; // Buffer to hold the default value char temp[256] = {0}; // Save the default value to the buffer sprintf(temp, "%X", defs[button]); // Write the default value to the window SetWindowText(hwnds[button], temp + 2); GeneratePreview(hwnds[button], button); } else if(LOWORD(wParam) >= BTN_PREVIEW_COLOR_WHSIPER && LOWORD(wParam) <= LOWORD(wParam)) { int button = LOWORD(wParam) - BTN_PREVIEW_COLOR_WHSIPER; GeneratePreview(hwnds[button], button); } } break; case WM_CLOSE: { DestroyWindow(hwnd); } break; case WM_DESTROY: { PostQuitMessage(0); } break; default: { return DefWindowProc(hwnd, msg, wParam, lParam); } } return 0; } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEX wc = {0}; MSG msg = {0}; wc.cbSize = sizeof(WNDCLASSEX); wc.style = 0; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = GetModuleHandle(0); wc.hIcon = LoadIcon(NULL, MAKEINTRESOURCE(101)); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+6); wc.lpszMenuName = NULL; wc.lpszClassName = "SROChatColor"; wc.hIconSm = (HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(101), IMAGE_ICON, 16, 16, 0);; // Win32 stuff to create the program if(!RegisterClassEx(&wc)) { MessageBox(NULL, "Window Registration Failed!", "Error!", MB_ICONERROR | MB_OK); return 0; } // Create main window hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, "SROChatColor", "Silkroad Chat Color - By: Drew Benton", WS_OVERLAPPEDWINDOW ^ WS_MAXIMIZEBOX ^ WS_THICKFRAME, CW_USEDEFAULT, CW_USEDEFAULT, 480, 290, NULL, NULL, hInstance, NULL); if(hwnd == NULL) { MessageBox(NULL, "Window Creation Failed!", "Error!", MB_ICONERROR | MB_OK); return 0; } // Try to open the sro client if(!sro.Open("sro_client.exe")) { MessageBox(0, "Cannot find your sro_client.exe", "Error!", MB_ICONERROR | MB_OK); return -1; } // Store the addresses addrs[0] = addrWhisper; addrs[1] = addrGlobal; addrs[2] = addrNotice; addrs[3] = addrGuild; addrs[4] = addrUnion; addrs[5] = addrParty; //addrs[6] = addrAll; // Store default colors defs[0] = defColorWhisper; defs[1] = defColorGlobal; defs[2] = defColorNotice; defs[3] = defColorGuild; defs[4] = defColorUnion; defs[5] = defColorParty; //defs[6] = defColorAll; // Store defaults for(int x = 0; x < 6; ++x) curs[x] = defs[x]; // Coords of controls int X = 0; int Y = 0; int W = 0; int H = 0; // Whisper X = 10; Y = 10; W = 125; H = 20; lblWhisper = CreateWindowEx(0, "STATIC", "Whisper Chat: ", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, NULL, NULL, 0); X = 110; editWhisper = CreateWindowEx(0, "EDIT", "", WS_CHILD | WS_VISIBLE | WS_BORDER, X, Y, W, H, hwnd, NULL, NULL, 0); X = 312; W = 70; btnDefWhisper = CreateWindowEx(0, "BUTTON", "Default", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_DEF_COLOR_WHISPER, NULL, 0); X = 392; btnGetWhisper = CreateWindowEx(0, "BUTTON", "Current", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_GET_COLOR_WHISPER, NULL, 0); X = 250; W = 24; preview[0] = CreateWindowEx(0, "BUTTON", "?", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_PREVIEW_COLOR_WHSIPER, NULL, 0); // Global X = 10; Y = 40; W = 125; H = 20; lblGlobal = CreateWindowEx(0, "STATIC", "Global Chat: ", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, NULL, NULL, 0); X = 110; editGlobal = CreateWindowEx(0, "EDIT", "", WS_CHILD | WS_VISIBLE | WS_BORDER, X, Y, W, H, hwnd, NULL, NULL, 0); X = 312; W = 70; btnDefWhisper = CreateWindowEx(0, "BUTTON", "Default", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_DEF_COLOR_GLOBAL, NULL, 0); X = 392; btnGetGlobal = CreateWindowEx(0, "BUTTON", "Current", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_GET_COLOR_GLOBAL, NULL, 0); X = 250; W = 24; preview[1] = CreateWindowEx(0, "BUTTON", "?", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_PREVIEW_COLOR_GLOBAL, NULL, 0); // Notice X = 10; Y = 70; W = 125; H = 20; lblNotice = CreateWindowEx(0, "STATIC", "Notice Chat: ", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, NULL, NULL, 0); X = 110; editNotice = CreateWindowEx(0, "EDIT", "", WS_CHILD | WS_VISIBLE | WS_BORDER, X, Y, W, H, hwnd, NULL, NULL, 0); X = 312; W = 70; btnDefNotice = CreateWindowEx(0, "BUTTON", "Default", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_DEF_COLOR_NOTICE, NULL, 0); X = 392; btnGetNotice = CreateWindowEx(0, "BUTTON", "Current", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_GET_COLOR_NOTICE, NULL, 0); X = 250; W = 24; preview[2] = CreateWindowEx(0, "BUTTON", "?", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_PREVIEW_COLOR_NOTICE, NULL, 0); // Guild X = 10; Y = 100; W = 125; H = 20; lblGuild = CreateWindowEx(0, "STATIC", "Guild Chat: ", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, NULL, NULL, 0); X = 110; editGuild = CreateWindowEx(0, "EDIT", "", WS_CHILD | WS_VISIBLE | WS_BORDER, X, Y, W, H, hwnd, NULL, NULL, 0); X = 312; W = 70; btnDefGuild = CreateWindowEx(0, "BUTTON", "Default", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_DEF_COLOR_GUILD, NULL, 0); X = 392; btnGetGuild = CreateWindowEx(0, "BUTTON", "Current", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_GET_COLOR_GUILD, NULL, 0); X = 250; W = 24; preview[3] = CreateWindowEx(0, "BUTTON", "?", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_PREVIEW_COLOR_GUILD, NULL, 0); // Union X = 10; Y = 130; W = 125; H = 20; lblUnion = CreateWindowEx(0, "STATIC", "Union Chat: ", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, NULL, NULL, 0); X = 110; editUnion = CreateWindowEx(0, "EDIT", "", WS_CHILD | WS_VISIBLE | WS_BORDER, X, Y, W, H, hwnd, NULL, NULL, 0); X = 312; W = 70; btnDefUnion = CreateWindowEx(0, "BUTTON", "Default", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_DEF_COLOR_UNION, NULL, 0); X = 392; btnGetUnion = CreateWindowEx(0, "BUTTON", "Current", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_GET_COLOR_UNION, NULL, 0); X = 250; W = 24; preview[4] = CreateWindowEx(0, "BUTTON", "?", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_PREVIEW_COLOR_UNION, NULL, 0); // Party X = 10; Y = 160; W = 125; H = 20; lblParty = CreateWindowEx(0, "STATIC", "Party Chat: ", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, NULL, NULL, 0); X = 110; editParty = CreateWindowEx(0, "EDIT", "", WS_CHILD | WS_VISIBLE | WS_BORDER, X, Y, W, H, hwnd, NULL, NULL, 0); X = 312; W = 70; btnDefParty = CreateWindowEx(0, "BUTTON", "Default", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_DEF_COLOR_PARTY, NULL, 0); X = 392; btnGetParty = CreateWindowEx(0, "BUTTON", "Current", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_GET_COLOR_PARTY, NULL, 0); X = 250; W = 24; preview[5] = CreateWindowEx(0, "BUTTON", "?", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_PREVIEW_COLOR_PARTY, NULL, 0); // Set chat color button X = 312; Y = 220; W = 150; H = 30; btnColorize = CreateWindowEx(0, "BUTTON", "Change Chat Colors!", WS_CHILD | WS_VISIBLE, X, Y, W, H, hwnd, (HMENU)BTN_COLORIZE_ON, NULL, 0); // Store the edit handles to make life easier hwnds[0] = editWhisper; hwnds[1] = editGlobal; hwnds[2] = editNotice; hwnds[3] = editGuild; hwnds[4] = editUnion; hwnds[5] = editParty; //hwnds[6] = editAll; // Start the program out by getting the current colors stored in memory for(int x = 0; x < 6; ++x) GetCurrentChatColors(x); // Reactivate this program SetForegroundWindow(hwnd); ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); while(msg.message != WM_QUIT) { if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } else { WaitMessage(); } } return 0; }
Remember the code is over 2 years old now and the setup of the program reflects not knowing too much about setting up programs in an easy to use and modify way lol. Anyways it should be enough to get the idea of what to do.Code:/*****************************************************************************/ /* cProcess /* By; Drew Benton /* /* This class was written to make working with processes a lot easier. With /* this class, the user will be able to open a process and read from memory /* or write to memory. It is designed with simplicty and ease of use in mind. /* If you have any questions or comments e-mail me at [Only registered and activated users can see links. Click Here To Register...] /* /******************************************************************************/ #ifndef CPROCESS_H_ #define CPROCESS_H_ #include <windows.h> #include <tlhelp32.h> #include <string> // Display the current error to the user via a message box void ShowError(LPTSTR lpszFunction); // The callback function used for processing HWNDs BOOL CALLBACK enumCallbackFunc(HWND hwnd, LPARAM lparam); class cProcess { public: // The process entry for the process PROCESSENTRY32 pe32; // Handle to the process HANDLE handle; // One of the HWNDs associated with the process HWND hwnd; public: /******************************************************************************************/ // MEMBER FUNCTIONS REFERENCE // /******************************************************************************************/ /* // This is the constructor for the cProcess class. /* cProcess(); /* // This is the destructor for the cProcess class. /* ~cProcess(); /* /* // This function will open the desired executable's process. /* bool Open( /* const std::string& exeName, /* bool lookForWindow = true, /* DWORD dwDesiredAccess = PROCESS_ALL_ACCESS, /* BOOL bInhereitHandle = FALSE); /* /* // This function will close the opened process. /* void Close(); /* /* // This function will read exactly 'one' unit of the passed datatype specified. /* template <class type> /* bool Read( /* unsigned long address, /* type& buffer); /* /* // This function will read exactly sizeOfBuffer units of the /* // passed datatype specified or until 'stopValue' is read. /* template <class type> /* bool ReadArray( /* unsigned long address, /* type* buffer, /* int sizeOfBuffer, /* type stopValue); /* /* // This function will read exactly sizeOfBuffer units of the passed datatype specified. /* template <class type> /* bool ReadArray( /* unsigned long address, /* type* buffer, /* int sizeOfBuffer); /* /* // This function will write the passed variable to memory. /* template <class type> /* bool Write( /* unsigned long address, /* type& buffer); /* /* // This function will write the buffer of passed datatype /* // specified into the memory address specificed. /* template <class type> /* bool WriteArray( /* unsigned long address, /* type* buffer, /* int sizeOfBuffer); /*****************************************************************************************/ /******************************************************************************************/ // MEMBER FUNCTION IMPLEMENTATIONS // /******************************************************************************************/ /**************************************************************************/ /* Function: cProcess */ /* */ /* Description: This is the constructor for the cProcess class. */ /* */ /* Return Type: None */ /* */ /* Parameters: None */ /**************************************************************************/ cProcess::cProcess() { // Simply clear all the memory of our variables handle = 0; hwnd = 0; ZeroMemory(&pe32, sizeof(PROCESSENTRY32)); // This is a must in Win32 for this struct! pe32.dwSize = sizeof(PROCESSENTRY32); } /**************************************************************************/ /* Function: cProcess */ /* */ /* Description: This is the destructor for the cProcess class. */ /* */ /* Return Type: None */ /* */ /* Parameters: None */ /**************************************************************************/ cProcess::~cProcess() { // Call the Close function on object destruction Close(); } /**************************************************************************/ /* Function: Open */ /* */ /* Description: This function will open the desired executable's process.*/ /* Since there could be many processes with the same executable, a */ /* feature exsits to help the user select the correct window. The hwnd is*/ /* activated and the user replies to a message box as to if it is correct*/ /* */ /* Return Type: bool: true = success, false = failure */ /* */ /* Parameters: */ /* const string& exeName - This parameter is the executable file of */ /* the process we with to open. */ /* bool lookForWindow - Should the class find the main HWND */ /* [Default: true] */ /* DWORD dwDesiredAccess - This is the optional desired access flag */ /* used to open the process. */ /* [Default: PROCESS_ALL_ACCESS] */ /* BOOL bInhereitHandle - This is the optional desired flag used to */ /* open the process */ /* [Default: FALSE] */ /**************************************************************************/ bool Open(const std::string& exeName, bool lookForWindow = true, DWORD dwDesiredAccess = PROCESS_ALL_ACCESS, BOOL bInhereitHandle = FALSE) { /****************************************/ /* First see if we can find the process */ /****************************************/ // Used to get our process snapshot HANDLE hProcessSnap = 0; // Current operating status bool status = false; // First wee if we can get a snapshot of all processes if((hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)) == INVALID_HANDLE_VALUE) { // If we cant, return false for failure return false; } // If we were able to get the snapshot, call the Close function in case this particular // Process object was already opened. Close(); // Retrieve the information about the first process encountered in the system snapshot if(Process32First(hProcessSnap, &pe32)) { // Now get ready to loop though all of the processes do { // First check to see if the exe file name matches the one we are looking for if(std::string(pe32.szExeFile) == exeName) { // If we should find the window for this process if(lookForWindow) { // Now we call the enumCallbackFunc in order to find the // main HWND associated with the process. Note that a process could // have more than one HWND, so this library just gets the first. We // pass 'this' current object to the function in order to be able to // assign the HWND back to this class object. EnumWindows(enumCallbackFunc, (LPARAM)this); // If the hwnd is not null, then we have found the main window and // no longer need to continue this loop if(hwnd) { status = true; } } else { // Otherwise if there is no window being looked for, // we take the first process we find status = true; } } } // For our do-while we will loop while the HWND was not found and we have another process to check while(!status && Process32Next(hProcessSnap, &pe32)); } else { // If we reach this part there was a major error because Process32First has failed ShowError("cProcess::Open - Process32First"); return false; } // Once we get here, we no longer need the snapshot because we looked though all the processes CloseHandle(hProcessSnap); // Now, we will check if we found the process or not. We set status to true above to indicate if we did if(!status) { return false; } /****************************************/ /* If we found it, now we can open it */ /****************************************/ // Now we will try to open the process and store it handle = OpenProcess(dwDesiredAccess, bInhereitHandle, pe32.th32ProcessID); if(!handle) { // If we reach this part there was a problem because we could not open our process ShowError("cProcess::Open - OpenProcess"); return false; } // If we get here, we have found our process and hwnd and are ready to use the clas object! return true; } /**************************************************************************/ /* Function: Close */ /* */ /* Description: This function will close the opened process. */ /* */ /* Return Type: None */ /* */ /* Parameters: None */ /**************************************************************************/ void Close() { // First we will want to see if the handle we have is valid and close it if(handle && CloseHandle(handle) != 0) { handle = 0; } // Next just clear out our variables ZeroMemory(&pe32, sizeof(PROCESSENTRY32)); pe32.dwSize = sizeof(PROCESSENTRY32); hwnd = 0; } /**************************************************************************/ /* Function: Read */ /* */ /* Description: This function will read exactly 'one' unit of the passed */ /* datatype specified. */ /* */ /* Return Type: bool: true = success, false = failure */ /* */ /* Parameters: */ /* unsigned long address - The address of the memory to read. */ /* type& buffer - The variable to store the read memory to. */ /**************************************************************************/ template <class type> bool Read(unsigned long address, type& buffer) { // Holds the number of bytes read SIZE_T read = 0; // Try to read the memory and if there was a problem, show the error if(!ReadProcessMemory(handle, (LPCVOID)address, (LPVOID)&buffer, sizeof(type), &read)) { ShowError("cProcess::Read - ReadProcessMemory"); return false; } // Success! buffer now contains the memory read. return true; } /**************************************************************************/ /* Function: ReadArray */ /* */ /* Description: This function will read exactly sizeOfBuffer units of the*/ /* passed datatype specified or until 'stopValue' is read. */ /* */ /* Return Type: bool: true = success, false = failure */ /* */ /* Parameters: */ /* unsigned long address - The address of the memory to read. */ /* type* buffer - The array of variables to store the read memory to.*/ /* int sizeOfBuffer - The number of elements the array has space for */ /* type stopValue - The value to signal to stop reading memory if */ /* the number of elements read is smaller than */ /* sizeOfBuffer. */ /**************************************************************************/ template <class type> bool ReadArray(unsigned long address, type* buffer, int sizeOfBuffer, type stopValue) { // Holds the number of bytes read SIZE_T read = 0; // Precalcuate and store the size of the data type being used SIZE_T dataSize = sizeof(type); // Loop though all of the elements in the array and fill them in for(int x = 0; x < sizeOfBuffer; ++x) { // Try to read the memory and if there was a problem, show the error if(!ReadProcessMemory(handle, (LPCVOID)(address + (dataSize * x)), (LPVOID)&buffer[x], dataSize, &read)) { ShowError("cProcess::ReadArray - ReadProcessMemory"); // We shouldn't try to continue return false; } // Check to see if the current value read in is our stop value, if so, we are done if(buffer[x] == stopValue) { // Success! return true; } } // Success! return true; } /**************************************************************************/ /* Function: ReadArray */ /* */ /* Description: This function will read exactly sizeOfBuffer units of the*/ /* passed datatype specified. */ /* */ /* Return Type: bool: true = success, false = failure */ /* */ /* Parameters: */ /* unsigned long address - The address of the memory to read. */ /* type* buffer - The array of variables to store the read memory to.*/ /* int sizeOfBuffer - The number of elements the array has space for.*/ /**************************************************************************/ template <class type> bool ReadArray(unsigned long address, type* buffer, int sizeOfBuffer) { // Holds the number of bytes read SIZE_T read = 0; // Precalcuate and store the size of the data type being used SIZE_T dataSize = sizeof(type); // Loop though all of the elements in the array and fill them in for(int x = 0; x < sizeOfBuffer; ++x) { // Try to read the memory and if there was a problem, show the error if(!ReadProcessMemory(handle, (LPCVOID)(address + (dataSize * x)), (LPVOID)&buffer[x], dataSize, &read)) { return false; } } // Success! return true; } /**************************************************************************/ /* Function: Write */ /* */ /* Description: This function will write the passed variable to memory. */ /* */ /* Return Type: bool: true = success, false = failure */ /* */ /* Parameters: */ /* unsigned long address - The address of the memory to read. */ /* type& buffer - The variable to store in memory. */ /**************************************************************************/ template <class type> bool Write(unsigned long address, type& buffer) { // Holds the number of bytes written SIZE_T write = 0; // Try to write the memory and if there was a problem, show the error and return a failure if(!WriteProcessMemory(handle, (LPVOID)address, (LPVOID)&buffer, sizeof(type), &write)) { ShowError("cProcess::Write - WriteProcessMemory"); return false; } // Success! return true; } /**************************************************************************/ /* Function: WriteArray */ /* */ /* Description: This function will write the buffer of passed datatype */ /* specified into the memory address specificed. */ /* */ /* Return Type: bool: true = success, false = failure */ /* */ /* Parameters: */ /* unsigned long address - The address of the memory to read. */ /* type* buffer - The array of variables to write into memory. */ /* int sizeOfBuffer - The number of elements the array has. */ /**************************************************************************/ template <class type> bool WriteArray(unsigned long address, type* buffer, int sizeOfBuffer) { // Holds the number of bytes written SIZE_T write = 0; // Precalcuate and store the size of the data type being used SIZE_T dataSize = sizeof(type); // Loop though all of the elements in the array and fill memory with them for(int x = 0; x < sizeOfBuffer; ++x) { // Try to write the memory and if there was a problem, show the error if(!WriteProcessMemory(handle, (LPVOID)(address + (dataSize * x)), (LPVOID)&buffer[x], dataSize, &write)) { ShowError("cProcess::WriteArray - WriteProcessMemory"); // We shouldn't try to continue return false; } } // Success! return true; } }; // Taken and modified from a MSDN example, it will present a messagebox // to the user with the current error. Dont worry about this function. void ShowError(LPTSTR lpszFunction) { LPVOID lpMsgBuf; LPVOID lpDisplayBuf; DWORD dw = GetLastError(); FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL ); lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, (lstrlen((LPCTSTR)lpMsgBuf)+lstrlen((LPCTSTR)lpszFunction)+40)*sizeof(TCHAR)); wsprintf((LPTSTR)lpDisplayBuf, TEXT("%s failed with error %d: %s"), lpszFunction, dw, lpMsgBuf); MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK | MB_ICONERROR); LocalFree(lpMsgBuf); LocalFree(lpDisplayBuf); } // This function is the callback function used for EnumWindows BOOL CALLBACK enumCallbackFunc(HWND hwnd, LPARAM lparam) { // Since we passed the cProcess object we are working on, first retrieve it cProcess* process = (cProcess*)lparam; // Holds the process id of the window we are looking at DWORD pid = 0; // Get the process id GetWindowThreadProcessId(hwnd, &pid); // If the cProcess object's id equals the windows id if(process->pe32.th32ProcessID == pid) { // Store the active window HWND active = ::GetForegroundWindow(); // Bring the window we are looking at to the top SetForegroundWindow(hwnd); // Check with the user as to if this is the right window if(MessageBox(hwnd, "Was the correct window activated?", "Desired Window?", MB_ICONQUESTION | MB_YESNO) == IDYES) { // If so, save the hwnd to the class object process->hwnd = hwnd; // Restore the old foreground window SetForegroundWindow(active); // Return false so we do not call this function anymore, we are done return FALSE; } else { // Otherwise simply restore the old foreground window SetForegroundWindow(active); } } // Return true to keep on going though windows return TRUE; } #endif
Here is what the process looks like after you compile and run.
[Only registered and activated users can see links. Click Here To Register...] [Only registered and activated users can see links. Click Here To Register...] [Only registered and activated users can see links. Click Here To Register...]
Just sharing because I did this a long time ago. I'm not going to maintain the project or rerelease it again since I've got enough stuff I'm working on. Feel free to compile and play with it though. ;)
I'll reply here instead of the PM you sent me.Quote:
please i need this program is necessary
0090BFE3 . 8D70 FF LEA ESI, DWORD PTR DS:[EAX-1] ; Switch (cases 2..10) 0090BFE6 . 83FE 0F CMP ESI, 0F 0090BFE9 . 77 4E JA SHORT sro_clie.0090C039 0090BFEB . FF24B5 3CC890>JMP NEAR DWORD PTR DS:[ESI*4+90C83C] 0090BFF2 > E8 C973BEFF CALL sro_clie.004F33C0 ; Case 2 of switch 0090BFE3 0090BFF7 . 8078 04 00 CMP BYTE PTR DS:[EAX+4], 0 0090BFFB .^ 0F84 ABFEFFFF JE sro_clie.0090BEAC 0090C001 > BD FEFF9FFF MOV EBP, FF9FFFFE ; Case A of switch 0090BFE3 0090C006 . EB 34 JMP SHORT sro_clie.0090C03C 0090C008 > BD 00FFFFFF MOV EBP, -100 ; Case 6 of switch 0090BFE3 0090C00D . EB 2D JMP SHORT sro_clie.0090C03C 0090C00F > BD C3AEFFFF MOV EBP, FFFFAEC3 ; Cases 3,7 of switch 0090BFE3 0090C014 . EB 26 JMP SHORT sro_clie.0090C03C 0090C016 > BD 41B5FFFF MOV EBP, FFFFB541 ; Case 5 of switch 0090BFE3 0090C01B . EB 1F JMP SHORT sro_clie.0090C03C 0090C01D > BD 73F5C2FF MOV EBP, FFC2F573 ; Case B of switch 0090BFE3 0090C022 . EB 18 JMP SHORT sro_clie.0090C03C 0090C024 > BD D0FF9AFF MOV EBP, FF9AFFD0 ; Case 4 of switch 0090BFE3 0090C029 . EB 11 JMP SHORT sro_clie.0090C03C 0090C02B > BD F8ADDBFF MOV EBP, FFDBADF8 ; Case D of switch 0090BFE3 0090C030 . EB 0A JMP SHORT sro_clie.0090C03C 0090C032 > BD FFC764FF MOV EBP, FF64C7FF ; Case 10 of switch 0090BFE3 0090C037 . EB 03 JMP SHORT sro_clie.0090C03C 0090C039 > 83CD FF OR EBP, FFFFFFFF ; Default case of switch 0090BFE3 0090C03C > B8 07000000 MOV EAX, 7