| 
 
 
 
 Легенда:
  новое сообщение 
  закрытая нитка 
  новое сообщение 
  в закрытой нитке 
  старое сообщение   | 
Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
Новичкам также крайне полезно ознакомиться с данным документом.
|  |  |  |  |  | [Win32] Посмотри в отладчике, правильно ли параметры передаются  17.07.02 16:40  Число просмотров: 1247 Автор: Cyril <sc> Статус: Member
 |  
|  |  | <programming> |  
| [Win32] Вот я попал с Win2k Security. Help, please ;-))))  15.07.02 22:12 Автор: HandleX <Александр М.> Статус: The Elderman
 Отредактировано 15.07.02 22:14  Количество правок: 1
 |  
| Hi, All! Блин, досадная трабла, не знаю как побороться.
 Уже что только не переделал.
 Итак, вот кусок кода (Delphi):
 
 
 
Var
    PSec: PSecurityDescriptor;
    Count: DWORD;
    pAccessList: PEXPLICIT_ACCESS_A;
    J: Integer;
    aDACL: PACL;
    dDefaulted, dPresent: BOOL;
  Begin
    PSec := GetServiceSD(DACL_SECURITY_INFORMATION);
    Try
      //ConvertSDtoAbsolute(pSec);
      Win32Check(GetSecurityDescriptorDacl(pSec, dPresent, aDACL, dDefaulted));
      If Not dPresent Then Exit;
      pAccessList := Nil; Count := 0;
      J := GetExplicitEntriesFromAcl(aDacl^, Count, pAccessList);
      If J <> ERROR_SUCCESS Then	// <=== Здесь происходит трабла. Возвращаемый код 
				// равен ошибке 87, что означает "Параметр задан неверно"
        Raise Exception.Create('Win32Error: ' + SysErrorMessage(J));
 ---
 
 Что здравого можно придумать по этому поводу? Я уже изматюгался весь. Мелкософт говорит, что GetExplicitEntriesFromAcl сам создаст нужный буфер, который надо потом LocalFree.
 Причём неважно, из кагого SD DACL пихаешь - абсолютного или Self-relative, всё равно ЕГГОГ 87 ;-))
 Заранее спасибо за советы, добрый All!
 |  
|  | [Win32] Внимание! Найден новый баг от Microsoft! Пожалуйста, проверьте.  18.07.02 22:06 Автор: HandleX <Александр М.> Статус: The Elderman
 |  
| У кого Delphi5 или 6 могут напрямую ввести кусок вот такого кода: 
 
 
implementation
Uses AclAPI, AccCtrl, WinSvc;
procedure TForm1.Button1Click(Sender: TObject);
Type
  TExplicitAccessArray = Array[0..0] Of EXPLICIT_ACCESS;
  PExplicitAccessArray = ^TExplicitAccessArray;
  Function GetEAListFromService(ServiceKeyName: String): PExplicitAccessArray;
  Var scHndl, srvHndl: THandle;
    Function GetServiceSD(SDFlags: DWORD): PSecurityDescriptor;
    Var BytesNeeded: DWord;
    Begin
      New(Result);
      BytesNeeded := 0;
      QueryServiceObjectSecurity(srvHndl, SDFlags, Result, 0, BytesNeeded);
      If BytesNeeded = 0 Then RaiseLastWin32Error;
      If SizeOf(Result^) <> BytesNeeded Then
      Begin
        ReallocMem(Result, BytesNeeded);
        Win32Check(QueryServiceObjectSecurity(srvHndl, SDFlags, Result, BytesNeeded, BytesNeeded));
      End;
    End;
  Var
    aSD: PSecurityDescriptor;
    pDACL: PACL;
    dPresent, dDefaulted: Bool;
    EACount, ErrCode: DWORD;
  Begin
    scHndl := OpenSCManager(Nil, Nil, GENERIC_EXECUTE);
    Win32Check(scHndl <> 0);
    Try
      srvHndl := OpenService(SCHndl, PChar(ServiceKeyName), STANDARD_RIGHTS_REQUIRED);
      Win32Check(srvHndl <> 0);
      Try
        aSD := GetServiceSD(DACL_SECURITY_INFORMATION);
        Result := Nil;
        If Not IsValidSecurityDescriptor(aSD) Then Exit;
        Try
          Win32Check(GetSecurityDescriptorDacl(aSD, dPresent, pDACL, dDefaulted));
          If Not dPresent Then Exit;
          ErrCode := GetExplicitEntriesFromAcl(pDACL^, EACount, @Result);
          If ErrCode <> ERROR_SUCCESS Then
            Application.MessageBox(PChar(Format('Error (%d): %s', [ErrCode, SysErrorMessage(ErrCode)])), Nil, mb_IconError);
        Finally
          FreeMem(aSD);
        End;
      Finally
        CloseServiceHandle(srvHndl);
      End;
    Finally
      CloseServiceHandle(scHndl);
    End;
  End;
