2009-07-16 15 views
7

私はVistaマシン上のシステム所有プロセスにDLLを注入することに興味があります。 VirtualAllocEx、WriteProcessMemory、CreateRemoteThreadといった伝統的な方法を使ってこれについて説明します。ただし、これはSYSTEMプロセスで動作するため、ターゲットプロセスを開く前に、注入プロセスでSeDebugPivilegeを有効にします。SeDebugPrivilegeを有効にしてSYSTEMプロセスにWriteProcessMemoryを実行します。 (C、Vista)


int EnableDebugPriv(LPCTSTR name) { 
    HANDLE hToken; 
    LUID luid; 
    TOKEN_PRIVILEGES tkp; 

    if(!OpenProcessToken(GetCurrentProcess(), 
         /*TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY*/ 
         TOKEN_ALL_ACCESS, 
         &hToken)) 
     return 0; 

    if(!LookupPrivilegeValue(NULL,name,&luid)) 
     return 0; 

    tkp.PrivilegeCount=1; 
    tkp.Privileges[0].Luid=luid; 
    tkp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED; 

    if(!AdjustTokenPrivileges(hToken,false,&tkp,sizeof(tkp),NULL,NULL)) 
    { 
     printf("!AdjustTokenPrivileges - %d\n",GetLastError()); 
     return 0; 
    } 
    if(GetLastError()==ERROR_NOT_ALL_ASSIGNED) 
    { 
     return 0; 
    } 

    CloseHandle(hToken); 
    return 1; 
} 

ここで、SE_DEBUG_NAME定数が名前として渡されます。

SeDebugPrivilegeを有効にした後、私は(道に沿ってすべての戻り値をチェック)、ターゲットプロセスを開くのLoadLibraryを配置、空間を割り当て、メモリにDLLのパスを書き込み、スレッドを作成するプロセスを経る:


if(NULL==(p=OpenProcess(PROCESS_ALL_ACCESS,FALSE,(DWORD)pid))) 
... 
if(NULL==(loadLib=(LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), 
             "LoadLibraryA"))) 
... 
if(NULL==(dllBuff=(LPVOID)VirtualAllocEx(p, 
             NULL, 
             strlen(dllPath)+1, 
             MEM_RESERVE|MEM_COMMIT, 
             PAGE_READWRITE))) 
... 
if(NULL==WriteProcessMemory(p, 
          (LPVOID)dllBuff, 
          dllPath, 
          strlen(dllPath), 
          &written)) 
... 
if(!CreateRemoteThread(p, 
         NULL, 
         NULL, 
         (LPTHREAD_START_ROUTINE)loadLib, 
         (LPVOID)dllBuff, 
         NULL, 
         NULL)) 
... 

dllPathはDLLのパスのchar *(明らかに)であり、pidはターゲットプロセスのPIDです。これらの値は両方ともコマンドラインから取り込まれ、使用前に検証されます。

問題は、8(「不足しているストレージ」)を返すCreateRemoteThreadまで何もエラーを返さないということです。しかし、WriteProcessMemoryはプロセスにバイトを書き込んでいません。呼び出し後、書き込まれた変数は常に0です。書き込み中のバイトはありませんが、関数は失敗していません。なぜこれが起こっているのか分かりません。私はSeRestorePrivilegeのような他の特権を調べましたが、SeRestorePrivilegeはすべてのプロセスへの書き込みアクセスを約束していますが、何も動作しません。

私はこのプログラムを管理者権限で実行しています。

注:このWriteProcessMemoryおよびCreateRemoteThreadの問題は、上位の特権ユーザー(SYSTEM、LOCAL SERVICEなど)に対してこのプログラムを実行した場合にのみ発生します。それは私が所有するプログラム(同じ特権)に対して完全に動作します。

編集:ここにソース全体へのリンクがあります。 http://pastebin.com/m77110d8e基本的なエラーチェックのほかに他に多くのことはありませんが、おそらくそれが役に立ちますか?

+1

スレッドを作成すると、ターゲットプロセスに暗黙的にスタックが割り当てられます。何故それが失敗したのかは分かりません。 –

答えて

4

これは、Vista以上のバージョンのWindowsでのセッション分離に関係します。 Vistaの機能を主張するCainやAbelのようなパスワードダンピングツールのソースや逆アセンブリを調べてください。基本的にはプロセスは同じですが、CreateRemoteThreadのために別の関数を呼び出すことになります(関数がエクスポートされているとは思いませんが、それを見つける必要があるので、作業ソフトウェアの分解が最善の策です)。

+0

今夜私はCreateRemoteThreadで問題を調べます。情報とヒントをありがとう。 しかし、なぜ0バイトがWriteProcessMemoryで書き込まれていますか?これには別の/並列の機能もありますか? ありがとうございます。他のヒントをいただければ幸いです。 – pcorey

+0

私はバイトが書かれているのを理解することはできますが、エラーコードの欠如は理解できません...それを考えるには至りましたが、デバッガが最もよく使用する関数ではありませんか? – SamB

4

CreateRemoteThreadの代わりにRtlCreateUserThreadを試してみることができます。このルーチンは、ターゲットプロセスがどんなセッションに入っているか気にしません。スレッドが終了する前にRtlExitUserThreadを呼び出すようにしてください。これらのスレッドは、CreateThread/CreateRemoteThreadのように、自分自身の後ではクリーンアップしません。

reactos codeは、これらのルーチンが何をしているかをよく見てくれます。

関連する問題