Czy można zainstalować aplikację na zdalnym komputerze, w ogóle do niego się nie zbliżając?
Tak, ale muszą być spełnione dwa warunki:
- Na zdalnym komputerze musi być zainstalowany Windows NT
- Nasza aplikacja musi być serwisem
Sprawa jest dosyć prosta. Oto algorytm:
- Znalezienie dysków na zdalnym komputerze
- Znalezienie dysku, na którym jest zainstalowane Windows
- Kopiowanie plików
- Zainstalowanie i uruchomienie serwisu
Znalezienie dysków na zdalnym komputerze
Standardowo Windows NT udostępnia wszystkie dyski lokalne - do odczytu i zapisu.
Nazwy udziałów składają się z litery dysku i ze znaku "$" na końcu.
Tak więc dla dysku C mamy udział C$, dla D - D$, itd.
Tylko
administrator ma dostęp do tych udziałów, tak więc zakładam,
że użytkownik wykonujący instalację ma prawa administratora
na zdalnym komputerze.
Jeśli nie, to można wykorzystać funkcję
ImpersonateLoggedOnUser. Może opiszę to kiedyś...
Tak więc mamy dostęp do dysków. Teraz trzeba znaleźć wszystkie dyski na zdalnym kompie.
Niestety funkcja
WNetEnumResource nie listuje tych udziałów.
Jedyne rozwiązanie jakie udało mi się wymyślić to wykorzystanie funkcji
WNetGetResourceInformation.
Problem z tą funkcją jest taki, że nie ma jej ani w Delphi ani w VS6 :-|. Ale co to dla nas:
interface
uses Windows;
function WNetGetResourceInformation(lpNetResource: PNetResource;
lpBuffer: Pointer; var cbBuffer: DWORD;
var lplpSystem: PAnsiChar): DWORD; stdcall;
implementation
function WNetGetResourceInformation;
external mpr name 'WNetGetResourceInformationA';
|
Mamy funkcję, teraz trzeba dla każdej literki od A do Z sprawdzić czy taki udział istnieje:
procedure FindDisks;
var
NetResource : TNetResource;
Size : DWORD;
Result : DWORD;
Res : PNetResource;
Str : PChar;
c : Char;
begin
with NetResource do
begin
dwScope := RESOURCE_GLOBALNET;
dwType := RESOURCETYPE_DISK;
dwDisplayType := RESOURCEDISPLAYTYPE_SHARE;
dwUsage := 0;
lpLocalName := nil;
lpComment := nil;
lpProvider := nil;
end;
Size := SizeOf(TNetResource);
GetMem(Res, Size);
try
for c := 'A' to 'Z' do
begin
NetResource.lpRemoteName := PChar('\\host\'+c+'$');
Result := WNetGetResourceInformation(@NetResource, Res, Size, Str);
if Result=ERROR_MORE_DATA then
begin
ReallocMem(Res, Size);
Result := WNetGetResourceInformation(@NetResource, Res, Size, Str);
end;
if Result=NO_ERROR then ShowMessage(Res^.lpRemoteName);
end;
finally
FreeMem(Res);
end;
end;
|
No i mamy listę dysków na zdalnym kompie.
Znalezienie dysku, na którym jest zainstalowane Windows
To już jest prostsze.
Wystarczy skorzystać z funkcji
RegConnectRegistry.
procedure GetSystemRoot;
var
Key : HKEY;
SubKey : HKEY;
Path : array[0..1024] of Char;
DataType : DWORD;
Size : DWORD;
begin
RegConnectRegistry('\\host', HKEY_LOCAL_MACHINE, Key);
try
RegOpenKeyEx(Key, 'SOFTWARE\Microsoft\Windows NT\CurrentVersion',
0, KEY_READ, SubKey);
try
Size := SizeOf(Path);
RegQueryValueEx(SubKey, 'SystemRoot', nil, @DataType, @Path, @Size);
ShowMessage(Path);
finally
RegCloseKey(SubKey);
end;
finally
RegCloseKey(Key);
end;
end;
|
Oczywiście wypada także sprawdzać błędy, ale to już pozostawiam Tobie.
W ten sposób można także odczytać inne wartości ze zdalnego rejestru.
Kopiowanie plików
To chyba każdy potrafi. Inna jest tylko ścieżka docelowa.
Zamiast liter dysków mamy
\\host\C$ dla dysku
C:, itd.
Zainstalowanie i uruchomienie serwisu
Podobnie jak przy rejestrze, łączymy się ze zdalnym komputerem za pomocą funkcji API.
procedure InstallService;
var
SCMan : SC_HANDLE;
Svc : SC_HANDLE;
begin
SCMan := OpenSCManager('\\host', nil, SC_MANAGER_ALL_ACCESS);
try
Svc := CreateService(SCMan, 'ServiceName', 'DisplayName',
SERVICE_ALL_ACCESS, ...);
CloseServiceHandle(Svc);
finally
CloseServiceHandle(SCMan);
end;
end;
|
Tutaj także należy sprawdzać poprawność wykonania funkcji :-).
W ten sposób zainstalowaliśmy aplikację na zdalnym komputerze,
a użytkownik na zdalnym kompie nawet nie wie,
że ma u siebie backdoor'a ;-).
Michał Bąkowski
Tutaj znajdzie się twoje zdanie jeśli znajdziesz chwilkę, żeby je wklepać...