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

Вызов функции по адресу


Гость MMAC

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

Привет!

Смотря какую функцию и смотря откуда. Если игровую и из инъекции кода, то тебе нужно будет знать ее адрес и аргументы. А дальше сделать примерно так:

 

  Показать контент

 

Если не из инъекции кода (не из адресного пространства игры), то нужна будет WinAPI-функция [CreateRemoteThread]. Если же нужно вызвать WinAPI-функцию из инъекции кода, то все как в первом примере, но адрес функции получается из [LoadLibrary] и [GetProcAddress].

alloc(mycode,4096)    // Выделяем 4096 байт памяти для записи нашего кодаCREATETHREAD(mycode); // Создаем новый поток и передаем управление на выделенную памятьmycode: PUSH arg2             // Кладем в стек аргументыPUSH arg1PUSH arg0CALL 0x1234567        // Вызываем функцию по адресу 0x1234567RET                   // Выходим
Ссылка на комментарий
Поделиться на другие сайты

keng, объясни пожалуйста чем CREATETHREAD(mycode); в данном случае будет отличается от label(mycode); ?

и почему в конце стоит RET? Ведь у той функции, которую вызываем уже есть свой RET и соответственно по ее завершению она перейдет на наш RET в инъекции кода, Но куда он нас выкинет? Разве не должно ли там стоять что-то типа jmp return, где return адрес возврата в оригинальный код

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

Тем, что label просто позволяет дать имя адресу памяти, а CreateThread создает поток. Почитать о них подробнее можно, например, [тут]. RET нужна, насколько я помню, для того чтобы поток понял, что пора завершаться.
Ссылка на комментарий
Поделиться на другие сайты

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

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

  В 24.03.2015 в 19:37, tirion сказал:

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

Вероятность нулевая, и игра не вылетит из-за потока, а вот из-за кода, который этот поток выполняет - вполне можно получить вылет, но это уже проблема программиста, а не программы, в которой он создает свой поток. И в каком смысле "испохабить" регистры? И почему в этом должен быть виноват поток?
Ссылка на комментарий
Поделиться на другие сайты

Испохабить, значит функция запишет в них другое значение и последующие выполнение кода уже будет считывать эти значения

 

В общем вызываю функцию так  (аргументы не принимает)

 
alloc(newmem,2048)CREATETHREAD(newmem)newmem:call 0x003016B0ret

получаю вылет

 
 
 
Вызываю вот так(по срабатыванию инструкции)
[ENABLE]alloc(newmem,2048)label(returnhere)newmem:mov [ecx+00000080],00000000call 0x003016B0jmp returnhere0042FCDC9:jmp newmemnopnopnopnopnopreturnhere:[DISABLE]dealloc(newmem)0042FCDC9:mov [ecx+00000080],00000000

все отлично

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

  В 24.03.2015 в 19:52, tirion сказал:

получаю вылет

Попробуй использовать перед выходом на функцию использовать pushad, а после возврата popad. 

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

Представь себе пример. Есть программа, которая показывает кнопку "Скачать файл", по нажатию на которую начинает этот самый файл скачивать. Файл размером в 100 Тб, скорость - 56 Кбит\сек. То есть понадобится дофигалион времени на скачивание. А пользователю во время скачивания нужно показывать индикатор загрузки. Раньше было так, что можно было или качать и ждать, или рисовать этот самый индикатор. Потом изобрели потоки, которые позволили разделить контекст выполнения программы - одна ее часть теперь рисует индикатор, а другая - грузит файл. Процессор переключается между этими двумя потоками и выполняет их код поочередно. Для пользователя это выглядит, будто оно одновременно делает и то и другое, но это просто процессор работает быстро. А потом изобрели многозадачные ОС, которые работают примерно по этому же принципу.

 

Дык вот в моем примере есть функция. Допустим, такая:

 

void func(int a, int b, int c);

 

Чтобы вызвать эту функцию из Си, надо сделать так:

 

func(1, 2, 3);

 

Чтобы из ассемблера - так:

 

PUSH 3PUSH 2PUSH 1CALL func

 

