Перейти к содержанию

Abraham08

Пользователи
  • Постов

    28
  • Зарегистрирован

  • Посещение

Сообщения, опубликованные Abraham08

  1. Извиняюсь сразу за тупой вопрос ) В общем, как мне известно, чтобы внедрить свою дллку в игру, необходимо написать эту самую библиотеку, а затем создать отдельно приложение типа такого:

    Скрытый текст


    
    int main(){
    
    	const char path[] = "hack.dll";
    
    	HANDLE op = OpenProcess();
    	HANDLE Thread;
    	HMODULE ll = GetModuleHandle("kernel32.dll");
    	FARPROC func = GetProcAddress(ll, "LoadLibraryA");
    	LPVOID arg_address = VirtualAllocEx(op, 0, strlen(path), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    	WriteProcessMemory(op, arg_address, path, strlen(path), 0);
    	Thread = CreateRemoteThread(op, 0, 0, (LPTHREAD_START_ROUTINE)func, arg_address, 0, 0);
    
    	return 0;
    }


     

     

    собственно, вопрос, а есть ли способ внедрить свою длл без стороннего приложения? Т.е. чтобы закинул библиотеку в папку с игрой и она сама подключилась?)

  2. 11 час назад, partoftheworlD сказал:

    Прочитай про недокументированные функции.(NtWow64QueryInformationProcess64
    NtWow64ReadVirtualMemory64) Инфы по ним мало.
     Для чтения из игры x64 можно использовать NtWow64ReadVirtualMemory64 в 32 битном трейнере и окошко будет работать, придется функции руками импортировать из ntdll. И вот статейку глянь.

    Вот спасибо, знать бы о них раньше)

    И, к слову, таки удалось запустить окно х64 проекта в в10, воспользовался этой шапкой:

    Скрытый текст
    
    
    HINSTANCE hInstance2;
    LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
    HWND hWnd;
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
    {
    	hInstance2 = hInstance;
    	WNDCLASSEX wc;
    	ZeroMemory(&wc, sizeof(WNDCLASSEX));
    	wc.cbSize = sizeof(WNDCLASSEX);
    	wc.style = CS_HREDRAW | CS_VREDRAW;
    	wc.lpfnWndProc = WindowProc;
    	wc.hInstance = hInstance;
    	wc.hCursor = LoadCursor(0, IDC_ARROW);
    
    	wc.lpszClassName = "WindowClass";
    	RegisterClassEx(&wc);
    	hWnd = CreateWindow("WindowClass", "DS2RANK", WS_SYSMENU | WS_MINIMIZEBOX, (GetSystemMetrics(SM_CXSCREEN) / 2) - 300, (GetSystemMetrics(SM_CYSCREEN) / 2) - 300, 600, 600, 0, 0, hInstance, 0);
    	ShowWindow(hWnd, nCmdShow);
    	
    	MSG msg;
    
    	while (1)
    	{
    		while (PeekMessage(&msg, 0, 0, 0, 1))
    		{
    			TranslateMessage(&msg);
    			DispatchMessage(&msg);
    		}
    		if (msg.message == WM_QUIT) break;
    	}
    	return (int)msg.wParam;
    }

     

    В итоге так и не понял почему мой вариант не работал. Вроде и тут и там одно и то же - создается, заполняется и регистриуется класс окна, создается окно с учетом разрешения, запускается цикл сообщений. Но мой вариант на х64 в10 не работал, а этот работает. Мистика.

  3. Вот полный код программы:

    Скрытый текст
    
    //Main.cpp
    
    #include <Windows.h>
    #include <string>
    #include "resource.h"
    #include <TlHelp32.h>
    #include <fstream>
    #include "MemReader.h"
    
    
    
    using namespace std;
    
    HWND hwnd;
    HINSTANCE hInstance2;
    DWORD64 var;
    fstream Logs;
    
    LRESULT CALLBACK DS2ZERO(HWND, UINT, UINT, LONG);
    
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR cmdLine, int nCmdShow){
    
    
    	MSG Msg;
    	WNDCLASSEX WndClass;
    	char name[] = "ClassName";
    	hInstance2 = hInstance;
    
    	WndClass.style = CS_HREDRAW | CS_VREDRAW;
    	WndClass.lpfnWndProc = (WNDPROC)DS2ZERO;
    	WndClass.cbClsExtra = 0;
    	WndClass.cbWndExtra = 0;
    	WndClass.hInstance = hInstance;
    	WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    	WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    	WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    	WndClass.lpszMenuName = NULL;
    	WndClass.lpszClassName = name;
    	WndClass.cbSize = sizeof(WNDCLASSEX);
    	WndClass.hIconSm = NULL;
    
    	if (!RegisterClassEx(&WndClass)){
    		MessageBox(NULL, "Cant register class", "Error", MB_OK);
    		exit(1);
    	}
    	HDC hDCScreen = GetDC(NULL);
    	int Horres = GetDeviceCaps(hDCScreen, HORZRES);
    	int Vertres = GetDeviceCaps(hDCScreen, VERTRES);
    	ReleaseDC(NULL, hDCScreen);
    
    
    
    	hwnd = CreateWindow(name, "DS2RANK", WS_OVERLAPPED | WS_SYSMENU, (Horres / 2) - 300, (Vertres / 2) - 300, 600, 600, NULL, NULL, hInstance, NULL);
    
    	if (!hwnd){
    		MessageBox(NULL, to_string(GetLastError()).c_str(), "Error", MB_OK);//
    		exit(1);
    	}
    
    	ShowWindow(hwnd, nCmdShow);
    	UpdateWindow(hwnd);
    
    	
    	while (GetMessage(&Msg, NULL, 0, 0)){
    
    		TranslateMessage(&Msg);
    		DispatchMessage(&Msg);
    	}
    
    	return Msg.wParam;
    
    
    }
    
    LRESULT CALLBACK DS2ZERO(HWND hwnd, UINT Message, UINT wParam, LONG lParam){
    	
    	static HANDLE background;
    	static Trainer ReadRank;
    	HDC hDC, hCompatibleDC;
    	PAINTSTRUCT PaintStruct;
    	RECT Rect, Rect2, Rect3;
    	
    	
    
    	switch (Message){
    
    	case WM_CREATE:
    
    		background = LoadBitmap(hInstance2, MAKEINTRESOURCE(IDB_BITMAP1)); //Фоновое изображение, загружаемое из RC файла
    
    		return 0;
    
    	case WM_PAINT:
    		GetClientRect(hwnd, &Rect);
    		hDC = BeginPaint(hwnd, &PaintStruct);
    		hCompatibleDC = CreateCompatibleDC(hDC);
    		SelectObject(hCompatibleDC, (HANDLE)background);
    		BitBlt(hDC, 0, 0, Rect.right, Rect.bottom, hCompatibleDC, 0, 0, SRCCOPY);
    
    		ReadRank.GetProcess();
    		ReadRank.GetModule();
    		ReadRank.OpenProc();
    
    
    		Rect2.left = 0;
    		Rect2.right = 192;
    		Rect2.top = 0;
    		Rect2.bottom = 367;
    
    		Rect3.left = 807;
    		Rect3.right = 192;
    		Rect3.top = 0;
    		Rect3.bottom = 367;
    
    		DrawText(hDC, to_string(ReadRank.GetBloodRank()).c_str(), -1, &Rect2, DT_CENTER|DT_SINGLELINE|DT_VCENTER);
    		DrawText(hDC, to_string(ReadRank.GetBlueRank()).c_str(), -1, &Rect3, DT_CENTER | DT_SINGLELINE | DT_VCENTER);
    		
    
    		DeleteDC(hCompatibleDC);
    		EndPaint(hwnd, &PaintStruct);
    
    
    		return 0;
    		
    	case WM_DESTROY:
    		DeleteObject(background);
    		PostQuitMessage(1);
    		return 0;
    
    	case WM_KEYDOWN:
    		if (wParam == 27) SendMessage(hwnd, WM_CLOSE, wParam, lParam);
    		InvalidateRect(hwnd, NULL, false);
    		return 0;
    	case WM_LBUTTONDOWN:
    		InvalidateRect(hwnd, NULL, false);
    		return DefWindowProc(hwnd, Message, wParam, lParam);
    	case WM_RBUTTONDOWN:
    		InvalidateRect(hwnd, NULL, false);
    		return DefWindowProc(hwnd, Message, wParam, lParam);
    	case WM_ERASEBKGND:
    		return 0;
    	}
    
    
    
    	return DefWindowProc(hwnd, Message, wParam, lParam);
    }
    

     

     

    Скрытый текст
    
    //MemReader.cpp
    #pragma once
    
    #include <Windows.h>
    #include <TlHelp32.h>
    #include <cstring>
    #include "MemReader.h"
    #include <string>
    
    
    
    Trainer::Trainer(){
    	ProcessName = new char[16];
    	BloodRank = 0;
    	BlueRank = 0;
    	strcpy_s(ProcessName, 16, "Game.exe");
    	pHandle = 0;
    }
    
    Trainer::~Trainer(){
    	delete[] ProcessName;
    }
    
    DWORD Trainer::GetProcess(){
    	HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    	PROCESSENTRY32 pInfo;
    	pInfo.dwSize = sizeof(PROCESSENTRY32);
    	if (Process32First(snapshot, &pInfo)){
    		do{
    			if (!strcmp(ProcessName, pInfo.szExeFile)){
    				pID = pInfo.th32ProcessID;
    				CloseHandle(snapshot);
    				return pInfo.th32ProcessID;
    			}
    		} while (Process32Next(snapshot, &pInfo));
    	}
    }
    
    MODULEENTRY32 Trainer::GetModule(){
    	HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pID);
    	MODULEENTRY32 mInfo;
    	mInfo.dwSize = sizeof(MODULEENTRY32);
    	Module32First(snapshot, &mInfo);
    	AddressBase = (INT64)mInfo.modBaseAddr;
    	//MessageBox(NULL, std::to_string(AddressBase).c_str(), "33", MB_OK);
    	CloseHandle(snapshot);
    	return mInfo;
    
    }
    
    HANDLE Trainer::OpenProc(){
    	return pHandle = OpenProcess(PROCESS_ALL_ACCESS, 0, pID);
    
    }
    
    short int Trainer::GetBloodRank(){
    	ReadProcessMemory(pHandle, (LPVOID)(AddressBase + 0x160B8D0), &AddressOffset, 8, NULL);
    	ReadProcessMemory(pHandle, (LPVOID)(AddressOffset + 0xd0), &AddressOffset, 8, NULL);
    	ReadProcessMemory(pHandle, (LPVOID)(AddressOffset + 0x490), &AddressOffset, 8, NULL);
    	ReadProcessMemory(pHandle, (LPVOID)(AddressOffset + 0x1c8), &BloodRank, 2, NULL);
    	return BloodRank;
    }
    
    short int Trainer::GetBlueRank(){
    	ReadProcessMemory(pHandle, (LPVOID)(AddressBase + 0x160B8D0), &AddressOffset, 8, NULL);
    	ReadProcessMemory(pHandle, (LPVOID)(AddressOffset + 0xd0), &AddressOffset, 8, NULL);
    	ReadProcessMemory(pHandle, (LPVOID)(AddressOffset + 0x490), &AddressOffset, 8, NULL);
    	ReadProcessMemory(pHandle, (LPVOID)(AddressOffset + 0x1c6), &BlueRank, 2, NULL);
    	return BlueRank;
    }
    
    DWORD64 Trainer::FindSignature(DWORD64 base, DWORD64 size, byte* sign, char* mask){
    	MEMORY_BASIC_INFORMATION mbi = { 0 };
    	DWORD64 offset = 0;
    	while (offset < size){
    		VirtualQueryEx(pHandle, (LPCVOID)(base + offset), &mbi, sizeof(MEMORY_BASIC_INFORMATION));
    		if (mbi.State != MEM_FREE){
    			byte* buffer = new byte[mbi.RegionSize];
    			ReadProcessMemory(pHandle, mbi.BaseAddress, buffer, mbi.RegionSize, NULL);
    			for (int i = 0; i < mbi.RegionSize; i++){
    				if (DataCompare(buffer + i, sign, mask)){
    					delete[] buffer;
    					return (DWORD64)mbi.BaseAddress + i;
    				}
    			}
    			delete[] buffer;
    		}
    		offset += mbi.RegionSize;
    		//MessageBox(NULL, std::to_string(mbi.RegionSize).c_str(), "33", MB_OK);
    	}
    	return 0;
    }
    
    bool Trainer::DataCompare(byte* data, byte* sign, char* mask){
    	for (; *mask; data++, mask++, sign++){
    		if (*mask == 'x' && *data != *sign) return false;
    	}
    	return true;
    }
    
    void Trainer::SetAddressBase(DWORD64 addr){
    	AddressBase = addr;
    }

     

     

    Скрытый текст
    
    //Memreader.h
    
    #pragma once
    
    #include <Windows.h>
    #include <TlHelp32.h>
    
    class Trainer{
    public:
    	Trainer();
    	~Trainer();
    	DWORD GetProcess();
    	MODULEENTRY32 GetModule();
    	HANDLE OpenProc();
    	short int GetBloodRank();
    	short int GetBlueRank();
    	DWORD64 FindSignature(DWORD64 base, DWORD64 size, byte* sign, char* mask);
    	bool DataCompare(byte* data, byte* sign, char* mask);
    	void SetAddressBase(DWORD64);
    private:
    	short int BloodRank;
    	short int BlueRank;
    	char*	  ProcessName;
    	HWND	  hWndDS;
    	DWORD	  pID;
    	HANDLE    pHandle;
    	INT64     AddressBase;
    	INT64     AddressOffset;
    };

     

     

    Как уже говорил, проблема только на windows 10 и только в режиме x64 (в режиме x32 на w10 окно создается, но программа не работает т.к. функции принимают 4 байтовые значения)

    Может нужно какие-то ещё параметры изменить в Project Properties? Или версия студии неподходит?

  4. В 29.01.2016в15:35, partoftheworlD сказал:

     

    А вы трейнеры для 64 битных игр делали под windows 10? Тут такое дело, чтобы функции ReadProcessMemory и подобные принимали в качестве параметров 8 байтовые значения (я имею в виду второй параметр, в который заносится адрес из которого нужно считать данные, а в 64 битной игре и адреса 64 битные), необходимо перевести проект в Visual Studio 2013 в 64 битный режим (Project-> Project Properties->Configuration Manager->Active Solution Platform->x64), но вот в чем беда, на Windows 7 при таком раскладе всё продолжает работать, а в Windows 10 не создается окно (функция CreateWindow возвращает 0), я даже без трейнера попытался его создать, банальный шаблон программы HelloWorld, где просто создается окно и более ничего, в 32 битной версии нормально всё, а в 64 окно не хочет создаваться (проблема только на Windows 10), не знаете в чём дело?

     

     

  5. Ещё такой вопрос: у меня есть байтовый адрес инструкции (48 8B 58 38 48 85 DB 74 * F6), есть сама инструкция (mov rbx,[rax+38]), в регистре rax хранится нужный мне адрес (тот самый, который был получен вчера через MODULEENTRY32), как можно на с++ добраться до этого регистра и считать из него информацию? Дело в том, что вчерашний вариант работает исключительно на в7, этот же вариант будет работать и на в10.

  6. А где именно в той структуре адрес лежит? Я сделал так

    	INT64 address;		snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);		pInfo.dwSize = sizeof(PROCESSENTRY32);		if (Process32First(snapshot, &pInfo)){			while (Process32Next(snapshot, &pInfo)){				if (!strcmp(name, pInfo.szExeFile)){					HANDLE hSnap;					hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pInfo.th32ProcessID);					MODULEENTRY32 mod;					if (Module32First(hSnap, &mod))					{																	}					CloseHandle(hSnap);				}			}		}

    В mod оказывается экзешник игры (если верить mod.szExePath), но как адрес вытащить?

    modBaseAddr мне 0 возвращает
  7. У меня такая проблема - в СЕ самый нижний указатель (который должен быть статическим ) имеет вид "xxx.exe+160B8D0", так вот, сам xxx.exe  - динамический и каждый раз меняется.

    Как его можно занести в код на с++? Был бы он статическим, записал бы так:

            ReadProcessMemory(phandle, (LPVOID)(0x13F8D0000 + 0x160B8D0), &address, 8, NULL);        ReadProcessMemory(phandle, (LPVOID)(address + 0xd0), &address, 8, NULL);        ReadProcessMemory(phandle, (LPVOID)(address + 0x490), &address, 8, NULL);        ReadProcessMemory(phandle, (LPVOID)(address + 0x1c6), &BlueRank, 2, NULL);

    Но увы, стоит перезрузить систему и уже не работает из-за измененного базового адреса (0x13F8D0000).

  8. Не, все эти типы тоже были 4 байтовые. Потратил пол дня на поиск ответа, а оказалось всё предельно просто.. http://www.mpgh.net/forum/showthread.php?t=860166 вот тут у человека была такая же проблема. Нужно было всего лишь перейти в режим 64 битного приложения в VS, после этого и LPVOID, и LPCVOID стали 8 байтовые и спокойно приняли этот адрес.

  9. В общем, хочу написать трейнер для 64битной игры (она использует 64 битные адреса, 0х7FFED6CF128, в этом духе), а функция ReadProcessMemory в качестве аргумента принимает LPVOID , который 4 байтовый. Т.е. передавая этой функции адрес, передается только ED6CF128, а остальная часть теряется и, соответственно, функция считывает мусор. Как передать ей полный адрес? С 32 битными процессами проблем нет, там всё считывается прекрасно.

  10. И снова здравствуйте. Может кто-нибудь помочь c пониманием как работает нижеследующий скрипт (сразу скажу - он рабочий, просто хочу наконец понять как точно он работает) ? Часть мне понятна, сам его несколько раз восстанавливал ибо для игры выходили патчи и ломали его, менялись адреса, поменялась инструкция раз и тд, но непонятная мне часть продолжала работать исправно.

     

    Итак, что делает этот скрипт? Он телепортирует всех монстров, которые в данный момент просчитываются игрой, к игроку. Работа здесь идет только с одной инструкцией:

     

    "DAI.exe"+BCB4AA:
    movaps xmm0,[rax+000001A0]

     

    Она отвечает за координаты как героя, так и монстров, в [rax+1A0] хранится адрес этой самой координаты (первой идет X, с шагом 4 идут Y и Z).

    Вначале (то, что находится между //1) мы cравниваем что лежит в [rax+1A0] (координата Х) и [rax+1A8] (координата Z) с тем, что лежит в адресах этих координат, принадлежащих игроку, т.е. делаем фильтр, отсеивающий их изменение. Далее (//2) мы кладем координаты игрока в [moffset+4,8,C], сам [moffset] равен 1, что отвечает за расстояние, на котором должны появится монстры относительно игрока, а [mmindist] - дистанция, на которой монстры могут быть захвачены (т.е. если ввести 1 - монстры не захватятся вообще, а в 5000 захватываюстя со всей локации), таким образом монстры должны были бы телепортироваться к игроку. Вот эта часть мне ясна. Собственно, если так и оставить (заменив [moffset+*] на [rax+*]), то монстры действительно будут телепортироваться к игроку, но после отключения скрипта, сделав хоть 1 движения, они сразу же вернутсья туда, откуда их вытащили. И вот дальнейшая часть скрипта каким-то образом это исправляет, заставляя их остаться на месте.

     

    С другими инструкциями, вроде бы, работы не ведется, потому мне не понятно как это происходит.

     

    Особенно мне непонятно то, что находится между //3 (в дальнейшем есть еще несколько таких конструкций). Как я понимаю, это какой-то цикл, но как именно он работает так и не смог разобраться, может кто-то объяснить эту конструкцию? Могу сказать одно - если отключить эти циклы, то телепорта не будет происходить никакого.. а еще, перед последним патчем в mov rcx,2 (это счетчик, как я понимаю, т.е. сколько раз должен цикл выполниться), был равен 9. После патча такая конструкция стала работать неверно - монстры захватывались далеко не все, могли телепортироваться те, которые стояли в другой части карты, а стоящие в 2х шагах не захватывались. Когда я поменял 9 на 2 - все заработало снова, как прежде.

     

    Извиняюсь за всю эту стену, но сам так и не разобрался во всем этом, может найдется кто-то, кому не лень будет немного пролить свет на все это?) Или, хотя бы, объяснить как работает цикл между //3.

    [ENABLE]alloc(magnet,4096,"DAI.exe"+BCB4AA)label(returned)label(skipme)label(skipplayer)label(pcoord)label(mcoord)label(moffset)label(mcount)label(mmindist)label(mcalcdist)label(mconst)label(pangle)label(tests)registersymbol(mmindist)registersymbol(mcount)registersymbol(moffset)magnet:push raxpush rbxpush rdxpush rcxpush rdipush rsipush edx //1push rbxmov rbx,[DAI.exe+160B8D0]mov rbx,[rbx+98]mov rbx,[rbx+28]mov rbx,[rbx+0]mov rbx,[rbx+100]mov rbx,[rbx+10]mov rbx,[rbx+10]mov rbx,[rbx+1d0]mov rbx,[rbx+20]mov edx,[rbx+1a0]pop rbxcmp [rax+000001A0],edxpop edxjne testspush edxpush rbxmov rbx,[DAI.exe+160B8D0]mov rbx,[rbx+98]mov rbx,[rbx+28]mov rbx,[rbx+0]mov rbx,[rbx+100]mov rbx,[rbx+10]mov rbx,[rbx+10]mov rbx,[rbx+1d0]mov rbx,[rbx+20]mov edx,[rbx+1a8]pop rbxcmp [rax+000001A8],edxpop edxje skipplayer //1{let's just check this isn't the player}//mov ebx,[[[[[[[DAI.exe+FDB074]+74]+B8]+8]+14]+1B0]+10]//cmp ebx,eax//je skipplayer{copy player coords}tests:push edx //2push rbxmov rbx,[DAI.exe+160B8D0]mov rbx,[rbx+98]mov rbx,[rbx+28]mov rbx,[rbx+0]mov rbx,[rbx+100]mov rbx,[rbx+10]mov rbx,[rbx+10]mov rbx,[rbx+1d0]mov rbx,[rbx+20]mov edx,[rbx+1a0]pop rbxmov [moffset+4],edxpop edxpush edxpush rbxmov rbx,[DAI.exe+160B8D0]mov rbx,[rbx+98]mov rbx,[rbx+28]mov rbx,[rbx+0]mov rbx,[rbx+100]mov rbx,[rbx+10]mov rbx,[rbx+10]mov rbx,[rbx+1d0]mov rbx,[rbx+20]mov edx,[rbx+1a8]pop rbxmov [moffset+C],edxpop edxpush edxpush rbxmov rbx,[DAI.exe+160B8D0]mov rbx,[rbx+98]mov rbx,[rbx+28]mov rbx,[rbx+0]mov rbx,[rbx+100]mov rbx,[rbx+10]mov rbx,[rbx+10]mov rbx,[rbx+1d0]mov rbx,[rbx+20]mov edx,[rbx+1a4]pop rbxmov [moffset+8],edxpop edx//2mov [mmindist],(float)5000mov [moffset],(float)1//3add rbx,1A0mov rsi,rbxmov rdi,pcoordcldmov rcx,2rep movsb //3//jmp skipplayer{copy monster coords}add rax,1A0mov rsi,raxmov rdi,mcoordcldmov rcx,2rep movsbsub rax,1A0{calculate distance}movss xmm0,[pcoord]movss xmm1,[mcoord]subss xmm0,xmm1mulss xmm0,xmm0movss [mcalcdist],xmm0movss xmm0,[pcoord+4]movss xmm1,[mcoord+4]subss xmm0,xmm1mulss xmm0,xmm0movss [mcalcdist+4],xmm0movss xmm0,[pcoord+8]movss xmm1,[mcoord+8]subss xmm0,xmm1mulss xmm0,xmm0movss [mcalcdist+8],xmm0movss xmm0,[mcalcdist]movss xmm1,[mcalcdist+4]addss xmm0,xmm1movss xmm1,[mcalcdist+8]addss xmm0,xmm1movss [mcalcdist+c],xmm0fld dword ptr [mcalcdist+c]fsqrtfstp dword ptr [mcalcdist+c]{test distance}movss xmm0,[mcalcdist+c]movss xmm1,[mmindist]cmpss xmm0,xmm1,1movss [mcalcdist+C],xmm0cmp [mcalcdist+C],0je skipme{increment monster counter}mov rcx,[mcount]inc rcxmov [mcount],rcx{get orientation}//mov ebx,[[[[DAI.exe+FDB074]+74]+B4]+A8]// movss xmm0,[ebx+54]//movss xmm0,[ebx]//addss xmm0,[mconst+4]//mulss xmm0,[mconst]//movss [pangle],xmm0{calculate sine/cosine pair}fld dword ptr [pangle]fsincosfstp dword ptr [pangle+4]fstp dword ptr [pangle+8]{calculate offsets}movss xmm0,[pcoord]addss xmm0,[moffset+4]movss xmm1,[moffset]mulss xmm1,[pangle+8]subss xmm0,xmm1movss [mcoord],xmm0movss xmm0,[pcoord+4]addss xmm0,[moffset+8]movss [mcoord+4],xmm0movss xmm0,[pcoord+8]addss xmm0,[moffset+C]movss xmm1,[moffset]mulss xmm1,[pangle+4]subss xmm0,xmm1movss [mcoord+8],xmm0{assign new coords to "previous" vector}add rax,1A0mov rsi,mcoordmov rdi,raxcldmov rcx,crep movsb{assign new coords to "next" vector}add rax,20mov rsi,mcoordmov rdi,raxcldmov rcx,crep movsbskipme:pop rsipop rdipop rcxpop rdxpop rbxpop rax{old scope}movaps xmm0,[rax+000001A0]jmp returnedskipplayer:mov [mcount],0 {start counting from zero again}pop rsipop rdipop rcxpop rdxpop rbxpop raxmovaps xmm0,[rax+000001A0]jmp returnedpcoord:dq 0dq 0dq 0pangle:dq 0dq 0dq 0mcoord:dq 0dq 0dq 0mcount:dq 0mcalcdist:dq 0dq 0dq 0dq 0mmindist:dq (float)10moffset:dq (float)5dq (float)0dq (float)0dq (float)0mconst:dq (float)3.14159265dq (float)1dq (float)-1{blank out the call to fall timer test (I think?)}//"DAI.exe"+34139D://nop//nop//nop//nop//nop{hook magnet at per-critter position update code}"DAI.exe"+BCB4AA:jmp magnetnopnopreturned:[DISABLE]"DAI.exe"+BCB4AA:movaps xmm0,[rax+000001A0]unregistersymbol(mmindist)unregistersymbol(mcount)unregistersymbol(moffset)dealloc(magnet)
  11. Для того, чтобы точно ответить на вопрос, нужны твой скрипт и информация на что срабатывает игровая инструкция, которую ты использовал в скрипте (на ход ГГ или всегда читает координаты, ну и т.д.).

     

    Инструкция вообще не имеет отношения к координатам..

    У меня есть структура заклинаний. Там можно изменить кол-во вылетающих снарядов, скорость, траекторию и даже дочерние части спелла, прикрепленные к заклинанию. Т.е. изменяя числа и id в этой структуре можно создавать свои уникальные заклинания. Так вот, я написал скрипт, который приделан к удару правой рукой (инструкция считывается пока нажата кнопка удара, успевает за 1 нажатие проработать раз 15-20), сразу после срабатывания этой инструкции я вписал свои mov [xxx],(float)xx или mov [xxx],#xx и так далее, где вместо [xxx] - адреса, в которые я хочу внести изменения (и которые не имеют отношения к выполняемой инструкции), а в (float)xx - новые значения. Так вот некоторые адреса, изменяемые таким образом, дают нужный результат, а другие нет, хотя если менять их вручную - все выдают нужный результат. Телепорт я привел только в качестве примера тк это один из вариантов, в которых такая подмена работала неверно. Вот и хочу понять где зарыта собака.. скрипт выкладывать нет смысла мне кажется - стандартный шаблон, сразу после оригинальной инструкции (повторюсь, не имеющей отношения к изменяемым адресам) эти строки с подменой значений в адресах. Или так вообще не стоит делать?

    И еще, эти адреса, которые пытаюсь изменить таким способом - статические.

  12. А может кто-нибудь ответить еще на 1 вопрос - почему некоторые адреса, изменяемые через скрипт, работают иначе, чем при ручном изменении? Простой пример: я нашел адрес с координатами героя (там их было штук 100 для каждой координаты, я выбрал нужный), если вручную, через таблицу, поменять значение, то происходит телепорт и все нормально. Но если в этот адрес занести нужное значение через скрипт (записью вида: mov [xxxxxxxx],(float)xx ), то происходит лишь иллюзия телепорта - герой перемещается на нужный участок, но при любом движении сразу же возвращаетя назад. Я обратил внимание, что при ручном изменении все оставшиеся 99 адресов также изменяются на то, что я ввел в первый адрес. А при изменении скриптом они остаются прежними, меняется только тот, в который я занес значение, что и заставляет, видимо, персонажа вернуться назад. Как с этим бороться, что сделать, чтобы при изменении адреса через скрипт эффект был бы аналогичен ручному изменению?

  13. Да, так тоже работает, адрес максимальных жизней лежал в [rbx+170].

    Но уже получилось и по другому сделать, запись вида:

    cmp rbx,000007FFEFDE9A40je exitoriginalcode:cmp dword ptr [rbx+00000168],00exit:jmp returnhere

    Оказалась неисправной, а вот так:

    push raxmov rax,000007FFEFDE9A40cmp rbx,raxje exitoriginalcode:cmp dword ptr [rbx+00000168],00exit:pop raxjmp returnhere

    заработало. Не  понимаю в чем разница, какие еще сюрпризы принесет 64 разрядность.. причем если бы я напрямую сравнивал не с адресом жизней, а с каким-нибудь "0" - простым числом, то фильтр сработал бы сразу.

  14. Возникла еще проблема. Захотел сделать для этой же игры бессмертие. Нашел нужную инструкцию - при ее отключении урон просто не засчитывается. Эта же инструкция работает также и с монстрами, соответственно все становятся бессмертными. Инструкция вида cmp dword ptr [rbx+00000168],00, в rbx+168 находится адрес жизней, если монстр бьет по мне - моих (который статический), если я бью по монстру - его. В других играх ставил простой фильтр, который сравнивал значение регистра с адресом жизней (с учетом смещения, естественно) и если адрес совпадал с геройским - скрипт перепрыгивал оригинальную инструкцию. Сейчас  же у меня что-то не выходит, фильтр не срабатывает, в чем может быть проблема? К слову, недавно делал еще 1 скрипт для этой игры и там также была проблема с фильтром, определяющим адрес, фильтр заработал только с регистром, в котором находился "0" в нужном мне случае.

     

     

    Адрес самих жизней - 7FFEFDE9BA8

     

    UPD

     

    Просидел полчаса, не понимал что не так, запостил здесь и сразу же пришла мысль сравнить rbx не с самим значением, а с rax, предварительно положив это же значение в него (rax) и все заработало.. теперь задаюсь другим вопросом - почему не получилось сравнить напрямую? В прошлых играх всегда напрямую сравнивал и работало.. точно также, как и с этими указателями - старая запись перестала работать в 64 битной игре..

    [ENABLE]//code from here to '[DISABLE]' will be used to enable the cheatalloc(newmem,2048,"DAI.exe"+1671B5)label(returnhere)label(originalcode)label(exit)newmem: //this is allocated memory, you have read,write,execute access//place your code herecmp rbx,000007FFEFDE9A40je exitoriginalcode:cmp dword ptr [rbx+00000168],00exit:jmp returnhere"DAI.exe"+1671B5:jmp newmemnopnopreturnhere:[DISABLE]//code from here till the end of the code will be used to disable the cheatdealloc(newmem)"DAI.exe"+1671B5:cmp dword ptr [rbx+00000168],00//Alt: db 83 BB 68 01 00 00 00
  15. Не, без указателя там нельзя было обойтись. Я rbx после внесения указателя в eax восстанавливал pop'ом.

    А насчет вашей замены alloc на registersymbol.. в чем вообще разница между ними? Я обычно в alloc все заношу, как-то мне это более понятно - резервирую место в памяти с указанием размера и туда забрасываю значения.

  16. NullAlex: большой код принято заключать не только в тег кода, но и в спойлер.
    [ENABLE]//code from here to '[DISABLE]' will be used to enable the cheatalloc(newmem,2048,"DAI.exe"+373B05)label(returnhere)label(originalcode)label(exit)alloc(Coord,64)alloc(offset,64)newmem: //this is allocated memory, you have read,write,execute access//place your code heremov [offset],(float)0.7push eaxmov eax,[[[[[[[[[[DAI.exe+160B8D0]+98]+28]+0]+100]+10]+10]+1d0]+20]+1a0]mov [Coord],eaxfld [Coord]fadd [offset]fstp [Coord]mov eax,[Coord]mov [rbx+10],eaxpop eaxpush eaxmov eax,[[[[[[[[[[DAI.exe+160B8D0]+98]+28]+0]+100]+10]+10]+1d0]+20]+1a4]mov [rbx+14],eaxpop eaxpush eaxmov eax,[[[[[[[[[[DAI.exe+160B8D0]+98]+28]+0]+100]+10]+10]+1d0]+20]+1a8]mov [rbx+18],eaxpop eaxoriginalcode:mov eax,[rbx+10]movss xmm1,[rbx+18]exit:jmp returnhere"DAI.exe"+373B05:jmp newmemnopnopnopreturnhere:  [DISABLE]//code from here till the end of the code will be used to disable the cheatdealloc(newmem)dealloc(Coord)dealloc(offset)"DAI.exe"+373B05:mov eax,[rbx+10]movss xmm1,[rbx+18]
  17. Как можно записать в скрипт указатель на нужный адрес? Раньше я использовал в одном из скриптов такую запись:

    mov eax,[[[[[[[1201ed44]+b8]+8]+14]+1b0]+10]+120]

    И все работало. Сейчас, в другой игре, которая использует 64 битные адреса, нужно сделать похожую запись, пишу вот так:

    mov eax,[[[[[[[[[[DAI.exe+160B8D0]+98]+28]+0]+100]+10]+10]+1d0]+20]+1a0]

    и компилятор ругается на эту запись. Указатель верный - в таблице все определяет и меняется через него правильно. Но мне нужно записать его в скрипт.. пока что мучаюсь, вручную указывая в скрипте в нескольких местах адрес, на который в конечном счете указывает этот указатель. Но каждый раз его менять  при перезапуске игры - очень утомляет.

  18. Выложи сюда скрипт, посмотрим - может ошибка в скрипте. Хотя это может быть и особенностью игры.

    Особо для этого ничего не писал - есть адрес для оси Х со значением типа float (для остальных осей аналогично), если этот адрес заморозить и вставить свое значение, то происходит описанная мной ситуация (без заморозки там вообще небольшой рывок в сторону и на этом все). Ставил на этот адрес бряк на доступ, первой инструкцией является movq xmm0,[eax+08], которая считывается каждый кадр. [eax+08] - это адрес нашей координаты Х. В скрипте я просто перед меткой оригинального кода ставил свое

    mov [eax+08],(float)***, где вместо звездочек любое выбранное заранее число. При запуске этого скрипта также происходит вышеописанная ситуация.

     

    UPD В дебрях сети обнаружил таблицу с функцией телепорта для главного героя. Вместо скриптов или осей xyz там длиннющий массив байтов, изменяющийся при любом малейшем движении игрока. Если его сохранить в одном месте, перейти в другую часть локации и вставить сохраненное значение, то произойдет моментальный телепорт. Пока самому выйти на этот адрес не удалось, если пойму как он был найден, то, возможно, удастся и для монстров найти подобные и будет дело в шляпе)

     

    Ребята сори за оффтоп.

     

     

    garik66 ты знаешь как тема эта называлась или может ссылка на нее у тебя есть. Я ее никак не могу найти.

     

    У меня тоже пока не получилось найти эту тему, если вдруг обнаружится - скинь пожалуйста ссылку сюда)

  19. Такой скрипт написать можно, сам я лично не делал, но читал где-то у MasterGH - он делал выстрел в игре из другой части кода (извини - объяснить не смог, читал давно и пока уровня моего опыта и знаний маловато чтобы было понять как это сделал MasterGH). Но точно помню, что он использовал Call для вызова кода выстрела и потом  Ret для возврата назад в свою инъекцию. Так что написать, то что описал, можно. 

     

    Это на этом форуме была статья/скрипт такой? Нужно будет поискать, с самого первого дня как познакомился с СЕ была мысль такое проворачивать.

     

    Зачем тебе проход монстра сквозь стены. Тебе просто нужно вписывать каждому монстру координаты ГГ, а игра обычно сама подвигает движущийся объект. Грубо говоря, то что ты хочешь сделать это Blink-телепорт наоборот: не ГГ прыгает на чьи-то координаты (прицел, НПС), а наоборот монстр будет прыгать на координаты ГГ.

    Посмотри, как пример у меня в скрипте  Blink-телепорт: ГГ прыгает на координаты ближайшего НПС и тот двигается (в видео, которое ниже в сообщении это видно) Скрипт и видео здесь. 

    Так я выше писал, что нашел координаты как игрока, так и монстров, но при их искусственном изменении не происходит моментального телепорта как в других играх - персонаж начинает рывками без анимации бега/ходьбы двигаться к новым координатам и если между старой и новой точкой присутствует препятствие - он через нее не пройдет. Если Xipho прав, то на это дело влияет как-то система коллизий.

  20. Не, там все правильно - когда игра запускает эту инструкцию и видит, что регистр edi равен указанному в сравнении, то она проверяет какое значение флага установлено. Если 0 (а оно 0 до тех пор, пока не пальнешь заклинанием), то флаг изменяется на 1 и дальше идет по коду (когда срабатывают другие инструкции, они также проверяют флаг и при значении "1" происходит выполнение моего кода, иначе все идет по стандарту), под конец нас снова перекидывают к старту первой инструкции, она вновь проверяет флаг, видит, что он равен 1 и переходит к "метке 2", в которой флаг меняется на 0, затем выполняется стандартный код выстрела заклинания и на этом все заканчивается. Меня интересует, вообще такие вещи можно делать? Первая инструкция срабатывает при выстреле заклинания, а вторая и остальные должны срабатывать при ударе по монстру, я же попытался добавить эффект удара при выстреле заклинания. Ошибка, мне кажется, в том, что так смешивать инструкции нельзя, а если и можно, то существуют какие-то правила, о которых мне неизвестно)

  21. Спасибо, keng, но у меня проблема именно с тем, чтобы подвигать монстра (вернее подвигать так, что б он прошел сквозь стену), если бы это удалось - найти координаты и соответствующие инструкции для каждого монстра было бы несложно, а затем написать скрипт, что б в эти инструкции вписал нужные мне значения. Искать массив указателей, конечно, правильней, приму к сведению)

     

    Такой еще вопрос, когда пишешь скрипт, можно ли делать так: при запуска некой инструкции, при проверке, например, флага или еще какого-нибудь фильтра, делать прыжок вообще в другую часть исполняемого кода, к инструкции, которая запускается при других условиях, предварительно изменив регистры на те, которые должны быть при правильном запуске этой инструкции, затем от нее пройти часть кода и, наконец, восстановив регистры назад, вернутся к тому месту, откуда был совершен прыжок или это заведомо фейл? Собственно, я уже написал такой скрипт:

    [ENABLE]alloc(newmem,2048)alloc(newmem2,2048)alloc(newmem3,2048)label(returnhere)label(returnhere2)label(returnhere3)label(originalcode)label(exit)label(originalcode2)label(exit2)label(originalcode3)label(exit3)label(flag1)label(metka)label(metka2)label(metka3)registersymbol(flag1)newmem:cmp edi,1098732Cjne originalcodecmp [flag1],1je metka2mov [flag1],1jmp DarkSoulsII.exe+1C36B2//mov [102AD8AC],#150metka2:mov [flag1],0originalcode:mov al,[edi+2F]movsx edx,alexit:jmp returnhere2newmem2://mov [ebp+08],#100cmp [flag1],0je metkamov eax,103FB600mov ebx,1030BF00mov ecx,00000000mov edx,1259DC20mov esi,103FC010mov edi,104CE8F0mov esp,0018F068mov ebp,0018F070metka:push eaxmov eax,[ebp+08]imul eax,eax,#2mov [ebp+08],eaxpop eaxoriginalcode2:mov edx,[ebp+08]mov eax,[esi+000000FC]cmp [flag1],1je metka3exit2:jmp returnheremetka3:jmp DarkSoulsII.exe+1C36B5newmem3:originalcode3:mov [esi+000000FC],ecxcmp [flag1],0je exit3mov eax,00000001mov ebx,0018F7F8mov ecx,00000001mov edx,00000000mov esi,10380770mov edi,1098732Cmov esp,0018F790mov ebp,0018F7F0jmp DarkSoulsII.exe+3ED7D2exit3:jmp returnhere3flag1:db 00"DarkSoulsII.exe"+1C36F1:jmp newmem3nopreturnhere3:"DarkSoulsII.exe"+3ED7D2:jmp newmemnopreturnhere2:"DarkSoulsII.exe"+1C36B2:jmp newmem2nopnopnopnopreturnhere: [DISABLE]dealloc(newmem)dealloc(newmem2)dealloc(newmem3)unregistersymbol(flag1)"DarkSoulsII.exe"+3ED7D2:mov al,[edi+2F]movsx edx,al"DarkSoulsII.exe"+1C36B2:mov edx,[ebp+08]mov eax,[esi+000000FC]"DarkSoulsII.exe"+1C36F1:mov [esi+000000FC],ecx

    При его запуске, пока флаг равен 0, все работает нормально, но если выстрелить определенным заклинанием (в этом случае регистр edi становится равным 1098732C), флаг переходит в состояние "1". По задумке, в конце флаг должен вернутся в состояние "0" и на этом все закончится, но у меня начинается бесконечный цикл, заклинания начинают стрелять как из пулемета, 50 снарядов в секунду, что через десяток секунд приводит к крашу.

     

     

  22. Ну я же расписал ради чего мне это - заснять эпичное видео с битвой полусотни монстров против героя, вооруженного кучей кастомных заклинаний, это пве. Учитывая, что на вашем форуме в разделе таблиц есть тема по дарк соулсу второму, в которой лежит скрипт, увеличивающий урон по противникам и уменьшающий по герою, то решил, что запрета на обсуждение взлома данной игры нет, иначе не создавал бы тему.

×
×
  • Создать...

Важная информация

Находясь на нашем сайте, Вы автоматически соглашаетесь соблюдать наши Условия использования.