ANASAYFA

C++ | Oyun Hile Yazılımı Dersleri #2

[responsivevoice_button voice="Turkish Male"]

Konu 1: Hangi Tür Verileri Değiştirebiliriz?

Veriler iki yerde saklanır:

1- Sunucu içinde
2- Client yani istemci içinde

Sunucu tarafında tutulan verileri değiştiremiyoruz ancak client yani istemci içinde tutulan (bu bizim bilgisayarımız oluyor) verileri değiştirebiliryoruz.

Sunucu tarafında tutulan verilere örnek verecek olursak;

Can, Mermi, Kişilerin Pozisyonları gibi veriler sunucu tarafında tutulur ve değiştirilemez.

Cheat Engine gibi programlarda veriyi değiştirsek de değiştirdiğimiz bu veri -örnek veriyorum can- verimiz sadece bizim bilgisayarımızdaki kopyası olacaktır yani veriyi değiştirseniz ve ekranda 100 yazısı yerine 9999 yazısını görseniz bile bu veri sadece sizde öyle görünecektir ve herhangi bir hasar alışınızda canınız tekrar eski hale dönecektir.

Öteki yandan bilgisayarımızda tutulan ve değiştirilebilir verilerimize örnek verecek olursam;

Bakış Açımız (Kafamızı çevirince değişen açı), Zıplama, Vurma gibi veriler.

Yani özet olarak sunucu tarafındaki verileri sadece okuyabiliriz, değiştiremeyiz.

“Peki ya direk hafızadaki sv_cheats verisini “1” yapıp hileleri açsak sonra zaten gerisi kolay” gibi düşünmemek de lazım.

Çünkü VAC bunu çok kolay bir şekilde anlar ve oyundan atılırsınız.

Konu 2: Basitce Cheat Engine Kullanımı

Cheat Engine bir işlemin hafızadaki verilerini değiştirmemizi ve diğer çeşitli işlemlerimizi yapmamızı sağlayan bir araçtır.

Oyun hileleriyle az çok ilgilenmişseniz bu programla ilgilenmişsiniz demektir zaten.

Mantık basit önce bir işleme bağlanıyoruz (bu bizim için csgo.exe) ardından verinin hafızadaki yerini bulmak için arama bölümüne veriyi yazıyoruz, veriyi azaltıyoruz ve işlemi tekrar yapıyoruz. Ta ki seçenekler azalana kadar. Ardından verinin hafızadaki yerini buluyoruz.

Cheat Engine ile ilgili daha sonradan bir konu açacağım o yüzden Cheat Engine’ye çok değinmeyeceğim.

Konu 3: Offsetler

Offsetler bizim veri adresimizin, bir adresten kaç byte uzak olduğunu gösterir. Bu adres sizin bellekteki adresiniz (Local Player) veya başka bir oyuncunun bellekteki adresi olabilir.

Örnek verirsem can değeri için
(Buradaki 0x7E değeri rastgele bir değerdir)

LocalPlayer + 0x7E = Kullanıcının Canının Bellekteki Adresi

Ve biz işlemlerimizi bu adresdeki veriyi okuyarak yapacağız.

Konu 4: Kodlamaya Giriş

Önceki derstekileri uyguladığınıza göre artık kodlamaya girebiliriz.

Öncekikle verileri değiştirmek için bir işleme yani csgo.exe’ye bağlanmamız gerek ardından Windows.h kütüphanesinde bulunan ReadProcessMemory ve WriteProcessMemory fonksiyonları ile işlemlerimizi gerçekleştireceğiz.

Konu 5: ReadProcessMemory

ReadProcessMemory veya kısaca RPM fonksiyonu bir işlemin bir adresindeki veriyi okumamızı sağlar.

Windows.h kütüphanesinde bulunur.

Şimdi gelin fonksiyonun MSDN sayfasına bakalım.

Gördüğünüz gibi fonksiyonumuza 5 adet argüman girmemiz gerek;

hProcess: Fonksiyonu uygulayacağımız işlemin HANDLE’ı

lpBaseAddress: Okumak istediğimiz verinin adresi (LPC****)

lpBuffer: Veri okundukdan sonra yazılacak değişken (Mesela 100 değerini okudukdan sonra lpBuffer’ı 100 olarak ayarlıyor.)

nSize: Adresden kaç byte okunacağı

*lpNumberOfBytesRead: Kaç byte okunduğunu yazdıracağı veri (aynı lpBuffer gibi)

Eğer fonksiyon başarılı bir şekilde çalışırsa ReadProcessMemory 0 dışında bir veri döndürür.

