Advertisement
Guest User

laba

a guest
Nov 11th, 2019
110
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 15.99 KB | None | 0 0
  1. // SecurityDescriptorOfProcess.cpp : Defines the entry point for the console application.
  2. //
  3.  
  4.  
  5. #include <Windows.h>
  6. #include <iostream>
  7. #include <string>
  8. #include <aclapi.h>
  9. #include <sddl.h>
  10.  
  11. #pragma comment(lib, "advapi32.lib")
  12. #define make_directories 1
  13. #define add_files 2
  14. #define write_file 3
  15. #define delete_dirs_and_file 4
  16.  
  17.  
  18.  
  19.  
  20. // converts PSID to string
  21. std::string SidToString(PSID pSid)
  22. {
  23.     char *pSidString = NULL;
  24.  
  25.     if (!ConvertSidToStringSid(pSid, &pSidString))
  26.     {
  27.         DWORD dwResult = GetLastError();
  28.  
  29.         if (dwResult == ERROR_NOT_ENOUGH_MEMORY)
  30.             std::cout << "Insufficient memory." << std::endl;
  31.         else if (dwResult == ERROR_INVALID_SID)
  32.             std::cout << "The SID is not valid." << std::endl;
  33.         else
  34.         {
  35.             // ERROR_INVALID_PARAMETER
  36.             std::cout << "One of the parameters contains a value that is not valid. " << std::endl;
  37.         }
  38.  
  39.         return   "";
  40.     }
  41.  
  42.     std::string SidString(pSidString);
  43.     LocalFree(pSidString);
  44.  
  45.     return SidString;
  46. }
  47.  
  48. void TestSecurityDescriptor()
  49. {
  50.     PSID pSidOwner = NULL;
  51.     PSID pSidGroup = NULL;
  52.  
  53.     PSECURITY_DESCRIPTOR pSD = NULL;
  54.  
  55.     if (GetSecurityInfo(GetCurrentProcess(),
  56.         SE_KERNEL_OBJECT,
  57.         OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION,
  58.         &pSidOwner,
  59.         &pSidGroup,
  60.         NULL, // for Dacl
  61.         NULL, // for Sacl
  62.         &pSD) != ERROR_SUCCESS)
  63.     {
  64.         std::cout << "Failed to retrieve Security Descriptor, error: " << GetLastError() << std::endl;
  65.         return;
  66.     }
  67.  
  68.     DWORD dwAccountName = 0;
  69.     DWORD dwDomainName = 0;
  70.     SID_NAME_USE SidUse = SidTypeUnknown;
  71.  
  72.     if (!LookupAccountSid(NULL,
  73.         pSidOwner,
  74.         NULL,
  75.         &dwAccountName,
  76.         NULL,
  77.         &dwDomainName,
  78.         &SidUse) && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
  79.     {
  80.         std::cout << "Failed to retrieve buffer size" << std::endl;
  81.         LocalFree(pSD);
  82.         return;
  83.     }
  84.  
  85.     std::string AccountName(dwAccountName - 1, '*');
  86.     std::string DomainName(dwDomainName - 1, '*');
  87.  
  88.     if (!LookupAccountSid(NULL,
  89.         pSidOwner,
  90.         &AccountName[0],
  91.         &dwAccountName,
  92.         &DomainName[0],
  93.         &dwDomainName,
  94.         &SidUse))
  95.     {
  96.         std::cout << "Failed to retrieve Account Name and Domain Name" << std::endl;
  97.         LocalFree(pSD);
  98.         return;
  99.     }
  100.  
  101.     std::cout << "pSidOwner - " << SidToString(pSidOwner) << std::endl;
  102.     std::cout << "pSidGroup - " << SidToString(pSidGroup) << std::endl;
  103.     std::cout << "Owner Name: [ " << AccountName << " ]" << std::endl;
  104.     std::cout << "Domain Name: [ " << DomainName << " ]" << std::endl;
  105.  
  106.     /*
  107.     We can use pSD, the Security Descriptor of our process
  108.  
  109.     You should not do
  110.     FreeSid(pSidOwner)
  111.     FreeSid(pSidGroup)
  112.     */
  113.  
  114.     LocalFree(pSD);
  115.     return;
  116.  
  117. }
  118.  
  119.  
  120. void DisplayError(std::string msg)
  121. {
  122.     std::cout << msg << ", Error: " << GetLastError() << std::endl;
  123. }
  124.  
  125. void DisplayError(std::wstring msg)
  126. {
  127.     std::wcout << msg << L", Error: " << GetLastError() << std::endl;
  128. }
  129.  
  130. template<typename T, size_t N>
  131. constexpr size_t ElementCount(T(&)[N])
  132. {
  133.     return N;
  134. }
  135.  
  136. void CreateSecurityDescriptorDIR()
  137. {
  138.     PSID pSidEveryone = NULL;
  139.     PSID pSidAdministrators = NULL;
  140.     PSID pSidTest = NULL;
  141.     PSID pSidDarina = NULL;
  142.     PACL pDacl = NULL;
  143.  
  144.     // typedef void* PSECURITY_DESCRIPTOR
  145.     PSECURITY_DESCRIPTOR pSDAbsolute = NULL;
  146.     // Should not do SECURIT_DESCRIPTOR* pSDAbsolute
  147.     // SECURITY_DESCRIPTOR, PISECURITY_DESCRIPTOR - https://goo.gl/yKjacY
  148.     // PSECURITY_DESCRIPTOR == typedef void* PSECURITY_DESCRIPTOR;
  149.     HKEY hSubKey = NULL;
  150.     while (1)
  151.     {
  152.         // STEP 1. Create SIDs for group "Everyone" and "Administrators"
  153.  
  154.         // STEP 1.1. Create a SID for group "Everyone"
  155.         SID_IDENTIFIER_AUTHORITY AuthorityEveryone = SECURITY_WORLD_SID_AUTHORITY;
  156.         // SID_IDENTIFIER_AUTHORITY - https://goo.gl/eVGZZi
  157.         // SID, PISID - https ://goo.gl/x1fivM
  158.         // AllocateAndInitializeSid function - https://goo.gl/rdwfRR
  159.  
  160.         if (!ConvertStringSidToSidA("Darina-SID", &pSidDarina)) printf("ConvertSID Darina Error %u\n", GetLastError());             // SID of 'Kostya Zaigraev' user
  161.         if (!ConvertStringSidToSidA("Test-SID", &pSidTest)) printf("ConvertSID Test Error %u\n", GetLastError());                   // SID of 'test' user
  162.        
  163.        
  164.         if (!AllocateAndInitializeSid(&AuthorityEveryone, 1, SECURITY_WORLD_RID,    0, 0, 0, 0, 0, 0, 0, &pSidEveryone))
  165.         {           DisplayError("Failed to allocate SID for group \"Everyone\""); break;
  166.         }
  167.  
  168.         // STEP 1.2. Create a SID for group "Administrators"
  169.         SID_IDENTIFIER_AUTHORITY AuthorityAdministrators = SECURITY_NT_AUTHORITY;
  170.  
  171.         if (!AllocateAndInitializeSid(&AuthorityAdministrators, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pSidAdministrators))
  172.         { DisplayError("Failed to allocate SID for group \"Administrators\""); break;
  173.         }
  174.  
  175.         // STEP 2. Create ACEs - Access Control Entry
  176.         // EXPLICIT_ACCESS - https://goo.gl/ZsEdYZ
  177.         EXPLICIT_ACCESS ea[] = { {}, {}, {}, {} };
  178.  
  179.         // element count of ea
  180.         ULONG ea_count = (ULONG)ElementCount(ea);
  181.  
  182.         // STEP 2.1. Create ACE for group "Everyone"
  183.         // ACCESS_MODE - https://goo.gl/Twn25z
  184.         // Indicates an ACCESS_ALLOWED_ACE structure that allows the specified rights.
  185.         ea[0].grfAccessMode = SET_ACCESS;
  186.         // Registry Key Security and Access Rights - https://goo.gl/zyCPJo
  187.         // give permission to read registry key
  188.         ea[0].grfAccessPermissions = GENERIC_EXECUTE;   //
  189.                                                         //2.4 - zminiti
  190.                                                         //3.4.1 Видаляти директорії  і виконувати всі дії, право на які дають дозволи Запис
  191.  
  192.         // do not allow inheritance for our ACE
  193.         ea[0].grfInheritance = NO_INHERITANCE;
  194.         // TRUSTEE - https://goo.gl/UKyACc
  195.         // TRUSTEE_FORM - https://goo.gl/xathsC
  196.         ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
  197.         // TRUSTEE_TYPE - https://goo.gl/xaScCH
  198.         ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
  199.         ea[0].Trustee.ptstrName = (LPCH)pSidEveryone;
  200.  
  201.         // STEP 2.2. Create ACE for group "Administrators"
  202.         ea[1].grfAccessMode = SET_ACCESS;
  203.         // Registry Key Security and Access Rights - https://goo.gl/zyCPJo
  204.         // give all access permissions to the registry key
  205.         ea[1].grfAccessPermissions = GENERIC_ALL;   //4.4.21 всі користувачі мають можливість Видаляти директорії  і виконувати всі дії,
  206.         ea[1].grfInheritance = NO_INHERITANCE;
  207.         ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
  208.         ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
  209.         ea[1].Trustee.ptstrName = (LPCH)pSidAdministrators;
  210.  
  211.  
  212.         //test-user
  213.         ea[2].grfAccessPermissions = GENERIC_EXECUTE; // 6.4.21 один користувач має можливість  виконувати всі дії, право на які дають дозволи Запис
  214.         ea[2].grfAccessMode = SET_ACCESS;
  215.         ea[2].grfInheritance = NO_INHERITANCE;
  216.         ea[2].Trustee.TrusteeForm = TRUSTEE_IS_SID;
  217.         ea[2].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
  218.         ea[2].Trustee.ptstrName = (LPTSTR)pSidTest;
  219.  
  220.  
  221.         //Darina user
  222.         ea[3].grfAccessPermissions = DELETE; //6.4.21 всі користувачі мають можливість Видаляти директорії
  223.         ea[3].grfAccessMode = SET_ACCESS;
  224.         ea[3].grfInheritance = NO_INHERITANCE;
  225.         ea[3].Trustee.TrusteeForm = TRUSTEE_IS_SID;
  226.         ea[3].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
  227.         ea[3].Trustee.ptstrName = (LPTSTR)pSidDarina;
  228.  
  229.  
  230.         // STEP 3. Create a DACL,
  231.         // DACL stands for Discretionary Access Control List
  232.         // SetEntriesInAcl function - https://goo.gl/5rA7W1
  233.         // A pointer to a variable that receives a pointer to the new ACL.
  234.         // If the function succeeds,
  235.         // you must call the LocalFree function to free the returned buffer.
  236.         if (SetEntriesInAcl(ea_count, ea, NULL, &pDacl) != ERROR_SUCCESS)
  237.         {
  238.             DisplayError("Failed to create a DACL with ACEs");
  239.             break;
  240.         }
  241.  
  242.         // STEP 4. Allocate and Initialize a Security Descriptor
  243.  
  244.         // STEP 4.1. Allocate memory for a Security Descriptor
  245.         // GlobalAlloc function - https://goo.gl/gT29aM
  246.         pSDAbsolute = (PSECURITY_DESCRIPTOR)GlobalAlloc(GMEM_FIXED, SECURITY_DESCRIPTOR_MIN_LENGTH);
  247.  
  248.         if (!pSDAbsolute)
  249.         {
  250.             DisplayError("Failed to allocate memory for a Security Descriptor");
  251.             break;
  252.         }
  253.  
  254.         // STEP 4.2. Initialize the Security Descriptor
  255.         // InitializeSecurityDescriptor function - https://goo.gl/TV69HX
  256.         if (!InitializeSecurityDescriptor(pSDAbsolute, SECURITY_DESCRIPTOR_REVISION))
  257.         {
  258.             DisplayError("Failed to initialize the Security Descriptor");
  259.             break;
  260.         }
  261.  
  262.         // STEP 5. Add DACL to the security descriptor
  263.         // SetSecurityDescriptorDacl - https://goo.gl/MfbbYp
  264.         if (!SetSecurityDescriptorDacl(pSDAbsolute, TRUE, pDacl, FALSE))
  265.         {
  266.             DisplayError("Failed to add DACL to the Security Descriptor");
  267.             break;
  268.         }
  269.  
  270.         // STEP 6. Create a Security Attribute
  271.         // SECURITY_ATTRIBUTES - https://goo.gl/BZ2sB3
  272.         SECURITY_ATTRIBUTES sa{ sizeof(SECURITY_ATTRIBUTES), pSDAbsolute, FALSE };
  273.         CreateDirectory("C:\\1", &sa);
  274.  
  275.         CreateDirectory("C:\\1\\kek", &sa);
  276.         // STEP 7. Use the security descriptor we created so far
  277.         // RegCreateKeyEx - https://goo.gl/dGxxrY
  278.         // Registry Key Security and Access Rights - https ://goo.gl/zyCPJo
  279.  
  280.         DWORD dwDisposition;
  281.         //if (RegCreateKeyEx(HKEY_CURRENT_USER, "MyFirstRegKey", 0, (LPSTR)"", 0,
  282.         //  KEY_READ | KEY_WRITE, &sa, &hSubKey, &dwDisposition) != ERROR_SUCCESS)
  283.         //{
  284.         //  DisplayError("Failed to create registry subkey");
  285.         //  break;
  286.         //}
  287.         //else
  288.         {
  289.             std::cout << "Successfully created registry subkey" << std::endl;
  290.             std::cout << "Thank you for watching!" << std::endl;
  291.             break;
  292.         }
  293.     }
  294.  
  295.     // STEP 8. Release the allocated resources
  296.  
  297.     if (pSidEveryone)
  298.         FreeSid(pSidEveryone);
  299.  
  300.     if (pSidAdministrators)
  301.         FreeSid(pSidAdministrators);
  302.  
  303.     if (pDacl)
  304.         LocalFree(pDacl);
  305.  
  306.     if (pSDAbsolute)
  307.         GlobalFree(pSDAbsolute);
  308.  
  309.     if (hSubKey)
  310.         RegCloseKey(hSubKey);
  311. }
  312.  
  313. int CreateSecurityDescriptorFile_341()
  314. {
  315.     PSID pSidEveryone = NULL;
  316.     PSID pSidAdministrators = NULL;
  317.     PSID pSidTest = NULL;
  318.     PSID pSidDarina = NULL;
  319.     PACL pDacl = NULL;
  320.  
  321.     // typedef void* PSECURITY_DESCRIPTOR
  322.     PSECURITY_DESCRIPTOR pSDAbsolute = NULL;
  323.     // Should not do SECURIT_DESCRIPTOR* pSDAbsolute
  324.     // SECURITY_DESCRIPTOR, PISECURITY_DESCRIPTOR - https://goo.gl/yKjacY
  325.     // PSECURITY_DESCRIPTOR == typedef void* PSECURITY_DESCRIPTOR;
  326.  
  327.     HKEY hSubKey = NULL;
  328.  
  329.     while (1)
  330.     {
  331.         // STEP 1. Create SIDs for group "Everyone" and "Administrators"
  332.         if (!ConvertStringSidToSidA("Darina-SID", &pSidDarina)) printf("ConvertSID Darina Error %u\n", GetLastError());             // SID of 'Kostya Zaigraev' user
  333.         if (!ConvertStringSidToSidA("Test-SID", &pSidTest)) printf("ConvertSID Test Error %u\n", GetLastError());                   // SID of 'test' user
  334.  
  335.         // STEP 1.1. Create a SID for group "Everyone"
  336.         SID_IDENTIFIER_AUTHORITY AuthorityEveryone =
  337.             SECURITY_WORLD_SID_AUTHORITY;
  338.  
  339.         // SID_IDENTIFIER_AUTHORITY - https://goo.gl/eVGZZi
  340.         // SID, PISID - https ://goo.gl/x1fivM
  341.         // AllocateAndInitializeSid function - https://goo.gl/rdwfRR
  342.         if (!AllocateAndInitializeSid(&AuthorityEveryone, 1,
  343.             SECURITY_WORLD_RID,
  344.             0, 0, 0, 0, 0, 0, 0, &pSidEveryone))
  345.         {
  346.             DisplayError("Failed to allocate SID for group \"Everyone\"");
  347.             break;
  348.         }
  349.  
  350.         // STEP 1.2. Create a SID for group "Administrators"
  351.         SID_IDENTIFIER_AUTHORITY AuthorityAdministrators
  352.             = SECURITY_NT_AUTHORITY;
  353.  
  354.         if (!AllocateAndInitializeSid(&AuthorityAdministrators, 2,
  355.             SECURITY_BUILTIN_DOMAIN_RID,
  356.             DOMAIN_ALIAS_RID_ADMINS,
  357.             0, 0, 0, 0, 0, 0, &pSidAdministrators))
  358.         {
  359.             DisplayError("Failed to allocate SID for group \"Administrators\"");
  360.             break;
  361.         }
  362.  
  363.         // STEP 2. Create ACEs - Access Control Entry
  364.         // EXPLICIT_ACCESS - https://goo.gl/ZsEdYZ
  365.         EXPLICIT_ACCESS ea[] = { {}, {}, {}, {} };
  366.  
  367.         // element count of ea
  368.         ULONG ea_count = (ULONG)ElementCount(ea);
  369.  
  370.         // STEP 2.1. Create ACE for group "Everyone"
  371.         // ACCESS_MODE - https://goo.gl/Twn25z
  372.         // Indicates an ACCESS_ALLOWED_ACE structure that allows the specified rights.
  373.         ea[0].grfAccessMode = SET_ACCESS;
  374.         // Registry Key Security and Access Rights - https://goo.gl/zyCPJo
  375.         // give permission to read registry key
  376.         ea[0].grfAccessPermissions = FILE_GENERIC_WRITE; //3.4.1 всі користувачі мають можливість Перезаписувати файл, змінювати атрибути файлів і переглядати        власників та дозволи -
  377.  
  378.         // do not allow inheritance for our ACE
  379.         ea[0].grfInheritance = NO_INHERITANCE;
  380.         // TRUSTEE - https://goo.gl/UKyACc
  381.         // TRUSTEE_FORM - https://goo.gl/xathsC
  382.         ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
  383.         // TRUSTEE_TYPE - https://goo.gl/xaScCH
  384.         ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
  385.         ea[0].Trustee.ptstrName = (LPCH)pSidEveryone;
  386.  
  387.         // STEP 2.2. Create ACE for group "Administrators"
  388.         ea[1].grfAccessMode = SET_ACCESS;
  389.         // Registry Key Security and Access Rights - https://goo.gl/zyCPJo
  390.         // give all access permissions to the registry key
  391.         ea[1].grfAccessPermissions = GENERIC_WRITE; //4.4.11 всі користувачі мають можливість Перезаписувати файл
  392.         ea[1].grfInheritance = NO_INHERITANCE;
  393.         ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID;
  394.         ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
  395.         ea[1].Trustee.ptstrName = (LPCH)pSidAdministrators;
  396.  
  397.         //test-user
  398.         ea[2].grfAccessPermissions = FILE_WRITE_ATTRIBUTES | STANDARD_RIGHTS_READ; // 6.4.11 один користувач має можливість змінювати атрибути файлів і переглядати власників
  399.  
  400.         ea[2].grfAccessMode = SET_ACCESS;
  401.         ea[2].grfInheritance = NO_INHERITANCE;
  402.         ea[2].Trustee.TrusteeForm = TRUSTEE_IS_SID;
  403.         ea[2].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
  404.         ea[2].Trustee.ptstrName = (LPTSTR)pSidTest;
  405.  
  406.  
  407.         //Darina user
  408.         ea[3].grfAccessPermissions = GENERIC_ALL;
  409.         ea[3].grfAccessMode = SET_ACCESS;
  410.         ea[3].grfInheritance = NO_INHERITANCE;
  411.         ea[3].Trustee.TrusteeForm = TRUSTEE_IS_SID;
  412.         ea[3].Trustee.TrusteeType = TRUSTEE_IS_GROUP;
  413.         ea[3].Trustee.ptstrName = (LPTSTR)pSidDarina;
  414.  
  415.  
  416.         // STEP 3. Create a DACL,
  417.         // DACL stands for Discretionary Access Control List
  418.         // SetEntriesInAcl function - https://goo.gl/5rA7W1
  419.         // A pointer to a variable that receives a pointer to the new ACL.
  420.         // If the function succeeds,
  421.         // you must call the LocalFree function to free the returned buffer.
  422.         if (SetEntriesInAcl(ea_count, ea, NULL, &pDacl)
  423.             != ERROR_SUCCESS)
  424.         {
  425.             DisplayError("Failed to create a DACL with ACEs");
  426.             break;
  427.         }
  428.  
  429.         // STEP 4. Allocate and Initialize a Security Descriptor
  430.  
  431.         // STEP 4.1. Allocate memory for a Security Descriptor
  432.         // GlobalAlloc function - https://goo.gl/gT29aM
  433.         pSDAbsolute =
  434.             (PSECURITY_DESCRIPTOR)GlobalAlloc(GMEM_FIXED, SECURITY_DESCRIPTOR_MIN_LENGTH);
  435.  
  436.         if (!pSDAbsolute)
  437.         {
  438.             DisplayError("Failed to allocate memory for a Security Descriptor");
  439.             break;
  440.         }
  441.  
  442.         // STEP 4.2. Initialize the Security Descriptor
  443.         // InitializeSecurityDescriptor function - https://goo.gl/TV69HX
  444.         if (!InitializeSecurityDescriptor(pSDAbsolute, SECURITY_DESCRIPTOR_REVISION))
  445.         {
  446.             DisplayError("Failed to initialize the Security Descriptor");
  447.             break;
  448.         }
  449.  
  450.         // STEP 5. Add DACL to the security descriptor
  451.         // SetSecurityDescriptorDacl - https://goo.gl/MfbbYp
  452.         if (!SetSecurityDescriptorDacl(pSDAbsolute, TRUE, pDacl, FALSE))
  453.         {
  454.             DisplayError("Failed to add DACL to the Security Descriptor");
  455.             break;
  456.         }
  457.  
  458.         // STEP 6. Create a Security Attribute
  459.         // SECURITY_ATTRIBUTES - https://goo.gl/BZ2sB3
  460.         SECURITY_ATTRIBUTES sa{ sizeof(SECURITY_ATTRIBUTES), pSDAbsolute, FALSE };
  461.         if (CreateFile("C:\\DisrPolitic\\test.txt", GENERIC_WRITE | GENERIC_READ, 0, &sa, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0)) return MessageBox(NULL, "File was created!", "Message", MB_OK);
  462.         else    return MessageBox(NULL, "Error in creating of the file.", NULL, MB_OK);
  463.  
  464.     }
  465.  
  466.     // STEP 8. Release the allocated resources
  467.  
  468.     if (pSidEveryone)
  469.         FreeSid(pSidEveryone);
  470.  
  471.     if (pSidAdministrators)
  472.         FreeSid(pSidAdministrators);
  473.  
  474.     if (pDacl)
  475.         LocalFree(pDacl);
  476.  
  477.     if (pSDAbsolute)
  478.         GlobalFree(pSDAbsolute);
  479.  
  480.     if (hSubKey)
  481.         RegCloseKey(hSubKey);
  482. }
  483.  
  484.  
  485.  
  486. int main()
  487. {
  488.  
  489.     //TestSecurityDescriptor();
  490.     CreateSecurityDescriptorDIR(); // punkt 2.4 up
  491.     CreateSecurityDescriptorFile_341();
  492.  
  493.     return 0;
  494. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement