午後をMSDNをめくって、この例を書きました。
TestDll.dllを書きました。これは、ファイルtest.txtに情報を出力するために使用されるログ関数のみを備えています。
テスト環境:WindowsServer2003+delphi7.0
プログラムは非常にシンプルなので、専門家はそれを読む必要はありません。
testdll.dllテスト用のソースコード(prjzzhost.exeに注入されます):
プログラムコードlibrarytestdll;
用途
sysutils、
システム、
窓、
クラス;
procedureLelog(s:pchar); stdcall;
var
F:TextFile;
始める
assightfile(f、 'test.txt');
iffileexists( 'test.txt')thenpend(f)
elserewrite(f);
writeeln(f、s);
closefile(f);
終わり;
procesturedlentrypoint(dwereason:dword);
始める
Casedwreasonof
dll_process_attach:
log( 'dllprocessattach');
dll_process_detach:
log( 'dllprocessdetach');
dll_thread_attach:
log( 'dllthreadattach');
dll_thread_detach:
log( 'dllthreaddetach');
終わり;
終わり;
輸出
ログ;
始める
dllproc:=@dllentrypoint;
dllentrypoint(dll_process_attach);
終わり。
注入されたホストプロセスprjzzhost.exe(それは何もしません、それはとても無実です:)、私はそれが単純すぎるのでここでコードを与えません、ハハ。
最後に、最も重要なことは次のとおりです。
Project1.exeのソースコード:
プログラムコードunitunit1;
インタフェース
用途
窓、メッセージ、sysutils、バリアント、クラス、グラフィック、コントロール、フォーム、
ダイアログ、stdctrls、tlhelp32;
タイプ
tlog = procedure(s:pchar); stdcall;
tservicemain = procedure(argc:integer; varargv:pchar); stdcall;
edllLoadError = class(例外);
tform1 = class(tform)
Button3:Tbutton;
procedureButton3Click(sender:tobject);
プライベート
{privatedeclarations}
公共
{publicdeclarations}
終わり;
var
form1:tform1;
実装
{$ r*.dfm}
{プロセスの登録}
proceduregetMyProcessid(constafileName:string; constpathmatch:boolean; varprocessid:dword);
var
LPPE:TPROCESSENTRY32;
sshandle:thandle;
Foundaproc、foundok:boolean;
始める
ProcessID:= 0;
{システムスナップショットを作成}
sshandle:= createToolHelp32SNAPSHOT(TH32CS_SNAPPROCESS、0);
{スナップショットで最初のプロセスを取得}
{必ず構造のサイズを設定してください。そうでなければ、Falseが返されます}
lppe.dwsize:= sizeof(tprocessentry32);
feindaproc:= process32first(sshandle、lppe);
whilefoundaprocdo
始める
{マッチを作る}
ifpathmatchthen
foundok:= ansistricomp(lppe.szexefile、pchar(afilename))= 0
それ以外
foundok:= ansistricomp(pchar(extractfilename(lppe.szexefile))、pchar(extractfilename(afilename)))= 0;
ifoundokthen
始める
processId:= lppe.th32processid;
壊す;
終わり;
{見つかりません、次のプロセスに進みます}
feindaproc:= process32next(sshandle、lppe);
終わり;
CloseHandle(sshandle);
終わり;
{設定権限}
functionedableddebugprivilege(constenabled:boolean):boolean;
var
HTK:Thandle; {トークンハンドルを開く}
rtntemp:dword; {アクセス許可の調整時に返される値}
tokenpri:token_privileges;
const
se_debug = 'sedebugprivilege'; {query値}
始める
結果:= false;
{プロセストークンハンドルを取得し、アクセス許可を設定します}
if(openProcessToken(getCurrentProcess()、token_adjust_privileges、htk))
始める
tokenpri.privilegecount:= 1;
{luid値を取得}
lookupprivilegevalue(nil、se_debug、tokenpri.privileges [0] .luid);
ifeanabledthen
tokenpri.privileges [0] .attributes:= se_privilege_enabled
それ以外
tokenpri.privileges [0] .attributes:= 0;
rtntemp:= 0;
{新しい権限を設定}
AductTokenPrivileges(HTK、FALSE、TOKENPRI、SIZEOF(TOKENPRI)、nil、rtntemp);
結果:= getLasterRor = error_success;
CloseHandle(HTK);
終わり;
終わり;
{デバッグ関数}
procedureOutputText(varch:pchar);
var
filehandle:textfile;
始める
assightfile(filehandle、 'zztest.txt');
append(filehandle);
writeln(filehandle、ch);
フラッシュ(filehandle);
closefile(filehandle);
終わり;
{リモートプロセスを注入}
functionInjectto(Consthost、Guest:String; constpid:dword = 0):dword;
var
{注入プロセスハンドル、プロセスID}
hremoteprocess:thandle;
dwremoteprocessid:dword;
{リモートプロセスに書き込まれるコンテンツのサイズ}
memsize:dword;
{リモートプロセスに書き込み後のアドレス}
pszlibfileremote:ポインター;
IRETURNCODE:Boolean;
Tempvar:dword;
{関数loadlibrarywのアドレスを指します}
pfnstartaddr:tfnthreadstartroutine;
{dllフルパス、リモートプロセスのメモリに書き込む必要があります}
pszlibafilename:pwidechar;
始める
結果:= 0;
{設定権限}
enableddebugprivilege(true);
{注入されたDLLファイルパスにメモリサイズを割り当てます。これは、Widecharであるため、2を掛ける必要があります}
getmem(pszlibafilename、length(guest)*2+1);
StringTowideChar(ゲスト、pszlibafilename、length(guest)*2+1);
{プロセスIDを取得}
ifpid> 0then
dwremoteprocessid:= pid
それ以外
getMyProcessid(host、false、dwremoteprocessid);
{リモートプロセスハンドルを取得し、書き込み許可を取得します}
hremoteprocess:= openProcess(process_create_thread+{スレッドのリモート作成を許可}
process_vm_operation+{リモートVM操作を許可}
process_vm_write、{リモートVMの書き込みを許可}
false、dwremoteprocessid);
{関数virtualAllocexを使用して、リモートプロセスでスペースを割り当て、writeprocessmemoryでDLLパスを書き込みます}
memsize:=(1+lstrlenw(pszlibafilename))*sizeof(wchar);
pszlibfileremote:= pwidestring(virtualallocex(hremoteprocess、nil、memsize、mem_commit、page_readwrite));
Tempvar:= 0;
IreturnCode:= writeprocessmemory(hremoteprocess、pszlibfileremote、pszlibafilename、memsize、tempvar);
ifireturncodethen
始める
pfnstartaddr:= getProcAddress(getModuleHandle( 'kernel32')、 'loadlibraryw');
Tempvar:= 0;
{リモートプロセスでDLLを開始}
結果:= createreMotethread(hremoteprocess、nil、0、pfnstartaddr、pszlibfileremote、0、tempvar);
終わり;
{無料メモリスペース}
Freemem(pszlibafilename);
終わり;
{テスト}
proceduretform1.button3click(sender:tobject);
始める
Injectto( 'prjzzhost.exe'、extractfilepath(paramstr(0))+'testdll.dll');
終わり;
終わり。
コードは、DLLがロードされていることの余波を考慮していません。