Комментарии 9
Спасибо за статью!
Мне кажется, что использование FASM в C# коде — это как кондиционер на велосипеде. Ну или велосипед на кондиционере. Да и вообще, внедрение в нативный код на C#, без DLLки, которую можно инжектить и спокойно вызывать (чтобы можно было хотя бы на С писать, а не на асме), странно.
Интересно было бы посмотреть на вызов C# кода из внедренного кода, хотя это, кажется, из области фантастики.
И еще,
Мне кажется, что использование FASM в C# коде — это как кондиционер на велосипеде. Ну или велосипед на кондиционере. Да и вообще, внедрение в нативный код на C#, без DLLки, которую можно инжектить и спокойно вызывать (чтобы можно было хотя бы на С писать, а не на асме), странно.
Интересно было бы посмотреть на вызов C# кода из внедренного кода, хотя это, кажется, из области фантастики.
И еще,
нужно предусмотреть очередь, для этого я и использовал 80 байт размер, как его реализовать, подумайте самине понял фразу.
Про DLL читайте Часть 0 и комментарии к ней, я доступно объяснил почему я отказался от dll injection.
Представьте, что у вас одновременно 2 вызова InjectAndExecute, которые пишут в argumentAddress1 и argumentAddress2, что случится? Случится, то что вы получите ответ одного из них в обоих вызовах.
Если у вас много потоков которые вызывают InjectAndExecute, то нужно предусмотреть очередь, для этого я и использовал 80 байт размер, как его реализовать, подумайте сами. А в следующей статье, я покажу свою реализацию и как прятать наш код.
Представьте, что у вас одновременно 2 вызова InjectAndExecute, которые пишут в argumentAddress1 и argumentAddress2, что случится? Случится, то что вы получите ответ одного из них в обоих вызовах.
вызов C# кода из внедренного кода, хотя это, кажется, из области фантастики.Нет, не фантастика :)
Готовых кусочков кода я вам не приведу (можете попробовать поискать на OwnedCore — хороший источник информации о читах, хаках, внутреннем устройстве WoW и не только; в том числе proof of concept интересующего вас вопроса), но если вкратце, то просто внедряется нативная dll, которая создаёт хост CLR, подгружает сборку и передаёт ей управление, как-то так (CppHostCLR).
А можно поподробнее что из чего вызывается? (я в ассемблере не очень)
Как я понял внедрённый код вызывается из хукнутой функции(куда предварительно воткнули jmp на этот код), а вот внедрённый код что делает? он самостоятельный или передаёт управление куда то ещё(«call eax»)? куда?
Так-же не понял момент про очередь и её связь с многопоточностью: ведь если внедрённый код не использует глобальных переменных то проблем быть не должно — стек то у каждого потока свой.
PS: popad/pushad — зачем, ведь, как я понимаю хукаются функции DirectX, а они используя соглашение stdcall получают аргументы через стек и следовательно(если мы внедрились в самое начало функции, а не в середину) сохранять регистры незачем.
PPS: хотелось бы по больше теории на тему что и как делается ибо по неполным кускам кода всю логику восстановить не получается.
Как я понял внедрённый код вызывается из хукнутой функции(куда предварительно воткнули jmp на этот код), а вот внедрённый код что делает? он самостоятельный или передаёт управление куда то ещё(«call eax»)? куда?
Так-же не понял момент про очередь и её связь с многопоточностью: ведь если внедрённый код не использует глобальных переменных то проблем быть не должно — стек то у каждого потока свой.
PS: popad/pushad — зачем, ведь, как я понимаю хукаются функции DirectX, а они используя соглашение stdcall получают аргументы через стек и следовательно(если мы внедрились в самое начало функции, а не в середину) сохранять регистры незачем.
PPS: хотелось бы по больше теории на тему что и как делается ибо по неполным кускам кода всю логику восстановить не получается.
Можно и нужно! Совершенно верно, ассемблерный код вызывается каждый фрейм из перехваченной функции. А вот что он делает, это весьма очевидно, нужно всего лишь проявить внимательность. Я специально его сделал таким, что бы оставить подсказку для реализации очереди в InjectAndExecute. Но увы — никто не догадался. call eax, это переход по указателю в (argumentAddress1 + offset), может это что-либо прояснит и кто-нибудь все же догадается и да, argumentAddress1 глобальна внутри класса, ведь ее используем в InjectAndExecute. Команды нужны popad/pushad — ведь мы не знаем, что будет по указателю в argumentAddress1 и лучше не рисковать. В следующей статье я максимально попытаюсь объяснить этот код с хорошим примером на C#, давайте подождем, вдруг кто-нибудь догадается.
Вы с какого процессора ассемблер изучать начали?
Я таких извращений даже на 8080 не встречал. Чем-то MCS-51 напоминает, разве что.
Не заставляйте новичков разбирать такое, да еще без комментариев. Садизм-же.
Эквивалентный код:
Я таких извращений даже на 8080 не встречал. Чем-то MCS-51 напоминает, разве что.
Не заставляйте новичков разбирать такое, да еще без комментариев. Садизм-же.
Эквивалентный код:
mov ebx, 0
loop_it:
mov eax, [ebx*4+argumentAddress1]
test eax, eax
jz skip_it
push ebx
call eax
pop ebx
mov [ebx*4+argumentAddress2], eax
skip_it:
inc ebx
cmp ebx, 80/4
jnz loop_it
Мне как новичку в этой сфере тема очень интересна. Да и актуальная будет в ближайшие 20+ лет. Но хотелось бы более развёрнутой информации от автора, без лишних тайн и разгадок. Всё таки устройство не велосипеда разбираем. У меня стаж программирования 7 лет, но эта тема даётся сложно. Комментарии типа «догадайтесь/решите/подумайте» вводят в ступор, потому что без опыта очень тяжело…
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Пишем бота для MMORPG с ассемблером и дренейками. Часть 1