Var
  pEAList: PExplicitAccessArray;
begin
  pEAList := GetEAListFromService('Messenger');
  If pEAList = Nil Then Application.MessageBox('Найден новый баг! Call for service ;-))', 'Microsoft снова обложался?', mb_IconQuestion)
  Else LocalFree(DWord(pEAList));
end;
 ---
 
 Указание по компиляции на Delphi5:
 Найти в каталоге Source\Rtl\Win библиотеку AclAPI.pas.
 Открыть библиотеку каким-либо текстовым редактором.
 Найти строчку: ModName = 'aclapi.dll' .
 Поменять на: ModName = 'advapi32.dll' . (И здесь баги! ;-))))))))
 Скомпилировать библиотеку командной строкой: dcc32 AclAPI.pas .
 Получившийся модуль aclapi.dcu переместить в каталог Delphi5\LIB, затерев старый файл.
 Запустить Delphi5. Дальше вроде всем понятно ;-)))))
 
 Очень было бы неплохо, если бы кто-нибудь сваял подобное на С — так, на всякий случай.
 По-моему, налицо явный баг.
 |  
|  |  | Всем спасибо! Кто всё-таки обложался, непонятно! Этот код у меня тоже заработал!  20.07.02 08:27 Автор: HandleX <Александр М.> Статус: The Elderman
 |  
| Наверное злобный Билли Гейтс, сидящий внутри моего компьютера, испугался и разрешил выполнятся этой функции. А ещё говорят, что расположение планет может влиять на работу компьютера ;-)))))))))))) 
 Но самый прикол в том, что я в своём приложении (где я наткнулся на этот косяк), уже всё сделал через GetAclInformation, GetAce, LookupAccountSid и т.п. Ну ладно, всё хорошо, что хорошо кончается ;-))))))
 |  
|  |  | [Win32] Пожалуйста, проверил  19.07.02 21:11 Автор: Cyril <sc> Статус: Member
 |  
| Cкомилил на delphi5, запустил, все нормально пашет, messagebox не появляется. w2000 prof 5.00.2195 sp2 rus
 advapi32.dll вер. 5.00.2195.2867
 |  
|  |  | [Win32]ты  обложался!  19.07.02 00:31 Автор: + <Mikhail> Статус: Elderman
 |  
