CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - Tworzenie i przechowywanie nazwy użytkownika w rejestrze
Strona 1 z 1

Tworzenie i przechowywanie nazwy użytkownika w rejestrze

Nowy postNapisane: środa, 17 listopada 2010, 10:21
przez PeTeKa
Witam,

piszę program do którego trzeba się uprzednio zalogować. Po uruchomieniu programu pojawia się Forma z ComboBoxem i Maskeditem do wybrania loginu i wpisania hasła. Dotychczas wszystko opierałem na plikach tekstowych, teraz chciałbym, żeby przy pierwszym uruchomieniu przy rejestracji nowego użytkownika, tworzył się klucz w rejestrze dla mojego programu, w którym przechowywane byłyby informacje dotyczące loginu i hasła konkretnego użytkownika/użytkowników. Chyba, że ktoś opracował lepszą metodę do tego typu procedury.

Zabezpieczanie danych - ZIPForge.

Nowy postNapisane: środa, 17 listopada 2010, 11:06
przez Cyfrowy Baron
Pytasz jak zapisać dane do rejestru? ► patrz serwis: Cyfrowy Baron dział: teroia -> obsługa rejestru. Czy raczej o inną metodę ukrywania danych?
Jeżeli o to drugie to dobrym rozwiązaniem jest użycie plików ZIP. Program tworzy plik ZIP, plik może mieć dowolne rozszerzenie np. *.INI. Plik ZIP jest zabezpieczony hasłem, hasło zapisane jest w kodzie programu, czyli ustalasz hasło na etapie programowania i tylko program zna hasło dostępu do archiwum ZIP , a wiec tylko program może pobrać dane z tego archiwum. Dodatkowo archiwum jest szyfrowane algorytmem caAES_256, co skutecznie zabezpiecza archiwum przed włamaniem metodą brute-force. Archiwum ZIP nie musi wypakowywać plików by pobrać z nich dane, może czytać bezpośrednio do pamięci, bez wypakowywania plików.
By sprawę sobie ułatwić, będziesz potrzebował komponentu ZIPForge, który posiada wszystko co potrzebne do obsługi archiwów ZIP.

Na tym forum, w dziale: Aplikacje do pobrania w wątku: Babilon wersja 2.0.3 - katalogowanie kolekcji filmów znajduje się program mojego autorstwa, którego baza danych w całości oparta jest na archiwach ZIP. Program posiada funkcje kontrola rodzicielska, która to funkcja zabezpieczana jest hasłem przechowywanym w archiwum ZIP. Sprawdź! Jeżeli chcesz wiedzieć czy to skuteczna metoda, to ustaw sobie w programie hasło, a potem spróbuj je wydobyć.

Więcej informacji o ZIPForge znajdziesz w tych wątkach:

viewtopic.php?f=5&t=1050&p=6956&hilit=ZIPForge#p6956
viewtopic.php?f=2&t=1005&p=6583&hilit=ZIPForge#p6583
viewtopic.php?f=5&t=1002&p=6566&hilit=ZIPForge#p6566
viewtopic.php?f=2&t=617&p=3637&hilit=ZIPForge#p3637
viewtopic.php?f=2&t=479&p=2936&hilit=zipforge#p2936
viewtopic.php?f=2&t=402&p=2492&hilit=zipforge#p2492

Jeżeli zakupisz ten komponent, gdyż jest to biblioteka komercyjna i będziesz potrzebował pomocy, to zadaj pytanie na forum.

Re: Tworzenie i przechowywanie nazwy użytkownika w rejestrze

Nowy postNapisane: środa, 17 listopada 2010, 11:29
przez PeTeKa
Powiem szczerze, że chodziło mi raczej o obsługę rejestru. Mam problem z poprawnym sformułowaniem kodu.
Podam przykład na start aplikacji wraz z systemem operacyjnym:

KOD cpp:     UKRYJ  
void __fastcall TForm1::Label6Click(TObject *Sender)
{
 String path = ExpandFileName(Application->ExeName);
 TRegistry *Rejestr = new TRegistry();
 Rejestr->RootKey = HKEY_LOCAL_MACHINE;
 Rejestr->OpenKey("Software\\Microsoft\\Windows\\CurrentVersion\\Run", false);
 Rejestr->WriteString("Project1.exe", path);
 delete Rejestr;
}


Po naciśnięciu labela wyskakuje mi komunikat: Project Project1.exe rapised exeption class ERegistry Exception with message 'Failed to set data for 'Project1.exe'