Konu 6: WriteProcessMemory

WriteProcessMemory yani kısaca WPM belirli bir adresdeki veriyi değiştirir veya yazar.

Windows.h kütüphanesinde bulunur.

hProcess: Veriyi yazacağımız işlemin HANDLE’si

lpBaseAddress: Veriyi yazacağımız adres

lpBuffer: Yazacağımız veri

nSize: Yazacağımız verinin boyutu

*lpNumberOfBytesWritten: İşlem boyunca yazılmış byte sayısı

Kullancağımız ana fonksiyonlar bu kadar kodlardaki diğer fonksiyonlara MSDN sayfasından bakabilirsiniz.

Konu 9: Hafıza Değiştirici Sınıfı

Hem programımızı düzenli tutmak için hemde işden tasaruf etmek için bir sınıf oluşturuyoruz.

Buradaki kodları anlamıyorsanız lütfen önce C++ öğrenin!

Kodun Tamamını 

include “pch.h”
#include <iostream>
#include <Windows.h>
#include <tlhelp32.h>
class CMemoryManager {
private:
HANDLE hProcess; // İşlemimizin belirlenecek olan HANDLE’si
DWORD dwProcessId; // İşlemimizin belirlenecek olan Id’si
const wchar_t* lpProcessName; // İşlemimizin belirlenecek olan adı
public:
// Çeşitlilik için 2 adet Attach fonksiyonu ürettim.
bool Attach(DWORD Id) { // Id kullanarak bağlanıyor.
hProcess = OpenProcess(PROCESS_ALL_ACCESS, // Bütün yetkiler ile // programı açtım
FALSE,
Id);
// Processimin HANDLE’sini aldım.
// PROCESS_ALL_ACCESS kipi sayesinde işlemde hem yazma hemde okuma
// yapabileceğim.
if (hProcess == INVALID_HANDLE_VALUE) // Process’e bağlanıldığını
return false; // kontrol ediyorum bağlanılmadıysa false döndürüyorum
dwProcessId = Id; // Bağlandıkdan sonra true döndürüyorum.
return true;
}
bool Attach(const wchar_t* ProcessName) { // İsim kullanarak bağlanıyor.
// Bu kısım biraz sancılı öncelikle bütün işlemlerin isimlerine
// bakıp eşleşen işlemin idsini kullanarak OpenProcess uyguluyorum.
// konumuzla çok alakası yok o yüzden yüzeysel anlatacağım.
PROCESSENTRY32 entry; // Bir PROCESSENTRY32 oluşturuyorum.
entry.dwSize = sizeof(PROCESSENTRY32);
// Bir Snapshot HANDLE’si oluşturuyorum.
HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
// HANDLE oluşturulamadıysa false döndürüyorum.
if (snap == INVALID_HANDLE_VALUE)
return false;
if (Process32First(snap, &entry)) { //Entryleri sırayla kıyaslıyorum.
if (wcscmp(entry.szExeFile, ProcessName) == 0) {
dwProcessId = entry.th32ProcessID;
CloseHandle(snap);
return Attach(dwProcessId); // Bulduğumuz ID ile bağlanıyoruz.
}
while (Process32Next(snap, &entry)) {
if (wcscmp(entry.szExeFile, ProcessName) == 0) {
dwProcessId = entry.th32ProcessID;
CloseHandle(snap);
return Attach(dwProcessId); // Bulduğumuz ID ile bağlanıyoruz.
}
}
}
return false;
}
template<class dataType>
bool WPM(DWORD dwAddress, dataType value) {
// Şablon değişkenimi kullanarak WPM uyguluyorum.
return WriteProcessMemory(hProcess,
(LPVOID)dwAddress,
&value,
sizeof(value),
NULL
);
}
template<class dataType>
dataType RPM(DWORD dwAddress) {
// Şablon değişkenimi kullanarak RPM uyguluyorum.
dataType lpBuffer;
ReadProcessMemory(hProcess,
(LPVOID)dwAddress,
&lpBuffer,
sizeof(lpBuffer),
NULL);
// Ardından okunan veriyi döndürüyorum.
return lpBuffer;
}
};
int main()
{
CMemoryManager MemoryManager;
if (MemoryManager.Attach(L”notepad.exe”) == true) {
std::cout << “Baglanti saglandi!” << std::endl;
}
getchar();
}

Artık oyuna da bağlandığımıza göre sonraki ders daha eğlenceli şeylere geçebiliriz.

[Toplam: 3   Ortalama: 5/5]
Yorum Yapmak İçin Tıklayın

Yorum Yapın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

To Top