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

edx

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

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

  • Посещение

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

  1. 1 час назад, JustHack сказал:

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

    Ну, собственно вопросы пронумерованы в самом низу, многобукв что ли? Или мне предисловие убрать?)

  2. Всем здравствуйте. Я уже как-то затрагивал эту тему, но вскользь (там было про пайпы, чтение\запись памяти, shared sections и прочее) и я так толком и не нашел ответа.

    Суть вот в чем, есть GUI в виде exe-шника, написанного в VS 2019 с использованием конструктора и есть dll, которая загружается в процесс. Необходимо организовать обмен данными между dll и exe.

    Я в этом не сильно шарю..) Но пока что я остановился на OpenFileMapping по которым передаются структуры с данными.

    Порядок действий:

    Создаю одинаковые структуры там и там, к примеру:

    struct sysMessages
    {
    	BOOL dllStatus = 0;
    	BOOL update = 0;
    	char* msg;
    };
    struct userInfo
    {
    	int User[50];
    	int Count;
    };
    
    typedef struct
    {
    	sysMessages messages;
    	userInfo info;
    }BufferStruct, * pBufferStruct;
    
    pBufferStruct buf;

    И далее файл мэппинг:

    В DLL

    DataMapping = OpenFileMappingW(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, L"Local\\gui.datamap");
    ActionsMapping = OpenFileMappingW(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, L"Local\\gui.actmap");
    
    Actions = (pActions*)MapViewOfFile(ActionsMapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
    buf = (BufferStruct*)MapViewOfFile(DataMapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);

    В GUI

    DataMapping = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(buf), L"Local\\gui.datamap");
    ActionsMapping = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(buf), L"Local\\gui.actmap");
    
    Actions = (pActions*)MapViewOfFile(ActionsMapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
    buf = (BufferStruct*)MapViewOfFile(DataMapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);

    И дальше просто пишу\читаю из структуры buf и Actoins.

    Тут возникло несколько вопросов:

    1. Сколько хэндлов(если можно так сказать) файл маппинга можно открывать и как это скажется на скорости работы?

    2. Не произойдет ли конфликта, если gui и dll одновременно будут писать/читать в/из структуру(ы)? Да, мне писали про согласование чтения\записи, но что будет если просто забить на это?

    3. Если dll будет только писать в структуру, а gui только читать из нее, нужно ли думать о согласовании?

    4. Есть ли какой-то мануал\статья по сокетам? По сути мне - нужно изменять значение переменных там и там.

     

    Еще где-то мельком видел инфу про создание внешних интерфейсов в dll и exe, но без каких-либо примеров.

  3. 12 минут назад, Xipho сказал:

    Посмотри в сторону Sikuli IDE. Там и без OpenCV такая решалка есть. Причем быстрая. Точнее, не решалка, а поисковик картинки по паттерну. И даже можно задать уровень точности совпадения.

    Хм, спасибо очень даже интересно и код при чем пишется на Python'е, что много проще, возьму в копилку.

     

    upd: Видео, и статейка на хабре:

     

  4. Всем доброго времени суток.

    Решил поботоводить известным ботом в известной игре:). Бот умеет решать капчу, но на данном сервере возникла проблема) Байпасы не перехватываются, а при попытке отправить какой-то из них (при чем верный), спустя пару попыток клиент закрывается, либо дисконнектит с сервера.

     

    Чтобы сильно не заморачиваться и не влезать в клиент, решил накидать прототип "решалки" на OpenCV. Применять можно абсолютно везде (в любой игре).

     

    Вид капчи:

    Спойлер

    image.png

     

    Софт:

    - VisualStudio 2019

    - OpenCV 3.4.10

     

    Итак, сначала нам надо получить handle окна, с которого мы будем снимать скрин:

    Для этого у нас будет 2 функции: GetPID и EnumWindowsProc

    Спойлер
    
    HWND hWindow = NULL;
    
    int GetPID()
    {
    	HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);;
    	PROCESSENTRY32 pentry32;
    
    	if (snap == INVALID_HANDLE_VALUE) return 0;
    	pentry32.dwSize = sizeof(PROCESSENTRY32);
    
    	if (!Process32First(snap, &pentry32)) { CloseHandle(snap); return 0; }
    	do
    	{
    		if (!lstrcmpi("L2.exe", &pentry32.szExeFile[0]))
    		{
    			CloseHandle(snap);
    			return pentry32.th32ProcessID;
    		}
    	} while (Process32Next(snap, &pentry32));
    	CloseHandle(snap);
    	return 0;
    }
    
    BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
    {
    	DWORD lpdwProcessId;
    	GetWindowThreadProcessId(hwnd, &lpdwProcessId);
    	if (lpdwProcessId == lParam)
    	{
    		hWindow = hwnd;
    		return FALSE;
    	}
    	return TRUE;
    }

     

     

    Далее описание в коде:

    Спойлер
    
    BOOL antibot_state = false;
    
    EnumWindows(EnumWindowsProc, GetPID());
    
    if (hWindow)
    	{
        RECT windowRect;
        GetWindowRect(hWindow, &windowRect);
    
      	// Получаем размеры и позицию окна
    	int left = windowRect.left;
    	int top = windowRect.top;
    	int right = windowRect.right;
    	int bot = windowRect.bottom;
    
    	int width = right - left;
    	int height = bot - top;
    
    	HDC hwndDC = GetWindowDC(hWindow);
    	HDC hdcMem = CreateCompatibleDC(hwndDC);
    	
        // Полный путь к папке в которой лежин паттерн с помощью которого мы определяем, что вылезло окно с капчей
      	// здесь - текущая папка с проектом
    	TCHAR dirBuffer[256];
    	DWORD ProjectPath = GetCurrentDirectory(256, dirBuffer);
    	const char* FILE_NAME = "\\antibot.jpg\0";
    	const char* FILE_PATH = strcat((char*)dirBuffer, FILE_NAME);
    
      	// Считываем паттерн из файла и прифодим к формату цвета RGB
    	Mat antibot = imread(FILE_PATH);
    	cvtColor(antibot, antibot, BI_RGB);
    
    	if (!antibot.data)
    	{
    		std::cout << "Image not loaded";
    		return -1;
    	}
    
    	// Далее сам цикл отработки
    	while (true)
    	{
    	HBITMAP hBitmap = CreateCompatibleBitmap(hwndDC, width, height);
    	SelectObject(hdcMem, hBitmap);
    	BitBlt(hdcMem, 0, 0, width, height, hwndDC, 0, 0, SRCCOPY);
    
    	BITMAPINFO BMI;
    	BMI.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    	BMI.bmiHeader.biWidth = width;
    	BMI.bmiHeader.biHeight = -height;
    	BMI.bmiHeader.biPlanes = 1;
    	BMI.bmiHeader.biBitCount = 32;
    	BMI.bmiHeader.biCompression = BI_RGB;
    	
    	Mat img = Mat(height, width, CV_8UC4);			// Сам скриншот
    	Mat result = Mat(height, width, CV_8UC4);		// Переменная для записи результата сравнения
    	Mat antibot_result = Mat(544, 60, CV_8UC4);		// Для записи результата сравнения паттерна окна капчи
    	Mat cropped_img, pattern, find_field;			// Обрезанное изображение без рамок
    
    	Rect cropp, roi, find_cropp;
    	
        // Rect обрезанного изображения. Здесь мы корректируем смещение координат по толщине рамки 
        // width - 16 это толщина рамки в 8 пикселей слева и справа
        // height - 39 толщина рамки 8 пикселей снизу и 31 пиксель сверху
    	cropp.x = 8;
    	cropp.y = 31;
    	cropp.width = width - 16;
    	cropp.height = height - 39;
    	
        // Для паттерна "Примера" картинки которую нужно найти и кликнуть (чтобы не искать по всему скриншоту)
    	roi.x = 561;
    	roi.y = 280;
    	roi.width = 25;
    	roi.height = 25;
    	
        // Область поиска в которой мы ищем нужную картинку (поле "Выбор")
    	find_cropp.x = 400;
    	find_cropp.y = 348;
    	find_cropp.width = 340;
    	find_cropp.height = 340;
    
    	cropped_img = img(cropp);		// Обрезаем скриншот (не знаю зачем конечно, но мне так больше нравится))
    	pattern = cropped_img(roi);		// Выделяем область из скриншота, в которой находится наш пример
    	find_field = cropped_img(find_cropp);	// Выделяем область поиска
    
    	GetDIBits(hwndDC, hBitmap, 0, height, img.data, &BMI, DIB_RGB_COLORS);
    
    	// Сравнение скриншота и паттерна антибота
    	matchTemplate(cropped_img, antibot, antibot_result, CV_TM_SQDIFF);
    	double    minval_a, maxval_a;
    	Point     minloc_a, maxloc_a;
    	minMaxLoc(antibot_result, &minval_a, &maxval_a, &minloc_a, &maxloc_a);
    	
        // Далее проверка. Необходимо вывести в консоль значения minval и maxval и посмотреть в каком диапазоне
        // находятся значения когда появляется наш паттерн на скриншоте. Я брал только по minval.
        // Также для удобства можно обводить область в которой нашелся наш паттерн
        if (minval_a >= 6.77e7 && minval_a <= 6.84e7)
        {
          char timeBuffer[80];
          time_t seconds = time(NULL);
          tm* timeinfo = localtime(&seconds);
          const char* format = "%H:%M:%S";
          strftime(timeBuffer, 80, format, timeinfo);
    
          cout << timeBuffer << " Finded ANTIBOT!" << endl;
          antibot_state = TRUE;
        }
    	else { antibot_state = FALSE; }
    	
        // Поиск паттерна "Примера" в нашей заданной области поиска и выполнение обводки первого попавшегося паттерна
        matchTemplate(find_field, pattern, result, CV_TM_SQDIFF);
        double    minval, maxval;
        Point     minloc, maxloc;
        minMaxLoc(result, &minval, &maxval, &minloc, &maxloc);
    	cv::rectangle(find_field, cvPoint(minloc.x, minloc.y), cvPoint(minloc.x + roi.width - 1, minloc.y + roi.height - 1), CV_RGB(255, 0, 0), 1, 8);
    
        if (antibot_state)
        {
          // Сохраняем координаты курсора
          POINT cur;
          GetCursorPos(&cur);
          
          // Центр квадрата найденной картинки
          int center_x = (minloc.x + minloc.x + roi.width - 1) / 2;
    	  int center_y = (minloc.y + minloc.y + roi.height - 1) / 2;
    	  
          // handle текущего активного окна
          HWND current_window = GetForegroundWindow();
          
          // Выбираем окно с игрой и совершаем клик в центре найденного квадрата с картинкой
          SetForegroundWindow(hWindow);
          Sleep(200);
          SetCursorPos(windowRect.left + find_cropp.x + center_x, windowRect.top + find_cropp.y + center_y + 29);
          Sleep(200);
          mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
          Sleep(200);
          mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
          mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
          Sleep(200);
          mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
    	  
          // Возвращаем окно с которого ушли
          SetForegroundWindow(current_window);
    
          // Восстановливаем координаты курсора
          SetCursorPos(cur.x, cur.y);
          ShowCursor(TRUE);
          Sleep(2000);
        }
    	
        // Для удобства подгона зоны в которой нужно искать паттерны можно вывести картинку
    	imshow("window", resized);
    
    	waitKey(1);
    	DeleteObject(hBitmap);
      }
    
    ReleaseDC(NULL, hwndDC);
    DeleteDC(hdcMem);	

     

     

    Скрины и описание:

    Спойлер

    Тут видим зеленый квадрат и красный. Подгоняем окно внутри игры так, чтобы "Пример" был в зеленом квадрате

    image.png

     

    Подогнали и видим, что программа нашла такую-же картинку. Кстати, несмотря на то, что наш пример темнее чем остальные картинки и там заштрихован фон.

    image.png

     

    В зависимости от позиции окна капчи внутри окна игры будет меняться и minval\maxval. Поэтому нужно следить за этим)

    Как только программа найдет картинку, выведет в лог сообщение и произведет необходимые действия :)

    image.png

     

    Пока что быстродействие сего чуда хромает.

    Программа является лишь прототипом для облегчения жизни себе любимому). Код "грязноват", есть лишние моменты, можно было упростить, перевести в GRAY, уменьшить картинку, возможно даже привести к сравнению хэшей, и так далее.

    Жду критики\предложений. Возможно буду дорабатывать программу под разные виды капч и сделаю GUI к ней (это не точно).

    Может кому пригодится)

  5. В 25.04.2020 в 22:22, mrPTyshnik сказал:

     

    1) найди код в игре который вызывает эту функцию и хорошенько присмотрись
    2) через asm вставки(если работаешь на x32) ИЛИ через отдельный *.asm файл(если в x64) повтори один в один вызов этой функции из своей DLL

    Параметры функции могут передаваться через стек, а могут через регистры. Возможно ты что-то упускаешь


    + Еще вариант:
    Поставь бряк на эту функцию и посмотри как туда передаются параметры с реальными данными когда сама игра вызывает эту функцию

     

    Спасибо, уже разобрался. Похукал немного функции, посмотрел что за параметры идут через стек и т.п.

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

    Есть какой-то способ заставить античит думать что эта DLL принадлежит клиенту и клиент сам использует свой API?

  6. Я не понимаю, не могу вызвать функции даже изнутри процесса. Клиент почему-то просто вырубается и все. Объявляю вроде правильно, вызываю тоже.

    typedef int(__thiscall* f_NextCreature)(int this_UNetworkHandler, float Radius, int PrevID);
    f_NextCreature call_GetNextCreature = reinterpret_cast<f_NextCreature>(0x203D7F30);
    
    float Radius = 100.0;
    int pClassUser = call_GetNextCreature(pUNetworkHandler, Radius, PrevID));
    
    

    И все, при таком вот вызове клиент закрывается. Работает только одна функция GetUser..

    Вот код из IDA 7:

    .text:203D7F30 ; Exported entry 5758. ?GetNextCreature@UNetworkHandler@@UAEPAUUser@@MH@Z
    .text:203D7F30
    .text:203D7F30 ; =============== S U B R O U T I N E =======================================
    .text:203D7F30
    .text:203D7F30
    .text:203D7F30 ; struct User *__thiscall UNetworkHandler::GetNextCreature(UNetworkHandler *__hidden this, float, int)
    .text:203D7F30                 public ?GetNextCreature@UNetworkHandler@@UAEPAUUser@@MH@Z
    .text:203D7F30 ?GetNextCreature@UNetworkHandler@@UAEPAUUser@@MH@Z proc near
    .text:203D7F30                                         ; DATA XREF: .text:20522E68↓o
    .text:203D7F30
    .text:203D7F30 var_8           = dword ptr -8
    .text:203D7F30 arg_0           = dword ptr  4
    .text:203D7F30 arg_4           = dword ptr  8
    .text:203D7F30
    .text:203D7F30                 mov     edx, [esp+arg_4]

    Чего я не так делаю?

  7. 2 часа назад, mrPTyshnik сказал:

     

     

    но лучше конечно использовать инжектируемую библиотеку в процесс.

    По поводу передачи данных - обычный FileMapping

    1) Создаешь FileMapping в основном приложении
    2) При инжекте, инжектируемая dll открывает этот FileMapping
    3) Читаешь/пишешь в цикле, тут главное согласовать структуры данных, например:

    typedef struct MyRedneckProtocol {

    BYTE ControlCode;
    Vector3 Coord1;

    Vector3 Coord2;
    int resultCode;

    }
    эта структуру одинакова в dll и в основном приложении.
     

    Метод грубый и лучше бы конечно использовать пайп.

    А что обычно используют в таких случаях? В расчет беру частое обращение на запись/чтение. Принципиально ли использовать что-то конкретное? Быстродействие пайпа и маппинга здесь роли не играет как я понимаю из-за маленького объема данных?

  8. 1 час назад, Xipho сказал:

    Еще вариант - собрать длл-ку с одной пошаренной секцией (shared sections). Но это больше геморроя. Имхо, самый наименее геморройный вариант - общение через сокет. Чуть более геморройный - именованный пайп, я помню, у меня тоже с ним были проблемы как-то. Замапленные файлы использовать - то еще "удовольствие", потому что нужно согласовывать их запись/чтение. 

    О, а можно немного подробнее про согласование? Я допустим сейчас сделал структуру общую, разметил её одинаково в обоих файлах, замапил. Вроде всё работает неплохо. Нужно не допустить одновременной записи и чтения одной и той же переменной? Я где-то читал про Event'ы, но так и не понял как они работают (пока что). Это из той оперы?

     

    upd:

    Или Вы имеете в виду очередность записи/чтения чтобы буфер не перекрывался разными переменными?

  9. UPD:

    Хм, в принципе, как вариант создать пару-тройку MappedFile, записать в них нужные переменные (а лучше структуру) для работы и использовать.. Но это же костыль и нерациональное использование ресурсов?)

  10. 44 минуты назад, Xipho сказал:

    Ну, собственно, именнованный пайп - самое оно. Или можно сокетом воспользоваться, с ним меньше геморроя.

    В общем, мне нужно как-то закостылить организовать (к примеру) вызов функции MoveToLocation, отправляя при этом в DLL координаты куда нужно бежать и BOOL параметр для активации функции.

    При этом, DLL должна непрерывно передавать параметры в GUI. Я немного не понимаю как использовать для этого пайп канал.

     

    Чтобы отправить команду в DLL из GUI мне приходится отстыковывать один пайп и пристыковывать другой.. Можно общаться одним пайпом как-то не перекрывая записанные данные?

    Я не нашел толковых примеров в гугле.. Нигде блин.

    Фрагмент кода GUI:

    Спойлер
    
    // По нажатию кнопки в GUI происходит инжект DLL в процесс, устанавливается флаг для работы BackgroundWorker и запускается сам воркер
    ...
    ...
    	private: System::Void btnInject_Click(System::Object^ sender, System::EventArgs^ e)
    	{
    		if (InjectDLL()) { tolog("DLL successfuly injected"); }
    		else { tolog("ERROR: DLL Injection was failed!"); }
    
    		statusBufferWorker = TRUE;
    		bufferWorker->RunWorkerAsync();
    	}
    ...
    ...
    // Воркер коннектится к DLL, и с установленной периодичностью получает стркутуру из DLL в которой записана инфа о персонаже и выводит данные в GUI.
    	private: System::Void bufferWorker_DoWork(System::Object^ sender, System::ComponentModel::DoWorkEventArgs^ e) 
    	{
    		Sleep(500);
    		if (!hPipeData1)
    		{
    			hPipeData1 = CreateFile("\\\\.\\pipe\\PipeData1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
    			if (hPipeData1) tolog("Connection with injected DLL was opened!");
    		}
    		else tolog("ERROR: Connection with injected DLL is closed!");
    
    		while (statusBufferWorker)
    		{
    			ReadFile(hPipeData1, &buf, sizeof(buf), &cbRead, NULL);
    
    			//if (buf.messages.msg.length() > 0) { tolog(sts(buf.messages.msg)); }
    		
    			float cp_percent = buf.me.curCP / (buf.me.maxCP / 100.0);
    			float hp_percent = buf.me.curHP / (buf.me.maxHP / 100.0);
    			float mp_percent = buf.me.curMP / (buf.me.maxMP / 100.0);
    
    			userCpBar->Size = System::Drawing::Size(cp_percent, 13);
    			userHpBar->Size = System::Drawing::Size(hp_percent, 13);
    			userMpBar->Size = System::Drawing::Size(mp_percent, 13);
    			userCpLabel->Text = its(buf.me.curCP) + "/" + its(buf.me.maxCP);
    			userHpLabel->Text = its(buf.me.curHP) + "/" + its(buf.me.maxHP);
    			userMpLabel->Text = its(buf.me.curMP) + "/" + its(buf.me.maxMP);
    
    			userIdField->Text = its(buf.me.ptrClass);
    			
    			Sleep(100);
    		}
    	
    	}
    ...
    ...
    // При нажатии кнопки для выгрузки DLL из процесса запускается другой воркер, устанавливается флаг для остановки первого воркера, отсоединяется пайп по которому шли данные, открывается новый пайп, посылает команду в DLL на выгрузку, а там DLL отрабатывает все для выгрузки себя из процесса.
    	private: System::Void backgroundWorker1_DoWork(System::Object^ sender, System::ComponentModel::DoWorkEventArgs^ e) 
    	{
    		statusBufferWorker = FALSE;
    
    		DisconnectNamedPipe(hPipeData1);
    		CloseHandle(hPipeData1);
    		hPipeData1 = 0;
    
    		BOOL dllStatus = FALSE;
    		hPipeDllStatus = CreateNamedPipeA("\\\\.\\pipe\\PipeDllStatus", 
                                              PIPE_ACCESS_DUPLEX,
                                              PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
                                              PIPE_UNLIMITED_INSTANCES,
                                              512, 512, 5000, NULL);
    
    		BOOL fConnected = ConnectNamedPipe(hPipeDllStatus, NULL);
    
    		BOOL msg = WriteFile(hPipeDllStatus, &dllStatus, sizeof(dllStatus), &cbWritten, NULL);
    		if (msg) tolog("DLL successfuly unloaded!");
    
    		DisconnectNamedPipe(hPipeDllStatus);
    		CloseHandle(hPipeDllStatus);
    		hPipeDllStatus = 0;
    	}

     

     

    Фрагмент кода DLL:

    Спойлер
    
    ...
    ...
    	// Создаем канал для передачи данных. При успехе возвращается HANDLE канала.
    	hPipeData1 = CreateNamedPipeA("\\\\.\\pipe\\PipeData1", 
                                      PIPE_ACCESS_DUPLEX,
                                      PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
                                      PIPE_UNLIMITED_INSTANCES,
                                      512, 512, 5000, NULL);
    	// Переходим в режим ожидания подключения клиента к каналу
    	fConnected = ConnectNamedPipe(hPipeData1, NULL);
    	// Пишем сообщение в структуру для GUI
    	if (fConnected) { strcpy(buf.messages.msg , "FROM DLL: Connect with DLL successful!"); }
    
    	// Действия выполняемые DLL-кой в цикле
    	for (;; Sleep(100))
    	{	// Проверяем запущен ли процесс GUI, если нет, то выгружаем DLL
    		if (!CheckLoadedGUI()) { DisconnectAll(); break; }
    
          	// Если есть соединение с таким именем ожидающее подключения, цепляем его, чекаем сообщение на выгрузку
    		if (WaitNamedPipeA("\\\\.\\pipe\\PipeDllStatus", 5000))
    		{
    			hPipeDllStatus = CreateFile("\\\\.\\pipe\\PipeDllStatus", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
    			
    			BOOL dllStatus;
    
    			ReadFile(hPipeDllStatus, &dllStatus, sizeof(dllStatus), &cbRead, NULL);
    			if (dllStatus == FALSE)
    			{
    				DisconnectAll();
    				break;
    			}
    		}
    		
          	// Пишем данные о персонаже в структуру и отправляем её
    		UpdateMyUserStruct();
    		WriteFile(hPipeData1, &buf, sizeof(buf), &cbWritten, NULL);
    ...
    ...

     

     

    Читал еще про FileMapping, выглядит очень удобно, но пока не понимаю как побайтно организовать несколько переменных, чтобы они корректно считывались?

    Как правильно отобразить несколько переменных в память? Не до конца понимаю смысл параметров dwFileOffsetHigh и dwFileOffsetLow.

    MapViewOfFileEx(HANDLE hFileMappingObject, DWORD dwDesiredAccess,  DWORD dwFileOffsetHigh,  DWORD dwFileOffsetLow, DWORD dwNumberOfBytesToMap, LPVOID lpBaseAddress);

     

  11. Всем здравствуйте.

    Пишу бота с интерфейсом, застопорился на вызове функций из внедренной в процесс DLL-ки.

    Некоторую информацию можно получить удаленно через ReadProcessMemory по адресам и оффсетам, да. Но чтобы получать класс User к примеру, который имеет динамический адрес надо внутри процесса вызвать API функцию.

    И вот вопрос: каким способом это сделать из интерфейса?

     

    Кусочек кода:

    void memRead(HANDLE hProc, DWORD address, LPVOID buffer)
    {
    	DWORD oldProtect = 0;
    	VirtualProtectEx(hProc, (LPVOID)address, sizeof(buffer), PAGE_READWRITE, &oldProtect);
    	ReadProcessMemory(hProc, (LPVOID)address, buffer, sizeof(buffer), 0);
    	VirtualProtectEx(hProc, (LPVOID)address, sizeof(buffer), oldProtect, &oldProtect);
    }
    
    
    typedef int(__thiscall* f_GetUser)(int this_UNetworkHandler, int id);
    f_GetUser call_GetUser = reinterpret_cast<f_GetUser>(0x203D9150);
    
    
    int GetMyUserClass()
    {
    	HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessID);
    
    	DWORD UNetworkHandler_this;
    	int my_id;
    
    	memRead(hProc, 0x20522A6C, &UNetworkHandler_this);
    	memRead(hProc, 0x2077ED7C, &my_id);
    
    	return call_GetUser(UNetworkHandler_this, my_id); //call_GetUser Возвращает адрес класса User
    	CloseHandle(hProc);
    }

    ID и адрес класса UNetworkHandler получаются корректно, но функция не вызывается. Не пинайте меня, я еще многого не знаю..:)

    Изнутри процесса все окей, функция работает.

    Можно конечно постоянно юзать ее из DLL, но тогда я не знаю как правильно организовать обмен информацией между DLL и exe-шником. Через пайп как-то геморно..

    Как вызвать функцию удаленно?

  12. В 18.11.2019 в 05:47, roma912 сказал:

    Без ProcessEvent никак
    Его нужно хукать и хукать обязательно

    Нашел Ваш мануал по UE3, не сразу въехал, но, да, я сделал это)

     

    Спойлер
    
    void coords(FEngine::ALineagePlayerController* pPlayerController)
    {
    	if (pPlayerController)
    	{
    		FCore::FVector loc = pPlayerController->ViewTarget->Location;
    		write("X: %i, Y: %i, Z: %i", (int)loc.X, (int)loc.Y, (int)loc.Z);
    	}
    }
    
    void __fastcall HookedPE(FCore::UObject* pObject, void* edx, FCore::UFunction* pFunction, void* pParms, void* pResult)
    {
    	const char* szName = pFunction->GetFullName().c_str();
    
    	if (strcmp(szName, "Function Engine.LineagePlayerController.PlayerTick") == 0)
    	{
    		coords((FEngine::ALineagePlayerController*)(pObject));
    	}
    
    	ProcessEvent(pObject, pFunction, pParms, pResult);
    }

     

    l59UogMb0vDqnUQWx7Jy3qTHQTJVCeljdsHLDIJTHycXw0QnvFGT2rmg2GTazGtDQ4U63ih1pyXNqkI7TEAeZA==?uid=0&filename=1.JPG&disposition=inline&hash=&limit=0&content_type=image%2Fjpeg&tknv=v2&owner_uid=548182919&size=1514x741

     

    И еще вопрос:) Это нормально сделать вот так? :

    Спойлер

    Задать указатель на класс как глобальную переменную

    
    FEngine::ALineagePlayerController* pPlayerController;

    А затем инициализировать его при хуке функции:

    
    pPlayerController = reinterpret_cast<FEngine::ALineagePlayerController*>((FEngine::ALineagePlayerController*)(pObject));

    Просто некоторые функции не нужно вызывать при каждом хуке..

     

  13. 4 минуты назад, Xipho сказал:

    Зачем его компилить? Берешь из поставки хедер и либ файл, и подключаешь их к проекту.

    А в том-то и дело, что либ файла там нет, либо я тупой совсем) Надо скомпилить чтобы либ вышел.. Он кстати появляется, даже с ошибкой компилирования, его можно использовать так?

     

    з.ы. 

    попробую, спасибо за ответы)

  14. 5 часов назад, roma912 сказал:

    Без ProcessEvent никак
    Его нужно хукать и хукать обязательно

    Понятно, спасибо. Буду пытаться компилить detours. Не подскажешь кстати, что за sn он при компиляции требует? Что то с какими-то ключами связано, 2 ошибки выбивает.

    И вообще, можно без деторса обойтись же?

    И ещё вопрос: почему работает функция GObjects?

  15. В принципе, работают найденные здесь функции, это точно.

    Спойлер
    
    // Lineage 2 (v273) SDK
    
    #ifdef _MSC_VER
    	#pragma pack(push, 0x4)
    #endif
    
    #include "../SDK.hpp"
    
    namespace L2v273
    {
    TArray<FNameEntry*>* FName::GNames = (TArray<FNameEntry*>*)GetProcAddress(GetModuleHandleW(L"core.dll"), "?Names@FName@@0V?$TArray@PAUFNameEntry@@@@A");
    TArray<FCore::UObject*>* FCore::UObject::GObjects = (TArray<FCore::UObject*>*)GetProcAddress(GetModuleHandleW(L"core.dll"), "?GObjObjects@UObject@@1V?$TArray@PAVUObject@@@@A");
    } 
    
    #ifdef _MSC_VER
    	#pragma pack(pop)
    #endif
    

     

    А дальше неточно..

    С помощью FCore::UObject::GObjects получилось вытащить названия и адреса всех объектов.

    (Отрывок) 

    Спойлер

    11961    04F72440    TimeEnv0.INT
    11962    04F71B80    TimeEnv1.INT
    11963    04F712C0    TimeEnv2.INT
    11964    04F70A00    TimeEnv3.INT
    11965    086EF5A0    FontManager
    11966    085B0D20    FontCacheManager
    11967    04D13C00    MasterLevel
    11968    12230000    AmbientSoundObject7933
    11969    085B0CD0    WinDrv
    11970    1112DBA8    WindowsViewport
    11971    1112D678    WindowsClient

    11972    090F0B40    UseJoystick
    11973    090F0AA0    UseWindowFrame
    11974    08A48E00    WindowsClient
    11975    08EF46A0    D3DDrv
    11976    096D1610    ShaderCommandlet
    11977    096D10E0    D3DRenderDevice
    11978    090F0A00    UseHardwareTL
    11979    090F0960    UseHardwareVS
    11980    090F08C0    UsePrecaching
    11981    090F0820    UseTrilinear
    11982    090F0780    UseVSync
    11983    090F06E0    UseTripleBuffering
    11984    090F0640    UseCubemaps

    Я нашел здесь этот чертов вьюпорт, но по этому адресу всё равно ничего не получается)

    Но мне нужно, как я понимаю, получать указатели на классы, чтобы вытащить хоть что-то оттуда..

    auto Viewport = FCore::UObject::FindObject<FWinDrv::UWindowsViewport>("WindowsViewport Transient.WindowsClient0.WindowsViewport0");

    Есть здесь кто-нибудь кто работал с этой SDK? Объясните хотя бы на словах что нужно делать и куда копать.

    А то про "посмотреть в отладчике" я итак знаю..) Там все равно темный лес, а тут целый SDK)

  16. 5 часов назад, imaginary сказал:

    Ну так ты посмотри что происходит в коде, почему адреса не получаются, через отладчик

    Т.е., по сути, я все таки могу это дело без detours'a и прочего получить? 

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

  17. Хэллоу всем. Учу С++, интересен реверс, знаний мало , если что - бейте по голове.

     

    Ковыряюсь в клиенте High Five, нашел SDK под него, всё как надо подцепил и нихрена в итоге не работает. 

    DLL после инжекта находит адреса функций, адреса других dll-ок процесса, а получать значения никак не желает.

     

    Куски кода брал с ютуба (под FarCry писался), немного переделал под себя, т.к. в VS19 никак не шел вывод в консоль.

    Код:

    Спойлер
    
    // main
    #include <Windows.h>
    #include <iostream>
    #include <string>
    // for console
    #include <io.h>
    #include <fcntl.h>
    #include <conio.h>
    // others
    
    // sdk
    #include "L2Sdk/SDK.hpp"
    
    using namespace L2v273;
    
    HINSTANCE hInst = 0;
    
    HANDLE hConsole;
    void CreateConsole() 
    {
    	AllocConsole();
    	hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
    }
    
    bool write(std::string description, ...)
    {
    	char buf[1024];
    	memset(buf, 0, sizeof(buf));
    
    	va_list vaList;
    	va_start(vaList, description);
    	vsprintf_s(buf, (description + "\n").c_str(), vaList);
    	va_end(vaList);
    
    	if (WriteConsoleA(hConsole, buf, strlen(buf), 0, 0) == 0) {
    
    		return false;
    	}
    
    	return true;
    }
    
    DWORD* ReadPointer(DWORD baseAddr, DWORD offset)
    {
    	return *(DWORD**)(baseAddr + offset);
    }
    
    DWORD __stdcall MainThread(LPVOID)
    {
    	CreateConsole();
    	write("Dll successfuly loaded!  ---  ESC to unload dll\n");
    
    	HMODULE hEngine = GetModuleHandleA("engine.dll");
    	HMODULE hCore = GetModuleHandleA("core.dll");
    	HMODULE hWinDrw = GetModuleHandleA("windrv.dll");
    	write("WinDrw addr: %p", hWinDrw);
    	HMODULE hNWindow = GetModuleHandleA("nwindow.dll");
    
    	FEngine::APawn* pawn = reinterpret_cast<FEngine::APawn*>(GetProcAddress(hEngine, "??0APawn@@QAE@ABV0@@Z"));
    	FCore::UObject* uobject = reinterpret_cast<FCore::UObject*>(GetProcAddress(hCore, "??0UObject@@QAE@ABV0@@Z"));
    	FWinDrv::UWindowsViewport* Viewport = reinterpret_cast<FWinDrv::UWindowsViewport*>(GetProcAddress(hWinDrw, "??0UWindowsViewport@@QAE@ABV0@@Z"));
    
    	write("Viewport: %p\n", Viewport);
    	write("Pawn: %p", pawn);
    	write("Uobject: %p\n", uobject);
    	
    	if(Viewport)
    	{
    		FCore::FVector Loc = Viewport->Actor->Location;
    		write("Location: X: %.2f, Y: %.2f, Z: %.2f", Loc.X, Loc.Y, Loc.Z);
    	}
    
    	/*
    	DWORD* ptr1 = ReadPointer( (DWORD)GetModuleHandleA("core.dll"), 0x000C6898);
    	DWORD* ptr2 = ReadPointer(reinterpret_cast<DWORD>(ptr1), 0x1bc);
    	DWORD* ptr3 = ReadPointer(reinterpret_cast<DWORD>(ptr2), 0x0);
    	DWORD* ptr4 = ReadPointer(reinterpret_cast<DWORD>(ptr3), 0x300);
    
    
    	FCore::UObject* uobj = reinterpret_cast<FCore::UObject*>(ReadPointer(reinterpret_cast<DWORD>(ptr1), 0x0034));
    	write("FCore::Uobject addr = %p", uobj);
    
    	auto gg = uobj->FindObject<FWinDrv::UWindowsViewport>("WindowsViewport Transient.WindowsClient0.WindowsViewport0");
    	*/
    
    
    	/* Пример получения координат (от Akumu)
    	auto Viewport = FCore::UObject::FindObject<FWinDrv::UWindowsViewport>("WindowsViewport Transient.WindowsClient0.WindowsViewport0");
    	if (Viewport)
    	{
    		write("Viewport: %p", &Viewport);
    		auto Controller = Viewport->Actor;
    		if (Controller)
    		{
    			auto Actor = Controller->ViewTarget;
    			if (Actor)
    			{
    				auto& Location = Actor->Location;
    				auto Name = Actor->GetHumanReadableName();
    				write("Pos = %.02f, %.02f, %.02f)", Location.X, Location.Y, Location.Z);
    			}
    		}
    	}
    	*/
    	
    	for (;; Sleep(100))
    	{
    		if (GetAsyncKeyState(VK_ESCAPE)) 
    		{
    			break;
    		}
    	}
    
    	FreeConsole();
    	FreeLibraryAndExitThread(hInst, 0);
    	return 0;
    }
    
    BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
    {
    	if (fdwReason == DLL_PROCESS_ATTACH)
    	{
    		
    		hInst = hinstDLL;
    		CreateThread(0, 0, &MainThread, 0, 0, 0); 
    	}
    
    	return 1;
    }
    

     

    Не работает как пример который предоставил Akumu вместе с SDK, так и написанный мной код. Вернее, он не выводит ничерта..

    В UE по этим адресам функции находит нормально.

     

    Скрин:

    Спойлер

    ca3c49d13fd313901c57f26adb2d87c1.jpg

    Объясните недалекому, что может быть не так? Неправильные исходные названия для поиска адреса?

     

    Перерыл все форумы, включая зарубежные, там говорят что в UE идет все через ProcessEvent (без хука сего чуда все же не обойтись, да?), но я пока не понимаю как его хукануть, тёмный лес ;(

    На кодерксе древние темы про отлов пакетов, это меня не интересует, т.к. под любой UE можно сделать SDK.

     

    Сам SDK вместе с исходными названиями функций (Yandex)

     

    P.s.

    С detours'ом я не дружу, да что там, он даже компилироваться не хочет падла, все какой-то sn требует ?

  18. 4 часа назад, partoftheworlD сказал:

    Но, есть же f.lux.

    Ну она насколько я знаю цветовой профиль настраивает?

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

  19. Хола! Нет на форуме раздела с полезным софтом, поэтому оставлю здесь.

    Сегодня мои "хацкерские" глаза начали краснеть и болеть от очередного часа за глубоким изучением плюсов, решил понизить яркость экрана - хрен там, нет в моей десятке такой функции. В настройки монитора лезть лень, а темные темы уже не помогают ><, поэтому нашёл такую софтинку: выводит в трей слайдер с яркостью.

     

    Спойлер

    123.jpg

     

     

    Глаза сказали спасибо. Может тоже кому пригодится)

    Скачать тут: v1.7.8 (git), сурсы там же.

    Автор: blackholeearth

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

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

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