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

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


Гость 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 нужна, насколько я помню, для того чтобы поток понял, что пора завершаться.
Ссылка на комментарий
Поделиться на другие сайты

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

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

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

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

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

 

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

 
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
Ссылка на комментарий
Поделиться на другие сайты

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

 

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

 

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

 

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

 

func(1, 2, 3);

 

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

 

PUSH 3PUSH 2PUSH 1CALL func

 

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

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

 

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

 

не помогло..

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

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

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

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

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

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

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

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

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

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

 

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

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

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

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

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

 

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

 

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

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

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

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

 

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

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

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

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

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

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

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

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

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

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

 

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

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

Изменено пользователем 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)
Ссылка на комментарий
Поделиться на другие сайты

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

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

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