Mógłbyś podać jakiś przykład? Chodzi tylko o pogrubiony tekst (zagadnienie)

Użytkownik wybiera dodanie nowego konta, podaje hasło, potwierdza je, zaznacza że akceptuję umowę i regulamin. Uaktywnia się button utwórz, który sprawdza czy hasła się zgadzają. Tu trzeba zaimplementować kod, który pobrałby w postaci zmiennej nazwę użytkownika, i zapisał ją w rejestrze z nazwą (zmienna użytkownika) i wartości (zmienna hasło).

Re: Tworzenie i przechowywanie nazwy użytkownika w rejestrze

Nowy postNapisane: środa, 17 listopada 2010, 13:22
przez Cyfrowy Baron
Sam kod jest poprawny, błędy są związane prawdopodobnie z samym Systemem Win7 x64, który ma podwyższone zabezpieczenia. Jak będę miał dostęp do tego systemu to sprawdzę.

Tu trzeba zaimplementować kod, który pobrałby w postaci zmiennej nazwę użytkownika, i zapisał ją w rejestrze z nazwą (zmienna użytkownika) i wartości (zmienna hasło).


To akurat jest opisane w serwisie Cyfrowy Baron w dziale: teoria -> obsługa rejestru.

Pobieranie nazwy użytkownika do zmiennej:

KOD cpp:     UKRYJ  
 String user_name = Rejestr->ReadString("Nazwa_wartości", "wartość_domyślna");


wartość_domyślna jest zwracana do zmiennej tylko wtedy gdy nie można pobrać wartości z rejestru.
Z hasłem postępujesz dokładnie tak samo.

W Windows 7 należy użyć takiego kodu do zapisania danych do rejestru:

KOD cpp:     UKRYJ  
 HKEY hKey;
 if(RegCreateKeyEx(HKEY_LOCAL_MACHINE,
                 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",
                0, NULL, 0, KEY_ALL_ACCESS, NULL,
                 &hKey, NULL) == ERROR_SUCCESS)
 {
  String name = "Username"; // nazwa wartosci
  String date = Edit1->Text; // wartość pobrana z Edit1 lub innego pola edycji

  RegSetValueEx(hKey, name.t_str(), 0, REG_SZ, (PBYTE)(date.c_str()), (date.Length() * 2));
  RegCloseKey(hKey);
 }


Do odczytania danych z rejestru w Windows 7 powinieneś użyć takiego kodu:

KOD cpp:     UKRYJ  
 HKEY hKey;
 String name = "Username";
 TCHAR date[255];
 DWORD length = 255 * sizeof(TCHAR);

 if(RegOpenKeyEx( HKEY_LOCAL_MACHINE,
                 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",
                0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
 {
  RegQueryValueEx( hKey, name.t_str(), NULL, NULL, (LPBYTE)date, &length);
  RegCloseKey(hKey);
 }

 Edit1->Text = (String)date;


To wszystko powinno zadziałać na koncie z uprawnieniami administratora, w przypadku konta użytkownika potrzebne będzie ustawienie tokenów. W pliku pomocy znalazłem taka funkcję:

KOD cpp:     UKRYJ  
BOOL SetPrivilege(HANDLE hToken, LPCTSTR lpszPrivilege, BOOL bEnablePrivilege)
{
 TOKEN_PRIVILEGES tp;
 LUID luid;

 if ( !LookupPrivilegeValue( NULL, lpszPrivilege, &luid ) )
 {
    ShowMessage("LookupPrivilegeValue błąd: %u\n" + GetLastError() );
    return FALSE;
 }

 tp.PrivilegeCount = 1;
 tp.Privileges[0].Luid = luid;

 if(bEnablePrivilege)
    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
 else
    tp.Privileges[0].Attributes = 0;

 if( !AdjustTokenPrivileges( hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES),
       (PTOKEN_PRIVILEGES) NULL, (PDWORD) NULL) )
 {
     ShowMessage("AdjustTokenPrivileges błąd: %u\n" + GetLastError() );
     return FALSE;
 }

 if(GetLastError() == ERROR_NOT_ALL_ASSIGNED)
 {
      ShowMessage("Ten token nie ma specjalnych przywilejów.");
      return FALSE;
 }
 return TRUE;
}


Nie wiem jednak z jakimi parametrami ją wywołać, by uzyskać dostęp do modyfikacji wartości rejestru z poziomu użytkownika. jak będę wiedział coś więcej, to dam znać.

Re: Tworzenie i przechowywanie nazwy użytkownika w rejestrze

Nowy postNapisane: środa, 17 listopada 2010, 13:48
przez Cyfrowy Baron
Sprawa z tokenami już się trochę wyjaśniła, podaje przykładowy kod:

KOD cpp:     UKRYJ  
BOOL SetPrivilege(HANDLE hToken, LPCTSTR lpszPrivilege, BOOL bEnablePrivilege)
{
 TOKEN_PRIVILEGES tp;
 LUID luid;

 if ( !LookupPrivilegeValue( NULL, lpszPrivilege, &luid ) )
 {
    ShowMessage("LookupPrivilegeValue błąd: %u\n" + GetLastError() );
    return FALSE;
 }

 tp.PrivilegeCount = 1;
 tp.Privileges[0].Luid = luid;

 if(bEnablePrivilege)
    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
 else
    tp.Privileges[0].Attributes = 0;

 if( !AdjustTokenPrivileges( hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES),
       (PTOKEN_PRIVILEGES) NULL, (PDWORD) NULL) )
 {
     ShowMessage("AdjustTokenPrivileges błąd: %u\n" + GetLastError() );
     return FALSE;
 }

 if(GetLastError() == ERROR_NOT_ALL_ASSIGNED)
 {
      ShowMessage("Ten token nie ma specjalnych przywilejów.");
      return FALSE;
 }
 return TRUE;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
 HANDLE hToken;
 OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);

 if( SetPrivilege(hToken, SE_TAKE_OWNERSHIP_NAME, true) )
 {
  /* w tym bloku umieszczasz zarówno kod odczytujący dane z rejestru jak i zapisujący. */
  HKEY hKey;
  String name = "Menu short";
  TCHAR date[255];
  DWORD length = 255 * sizeof(TCHAR);

  if(RegOpenKeyEx( HKEY_LOCAL_MACHINE,
                   L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",
                   0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
  {
   RegQueryValueEx( hKey, name.t_str(), NULL, NULL, (LPBYTE)date, &length);
   RegCloseKey(hKey);
  }

  Edit1->Text = (String)date;
 }
}


Jeżeli jednak administrator zablokował użytkownikowi dostęp do rejestru, to niestety niczego do niego taki użytkownik nie zapisze. Nie będzie więc taki użytkownik mógł ani hasła utworzyć, ani go zmienić.

Re: Tworzenie i przechowywanie nazwy użytkownika w rejestrze

Nowy postNapisane: środa, 17 listopada 2010, 19:25
przez PeTeKa
Przeanalizowałem materiały, które mi podałeś. Jeśli chodzi o kod, który umieściłem w poprzedniej wypowiedzi jest on poprawny - to znaczy odpaliłem aplikację na systemie Windows XP, po restarcie zgłasza się wraz ze startem systemu.To prawda, że problem o którym rozmawiamy jest związany z dodatkowymi zabezpieczeniami w które wyposażony jest Windows 7. W 7ce wystarczy zaznaczyć opcję uruchamiaj jako administrator i też zadziała.

Informacja jaką znalazłem w rejestrze na temat aplikacji znajduje się w:
HKEY_CURRENT_USER->Software->Classes->Local settings->MuiCache

nazwa to: lokalizacja z której uruchomiono aplikację czyt. nasze path [wartość domyślna]
dane to: Project1 czyt. nasze "Project1" [nazwa wartości]

Mam rozumieć, że zawsze będzie się tam dodawało? Myślałem, że będziemy zapisywać informacje o uruchamianiu aplikacji do lokalizacji:
HKEY_LOCAL_MACHINE->Software->Microsoft->Windows->CurrentVersion->Run
-----------------------------------------------------------------------

Próbowałem funkcji którą mi podałeś:

KOD cpp:     UKRYJ  
//--- Przycisk zaloguj się do programu --------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{

        if (Form1->Edit2->Text == Form2->Edit3->Text)
        {
                HKEY hKey;
                if(RegCreateKeyEx(HKEY_LOCAL_MACHINE,
                                 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",
                                0, NULL, 0, KEY_ALL_ACCESS, NULL,
                                 &hKey, NULL) == ERROR_SUCCESS)
                {
                String user = Form1->Edit1->Text; // proponowana nazwa użytkownika
                String pass = Form1->Edit2->Text; // hasło proponowane przez użytkownika [zweryfikowane]
                RegSetValueEx(hKey, user.t_str(), 0, REG_SZ, (PBYTE)(pass.c_str()), (pass.Length() * 2));
                RegCloseKey(hKey);
                }
        }
}
//---------------------------------------------------------------------------


