5

Tôi có dịch vụ Windows đang chạy trong tài khoản Hệ thống Cục bộ tạo thiết bị DOS sử dụng hàm DefineDosDevice. Dịch vụ đang chạy trên Máy chủ để bàn từ xa W2K8. Nếu các thiết bị được tạo bằng cách sử dụng thông tin đăng nhập của dịch vụ, chúng sẽ được tạo trong không gian tên thiết bị GLOBAL và do đó sẽ hiển thị cho tất cả người dùng. Tôi cần các thiết bị chỉ hiển thị cho một phiên tương tác cụ thể.Tại sao các thiết bị DOS được xác định trong phiên không được mạo danh không xuất hiện trong Explorer

Tôi thực hiện việc này bằng cách mạo danh người dùng trong phiên mà tôi muốn các ổ xuất hiện. Điều này khá đơn giản, miễn là id phiên có sẵn. Dưới đây là một ứng dụng thử nghiệm đơn giản tôi đã viết để minh họa cho vấn đề:

int _tmain(int argc, _TCHAR* argv[]) 
{ 
BOOL result = TRUE; 

if(argc > 3 && !wcscmp(argv[2], L"/i")) 
{ 
    HANDLE hToken = 0; 
    DWORD dwSessionId = _wtoi(argv[3]); 
    result = WTSQueryUserToken(dwSessionId, &hToken); 
    if(result) result = ImpersonateLoggedOnUser(hToken); 
} 
if(result) 
{ 
    LPTSTR drive = argv[1]; 
    DefineDosDevice(DDD_REMOVE_DEFINITION, drive, NULL); 
    result = DefineDosDevice(0, drive, L"C:\\test"); 
} 

if(!result) 
{ 
    printf("Error: %d\n", GetLastError()); 
} 
return 0; 
} 

Để kiểm tra mã này, tôi tạo ra một dịch vụ mà ra mắt một tiện ích dòng lệnh dưới tài khoản LocalSystem:

sc tạo binpath test_svc = " cmd/K bắt đầu "type = own type = tương tác

Dịch vụ này không khởi động được, nhưng trước khi nó không thành công, nó sẽ sinh ra một lệnh shell chạy trong tài khoản LocalSystem.

Từ cmd.exe LocalSystem, tôi chạy:

MySubst.exe x:/i 2

mà gọi ImpersonateLoggedOnUser(), sau đó gọi DefineDosDevice()

Từ cmd.exe đang chạy trong phiên của người dùng, tôi chạy:

MySubst.exe y:

Cuộc gọi nào DefineDosDevice mà không cần gọi ImpersonateLoggedOnUser().

Tác phẩm này. Từ cmd.exe tôi có thể truy cập vào hai ổ đĩa X: và Y :. Tôi có thể khởi chạy notepad.exe từ trình đơn bắt đầu, và xem các ổ đĩa X: và Y:. Hơn nữa, nếu tôi tạo một phiên dịch vụ đầu cuối mới với một người dùng khác, tôi không thấy X: hoặc Y :.

Tuy nhiên, Trình khám phá chỉ hiển thị ổ Y: trong "tất cả máy tính". Y: là ổ đĩa được tạo bằng cách chạy ứng dụng thử nghiệm của tôi từ cmd.exe đang chạy trong phiên đích, tức là mạo danh không được thực hiện. Nếu tôi khởi động lại explorer.exe từ Task Manager, cả hai ổ X: và Y: đều hiển thị.

Tôi cũng đã sử dụng WinObj.exe từ SysInternals để kiểm tra các thiết bị Win NT đã xác định. Những gì tôi thấy là:

- Sessions 
    - 0 
     - DosDevices 
      00000000-000057607 

(57607 là ID của phiên đăng nhập liên quan đến phiên mà tôi đang mạo danh)

Nội dung của "00.000.000-000.057.607" là:

Global SymbolicLink \Global?? 
X:  SymbolicLink \\??\C:\test 
Y:  SymbolicLink \\??\C:\test 

Theo WinObj, hai thiết bị dos giống hệt nhau. Chúng thuộc cùng một phiên và phiên đăng nhập. Chúng là các liên kết tượng trưng đến cùng một đối tượng NT.

Làm cách nào để một trong số đó xuất hiện trong Trình khám phá và trình duyệt khác thì không.

+0

Nếu bạn buộc thoát và khởi động lại Explorer, sau đó bạn có thấy ổ đĩa không? –

+0

Có thể không thực hiện được điều này chỉ với sự mạo danh. Bạn có thể cần phải khởi chạy một quy trình thực tế trong bối cảnh đích để thay mặt bạn thực hiện thay đổi. –

+0

@HarryJohnston Việc khởi động lại Explorer không làm cho các ổ đĩa hiển thị, nhưng tôi không chắc chắn nên kết thúc điều gì từ điều này. – FishesCycle

Trả lời

4

@arx và @HarryJohnston đã nhận tiền. Nếu tôi phát một tin nhắn WM_DEVICECHANGE từ một chuỗi trong cùng một phiên làm trình khám phá, ổ đĩa mới sẽ xuất hiện trong My Computer. Dưới đây là mã:

DWORD recipients = BSM_ALLDESKTOPS | BSM_APPLICATIONS; 

DEV_BROADCAST_VOLUME msg; 
ZeroMemory(&msg, sizeof(msg)); 
msg.dbcv_size = sizeof(msg); 
msg.dbcv_devicetype = DBT_DEVTYP_VOLUME; 
msg.dbcv_unitmask = 1 << ('X' - 'A'); 

long success = BroadcastSystemMessage(0, &recipients, WM_DEVICECHANGE, DBT_DEVICEARRIVAL, (LPARAM)&msg); 
Các vấn đề liên quan