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

Как проверить в CE-шном скрипте указатель находится по смещению или нет?


Рекомендуемые сообщения

Вопрос мастерам.

 

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

Вот свежий пример подобной игры.

Мне удавалось "заслоном из фильтров" писать скрипт и получать нужное.

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

 

Чтобы было понятнее, возьму часть скрипта из сообщения, на которое я дал выше ссылку:

Fuel:  cmp [FlagAdd],2  jne code  cmp [ebx+08],3  jne code  cmp [ebx+18],4  jne code  mov ecx,[ebx+10]      // Вот этот участок, здесь мы загружаем смещение, где должен быть поинтер.  cmp ecx,0             // Это я пытаюсь определить указатель лежит в ECX или нет, но я понимаю,   je code               // что это не верно.    cmp [ecx+10],6C657566 // И вот здесь чаще всего происходит вылет, если в ECX не указатель.  jne code  cmp [ecx+14],6C6C6946  jne code  cmp [ecx+18],6576654C  jne code  cmp byte ptr [ecx+1C],6C  jne code  mov [ebx],00000000  mov [ebx+04],40690000  mov [FlagAdd],0 

Как узнать в этом скрипте, что будет у меня в ECX (что поставить вместо строчки cmp ecx,0)  ? Т.е. если там не указатель, то прыгаем на оригинальный код игры, если указатель, то продолжаем двигать по коду инъекции.

Если поможете, то скрипты станут гораздо короче, потому что "заслона из фильтров" не нужно будет делать. 

 

Надеюсь, что понятно объяснил. Нечто подобное уже было у нас на форуме - здесь, но я не понимаю ни на каком языке это написано, ни как это использовать в моём скрипте. 

 

Заранее - БОЛЬШОЙ спасыб!!!

 

Ссылка на комментарий
Поделиться на другие сайты

Вроде твой случай тык.

partoftheworlD, вроде мой, но ни чё к сожалению не понял. %)  

2-й пример написан на C++ и это обработчик ошибок.

partoftheworlD, интересно, а можно его переделать на LUA, чтобы вставить в СE-скрипт?

Ссылка на комментарий
Поделиться на другие сайты

Надеюсь, что понятно объяснил. Нечто подобное уже было у нас на форуме - здесь, но я не понимаю ни на каком языке это написано, ни как это использовать в моём скрипте.

 

На ассемблере ты не можешь понять указатель это или нет. Он может быть или указателем, или флоатом или 4 байтовым целым. Можно попробовать установить диапазон адресов куда он может указывать для данной игры.

partoftheworlD, вроде мой, но ни чё к сожалению не понял. %)  

partoftheworlD, интересно, а можно его переделать на LUA, чтобы вставить в СE-скрипт?

 

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

Ссылка на комментарий
Поделиться на другие сайты

На ассемблере ты не можешь понять указатель это или нет.

Если так, то очень жаль. А на LUA?

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

A1t0r, если сделаешь такую проверку на LUA - заранее БОЛЬШОЙ, БОЛЬШОЙ СПАСЫБ!!!

Ссылка на комментарий
Поделиться на другие сайты

partoftheworlD, вроде мой, но ни чё к сожалению не понял. %)  

partoftheworlD, интересно, а можно его переделать на LUA, чтобы вставить в СE-скрипт?

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

Стек обслуживается тремя регистрами:

  • ESS - указатель дна стека (начала сегмента стека);
  • ESP - указатель вершины стека;
  • EBP - указатель базы.
Изменено пользователем partoftheworlD
Ссылка на комментарий
Поделиться на другие сайты

partoftheworlD, пока не уловил, как это использовать, если сможешь, пример на моём скрипте сделай ПЖЛСТа

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

 

Наверное будет проще написать на C++ программу которая проверяет исключения и выводит адрес и текущее значение, а потом уже подходящие значения добавить в СЕ.

Изменено пользователем partoftheworlD
Ссылка на комментарий
Поделиться на другие сайты

но вроде как тебе надо сделать проверку по ESP. в него записываются 4 байта которые и есть адрес возврата, если условие проверки не выполнится, то сделать переход или что-нибудь вывести. 

