2008-08-23 2 views
13

Можете ли вы использовать крючки для Windows или другие методы для ввода кода с помощью C#? Я видел много вещей о введении кода, но все они выполняются на C/C++. Я не знаю ни одного из этих языков и очень тяжело переводил. Кто-нибудь есть идеи о том, как это сделать?Code Injection With C#

ответ

5

Kevin, можно. Вы можете создать библиотеку с помощью обработчика окон, используя управляемый C++. Все, что вам нужно сделать, это вставить этот крючок в какое-то приложение, используя стандартный WinAPI (SetWindowsHookEx и т. Д.). Внутри этого крюка вы можете вызвать метод System :: AppDomain :: CurrentDomain-> Load для загрузки вашей сборки в AppDomain целевого приложения. Затем вы можете вызывать методы, определенные в вашей сборке, используя отражение. Например, Snoop использует этот метод.

+2

Ссылка не работает – 2016-03-24 07:49:54

+0

Возможно, кому-то будет полезно ознакомиться с https://web.archive.org/web/20081228210203/http://blois.us/Snoop/ w.r.t. сломанная ссылка. – 2016-09-21 20:35:45

9

Просто наткнулся на ссылку, которая обсуждает этот вопрос в деталях, так что я хотел отправить его обратно здесь: How To Inject a Managed .NET Assembly (DLL) Into Another Process

+2

Ссылка кажется сломанной – 2014-04-27 08:00:33

+1

Вот архив от Wayback Machine https://web.archive.org/web/20130303142450/http://www.codingthewheel.com/archives/how-to-inject-a-managed -assembly-dll – 2014-04-28 15:29:14

3

Mike Stall имеет this sample, который использует CreateRemoteThread. Это имеет то преимущество, что не требует никакого C++.

2

Вы можете проверить CInject для ввода кода в сборках .NET на сайте CodePlex http://codeinject.codeplex.com/. Вам не нужно знать о введении кода для инъекции любого кода при использовании CInject.

2

EDIT: Я, кажется, неправильно истолковал вопрос .... У меня создалось впечатление, что вопрос был о введении кода в текущий процесс.


Я присоединяюсь к партии довольно поздно, но я просто использовал именно это несколько недель назад:

Делегат содержит закрытые поля IntPtr _methodPtr and IntPtr _methodPtrAux, которые представляют адреса памяти организма. Установив поле (через отражение) на определенные значения, можно изменить адрес памяти, на который будет указываться EIP.
Используя эту информацию, можно сделать следующее:

  1. Создать массив с монтажными байтов, которые должны быть выполнены
  2. Перемещение указателя метод делегата в байтах в вопросе
  3. Вызов делегата
  4. Прибыль ???

(Конечно, вы можете изменить _methodPtr -Value по любому адресу памяти - даже в пространстве ядра, но это может потребовать соответствующие привилегии выполнения).


У меня есть пример рабочего кода здесь, если вы хотите:

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 

Конечно, на также может написать следующий метод:

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-compiler switch.