Внедрение кода С помощью C#
-
09-06-2019 - |
Вопрос
Можете ли вы использовать перехваты Windows или другие методы для выполнения внедрения кода с помощью c #?Я видел много вещей о внедрении кода, но все они выполнены на C / C ++.Я не знаю ни одного из этих языков, и мне очень трудно переводить.У кого-нибудь есть какие-нибудь идеи о том, как это сделать?
Решение
Кевин, это возможно.Вы можете создать библиотеку с помощью window hook proc, используя управляемый C ++.Все, что вам нужно сделать, это внедрить этот хук в какое-либо приложение, используя стандартный WinAPI (SetWindowsHookEx и т.д.).Внутри этого хука вы можете вызвать System::AppDomain:: CurrentDomain-> Метод загрузки, чтобы загрузить вашу сборку в AppDomain целевого приложения.Затем вы можете вызывать методы, определенные в вашей сборке, используя отражение.Например, Вынюхивать использует этот метод.
Другие советы
У Майка Столла есть этот образец, который использует CreateRemoteThread.Его преимущество в том, что он не требует никакого C ++.
Редактировать: Кажется , я неправильно истолковал вопрос ....У меня сложилось впечатление, что вопрос касался внедрения кода в текущий процесс.
Я присоединяюсь к вечеринке довольно поздно, но я использовал именно это всего несколько недель назад:
Делегат содержит закрытые поля IntPtr _methodPtr
и IntPtr _methodPtrAux
, которые представляют адрес памяти тела.Установив для поля (с помощью отражения) определенные значения, можно изменить адрес памяти, на который будет указывать EIP.
Используя эту информацию, можно сделать следующее:
- Создайте массив с байтами сборки, которые должны быть выполнены
- Переместите указатель метода делегата на соответствующие байты
- Вызовите делегата
- Прибыль ???
(Конечно, вы можете изменить _methodPtr
-значение для любого адреса памяти - даже в пространстве ядра, но для этого могут потребоваться соответствующие привилегии выполнения).
У меня есть здесь пример рабочего кода, если вы хотите:
public static unsafe int? InjectAndRunX86ASM(this Func<int> del, byte[] asm)
{
if (del != null)
fixed (byte* ptr = &asm[0])
{
FieldInfo _methodPtr = typeof(Delegate).GetField("_methodPtr", BindingFlags.NonPublic | BindingFlags.Instance);
FieldInfo _methodPtrAux = typeof(Delegate).GetField("_methodPtrAux", BindingFlags.NonPublic | BindingFlags.Instance);
_methodPtr.SetValue(del, ptr);
_methodPtrAux.SetValue(del, ptr);
return del();
}
else
return null;
}
Который может быть использован следующим образом:
Func<int> del = () => 0;
byte[] asm_bytes = new byte[] { 0xb8, 0x15, 0x03, 0x00, 0x00, 0xbb, 0x42, 0x00, 0x00, 0x00, 0x03, 0xc3 };
// mov eax, 315h
// mov ebx, 42h
// add eax, ebx
// ret
int res = del.InjectAndRunX86ASM(asm_bytes); // should be 789 + 66 = 855
Конечно, on также мог бы написать следующий метод:
public static unsafe int RunX86ASM(byte[] asm)
{
Func<int> del = () => 0; // create a delegate variable
Array.Resize(ref asm, asm.Length + 1);
// add a return instruction at the end to prevent any memory leaks
asm[asm.Length - 1] = 0xC3;
fixed (byte* ptr = &asm[0])
{
FieldInfo _methodPtr = typeof(Delegate).GetField("_methodPtr", BindingFlags.NonPublic | BindingFlags.Instance);
FieldInfo _methodPtrAux = typeof(Delegate).GetField("_methodPtrAux", BindingFlags.NonPublic | BindingFlags.Instance);
_methodPtr.SetValue(del, ptr);
_methodPtrAux.SetValue(del, ptr);
return del();
}
}
Вероятно, то же самое можно было бы сделать с существующими методами (не делегатами) с помощью отражения:
// UNTESTED //
Action new_method_body = () => { };
MethodInfo nfo = typeof(MyType).GetMethod( ..... );
IntPtr ptr = nfo.MethodHandle.Value; // ptr is a pointer to the method in question
InjectX86ASM(new_method_body, new byte[] { ......., 0xC3 }); // assembly bytes to be injected
int target = new_method_body.Method.MethodHandle.Value.ToInt32();
byte[] redirector = new byte[] {
0xE8, // CALL INSTRUCTION + TARGET ADDRESS IN LITTLE ENDIAN
(byte)(target & 0xff),
(byte)((target >> 8) & 0xff),
(byte)((target >> 16) & 0xff),
(byte)((target >> 24) & 0xff),
0xC3, // RETURN INSTRUCTION
};
Marshal.Copy(redirector, 0, ptr, redirector.Length);
Используйте любой код на свой страх и риск. Примеры кода должны быть скомпилированы с использованием
/unsafe
-переключатель компилятора.
Вы можете ознакомиться с CInject для внедрения кода в сборки .NET на сайте CodePlex http://codeinject.codeplex.com/.Вам не нужно иметь никаких знаний о внедрении кода, чтобы внедрить какой-либо код при использовании CInject.