Чёй-то пока в мозгу не укладывается. Не могу переварить.

Ладно подождём MasterGH и Xipho - основных моих ШИФУ, помогут понять - как это готовить. :)

Ссылка на комментарий
Поделиться на другие сайты

Самое просто решение

 

Ecx через инъекцию кода сохранить в известную переменную и зарегистрировать её. 

В таблице CE создать запись. В адрес ввести указатель с этой зарегистрированной меткой.

Поставить заморозку указателя.

Готово

 

О других способах писать не буду, это долго.

Ссылка на комментарий
Поделиться на другие сайты

Самое просто решение

MasterGH, либо я тебя совсем не понимаю, либо (у меня такое ощущение), что я плохо объяснил и ты меня не понял.

Чем мне может помочь заморозка указателя в моём скрипте?

 

Мне нужно убедиться, что в ECX, будет лежать указатель и соответственно в [ECX+10] и т.д. будет лежать какое-то значение и соответственно не будет вылета из игры при работе инструкции CMP [ECX+10],.....

 

Ну у тебя в примере, ты вроде правильно пишешь:

lds esi,[eax] //<<< здесь нужна обработка исключения в случае если по eax нет указателя на строку
Ссылка на комментарий
Поделиться на другие сайты

если там кроме ecx 0, всегда указатель -

gmz, так проблема в том я не знаю точно, что там проскакивает (слишком много адресов нужно отсеить - их там по 2000 адресов наверное) 0 и указатели, или ещё что-то. А cmp ecx,0 - это я сам сделал как бы частичный отсев не указателей.

 

Но ведь сам СЕ как-то определяет указатель или нет находится по смещению (Хотя бы взять "Анализ структур" или "Сканер указателей"), значит и мы по идее можем определить, что там в ECX в каждый момент времени. 

gmz, кстати посмотри эту тему, как мне кажется это решение, но как его приспособить к моему скрипту не знаю, если бы переделать в LUA хотя бы, а лучше в ассемблер.

Ссылка на комментарий
Поделиться на другие сайты

Я ошибся, т.к. спешил. У тебя там сравнения идут вложенные

 

1. Можно проверить на Lua по таймеру, но это не интересно.

 

2. Можно написать обработку исключения на АА. Только, что сделал по примеру Xipho с темы, которую привели

 

3. Можно через функции чтения памяти из WinAPI в АА скрипте. Эта функция никогда не вызывает исключений и возвращает результат в виде счетчика прочитаный байт

4. Можно адрес проверять каждые 200 мс в АА через проверку прав доступа к адресу перечисляя регионы, страницы памяти, сравнивая размеры областей памяти и типы защиты памяти.

5. А можно исследовать код игры. Игра всегда находит нужный адрес сама от начала ветви кода до инструкции обращающейся к адресу. Только найти вверх ветки кода, где её выполнение происходит столько раз, сколько происходит обращений к адресу на брейкпоинте при изменении значения.

label(Handler)label(NoException)label(ExceptionHandled)label(lpCaption)label(lpText)00270000:	pushad	mov esi, Handler	push esi	push fs:[0]	mov fs:[0], esp	// Код в этом месте будет проверен на исключения	mov ecx, [0]					// специальная ошибка доступа к адресу	Jmp NoExceptionHandler:	mov esp,[esp+0x08]	pop fs:[0]	add esp, 4	popad	// Код в этом месте будет выполнен, если исключение произойдет	Jmp ExceptionHandled	Jmp NoExceptionNoException:	pop fs:[0]			// востанавливаем старое исключение	add esp, 0x24 //32+4	retExceptionHandled:	// исключение было обработано	push 0 				//uType  (0=mb_ok)	push lpCaption	push lpText	push 0  			//hWnd	call MessageBoxA	retlpCaption:	db 'Exception!' 0lpText:	db 'You have exception' 0
Ссылка на комментарий
Поделиться на другие сайты

MasterGH, хочу попробовать 2., но чёй-то очень сложновато для меня получилось, пока ни чего не понимаю - как применить это к моему скрипту (да и вместо сокращения скрипта -скрипт удлиняется).

 