jednak przy próbie kompilacji wyskakuje mi:
[BCC32 Error] Unit1.cpp(23): E2034 Cannot convert 'const wchar_t *' to 'const char *'
Full parser context
Unit1.cpp(18): parsing: void _fastcall TForm1::Button1Click(TObject *)
[BCC32 Error] Unit1.cpp(23): E2342 Type mismatch in parameter 'lpSubKey' (wanted 'const char *', got 'const wchar_t *')
Full parser context
Unit1.cpp(18): parsing: void _fastcall TForm1::Button1Click(TObject *)



także prawdopodobnie mam błąd gdzieś tu:
if(RegCreateKeyEx(HKEY_LOCAL_MACHINE,
L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",
0, NULL, 0, KEY_ALL_ACCESS, NULL,
&hKey, NULL) == ERROR_SUCCESS)

Re: Tworzenie i przechowywanie nazwy użytkownika w rejestrze

Nowy postNapisane: środa, 17 listopada 2010, 20:11
przez Cyfrowy Baron
Informacja jaką znalazłem w rejestrze na temat aplikacji znajduje się w:
HKEY_CURRENT_USER->Software->Classes->Local settings->MuiCache


Nie wiem co to jest, w Windows XP nie ma takiego klucza. To pewnie coś w rodzaju list MRU, czyli trafia tam informacja o wszystkich uruchomionych aplikacjach. Jeżeli to coś w rodzaju listy MRU, to program może z tego klucza przy każdym uruchomieniu i zamknięciu usuwać informacje o sobie.

jednak przy próbie kompilacji wyskakuje mi:


To błędy konwersji zależą od ustawień środowiska, a problem opisałem dość szczegółowo w tym poście: http://programowanie.cal.pl/forum/viewtopic.php?f=16&t=1098&p=7401&hilit=wchar_t+b_str+#p7401

Ja domyślnie mam ustawione wchar_t - przeczytaj podany post.
Jeżeli chcesz używać środowiska C++Builder 2009 i 2010 to musisz nauczyć się konwersji w UnicodeString i wchar_t.

KOD cpp:     UKRYJ  
RegSetValueEx(hKey, user.t_str(), 0, REG_SZ, (PBYTE)(pass.c_str()), (pass.Length() * 2));


Skoro zmienne user jak i pass są typu UnicodeString (String - domyślnie UnicodeString w C++Builder 2009 i 2010) to należy użyć tego samego operatora konwersji. Masz mapowanie ustawione na char, dlatego funkcja RegCreateKeyEx, oczekuje zmiennych typu char, a nie wchar_t, więc nie należy używać operatora konwersji L (konwersja do wchar_t), czyli:

KOD cpp:     UKRYJ  
if(RegCreateKeyEx(HKEY_LOCAL_MACHINE,
                    "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",
                    0, NULL, 0, KEY_ALL_ACCESS, NULL,
                    &hKey, NULL) == ERROR_SUCCESS)


Kolejna sprawa to w kluczu "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run" umieszczane są aplikacje autostartu, nie należy w żadnym razie, umieszczać tutaj żadnych haseł i innych danych. Jeżeli chcesz uruchomić program na starcie systemu to załaduj go do tego klucza, jeżeli jednak chcesz przechowywać dane programu w rejestrze, to utwórz własny klucz i w żadnym razie tak jak to robisz teraz, gdyż tworzysz w kluczu wartość ciągu o nazwie Form1->Edit1->Text i wartości: Form1->Edit2->Text, czyli np. Edit1->Text = "User name", a Edit2->Text = "password", to w rejestrze zostanie utworzona wartość ciągu:

User name password



rejestr.png


Trzeba utworzyć dwie wartości ciągu, jedną dla nazwy użytkownika, drugą dla hasła, czyli:

Przy mapowaniu na _CHAR maps to = char
KOD cpp:     UKRYJ  
 HANDLE hToken;
 OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);

 if( SetPrivilege(hToken, SE_TAKE_OWNERSHIP_NAME, true) )
 {
  HKEY hKey;
  if(RegCreateKeyEx(HKEY_LOCAL_MACHINE,
                    "SOFTWARE\\My key name",
                    0, NULL, 0, KEY_ALL_ACCESS, NULL,
                    &hKey, NULL) == ERROR_SUCCESS)
  {
   String user = "Cyfrowy Baron";//Form1->Edit1->Text; // proponowana nazwa użytkownika
   String pass = "hasło";//Form1->Edit2->Text; // hasło proponowane przez użytkownika [zweryfikowane]

   RegSetValueEx(hKey, "Username", 0, REG_SZ, (PBYTE)(user.t_str()), (user.Length()));
   RegSetValueEx(hKey, "Password", 0, REG_SZ, (PBYTE)(pass.t_str()), (pass.Length()));
   RegCloseKey(hKey);
  }
 }