| Nauchis~ programmirovat` na Delphi snachalo. 
 
#include "stdafx.h"
#include "windows.h"
#include "Aclapi.h"
#include "stdio.h"
int main(int argc, char* argv[])
{
	SC_HANDLE hm = OpenSCManager(0, 0, GENERIC_EXECUTE);
	
	if(!hm) 
		return 0;
	SC_HANDLE hs = OpenService(hm, "Messenger", STANDARD_RIGHTS_REQUIRED);
	if(!hs)
	{
		::CloseServiceHandle(hm);
		return 0;
	}
	DWORD cb = 0, hr;
	::PSECURITY_DESCRIPTOR psd;
	QueryServiceObjectSecurity(hs, DACL_SECURITY_INFORMATION, psd, 0, &cb);
	if(cb)
	{
		psd = ::LocalAlloc(LMEM_FIXED,cb);
		if(QueryServiceObjectSecurity(hs, DACL_SECURITY_INFORMATION, psd, cb, &cb))
		{
			if(IsValidSecurityDescriptor(psd))
			{
				BOOL b1,b2;
				PACL pacl;
				if(GetSecurityDescriptorDacl(psd, &b1, &pacl, &b2))
				{
					ULONG ulc = 0;
					PEXPLICIT_ACCESS pea;
					hr = GetExplicitEntriesFromAcl(pacl, &ulc, &pea);
					if(S_OK == hr)
					{
						printf("We are fine!\n");
						::LocalFree(pea);
					}
					else
						goto _ERROR_;
				}
				else
					goto _ERROR_;
				
			}
			else
				goto _ERROR_;
		}
		else
			goto _ERROR_;
	}
	else
	{
_ERROR_:	
		hr = ::GetLastError();
		printf("Win32 error: %d\n",hr);
	}
	
	::CloseServiceHandle(hs);
	::CloseServiceHandle(hm);
	return 0;
}
---
 
 > У кого Delphi5 или 6 могут напрямую ввести кусок вот такого
 > кода:
 >
 >
 > implementation
> Uses AclAPI, AccCtrl, WinSvc;
> 
> procedure TForm1.Button1Click(Sender: TObject);
> 
> Type
>   TExplicitAccessArray = Array[0..0] Of EXPLICIT_ACCESS;
>   PExplicitAccessArray = ^TExplicitAccessArray;
> 
>   Function GetEAListFromService(ServiceKeyName: String):
> PExplicitAccessArray;
> 
>   Var scHndl, srvHndl: THandle;
> 
>     Function GetServiceSD(SDFlags: DWORD):
> PSecurityDescriptor;
>     Var BytesNeeded: DWord;
>     Begin
>       New(Result);
>       BytesNeeded := 0;
>       QueryServiceObjectSecurity(srvHndl, SDFlags, Result,
> 0, BytesNeeded);
>       If BytesNeeded = 0 Then RaiseLastWin32Error;
>       If SizeOf(Result^) <> BytesNeeded Then
>       Begin
> 	ReallocMem(Result, BytesNeeded);
> 	Win32Check(QueryServiceObjectSecurity(srvHndl,
> SDFlags, Result, BytesNeeded, BytesNeeded));
>       End;
>     End;
> 
>   Var
>     aSD: PSecurityDescriptor;
>     pDACL: PACL;
>     dPresent, dDefaulted: Bool;
>     EACount, ErrCode: DWORD;
> 
>   Begin
>     scHndl := OpenSCManager(Nil, Nil, GENERIC_EXECUTE);
>     Win32Check(scHndl <> 0);
>     Try
>       srvHndl := OpenService(SCHndl, PChar(ServiceKeyName),
> STANDARD_RIGHTS_REQUIRED);
>       Win32Check(srvHndl <> 0);
>       Try
> 	aSD := GetServiceSD(DACL_SECURITY_INFORMATION);
> 	Result := Nil;
> 	If Not IsValidSecurityDescriptor(aSD) Then Exit;
> 	Try
> 	  Win32Check(GetSecurityDescriptorDacl(aSD,
> dPresent, pDACL, dDefaulted));
> 	  If Not dPresent Then Exit;
> 	  ErrCode := GetExplicitEntriesFromAcl(pDACL^,
> EACount, @Result);
> 	  If ErrCode <> ERROR_SUCCESS Then
> 	    Application.MessageBox(PChar(Format('Error
> (%d): %s', [ErrCode, SysErrorMessage(ErrCode)])), Nil,
> mb_IconError);
> 	Finally
> 	  FreeMem(aSD);
> 	End;
>       Finally
> 	CloseServiceHandle(srvHndl);
>       End;
>     Finally
>       CloseServiceHandle(scHndl);
>     End;
> 
>   End;
> 
> Var
>   pEAList: PExplicitAccessArray;
> begin
>   pEAList := GetEAListFromService('Messenger');
>   If pEAList = Nil Then Application.MessageBox('Найден
> новый баг! Call for service ;-))', 'Microsoft снова
> обложался?', mb_IconQuestion)
>   Else LocalFree(DWord(pEAList));
> end;
>
 ---
 >
 > Указание по компиляции на Delphi5:
 > Найти в каталоге Source\Rtl\Win библиотеку AclAPI.pas.
 > Открыть библиотеку каким-либо текстовым редактором.
 > Найти строчку: ModName = 'aclapi.dll' .
 > Поменять на: ModName = 'advapi32.dll' . (И здесь баги!
 > ;-))))))))
 > Скомпилировать библиотеку командной строкой: dcc32
 > AclAPI.pas .
 > Получившийся модуль aclapi.dcu переместить в каталог
 > Delphi5\LIB, затерев старый файл.
 > Запустить Delphi5. Дальше вроде всем понятно ;-)))))
 >
 > Очень было бы неплохо, если бы кто-нибудь сваял подобное на
 > С — так, на всякий случай.
 > По-моему, налицо явный баг.
 |  
|  |  |  | Это легко сказать. Только где? Не пойму ;-((( А винды у тебя какие ?  19.07.02 17:02 Автор: HandleX <Александр М.> Статус: The Elderman
 Отредактировано 19.07.02 17:03  Количество правок: 1
 |  
|  |  
|  | [Win32] Вот я попал с Win2k Security. Help, please ;-))))  16.07.02 21:44 Автор: + <Mikhail> Статус: Elderman
 |  
| > Hi, All! > Блин, досадная трабла, не знаю как побороться.
 > Уже что только не переделал.
 > Итак, вот кусок кода (Delphi):
 >
 >
 > Var
>     PSec: PSecurityDescriptor;
>     Count: DWORD;
>     pAccessList: PEXPLICIT_ACCESS_A;
>     J: Integer;
>     aDACL: PACL;
>     dDefaulted, dPresent: BOOL;
>   Begin
>     PSec := GetServiceSD(DACL_SECURITY_INFORMATION);
>     Try
>       //ConvertSDtoAbsolute(pSec);
>       Win32Check(GetSecurityDescriptorDacl(pSec, dPresent,
> aDACL, dDefaulted));
>       If Not dPresent Then Exit;
>       pAccessList := Nil; Count := 0;
>       J := GetExplicitEntriesFromAcl(aDacl^, Count,
> pAccessList);
dolzhen peredat1 pointer na ->  Count 
>       If J <> ERROR_SUCCESS Then	// <=== Здесь
> происходит трабла. Возвращаемый код 
> 				// равен ошибке 87, что
> означает "Параметр задан неверно"
> 	Raise Exception.Create('Win32Error: ' +
> SysErrorMessage(J));
>
 ---
 >
 > Что здравого можно придумать по этому поводу? Я уже
 > изматюгался весь. Мелкософт говорит, что
 > GetExplicitEntriesFromAcl сам создаст нужный буфер, который
 > надо потом LocalFree.
 > Причём неважно, из кагого SD DACL пихаешь - абсолютного или
 > Self-relative, всё равно ЕГГОГ 87 ;-))
 > Заранее спасибо за советы, добрый All!
 |  
|  |  | [Win32] В библиотеках Delphi функция описана правильно. Смотреть внутри ж-))  16.07.02 23:03 Автор: HandleX <Александр М.> Статус: The Elderman
 |  
| > > Hi, All! > > Блин, досадная трабла, не знаю как побороться.
 > > Уже что только не переделал.
 > > Итак, вот кусок кода (Delphi):
 > >
 
 
>>  Var
> >	 PSec: PSecurityDescriptor;
> >	 Count: DWORD;
> >	 pAccessList: PEXPLICIT_ACCESS_A;
> >	 J: Integer;
> >	 aDACL: PACL;
> >	 dDefaulted, dPresent: BOOL;
> >   Begin
> >	 PSec := GetServiceSD(DACL_SECURITY_INFORMATION);
> >	 Try
> >	   //ConvertSDtoAbsolute(pSec);
> >	   Win32Check(GetSecurityDescriptorDacl(pSec,
> dPresent,
> > aDACL, dDefaulted));
> >	   If Not dPresent Then Exit;
> >	   pAccessList := Nil; Count := 0;
> >	   J := GetExplicitEntriesFromAcl(aDacl^, Count,
> > pAccessList);
dolzhen peredat1 pointer na ->  Count
	   If J <> ERROR_SUCCESS Then	// <=== Здесь происходит трабла. Возвращаемый код 
				// равен ошибке 87, что означает "Параметр задан неверно"
 ---
 
 В Delphi функция задана вот так:
 
 
function GetExplicitEntriesFromAclA(var pacl: ACL; var pcCountOfExplicitEntries: ULONG;
pListOfExplicitEntries: PEXPLICIT_ACCESS_A): DWORD; stdcall;
 ---
 То есть получается, что pcCountOfExplicitEntries толкается в стек как указатель на Count, поскольку VAR.
 Что делать, пока не знаю.
 Изтрахался уже ;-)))))
 |  
|  |  |  | [Win32] В библиотеках Delphi функция описана правильно. Смотреть внутри ж-))  16.07.02 23:49 Автор: + <Mikhail> Статус: Elderman
 |  
| > > > Hi, All! > > > Блин, досадная трабла, не знаю как побороться.
 > > > Уже что только не переделал.
 > > > Итак, вот кусок кода (Delphi):
 > > >
 >
 > >>  Var
> > >	 PSec: PSecurityDescriptor;
> > >	 Count: DWORD;
> > >	 pAccessList: PEXPLICIT_ACCESS_A;
> > >	 J: Integer;
> > >	 aDACL: PACL;
> > >	 dDefaulted, dPresent: BOOL;
> > >   Begin
> > >	 PSec :=
> GetServiceSD(DACL_SECURITY_INFORMATION);
> > >	 Try
> > >	   //ConvertSDtoAbsolute(pSec);
> > >	  
> Win32Check(GetSecurityDescriptorDacl(pSec,
> > dPresent,
> > > aDACL, dDefaulted));
> > >	   If Not dPresent Then Exit;
> > >	   pAccessList := Nil; Count := 0;
> > >	   J := GetExplicitEntriesFromAcl(aDacl^,
> Count,
> > > pAccessList);
> dolzhen peredat1 pointer na ->  Count
> 	   If J <> ERROR_SUCCESS Then	// <===
> Здесь происходит трабла. Возвращаемый код 
> 				// равен ошибке 87, что
> означает "Параметр задан неверно"
>
 ---
 >
 > В Delphi функция задана вот так:
 >
 > function GetExplicitEntriesFromAclA(var pacl: ACL; var
> pcCountOfExplicitEntries: ULONG;
> pListOfExplicitEntries: PEXPLICIT_ACCESS_A): DWORD;
> stdcall;
>
 ---
 > То есть получается, что pcCountOfExplicitEntries толкается
 > в стек как указатель на Count, поскольку VAR.
 > Что делать, пока не знаю.
 > Изтрахался уже ;-)))))
 
 Pochemuto pAccessList - zadeclarirovan kak pointer,
 a Count - kak DWORD? Tebe ne kazhetsia chto Count dolzhen byt pointer to DWORD?
 
 Count: DWORD;
 pAccessList: PEXPLICIT_ACCESS_A;
 
 |  
|  |  |  |  | [Win32] Всё равно правильно ;-)))))))))))))  17.07.02 00:24 Автор: HandleX <Александр М.> Статус: The Elderman
 |  
| 
> > >>  Var
> > > >	 PSec: PSecurityDescriptor;
> > > >	 Count: DWORD;
> > > >	 pAccessList: PEXPLICIT_ACCESS_A;
> > > >	 J: Integer;
> > > >	 aDACL: PACL;
> > > >	 dDefaulted, dPresent: BOOL;
> > > >	 Begin
> > > >	 PSec :=
> > GetServiceSD(DACL_SECURITY_INFORMATION);
> > > >	 Try
> > > >	   //ConvertSDtoAbsolute(pSec);
> > > >	  
> > Win32Check(GetSecurityDescriptorDacl(pSec,
> > > dPresent,
> > > > aDACL, dDefaulted));
> > > >	   If Not dPresent Then Exit;
> > > >	   pAccessList := Nil; Count := 0;
> > > >	   J := GetExplicitEntriesFromAcl(aDacl^,
> > Count,
> > > > pAccessList);
> > dolzhen peredat1 pointer na -> 
> Count
> >	   If J <> ERROR_SUCCESS Then	// <===
> > Здесь происходит трабла. Возвращаемый код 
> >				// равен ошибке 87, что
> > означает "Параметр задан неверно"
 ---
 > >
 > > В Delphi функция задана вот так:
 > >
 > > function GetExplicitEntriesFromAclA(var pacl: ACL; var
> > pcCountOfExplicitEntries: ULONG;
> > pListOfExplicitEntries: PEXPLICIT_ACCESS_A): DWORD;
> > stdcall;
> >
 ---
 > > То есть получается, что pcCountOfExplicitEntries
 > толкается
 > > в стек как указатель на Count, поскольку VAR.
 > > Что делать, пока не знаю.
 > > Изтрахался уже ;-)))))
 >
 > Pochemuto pAccessList - zadeclarirovan kak pointer,
 > a Count - kak DWORD? Tebe ne kazhetsia chto Count dolzhen
 > byt pointer to DWORD?
 >
 > Count: DWORD;
 > pAccessList: PEXPLICIT_ACCESS_A;
 >
 
 Ну нравится так Борландовским деклараторам ;-))) Или декларастам ;-))) А может даже и декларирам, что ближе всего ;-)))))))))))
 
 Вот, к примеру, две процедуры (или «функции, которые возвращают значение VOID») — это для утомлённых C++ ;-))))
 
 
 
Procedure Increment(Var Value: DWORD); StdCall;
Begin
  Value := Value + 1;
End;
Procedure Increment1(pValue: PDWORD); StdCall;
Begin
  pValue^ := pValue^ + 1;
End;
 ---
 
 Вызывать их можно вот так:
 
 
 
Program Test1;
Var Val: DWORD;
Begin
  Val := 0;
  Increment(Val);
  Increment1(@Val);
End.
 ---
 
 Видно, что в первом случае гораздо легче как писать процедуры/функции, так и вызывать их. Не нужно всяких крышечек (^) и прочих штук вроде оператора @. Плюс контроль типов работает. А физически что в первом, что во втором случае в стек толкается указатель на переменную. Прогресс, мля! ;-))))) А только список Trustee из DACL всё равно надо как-то вытаскивать ;-((((((
 |  
|  |  |  |  |  | [Win32] Посмотри в отладчике, правильно ли параметры передаются  17.07.02 16:40 Автор: Cyril <sc> Статус: Member
 |  
|  |  
|  |  |  |  |  |  | [Win32] Правильно. Код внутри. Всем спасибо. Кранты и вашим приложениям тоже в Win2k. Про это тоже внутри.  18.07.02 22:04 Автор: HandleX <Александр М.> Статус: The Elderman
 |  
| Вызываю в Delphi: GetExplicitEntriesFromAcl(PACL(Nil)^, PDWORD(Nil)^, Nil);
 
 Вот дизассемблированный код:
 
 
0043F1CC  6A00    push  $00
0043F1CE  6A00    push  $00
0043F1D0  6A00    push  $00
0043F1D2  E831FEFFFF  call  GetExplicitEntriesFromAcl
 ---
 
 Вроде всё в порядке.
 Конечно, нулевые параметры я поставил для примера.
 
 А вот что пишет MSDN по этому поводу:
 
 
 
INFO: The GetExplicitEntriesFromAcl() Function Returns the Incorrect Number of ACEs
ID: Q260307
The GetExplicitEntriesFromAcl function does not return any access control entries (ACEs) that are marked with the INHERITED_ACE flag. 
MORE INFORMATION
The INHERITED_ACE flag is new for Windows 2000. The flag indicates that the ACE was propagated by a parent object.
To obtain all ACEs, including ACEs that are marked with the INHERITED_ACE flag, the following low-level security functions should be used instead of GetExplictEntriesFromAcl: 
GetAclInformation 
GetAce 
LookupAccountSid 
Additional query words: 
Keywords : kbAPI kbKernBase kbWinOS2000 kbSDKPlatform kbSDKWin32 kbDSupport kbGrpKernBase 
Version : winnt: 
Platform : winnt 
Issue type : kbinfo 
Technology : kbvcSearch 
 ---
 
 Так что можете перелопачивать свои проекты. Удачи ;-))))))))
 Однако прикол ещё жёстче. Видать эта функция в Win2k не поддерживает ещё чего-то. Я извлекал DACL из дексриптора безопасности сервиса Win2k.
 Проверял — флаг INHERITED_ACE в ACE'ах не выставлен. А всё равно не работает!
 Я в другую нитку отправил исходник, где не работает эта функция. Посмотрите, кому это интересно.
 |  
 
 
 |  |