Мы взяли и нашли через Cheat Engine адрес этой самой функции, но нам хочется сделать такую инъекцию, чтобы не трогать сам код игры, но чтобы эта функция вызвалась в нужный нам момент. Тут и спасут потоки. Создаем поток и передаем ему код вызова функции - при создании потока ОС увидит его, скажет об этом процессору, тот переключит контекст выполнения на этот поток и выполнит код, а затем поток просто завершится и ничего больше не будет делать. Регистры и флаги не пострадают, потому что это выполнится "параллельно" (отдельно) от остального игрового кода. Такая вот штука.

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

 
  В 24.03.2015 в 20:08, garik66 сказал:

Попробуй использовать перед выходом на функцию использовать pushad, а после возврата popad. 

 

не помогло..

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

  В 24.03.2015 в 20:16, keng сказал:

Регистры и флаги не пострадают, потому что это выполнится "параллельно" (отдельно) от остального игрового кода

keng, не очень понятно (я про реализацию этого в СЕ ассемблер):

1. Если вызывать функцию без инъекции, то как не повредить код игры.

2. А если через инъекцию, то напиши пожалуйста пример на основе примера tirion из этогосообщения.

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

  В 24.03.2015 в 20:33, garik66 сказал:

tirion, посмотри у MasterGH здесь, может это поможет?

прочитал, к сожалению ничего нового не узнал..

Тоже интересен момент, как именно сделать удаленный поток средствами Cheat Engine.

Щас буду искать статьи от Dark Byte

 

А у тебя тоже вылет происходит?

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

  В 24.03.2015 в 20:52, tirion сказал:

А у тебя тоже вылет происходит?

Нет я пока только в одном своём скрипте здесь (скрипт "12 Телепорт + возврат к старту телепорта":) вызывал функцию и это была не игровая функция, а функция написанная мною для инъекции.

А игровую функцию из другой инструкции я пока не вызывал и тоже пока до конца не допонял - как это правильно сделать.

 

И вот здесь  ещё, но здесь я просто тупо скопировал то, что написал MasterGH (особо не разбираясь).

 

ЗЫ: А в отдельном потоке вообще ни разу не делал.

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

Говорят, что создание потока в скрипте нужно вызывать последним, т.е. в самом низу. Сначала, мол, код записать, а потом уже поток сделать.
  • Плюс 1
Ссылка на комментарий
Поделиться на другие сайты

  В 24.03.2015 в 22:11, garik66 сказал:

tirion, попробуй как у MasterGH, т.е. так:

  Показать контент

 

да я и так уже пробовал. Щас детально разбираюсь, по-сколько у меня в этой функции еще 3 подфункции, видимо что-то рушится

Но все равно спасибо.

[ENABLE]alloc(newmem,2048)CREATETHREAD(newmem)newmem:call 0x003016B0ret[DISABLE]dealloc(newmem) 
Ссылка на комментарий
Поделиться на другие сайты

Да, моя теория подтвердилась. Вызвал  эти подфункции отдельно, теперь не критует. По всей видимости указатель стека смещался и прыгал не туда

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

  В 24.03.2015 в 22:18, tirion сказал:

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

Да Call в отличии от jmp смещает стек на 4 байта (так как записывает туда адрес возврата) Точнее - здесь.

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

  В 24.03.2015 в 22:18, tirion сказал:

Да, моя теория подтвердилась. Вызвал  эти подфункции отдельно, теперь не критует. По всей видимости указатель стека смещался и прыгал не туда

Как я тебя понял - всё сработало?

 

  В 24.03.2015 в 22:25, tirion сказал:

Автору топика, думаю, будет о чем поразмышлять 

Это точно. А тебе тоже спасибо - я тоже ещё не много узнал.

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

  В 24.03.2015 в 22:51, garik66 сказал:

Как я тебя понял - всё сработало?

отчасти да.

 

Эксперты, подскажите, это корректное зацикливание потока?

[ENABLE]alloc(newmem,4096)CREATETHREAD(newmem);label(flag)registersymbol(flag)newmem:push 00mov ecx,023FB090call 0x00393A20mov ecx,eaxcall 0x00366100{$lua}sleep(1000){$asm}cmp [flag],0jne newmemretflag:db 1[DISABLE]unregistersymbol(flag)dealloc(newmem)
Ссылка на комментарий
Поделиться на другие сайты

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

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

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