Гость MMAC Опубликовано 24 марта, 2015 Поделиться Опубликовано 24 марта, 2015 Возможно ли вызвать функцию по адресу? Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 24 марта, 2015 Поделиться Опубликовано 24 марта, 2015 Привет!Смотря какую функцию и смотря откуда. Если игровую и из инъекции кода, то тебе нужно будет знать ее адрес и аргументы. А дальше сделать примерно так: Показать контент Если не из инъекции кода (не из адресного пространства игры), то нужна будет WinAPI-функция [CreateRemoteThread]. Если же нужно вызвать WinAPI-функцию из инъекции кода, то все как в первом примере, но адрес функции получается из [LoadLibrary] и [GetProcAddress].alloc(mycode,4096) // Выделяем 4096 байт памяти для записи нашего кодаCREATETHREAD(mycode); // Создаем новый поток и передаем управление на выделенную памятьmycode: PUSH arg2 // Кладем в стек аргументыPUSH arg1PUSH arg0CALL 0x1234567 // Вызываем функцию по адресу 0x1234567RET // Выходим Ссылка на комментарий Поделиться на другие сайты Поделиться
tirion Опубликовано 24 марта, 2015 Поделиться Опубликовано 24 марта, 2015 keng, объясни пожалуйста чем CREATETHREAD(mycode); в данном случае будет отличается от label(mycode); ?и почему в конце стоит RET? Ведь у той функции, которую вызываем уже есть свой RET и соответственно по ее завершению она перейдет на наш RET в инъекции кода, Но куда он нас выкинет? Разве не должно ли там стоять что-то типа jmp return, где return адрес возврата в оригинальный код Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 24 марта, 2015 Поделиться Опубликовано 24 марта, 2015 Тем, что label просто позволяет дать имя адресу памяти, а CreateThread создает поток. Почитать о них подробнее можно, например, [тут]. RET нужна, насколько я помню, для того чтобы поток понял, что пора завершаться. Ссылка на комментарий Поделиться на другие сайты Поделиться
tirion Опубликовано 24 марта, 2015 Поделиться Опубликовано 24 марта, 2015 Т.е по сути у нас тут никого оригинального кода, а лишь одиночный вызов функции? Ссылка на комментарий Поделиться на другие сайты Поделиться
tirion Опубликовано 24 марта, 2015 Поделиться Опубликовано 24 марта, 2015 Почитал я статью, но все равно не пойму, как эти потоки работают. Ну работают они параллельно с нашим кодом(на сколько я понял). Но какова вероятность, что этот самый поток вызова функции испохабит нам все регистры, из - за чего игра просто вылетет Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость Опубликовано 24 марта, 2015 Поделиться Опубликовано 24 марта, 2015 В 24.03.2015 в 19:37, tirion сказал: Почитал я статью, но все равно не пойму, как эти потоки работают. Ну работают они параллельно с нашим кодом(на сколько я понял). Но какова вероятность, что этот самый поток вызова функции испохабит нам все регистры, из - за чего игра просто вылететВероятность нулевая, и игра не вылетит из-за потока, а вот из-за кода, который этот поток выполняет - вполне можно получить вылет, но это уже проблема программиста, а не программы, в которой он создает свой поток. И в каком смысле "испохабить" регистры? И почему в этом должен быть виноват поток? Ссылка на комментарий Поделиться на другие сайты Поделиться
tirion Опубликовано 24 марта, 2015 Поделиться Опубликовано 24 марта, 2015 (изменено) Испохабить, значит функция запишет в них другое значение и последующие выполнение кода уже будет считывать эти значения В общем вызываю функцию так (аргументы не принимает) 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все отлично Изменено 24 марта, 2015 пользователем tirion Ссылка на комментарий Поделиться на другие сайты Поделиться
Garik66 Опубликовано 24 марта, 2015 Поделиться Опубликовано 24 марта, 2015 В 24.03.2015 в 19:52, tirion сказал: получаю вылетПопробуй использовать перед выходом на функцию использовать pushad, а после возврата popad. 1 Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 24 марта, 2015 Поделиться Опубликовано 24 марта, 2015 Представь себе пример. Есть программа, которая показывает кнопку "Скачать файл", по нажатию на которую начинает этот самый файл скачивать. Файл размером в 100 Тб, скорость - 56 Кбит\сек. То есть понадобится дофигалион времени на скачивание. А пользователю во время скачивания нужно показывать индикатор загрузки. Раньше было так, что можно было или качать и ждать, или рисовать этот самый индикатор. Потом изобрели потоки, которые позволили разделить контекст выполнения программы - одна ее часть теперь рисует индикатор, а другая - грузит файл. Процессор переключается между этими двумя потоками и выполняет их код поочередно. Для пользователя это выглядит, будто оно одновременно делает и то и другое, но это просто процессор работает быстро. А потом изобрели многозадачные ОС, которые работают примерно по этому же принципу. Дык вот в моем примере есть функция. Допустим, такая: void func(int a, int b, int c); Чтобы вызвать эту функцию из Си, надо сделать так: func(1, 2, 3); Чтобы из ассемблера - так: PUSH 3PUSH 2PUSH 1CALL func Мы взяли и нашли через Cheat Engine адрес этой самой функции, но нам хочется сделать такую инъекцию, чтобы не трогать сам код игры, но чтобы эта функция вызвалась в нужный нам момент. Тут и спасут потоки. Создаем поток и передаем ему код вызова функции - при создании потока ОС увидит его, скажет об этом процессору, тот переключит контекст выполнения на этот поток и выполнит код, а затем поток просто завершится и ничего больше не будет делать. Регистры и флаги не пострадают, потому что это выполнится "параллельно" (отдельно) от остального игрового кода. Такая вот штука. 1 Ссылка на комментарий Поделиться на другие сайты Поделиться
tirion Опубликовано 24 марта, 2015 Поделиться Опубликовано 24 марта, 2015 (изменено) В 24.03.2015 в 20:08, garik66 сказал: Попробуй использовать перед выходом на функцию использовать pushad, а после возврата popad. не помогло.. Изменено 24 марта, 2015 пользователем tirion Ссылка на комментарий Поделиться на другие сайты Поделиться
Garik66 Опубликовано 24 марта, 2015 Поделиться Опубликовано 24 марта, 2015 В 24.03.2015 в 20:16, keng сказал: Регистры и флаги не пострадают, потому что это выполнится "параллельно" (отдельно) от остального игрового кодаkeng, не очень понятно (я про реализацию этого в СЕ ассемблер):1. Если вызывать функцию без инъекции, то как не повредить код игры.2. А если через инъекцию, то напиши пожалуйста пример на основе примера tirion из этогосообщения. 1 Ссылка на комментарий Поделиться на другие сайты Поделиться
Garik66 Опубликовано 24 марта, 2015 Поделиться Опубликовано 24 марта, 2015 В 24.03.2015 в 20:20, tirion сказал: не помогло..Уже понял, мы не до конца поняли keng, как это сделать. Ссылка на комментарий Поделиться на другие сайты Поделиться
Garik66 Опубликовано 24 марта, 2015 Поделиться Опубликовано 24 марта, 2015 tirion, посмотри у MasterGH здесь, может это поможет? Ссылка на комментарий Поделиться на другие сайты Поделиться
tirion Опубликовано 24 марта, 2015 Поделиться Опубликовано 24 марта, 2015 (изменено) В 24.03.2015 в 20:33, garik66 сказал: tirion, посмотри у MasterGH здесь, может это поможет?прочитал, к сожалению ничего нового не узнал..Тоже интересен момент, как именно сделать удаленный поток средствами Cheat Engine.Щас буду искать статьи от Dark Byte А у тебя тоже вылет происходит? Изменено 24 марта, 2015 пользователем tirion Ссылка на комментарий Поделиться на другие сайты Поделиться
Garik66 Опубликовано 24 марта, 2015 Поделиться Опубликовано 24 марта, 2015 (изменено) В 24.03.2015 в 20:52, tirion сказал: А у тебя тоже вылет происходит?Нет я пока только в одном своём скрипте здесь (скрипт "12 Телепорт + возврат к старту телепорта":) вызывал функцию и это была не игровая функция, а функция написанная мною для инъекции.А игровую функцию из другой инструкции я пока не вызывал и тоже пока до конца не допонял - как это правильно сделать. И вот здесь ещё, но здесь я просто тупо скопировал то, что написал MasterGH (особо не разбираясь). ЗЫ: А в отдельном потоке вообще ни разу не делал. Изменено 24 марта, 2015 пользователем garik66 1 Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 24 марта, 2015 Поделиться Опубликовано 24 марта, 2015 Говорят, что создание потока в скрипте нужно вызывать последним, т.е. в самом низу. Сначала, мол, код записать, а потом уже поток сделать. 1 Ссылка на комментарий Поделиться на другие сайты Поделиться
Garik66 Опубликовано 24 марта, 2015 Поделиться Опубликовано 24 марта, 2015 tirion, попробуй как у MasterGH, т.е. так: Показать контент [ENABLE]alloc(newmem,2048)CREATETHREAD(newmem)newmem:call 0x003016B0ret[DISABLE]dealloc(newmem) 1 Ссылка на комментарий Поделиться на другие сайты Поделиться
tirion Опубликовано 24 марта, 2015 Поделиться Опубликовано 24 марта, 2015 В 24.03.2015 в 22:11, garik66 сказал: tirion, попробуй как у MasterGH, т.е. так: Показать контент да я и так уже пробовал. Щас детально разбираюсь, по-сколько у меня в этой функции еще 3 подфункции, видимо что-то рушитсяНо все равно спасибо.[ENABLE]alloc(newmem,2048)CREATETHREAD(newmem)newmem:call 0x003016B0ret[DISABLE]dealloc(newmem) Ссылка на комментарий Поделиться на другие сайты Поделиться
tirion Опубликовано 24 марта, 2015 Поделиться Опубликовано 24 марта, 2015 Да, моя теория подтвердилась. Вызвал эти подфункции отдельно, теперь не критует. По всей видимости указатель стека смещался и прыгал не туда 1 Ссылка на комментарий Поделиться на другие сайты Поделиться
Garik66 Опубликовано 24 марта, 2015 Поделиться Опубликовано 24 марта, 2015 (изменено) В 24.03.2015 в 22:18, tirion сказал: По всей видимости указатель стека смещался и прыгал не тудаДа Call в отличии от jmp смещает стек на 4 байта (так как записывает туда адрес возврата) Точнее - здесь. Изменено 24 марта, 2015 пользователем garik66 Ссылка на комментарий Поделиться на другие сайты Поделиться
tirion Опубликовано 24 марта, 2015 Поделиться Опубликовано 24 марта, 2015 Спасибо вам ребят. Автору топика, думаю, будет о чем поразмышлять 1 Ссылка на комментарий Поделиться на другие сайты Поделиться
Garik66 Опубликовано 24 марта, 2015 Поделиться Опубликовано 24 марта, 2015 (изменено) В 24.03.2015 в 22:18, tirion сказал: Да, моя теория подтвердилась. Вызвал эти подфункции отдельно, теперь не критует. По всей видимости указатель стека смещался и прыгал не тудаКак я тебя понял - всё сработало? В 24.03.2015 в 22:25, tirion сказал: Автору топика, думаю, будет о чем поразмышлять Это точно. А тебе тоже спасибо - я тоже ещё не много узнал. Изменено 24 марта, 2015 пользователем garik66 Ссылка на комментарий Поделиться на другие сайты Поделиться
tirion Опубликовано 25 марта, 2015 Поделиться Опубликовано 25 марта, 2015 В 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) Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 25 марта, 2015 Поделиться Опубликовано 25 марта, 2015 Вроде бы, все ок. Думаю, корректнее было бы скрипт обернуть в lua-таймер - оно вроде как это умеет. 1 Ссылка на комментарий Поделиться на другие сайты Поделиться
Рекомендуемые сообщения