7

この質問は教育目的のみです。
ネイティブプログラムがどのように機能しているかを知っています。コンパイラは各プリミティブを受け取り、それにアドレスを与えてから、プログラムでそのアドレスを使用します。構造体の場合、アドレスを(いくつかのパディングを使用して)単純にスタックしますが、基本的に、構造体は実際には「存在」しません。

ネイティブプログラムは、どのフィールドと変数を持っているかを教えてくれません。異なるアドレスにのみアクセスします。アセンブリを見ると、必要に応じて各アドレスに名前を付けることができますが、プログラムはその情報を提供しません。したがって、特定の変数を探していると仮定すると、プログラムの実行またはそのアセンブリを調べることなしにそれを行うことはできません。

.NET環境は、どの変数とどのフィールドを持っているかを教えてくれます。AssemblyReflection名前空間では、ファイルをロードして、そのファイルに含まれるフィールドとクラスを確認できます。
次に、メモリを検索するプログラム(ネイティブかどうかに関係なく)を使用して、フィールドの物理的な場所を見つけることができます(値を使用したり、フィルターで除外したりするなど)Cheat Engine。によって作成されたアセンブリによってアクセスされる、メモリ内のフィールドの実際のアドレスが表示されますJIT
MSILには、特定のフィールドの目的の場所に関する情報が含まれていないことを知っています。JITまた、クラスを削除してもコードが最適化されることはないとほぼ確信しています。

Visual Studio.NETデバッガーは、アプリケーションの内部情報と対話できるようにするプログラムの実際のクラスであることを私は知っています。デバッガーが見つからない場合、Visual Studioフィールドの読み取りまたは書き込みはできず、アプリケーションを検査することもできません。


実行中の.NETプロセスの静的(または特定のインスタンス)クラスのフィールドの物理的な場所を見つけるためCheat Engineに、または同様のツールを使用せずに、方法はありますか?(ネイティブプログラムなどで)実行するたびにアドレスは同じになりますか?異なるプラットフォームまたはマシンでのみ異なる可能性がありますか?フィールドを配置する場所をどのように決定しますか?JIT

よくわからない場合は、プログラムのコードにアクセスせずに、つまり外部で別のプロセス(デバッガーなどですが、リリース時にコンパイルされたプログラムの場合)で実行したいと思います。

4

1 に答える 1

0

次のコードは、Paint.netにInjectorメソッドを挿入し、MainFormフィールドを取得します。

NInject.exe

public static int Injector(string parameter)
{
  try
  {
    var mainForm = Application.OpenForms.OfType<Form>().FirstOrDefault(form => form.GetType().FullName.EndsWith("MainForm"));

    var builder = new StringBuilder();
    builder.AppendFormat("process: {0}\r\n\r\n", Application.ExecutablePath);
    builder.AppendFormat("type: {0}\r\n", mainForm.GetType().FullName);
    foreach (var field in mainForm.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic))
    {
      builder.AppendFormat("field {0}: {1}\r\n", field.Name, field.GetValue(mainForm));
    }


    new Form()
    {
      Controls = 
      {
        new TextBox
        {
          Text = builder.ToString(),
          Multiline = true,
          Dock = DockStyle.Fill
        }
      }
    }
    .ShowDialog();
  }
  catch (Exception exc)
  {
    MessageBox.Show(exc.ToString());
  }
  return 0;      
}

static void Main(string[] args)
{
  var process = System.Diagnostics.Process.GetProcessesByName("PaintDotNet").FirstOrDefault();

  var processHandle = OpenProcess(ProcessAccessFlags.All, false, process.Id);

  var proxyPath = System.IO.Path.Combine(System.Windows.Forms.Application.StartupPath, "NInjector.dll");

  var pathBytes = System.Text.Encoding.ASCII.GetBytes(proxyPath);

  var remoteBuffer = VirtualAllocEx(processHandle, IntPtr.Zero, (uint)pathBytes.Length, AllocationType.Commit, MemoryProtection.ReadWrite);
  WriteProcessMemory(process.Handle, remoteBuffer, pathBytes, (uint)pathBytes.Length, IntPtr.Zero);


  var remoteThread = CreateRemoteThread(processHandle, IntPtr.Zero, 0, GetProcAddress(GetModuleHandle("kernel32"), "LoadLibraryA") , remoteBuffer, 0, IntPtr.Zero);

  WaitForSingleObject(remoteThread, unchecked((uint)-1)); 

  CloseHandle(remoteThread);

}

NInjector.dll(ネイティブ)

#include "MSCorEE.h"
#pragma comment  (lib, "MSCorEE")

void StartTheDotNetRuntime()
{
    MessageBox(0, L"Started", L"proxy", 0);

    ICLRRuntimeHost *pClrHost = NULL;
    HRESULT hr = CorBindToRuntimeEx(
        NULL, L"wks", 0, CLSID_CLRRuntimeHost,
        IID_ICLRRuntimeHost, (PVOID*)&pClrHost);


    hr = pClrHost->Start();


    DWORD dwRet = 0;
    hr = pClrHost->ExecuteInDefaultAppDomain(
        L"bla-bla\\NInject.exe",
        L"NInject.NInject_Program", L"Injector", L"MyParameter", &dwRet);



    hr = pClrHost->Stop();

    pClrHost->Release();
}


BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    StartTheDotNetRuntime();
    break;
    case DLL_THREAD_ATTACH:
    break;
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:


        break;
    }
    return TRUE;
}

出力:

process: C:\Program Files\Paint.NET\PaintDotNet.exe

type: PaintDotNet.Dialogs.MainForm
field appWorkspace: PaintDotNet.Controls.AppWorkspace
field defaultButton: System.Windows.Forms.Button, Text: 
field floaters: PaintDotNet.Dialogs.FloatingToolForm[]
field floaterOpacityTimer:  [System.Windows.Forms.Timer], Interval: 25
field deferredInitializationTimer: 
field components: System.ComponentModel.Container
field killAfterInit: False
field singleInstanceManager: PaintDotNet.SystemLayer.SingleInstanceManager
field queuedInstanceMessages: System.Collections.Generic.List`1[System.String]
field processingOpen: False
field scrollPosition: {X=0,Y=0}
于 2012-07-26T22:09:39.743 に答える