Przy mapowaniu na _CHAR maps to = wchar_t
KOD cpp:     UKRYJ  
 HANDLE hToken;
 OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);

 if( SetPrivilege(hToken, SE_TAKE_OWNERSHIP_NAME, true) )
 {
  HKEY hKey;
  if(RegCreateKeyEx(HKEY_LOCAL_MACHINE,
                    L"SOFTWARE\\My key name", /* utworzy w kluczu SOFWARE nowy klucz o nazwie My key name */
                    0, NULL, 0, KEY_ALL_ACCESS, NULL,
                    &hKey, NULL) == ERROR_SUCCESS)
  {
   String user = "Cyfrowy Baron";//Form1->Edit1->Text; // proponowana nazwa użytkownika
   String pass = "hasło";//Form1->Edit2->Text; // hasło proponowane przez użytkownika [zweryfikowane]

   RegSetValueEx(hKey, L"Username", 0, REG_SZ, (PBYTE)(user.t_str()), (user.Length() * 2));
   RegSetValueEx(hKey, L"Password", 0, REG_SZ, (PBYTE)(pass.t_str()), (pass.Length() * 2));
   RegCloseKey(hKey);
  }
 }


W rejestrze pojawi się coś takiego:

rejestr2.png


Nie twórz klucza zawierającego nazwę programu (My key name), gdyż każdy kto zajrzy do rejestru od razu znajdzie klucz po nazwie programu i bez problemu pozna nazwę użytkownika i hasło. Nie we wszystkich kluczach rejestru użytkownik może dodawać nowe klucze, niektóre są zastrzeżone tylko dla systemu.

Jeżeli będziesz przepisywał kod bez zrozumienia, to nic Tobie z tego nie wyjdzie.




W 7ce wystarczy zaznaczyć opcję uruchamiaj jako administrator i też zadziała.

Użytkownik nie zna hasła administratora, więc nie uruchomi programu w tym trybie. Kod który podałem ostatnio powinien działać w Windows 7 bez uruchamiania programu w trybie administratora, jeżeli nie użyj tokenów, tak jak podałem w ostatnim poście.

Re: Tworzenie i przechowywanie nazwy użytkownika w rejestrze

Nowy postNapisane: środa, 17 listopada 2010, 20:57
przez PeTeKa
Cyfrowy Baron napisał(a):To błędy konwersji zależą od ustawień środowiska, a problem opisałem dość szczegółowo w tym poście: viewtopic.php?f=16&t=1098&p=7401&hilit=wchar_t+b_str+#p7401

Dziękuję za informacje, zastanawiałem się dlaczego nie działają mi niektóre porady (między innymi funkcja sprawdzająca zewnętrzne IP). Przydatna informacja.
Jeśli chodzi o lokalizację klucza chciałem zrobić dwie rzeczy od razu (ładowanie przy starcie systemu i zapisywanie) zrobiłem sobie testowo nowy projekt i faktycznie pomieszałem. Kod był dla mnie w miarę czytelny, tylko nie mogłem dojść do tego dlaczego nie chcę mi się to kompilować.

Uwzględniając Twoją odpowiedź w podanym wyżej poście, wszystko zrozumiałem i dziękuję za pomoc.

Cyfrowy Baron napisał(a):Jeżeli będziesz przepisywał kod bez zrozumienia, to nic Tobie z tego nie wyjdzie.


To dopiero początek mojej drogi i wiele pracy przede mną, jednak dziękuję za mobilizację.

Re: Tworzenie i przechowywanie nazwy użytkownika w rejestrze

Nowy postNapisane: środa, 17 listopada 2010, 21:09
przez Cyfrowy Baron
Jeśli chodzi o lokalizację klucza chciałem zrobić dwie rzeczy od razu (ładowanie przy starcie systemu i zapisywanie) zrobiłem sobie testowo nowy projekt i faktycznie pomieszałem.

Jeżeli chcesz najpierw wykonywać na jednym kluczu, a potem na drugim to musisz najpierw zamknąć pierwszy klucz RegCloseKey(hKey);, a potem w podobny sposób jak za pierwszym razem otworzyć nowy klucz.