Ну и так ещё, мне визуально показалось, что код у тебя не совсем верен, допустим вот этот участок:  

Jmp NoExceptionNoException:	pop fs:[0]			// востанавливаем старое исключение	add esp, 0x24 //32+4	ret

разве он не зациклин сам на себя?

Ссылка на комментарий
Поделиться на другие сайты

2. Можно написать обработку исключения на АА.

MasterGH, вот попробовал, как я это понял, убрал лишнее из кода и вставил себе в скрипт:

Но как я и думал - сразу же (при активации скрипта) зависла игра и потом вылет.

MasterGH, посмотри пжлста, где я ошибаюсь.

Напомню: 

что мне нужно, после загрузки в есх:

если в ecx не поинтер, то прыгнуть на code:

если в ecx поинтер, то вернуться назад :

{ Game   : game.exe  Version:   Date   : 2016-01-11  Author : Garik66  This script does blah blah blah}[ENABLE]{$LUA}PlaySound(findTableFile([[Activate]])){$ASM}aobscanmodule(INJECT,game.exe,8B 48 10 8B B1 BC 00 00 00) // should be uniquealloc(newmem,$1000)label(code)label(Fuel)label(return)label(CheckPointer)label(Handler)label(NoException)registersymbol(INJECT)newmem:  mov ecx,[ebx+10]  call CheckPointer  cmp [ecx+10],656E6F6D  jne Fuel  cmp byte ptr [ecx+14],79  jne code  mov [ebx],00000000  mov [ebx+04],412E8480  jmp codeFuel:  cmp [ecx+10],6C657566  jne code  cmp [ecx+14],6C6C6946  jne code  cmp [ecx+18],6576654C  jne code  cmp byte ptr [ecx+1C],6C  jne code  mov [ebx],00000000  mov [ebx+04],407F4000CheckPointer:        pushad	mov esi,Handler	push esi	push fs:[0]	mov fs:[0],esp	mov ecx,[ebx+10] // Код в этом месте будет проверен на исключения	mov ecx,[0]      // специальная ошибка доступа к адресу	Jmp NoExceptionHandler:	mov esp,[esp+0x08]	pop fs:[0]	add esp, 4	popad	je code         // Код в этом месте будет выполнен, если исключение произойдет	Jmp NoExceptionNoException:	pop fs:[0]      // востанавливаем старое исключение	add esp, 0x24   //32+4	retcode:  mov ecx,[ebx]  mov eax,[ebp+14]  jmp returnINJECT+26:  jmp newmemreturn:[DISABLE]{$LUA}PlaySound(findTableFile([[Deactivate]])){$ASM}INJECT+26:  db 8B 0B 8B 45 14unregistersymbol(FlagAdd)unregistersymbol(INJECT)dealloc(newmem){// ORIGINAL CODE - INJECTION POINT: "game.exe"+D63D5"game.exe"+D63BB: 83 7B 08 00              -  cmp dword ptr [ebx+08],00"game.exe"+D63BF: 75 3A                    -  jne game.exe+D63FB"game.exe"+D63C1: 8B 56 08                 -  mov edx,[esi+08]"game.exe"+D63C4: 85 D2                    -  test edx,edx"game.exe"+D63C6: 74 33                    -  je game.exe+D63FB"game.exe"+D63C8: F6 42 06 01              -  test byte ptr [edx+06],01"game.exe"+D63CC: 74 04                    -  je game.exe+D63D2"game.exe"+D63CE: 33 FF                    -  xor edi,edi"game.exe"+D63D0: EB 21                    -  jmp game.exe+D63F3"game.exe"+D63D2: 8B 45 08                 -  mov eax,[ebp+08]// ---------- INJECTING HERE ----------"game.exe"+D63D5: 8B 48 10                 -  mov ecx,[eax+10]"game.exe"+D63D8: 8B B1 BC 00 00 00        -  mov esi,[ecx+000000BC]// ---------- DONE INJECTING  ----------"game.exe"+D63DE: E8 6D EB FF FF           -  call game.exe+D4F50"game.exe"+D63E3: 83 78 08 00              -  cmp dword ptr [eax+08],00"game.exe"+D63E7: 75 08                    -  jne game.exe+D63F1"game.exe"+D63E9: 80 4A 06 01              -  or byte ptr [edx+06],01"game.exe"+D63ED: 33 FF                    -  xor edi,edi"game.exe"+D63EF: EB 02                    -  jmp game.exe+D63F3"game.exe"+D63F1: 8B F8                    -  mov edi,eax"game.exe"+D63F3: 85 FF                    -  test edi,edi"game.exe"+D63F5: 0F 85 99 00 00 00        -  jne game.exe+D6494"game.exe"+D63FB: 8B 0B                    -  mov ecx,[ebx]} 
mov ecx,[ebx+10]      // Код в этом месте будет проверен на исключения
je code               // Код в этом месте будет выполнен, если исключение произойдет
cmp [ecx+10],656E6F6D // вот сюда нужно вернуться, если в ecx pointer. jne Fuel
Изменено пользователем Garik66
Ссылка на комментарий
Поделиться на другие сайты

