Делаю так Код (Text): DeleteSysFileVista proc path:DWORD LOCAL hToken:DWORD LOCAL buf:TOKEN_USER LOCAL tu_size:DWORD LOCAL sdSID:SECURITY_DESCRIPTOR LOCAL WasEnabled:DWORD invoke RtlAdjustPrivilege,9,TRUE,FALSE,addr WasEnabled invoke GetCurrentProcess xchg ecx,eax invoke OpenProcessToken,ecx,TOKEN_QUERY,addr hToken .if eax!=0 invoke GetTokenInformation,hToken,TokenUser,addr buf,0,addr tu_size invoke GetLastError .if eax==ERROR_INSUFFICIENT_BUFFER invoke GetTokenInformation,hToken,TokenUser,addr buf,tu_size,addr tu_size .if eax!=0 mov sdSID.Revision,SECURITY_DESCRIPTOR_REVISION lea ebx,buf assume ebx:ptr TOKEN_USER mov eax,[ebx].User.Sid mov sdSID.Owner,eax assume ebx:nothing invoke SetFileSecurity,path,OWNER_SECURITY_INFORMATION,addr sdSID invoke SetFileSecurity,path,DACL_SECURITY_INFORMATION,addr sdSID .endif .endif .endif invoke CloseHandle,hToken invoke DeleteFile,path xor eax,eax ret DeleteSysFileVista endp GetLastError после второго GetTokenInformation опять выдаёт 122 и прога вылетает
vg после второго GetTokenInformation опять выдаёт 122 Сколько в tu_size после первого вызова GetTokenInformation? Больше sizeof TOKEN_USER, которое 8?
vg Надо так Код (Text): ... local buf : ptr TOKEN_USER local tu_size : dword ... mov tu_size,0 mov buf,NULL @@1: invoke GetTokenInformation, hToken, TokenUser, buf, tu_size, addr tu_size test eax,eax jnz short @@GetTokenInformation_ok invoke GetLastError cmp eax,ERROR_INSUFFICIENT_BUFFER jnz @@GetTokenInformation_failed cmp buf,NULL jz short @F invoke GlobalFree, buf mov buf,NULL @@: ;; параноя ;; cmp tu_size,0 ;; jz @@paranoja invoke GlobalAlloc, GPTR, tu_size test eax,eax jz @@GlobalAlloc_failed mov buf,eax jmp short @@1 @@GetTokenInformation_ok: ... @@GetTokenInformation_failed: ... @@GlobalAlloc_failed: ... cmp buf,NULL jz short @F invoke GlobalFree, buf @@: ... ret ... ps функции резервирования и освобождения памяти на свой вкус.
q_q Если я правильно понял, мой предыдущий код отличается от предложенного только local buf : ptr TOKEN_USER mov tu_size,0 mov buf,NULL invoke GetTokenInformation, hToken, TokenUser, buf, tu_size, addr tu_size ? Это если не обращать внимания на функции резервирования и освобождения памяти. Следовательно Код (Text): DeleteSysFileVista proc path:DWORD LOCAL hToken:DWORD LOCAL buf:ptr TOKEN_USER LOCAL tu_size:DWORD LOCAL sdSID:SECURITY_DESCRIPTOR LOCAL WasEnabled:DWORD mov tu_size,0 mov buf,0 invoke RtlAdjustPrivilege,9,TRUE,FALSE,addr WasEnabled invoke GetCurrentProcess xchg ecx,eax invoke OpenProcessToken,ecx,TOKEN_QUERY,addr hToken .if eax!=0 invoke GetTokenInformation,hToken,TokenUser,buf,0,addr tu_size invoke GetLastError .if eax==ERROR_INSUFFICIENT_BUFFER invoke GetTokenInformation,hToken,TokenUser,buf,tu_size,addr tu_size .if eax!=0 mov sdSID.Revision,SECURITY_DESCRIPTOR_REVISION lea ebx,buf assume ebx:ptr TOKEN_USER mov eax,[ebx].User.Sid mov sdSID.Owner,eax assume ebx:nothing invoke SetFileSecurity,path,OWNER_SECURITY_INFORMATION,addr sdSID invoke SetFileSecurity,path,DACL_SECURITY_INFORMATION,addr sdSID .endif .endif .endif invoke CloseHandle,hToken invoke DeleteFile,path xor eax,eax ret DeleteSysFileVista endp 36
vg мой предыдущий код отличается от предложенного только ... Следовательно ... ты не понимаешь третий и четвертый параметры GetTokenInformation, почитай ее описание. Можно вызывать ее один раз, как в #2, только надо сразу передать адрес буфера, в котором достаточно места. Можно вызывать ее два раза, как в #23, первый раз для определения размера буфера, второй раз для получения информации, а между ними необходимо зарезервировать память под буфер. Что касается твоих вариантов: 1) #3 и #8 - два вызова, после первого стоит проверка на ошибку, которая не позволяет произойти второму вызову; 2) #16 - один вызов, в котором ошибка в четвертом параметре; 3) #19 - один вызов, в третьем параметре адрес буфера недостаточного объема, а в четвертом, его размер, который не соответствует действительности; 4) #21 - два вызова, между ними ты ничего не сделал, чтобы убедиться, что во втором вызове ты передашь адрес буфера, который объемом устроит GetTokenInformation; 4) #24 - два вызова, но между ними ты не зарезервировал память под буфер. Итого. Самый близкий вариант #3(#8), только надо перенести .if eax!=0, с места перед вторым вызовом GetTokenInformation на место после него. q_q > Сколько в tu_size после первого вызова GetTokenInformation? vg > 36 Это больше чем sizeof(TOKEN_USER), который зарезервирован под buf в #16, #19 и #21.
Не понимаю. Может все-таки #24 ближе, т. к. здесь не хватает только резервирования памяти под буфер, а в #3(#8) к тому же не хватает проверки на GetLastError() == ERROR_INSUFFICIENT_BUFFER? В #23 вместо invoke GlobalAlloc, GPTR, tu_size не должно быть invoke GlobalAlloc, GPTR, buf ?
vg Может все-таки #24 ближе, т. к. здесь не хватает только резервирования памяти под буфер Не только. В нем надо менять строки lea ebx,buf | assume ebx:ptr TOKEN_USER | mov eax,[ebx].User.Sid, т.к. они рассчитаны на то, что buf - это буфер, а определена она как адрес буфера. в #3(#8) ... не хватает проверки на GetLastError() == ERROR_INSUFFICIENT_BUFFER По-хорошему да. + нужна проверка на успешность второго вызова GetTokenInformation. В #23 вместо ... не должно быть ... Нет. У GlobalAlloc первый параметр флаги, второй - размер буфера, а возвращает она адрес. В #23 переменная buf служит для хранения адреса буфера.
Мне уже кажется (или не кажется), что я ничего не понимаю. А в #3(#8) не надо менять? Т. е. LOCAL buf[1024]:BYTE . . lea ebx,buf assume ebx:ptr TOKEN_USER mov eax,[ebx].User.Sid правильно?
vg А в #3(#8) не надо менять? ... правильно? Да. Правильно. Мне уже кажется (или не кажется), что я ничего не понимаю. В #25 второй и третий абзацы не понятны?
Думаю, что да. Исходя из вышеизложенного предпологаю, что должно быть так Код (Text): DeleteSysFileVista proc path:DWORD LOCAL hToken:DWORD LOCAL buf[1024]:DWORD LOCAL tu_size:DWORD LOCAL sdSID:SECURITY_DESCRIPTOR LOCAL WasEnabled:DWORD mov tu_size,0 mov buf,0 invoke RtlAdjustPrivilege,9,TRUE,FALSE,addr WasEnabled invoke GetCurrentProcess xchg ecx,eax invoke OpenProcessToken,ecx,TOKEN_QUERY,addr hToken .if eax!=0 invoke GetTokenInformation,hToken,TokenUser,0,tu_size,addr tu_size invoke GetLastError .if eax==ERROR_INSUFFICIENT_BUFFER invoke GlobalAlloc,GPTR,tu_size mov buf,eax invoke GetTokenInformation,hToken,TokenUser,buf,tu_size,addr tu_size .if eax!=0 mov sdSID.Revision,SECURITY_DESCRIPTOR_REVISION mov ebx,buf assume ebx:ptr TOKEN_USER mov eax,[ebx].User.Sid mov sdSID.Owner,eax assume ebx:nothing invoke SetFileSecurity,path,OWNER_SECURITY_INFORMATION,addr sdSID invoke SetFileSecurity,path,DACL_SECURITY_INFORMATION,addr sdSID .endif invoke GlobalFree,buf .endif .endif invoke CloseHandle,hToken invoke DeleteFile,path xor eax,eax ret DeleteSysFileVista endp Оба вызова GetTokenInformation завершаются успешно. Но файл не удаляется. ?
vg должно быть так Не совсем. Вместо LOCAL buf[1024]WORD надо писать LOCAL bufWORD. файл не удаляется Успешно ли выполняются RtlAdjustPrivilege, SetFileSecurity и DeleteFile?
RtlAdjustPrivilege возвращает STATUS_SUCCESS первый SetFileSecurity - 0 и GetLastError после неё - 998 MSDN: ERROR_NOACCESS 998 0x3E6 Invalid access to memory location.
vg Попробуй собрать такой код Код (Text): .386 .model flat, stdcall .nolist include windows.inc include kernel32.inc include user32.inc include advapi32.inc includelib kernel32.lib includelib user32.lib includelib advapi32.lib .list .const even path db "C:\System Volume Information",0 even szFormat db "sizeof(SECURITY_DESCRIPTOR) = %d", 0Dh, 0Ah db "OWNER_SECURITY_INFORMATION = %d", 0Dh, 0Ah db "DACL_SECURITY_INFORMATION = %d", 0Dh, 0Ah, 0 .code ;;------------------------------------------------------------------- even SimplePrintf proc C, pszFormat : ptr BYTE, param : VARARG local buffer[1024] : BYTE local hOutPut : DWORD local bWritten : DWORD lea ecx,param invoke wvsprintf, addr buffer, pszFormat, ecx invoke GetStdHandle,STD_OUTPUT_HANDLE mov hOutPut,eax invoke lstrlen,addr buffer mov ecx,eax invoke WriteFile, hOutPut, addr buffer, ecx, addr bWritten, NULL mov eax, bWritten ret SimplePrintf endp ;;------------------------------------------------------------------- even foo proc pszFilespec : ptr BYTE local buf[512] : BYTE local cb1 : DWORD local cb2 : DWORD mov cb1,0 mov cb2,0 invoke GetFileSecurity, pszFilespec, OWNER_SECURITY_INFORMATION,\ addr buf, sizeof buf, addr cb1 invoke GetFileSecurity, pszFilespec, DACL_SECURITY_INFORMATION,\ addr buf, sizeof buf, addr cb2 invoke SimplePrintf, offset szFormat, sizeof(SECURITY_DESCRIPTOR),\ cb1, cb2 ret foo endp ;;------------------------------------------------------------------- even start proc invoke foo, offset path invoke ExitProcess, 0 start endp end start консольное приложение, в переменную path впиши полное имя своего файла. То, что оно выдаст на экран запости на форум.
Не ассемблируется. Выдаёт кучу ошибок ...\windows.inc(129) : error A2004: symbol type conflict : bool ...\windows.inc(7804) : error A2179: structure improperly initialized ...\windows.inc(7804) : error A2008: syntax error : in structure ...\windows.inc(8711) : error A2179: structure improperly initialized . . . ..\windows.inc(9096) : fatal error A1012: error count exceeds 100; stopping assembly
vg Добавь строчку Код (Text): ... .model flat, stdcall option casemap :none ;; ++ .nolist ... у меня в командной строке компилятору /Cp, поэтому в коде не пишу.
извиняюсь забыл sizeof(SECURITY_DESCRIPTOR) = 20 OWNER_SECURITY_INFORMATION = 52 DACL_SECURITY_INFORMATION = 136
Попробуй так Код (Text): ... ;; mov sdSID.Revision,SECURITY_DESCRIPTOR_REVISION ;; mov ebx,buf ;; assume ebx:ptr TOKEN_USER ;; mov eax,[ebx].User.Sid ;; mov sdSID.Owner,eax ;; assume ebx:nothing ;; invoke SetFileSecurity,path,OWNER_SECURITY_INFORMATION,addr sdSID ;; invoke SetFileSecurity,path,DACL_SECURITY_INFORMATION,addr sdSID mov ebx,buf invoke InitializeSecurityDescriptor, addr sdSID, SECURITY_DESCRIPTOR_REVISION .if eax == 0 invoke GetLastError ;; (1) .else invoke SetSecurityDescriptorOwner, addr sdSID, (TOKEN_USER ptr [ebx]).User.Sid, FALSE .if eax == 0 invoke GetLastError ;; (2) .else invoke SetFileSecurity,path,OWNER_SECURITY_INFORMATION,addr sdSID .if eax == 0 invoke GetLastError ;; (3) .else invoke SetFileSecurity,path,DACL_SECURITY_INFORMATION,addr sdSID .if eax == 0 invoke GetLastError ;; (4) .else ;; ok .endif .endif .endif .endif ... если ошибки, то результат GetLastError сюда. ps Почему EBX не сохраняешь?