CreateRemoteThread를 이용한 DLL Injection.
주의할 점은, Delphi2009 부터 기본 문자열 관련 변수들이 Wide이므로 명시적으로 Ansi를 지정해줘야 함. (PAnsiChar)
LoadLibraryA 를 이용하므로.
// DLL Injection 함수
procedure InjectDLL(dwPID: DWORD; DLLPath: PAnsiChar);
var
dwBufferSize, dwWritten, dwThreadID: DWORD;
hProc, hThread: THandle;
pRemoteBuffer: Pointer;
begin
// 프로세스 까기
hProc:=OpenProcess(PROCESS_ALL_ACCESS, False, dwPID);
if hProc=0 then begin
OutputDebugString('[Error] OpenProcess');
Exit;
end;
// 다른 프로세스에 LoadLibraryA의 변수로 사용할 문자열 쓰기(=로딩할 DLL 경로)
dwBufferSize:=Length(DLLPath);
pRemoteBuffer:=VirtualAllocEx(hProc, nil, dwBufferSize, MEM_COMMIT, PAGE_READWRITE);
if pRemoteBuffer=nil then begin
OutputDebugString('[Error] VirtualAllocEx');
Exit;
end;
if WriteProcessMemory(hProc, pRemoteBuffer, DLLPath, dwBufferSize, dwWritten)=False then begin
OutputDebugString('[Error] WriteProcessMemory');
Exit;
end;
// DLL Injection
hThread:=CreateRemoteThread(hProc, nil, 0, GetProcAddress(LoadLibrary('kernel32.dll'), 'LoadLibraryA'), pRemoteBuffer, 0, dwThreadID);
WaitForSingleObject(hThread, INFINITE);
// 정리...
VirtualFreeEx(hProc, pRemoteBuffer, dwBufferSize, MEM_RELEASE);
CloseHandle(hThread);
CloseHandle(hProc);
end;
// 사용예
// 계산기를 실행시키고 DLL 주입
procedure TForm1.Button1Click(Sender: TObject);
var
SecAttr: TSecurityAttributes;
ProcInfo: TProcessInformation;
StartupInfo: TStartupInfo;
cmd: array [0..1023] of WideChar;
begin
SecAttr.nLength:=SizeOf(SecAttr);
SecAttr.lpSecurityDescriptor:=nil;
SecAttr.bInheritHandle:=True;
ZeroMemory(@StartupInfo, SizeOf(StartupInfo));
StartupInfo.cb:=SizeOf(StartupInfo);
StartupInfo.dwFlags:=STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
StartupInfo.wShowWindow:=SW_SHOW;
ZeroMemory(@cmd, SizeOf(cmd));
StrCopy(cmd, 'calc.exe');
CreateProcess(nil, cmd, @SecAttr, @SecAttr, True, DETACHED_PROCESS or NORMAL_PRIORITY_CLASS, nil, nil, StartupInfo, ProcInfo);
WaitForInputIdle(ProcInfo.hProcess, INFINITE);
// DLL Injection
InjectDLL(ProcInfo.dwProcessId, 'C:\MyDLL\mydll.dll');
end;
procedure InjectDLL(dwPID: DWORD; DLLPath: PAnsiChar);
var
dwBufferSize, dwWritten, dwThreadID: DWORD;
hProc, hThread: THandle;
pRemoteBuffer: Pointer;
begin
// 프로세스 까기
hProc:=OpenProcess(PROCESS_ALL_ACCESS, False, dwPID);
if hProc=0 then begin
OutputDebugString('[Error] OpenProcess');
Exit;
end;
// 다른 프로세스에 LoadLibraryA의 변수로 사용할 문자열 쓰기(=로딩할 DLL 경로)
dwBufferSize:=Length(DLLPath);
pRemoteBuffer:=VirtualAllocEx(hProc, nil, dwBufferSize, MEM_COMMIT, PAGE_READWRITE);
if pRemoteBuffer=nil then begin
OutputDebugString('[Error] VirtualAllocEx');
Exit;
end;
if WriteProcessMemory(hProc, pRemoteBuffer, DLLPath, dwBufferSize, dwWritten)=False then begin
OutputDebugString('[Error] WriteProcessMemory');
Exit;
end;
// DLL Injection
hThread:=CreateRemoteThread(hProc, nil, 0, GetProcAddress(LoadLibrary('kernel32.dll'), 'LoadLibraryA'), pRemoteBuffer, 0, dwThreadID);
WaitForSingleObject(hThread, INFINITE);
// 정리...
VirtualFreeEx(hProc, pRemoteBuffer, dwBufferSize, MEM_RELEASE);
CloseHandle(hThread);
CloseHandle(hProc);
end;
// 사용예
// 계산기를 실행시키고 DLL 주입
procedure TForm1.Button1Click(Sender: TObject);
var
SecAttr: TSecurityAttributes;
ProcInfo: TProcessInformation;
StartupInfo: TStartupInfo;
cmd: array [0..1023] of WideChar;
begin
SecAttr.nLength:=SizeOf(SecAttr);
SecAttr.lpSecurityDescriptor:=nil;
SecAttr.bInheritHandle:=True;
ZeroMemory(@StartupInfo, SizeOf(StartupInfo));
StartupInfo.cb:=SizeOf(StartupInfo);
StartupInfo.dwFlags:=STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
StartupInfo.wShowWindow:=SW_SHOW;
ZeroMemory(@cmd, SizeOf(cmd));
StrCopy(cmd, 'calc.exe');
CreateProcess(nil, cmd, @SecAttr, @SecAttr, True, DETACHED_PROCESS or NORMAL_PRIORITY_CLASS, nil, nil, StartupInfo, ProcInfo);
WaitForInputIdle(ProcInfo.hProcess, INFINITE);
// DLL Injection
InjectDLL(ProcInfo.dwProcessId, 'C:\MyDLL\mydll.dll');
end;
'Delphi' 카테고리의 다른 글
[Delphi] 문자열이 숫자로만 되어 있는지 체크 (0) | 2010.06.03 |
---|---|
[Delphi] 윈도우 다시 그리기 (0) | 2010.06.01 |
[Delphi] TStringList의 CustomSort (0) | 2010.05.24 |
[Delphi] 문자가 배열에 속하는지 비교 (0) | 2010.05.24 |
[Delphi] Memory leak - TThemeServices (0) | 2010.05.18 |