ндааа лучше поменяй место хука, посмотри кто зовет эту функцию когда там указатель и поставь там хук...

gmz, я тебя не понимаю - для чего мне менять место хука?

Скрипт работает нормально, только изредко происходит вылет из игры из-за того (это моё предположение), что по смещению [ebx+10] иногда у адресов работающих с инструкцией нет указателя.

В первом посте есть ссылка на тему откуда я для примера взял скрипт (я его чуть-чуть переделал, чтобы не был таким громоздким). Повторю ссылку тык

Ссылка на комментарий
Поделиться на другие сайты

Скрипт, который я привел в пример, вызывается отдельным потоком. Ret - для выхода из этого потока. mov ecx,[0] это специально для вызова исключения.

 

Т.е. тебе нужно

- убрать ret-ы

- убрать mov ecx,[0]

- убрать "je code"

fs:[0] содержит адрес текущей структуры исключений. Мы подставляем адрес своей создаваемой структуры исключений, при этом сохраняем предыдущий.

На Wasm есть интересная переведенная статья по SEH. Часть1 Часть2 Часть3

 

Можешь все не читать, а посмотреть пример ниже

 

//==================================================// MYSEH - Мэт Питрек 1997// Microsoft Systems Journal, Январь 1997// FILE: MYSEH.CPP// To compile: CL MYSEH.CPP//==================================================#define WIN32_LEAN_AND_MEAN#include #include DWORD  scratch;int main(){    DWORD handler = (DWORD)_except_handler;    __asm    {                      // Создаем структуру EXCEPTION_REGISTRATION:        push    handler    // Адрес функции обработчика исключений.        push    FS:[0]     // Адрес предыдущего EXECEPTION_REGISTRATION.        mov     FS:[0],ESP // Добавляем в связанный список EXECEPTION_REGISTRATION.    }    __asm    {        mov     eax,0      // Обнуляем значение регистра EAX.        mov     [eax], 1   // Чтобы преднамеренно вызвать исключение, делаем запись                           // по нулевому адресу.    }    printf( " After writing!\n" );    __asm    {                       // Удаляем из связанного списка EXECEPTION_REGISTRATION.        mov     eax,[ESP]   // Получаем указатель на предыдущий                            // EXECEPTION_REGISTRATION.        mov     FS:[0], EAX // Устанавливаем в начале списка предыдущий                            // EXECEPTION_REGISTRATION.        add     esp, 8      // Удаляем из стека структуру EXECEPTION_REGISTRATION.    }    return 0;}
Ссылка на комментарий
Поделиться на другие сайты

УПС!!!

Вместо упрощения, оказалось ещё сложнее.

Это нужно переварить.

Ну теперь уже не к спеху.

 

Скрипт в игре (по ссылке) я уже поправил, вылеты из игры оказались не из-за указателей, ну я в теме там объяснил.

А к указателям вернёмся при возникновении новой необходимости.

Ссылка на комментарий
Поделиться на другие сайты

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

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

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