Diskuze: Jak na inicializace pole const char*
V předchozím kvízu, Online test znalostí C++, jsme si ověřili nabyté zkušenosti z kurzu.


DarkCoder:14.10.2022 17:07
Inicializace ukazatele na konstantní řetězec:
const char* error = "Chyba alokace pameti.";
Inicializace pole ukazatelů na konstantní řetězce:
const char* sports[] = {
"Hokej",
"Fotbal",
"Tenis",
"Kuzelky"
};
Caster:14.10.2022 17:18
Špatně jsem to vysvětlil. Jde mi o to, abych definoval const char* VarA s tím, že půjde o jeden string zadaný "Ahoj" a dvěma MAC adresami v Hex tvaru za sebou. Tj. jako když potřebuji do proměnné VarA zadat jeden text sloučený ze tří částí:
"Ahoj"
MAC adresa 1
MAC adresa 2
Výsledný const char* VarA tedy bude ukazovat na začátek souvislého pole bytů textu "Ahoj" za nímž ihned následuje 2x 6 bytů MAC adres. Mám problém, jak to zadat.
DarkCoder:14.10.2022 17:47
Pokud máš několik relevantních dat tak použij struktury.
Např.
Deklarace struktury
typedef struct Person{
char firstname[40];
char lastname[40];
unsigned char age;
} PERSON;
a inicializace
PERSON arr[] = {
{ "Jan", "Novak", 30},
{ "Tomas", "Marny", 40}
};
Caster:14.10.2022 18:49
Nějak si nerozumíme. Jde mi hlavně o převod MAC adres v HEX tvaru do pole const char*. Stále pracuji na programu pro hledání hesel viz mé dotazy níže a tato věc je poslední, abych si ověřil, že ze známých údajů generuji PMKID správně.
K zodpovězení mého dotazu by mohla pomoci diskuze k dotazu někoho jiného ""How to turn a hex string into an unsigned char array?":https://stackoverflow.com/…d-char-array"
DarkCoder:14.10.2022 19:12
Pokaždé popisuješ jiný problém. Je třeba se vyjadřovat jasně.
Takže zde je způsob jak prezentovat Mac adresu.
Není nic jednoduššího než si vytvořit objekt opět pomocí struktur pro Mac adresu:
struct mac_addr {
unsigned char bytes[6];
}
DarkCoder:14.10.2022 19:30
Nejednodušší forma reprezentace a inicializace MAC adresy:
#define MAC_LEN 6
unsigned char macaddress[MAC_LEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
Caster:14.10.2022 19:51
Pro lepší představu jsem udělal testovací program, který převede MAC adresu v HEX tvaru na 6 bytů. Potřebuji poradit, jak program upravit aby proměnná const char* VarA = "Ahoj" obsahovala za slovem "Ahoj" 2x 6 bytů MAC_AP a MAC_STA.
#include <iostream>
#include <cstdio>
const char* VarA = "Ahoj";
const char MAC_AP[] = "354d12ba8e36";
const char MAC_STA[] = "7c5d253b7425";
unsigned char addressBytes[6];
void MACtoBYTES(const char* MAC_adr)
{
sscanf_s(MAC_adr, "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
&addressBytes[0], &addressBytes[1], &addressBytes[2], &addressBytes[3], &addressBytes[4], &addressBytes[5]);
}
int main()
{
MACtoBYTES(MAC_AP);
int i;
for (i = 0; i < 6; i++) {
(void)printf("addressBytes[%d] = %02x\n", i, addressBytes[i]);
}
}
DarkCoder:14.10.2022 20:36
Takto nemůžeš deklarovat proměnnou pokud chceš její obsah modifikovat.
const char* VarA = "Ahoj";
Překladač může řetězec "Ahoj" umístit do ROM. Na tento řetězec máš sice ukazatel, ale nemůžeš jej měnit. Nemůžeš k němu přidat jakékoliv informace.
Ty musíš vědět co všechno proměnná bude obsahovat a jak vše bude velké. Měl bys alokovat pole o velikosti řetězce + 2 * 6 bytů + 1 (nulový znak).
Dále se jedná o převod řetězce na byty nikoli HEX na byty. Poté co provedeš převod máš naplněno pole o velikosti 6 bytů. Toto pole je typu unsigned char, můžeš tedy velmi snadno připojit obsah celého pole k řetězci, který si předtím uložil do vytvořeného pole. Je třeba si uvědomit že bytové pole není ukončené nulovým znakem, tedy nemůžeš použít funkci strcat(). Musíš použít buď ruční kopírování nebo funkcím pro práci s pamětí memcpy(). To provedeš 2x jednou pro výsledek MAC_AP podruhé pro výsledek MAC_STA. Nyní máš v poli řetězec a 12 bytů z konverze. Jelikož pole má představovat řetězec, přidáš na konec nulový znak '\0'. Tím máš vytvořeno pole obsahující vše co požaduješ. To je celé.
Je třeba si uvědomit, jak velký řetězec je součástí pole a kde začíná konverze MAC. Tuto informaci v řetězci nemáš. Takže buď řetězec uložený do pole bude mít konstantní délku, nebo musíš jako první bytě před informací o délce. Struktura by byla mnohem čitelnější nežli cpát všechny informace do jednoho.
Caster:14.10.2022 23:40
Ta data potřebuji dostat za sebou jen při spuštění programu, abych je mohl předat hašovací funkci PMKID=HMAC-SHA1-128(PMK,"PMK Name" | MAC_AP | MAC_STA), nejde o řetězec ukončený nulou. Nic jiného s nimi dál dělat nebudu. Většinou programuji v x64 ASM kde by to bylo snadné, neřešil bych žádné datové typy, pointry, přetypování aj.
.data ;x64 assembler
VarA DB "PMK Name", 035h, 04dh, 012h, 0bah, 08eh, 036h, 07ch, 05dh, 025h, 03bh, 074h, 025h
DarkCoder:15.10.2022 0:44
Ta data z toho co nyní uvádíš vůbec nejdou za sebou, nejsou spojitá, ale jsou oddělená.
Hoď sem odkaz na úplný prototyp a dokumentaci k funkci do které chceš vše předat.
Dále předpokládám, že veškerá potřebná data které máš k dispozici jsou tato:
const char* VarA = "Ahoj";
const char MAC_AP[] = "354d12ba8e36";
const char MAC_STA[] = "7c5d253b7425";
Posílám aktuální program, který není plně funkční pro generování PMKID. Jedinou jistotu mám, že generuji správně PSK viz Wireshark · WPA PSK Generator.
#include <iostream>
#include <openssl/evp.h>
#include <openssl/sha.h>
#include <openssl/hmac.h>
// crypto.h used for the version
#include <openssl/crypto.h>
#include <cstdio>
#include <string>
int32_t iterations = 4096;
const char* password = "radiustest";
const char* salttext = "linksys54gh";
const char MAC_AP[] = "354d12ba8e36";
const char MAC_STA[] = "7c5d253b7425";
//Pokus o "vyřešení" mého problému sloučením 3 položek "PMK Name" | MAC_AP | MAC_STA
//do jednoho textového řetězce (MAC adresy jsme použil jiné, než jsou uvedeny výše)
const char* saltPMKID = "PMK Name\DLĆśŞµgz´‡";
unsigned char PSK[0x20];
unsigned char PMK[0x20];
unsigned char PMKID[0x10];
uint32_t outputBytes = 32;
uint32_t outputBytesPMKID = 16;
void PBKDF2_HMAC_SHA_1_PSK(const char* pass, const char* salt, int32_t iterations, uint32_t outputBytes, char* hexResult)
{
unsigned int i;
unsigned char digest[0x20];
//Calculate PSK = PBKDF2(Passphrase, SSID, 4096)
PKCS5_PBKDF2_HMAC(pass, (int)strlen(pass), (const unsigned char*)salt, (int)strlen(salt), iterations, EVP_sha1(), outputBytes, digest);
for (i = 0; i < sizeof(digest); i++)
sprintf(hexResult + (i * 2), "%02x", 255 & digest[i]);
for (i = 0; i < 32; i++)
PSK[i] = digest[i];
}
void PBKDF2_HMAC_SHA_1_PMK(const char* pass, const char* salt, int32_t iterations, uint32_t outputBytes, char* hexResult)
{
unsigned int i;
unsigned char digest[0x20];
//Calculate PMK = PBKDF2(HMAC−SHA1, PSK, SSID, 4096, 256)
PKCS5_PBKDF2_HMAC(pass, (int)strlen(pass), (const unsigned char*)salt, (int)strlen(salt), iterations, EVP_sha1(), outputBytes, digest);
for (i = 0; i < sizeof(digest); i++)
sprintf(hexResult + (i * 2), "%02x", 255 & digest[i]);
for (i = 0; i < 32; i++)
PMK[i] = digest[i];
}
void HMAC_SHA_1_128_PMKID(const char* pass, const char* salt, int32_t iterations, uint32_t outputBytes, char* hexResult)
{
unsigned int i;
unsigned char digest[0x10];
//Calculate PMKID = HMAC-SHA1-128(PMK,"PMK Name" | MAC_AP | MAC_STA)
digestH = HMAC(EVP_sha1(), (const char*)pass, 32, (const unsigned char *)saltPMKID, (size_t)20, digestH, NULL);
for (i = 0; i < 16; i++)
sprintf(hexResult + (i * 2), "%02x", 255 & digestH[i]);
for (i = 0; i < 16; i++)
PMKID[i] = digest[i];
}
int main()
{
// 2*outputBytes+1 is 2 hex bytes per binary byte,
// and one character at the end for the string-terminating \0
char hexResult[2 * 32 + 1];
memset(hexResult, 0, sizeof(hexResult));
//Calculate PSK & PMK
PBKDF2_HMAC_SHA_1_PSK(password, salttext, iterations, outputBytes, hexResult);
printf_s("PSK = %s\n", hexResult);
PBKDF2_HMAC_SHA_1_PMK((const char*)PSK, salttext, iterations, outputBytes, hexResult);
printf_s("PMK = %s\n", hexResult);
HMAC_SHA_1_128_PMKID((const char*)PMK, saltPMKID, outputBytesPMKID, hexResult);
printf_s("PMK = %s\n", hexResult);
//PSK = 9e9988bde2cba74395c0289ffda07bc41ffa889a3309237a2240c934bcdc7ddb
V diskuzi někdo uvádí, jak se počítá PMKID:
PMK is calculated by:
PKCS5_PBKDF2_HMAC((const char*)psk, psklen, (unsigned char*)essid, essidlen, 4096, EVP_sha1(), 32, pmk)
successfull if result > 0
PMKID is calculated by:
HMAC(EVP_sha1(), pmk, 32, salt, 20, pmkid, NULL);
successfull if result > 0
and the salt is calculated by:
char *pmkname = "PMK Name";
uint8_t salt[32];
memcpy(&salt, pmkname, 8);
memcpy(&salt[8], mac_ap, 6);
memcpy(&salt[14], mac_sta, 6);
viz také kód na GitHubu. Každý ale udává jiný způsob výpočtu.
Program je již funkční, ale PMKID nesouhlasí s reálně odchyceným. Je možné, že pro WPA2 nestačí spočítat PSK, PMK a PMKID ale je nutné postupovat podle tohoto příkladu. Zkusím někde najít nějaké data z příkladu, abych se na to podíval.
#include <iostream>
#include <openssl/evp.h>
#include <openssl/sha.h>
#include <openssl/hmac.h>
// crypto.h used for the version
#include <openssl/crypto.h>
#include <cstdio>
#include <string>
int32_t iterations = 4096;
const char* password = "radiustest";
const char* salttext = "linksys54gh";
const char MAC_AP[] = "354d12ba8e36";
const char MAC_STA[] = "7c5d253b7425";
//"PMK Name" | MAC_AP | MAC_STA
unsigned char salt_PMKID[20] = { 'P', 'M', 'K', ' ', 'n', 'a', 'm', 'e', 0x35, 0x4d, 0x12, 0xba, 0x8e, 0x36, 0x7c,0x5d, 0x25, 0x3b, 0x74, 0x25 };
unsigned char PSK[0x20];
unsigned char PMK[0x20];
unsigned char PMKID[0x10];
uint32_t outputBytes = 32;
void PBKDF2_HMAC_SHA_1_PSK_PMK_PMKID(const char* pass, const char* salt, int32_t iterations, uint32_t outputBytes, char* hexResult)
{
unsigned int i;
unsigned int digest_PMKID_len = 16;
unsigned int* PMKID_len = &digest_PMKID_len;
unsigned char digest[0x20];
//Calculate PSK = PBKDF2(Passphrase, SSID, 4096)
PKCS5_PBKDF2_HMAC(pass, (int)strlen(pass), (const unsigned char*)salt, (int)strlen(salt), iterations, EVP_sha1(), outputBytes, digest);
for (i = 0; i < sizeof(digest); i++)
sprintf(hexResult + (i * 2), "%02x", 255 & digest[i]);
printf_s("PSK = %s\n", hexResult);
//Calculate PMK = PBKDF2(HMAC−SHA1, PSK, SSID, 4096, 256)
PKCS5_PBKDF2_HMAC((const char*)digest, 32, (const unsigned char*)salt, (int)strlen(salt), iterations, EVP_sha1(), outputBytes, digest);
for (i = 0; i < sizeof(digest); i++)
sprintf(hexResult + (i * 2), "%02x", 255 & digest[i]);
printf_s("PMK = %s\n", hexResult);
//Calculate PMKID = HMAC-SHA1-128(PMK,"PMK Name" | MAC_AP | MAC_STA)
HMAC(EVP_sha1(), (const char*)digest, 32, (const unsigned char*)salt_PMKID, (size_t)20, digest, NULL);
for (i = 0; i < 16; i++)
sprintf(hexResult + (i * 2), "%02x", 255 & digest[i]);
printf_s("PMKID = %s\n", hexResult);
}
int main()
{
// 2*outputBytes+1 is 2 hex bytes per binary byte,
// and one character at the end for the string-terminating \0
char hexResult[2 * 32 + 1];
memset(hexResult, 0, sizeof(hexResult));
PBKDF2_HMAC_SHA_1_PSK_PMK_PMKID(password, salttext, iterations, outputBytes, hexResult);
//PSK = 9e9988bde2cba74395c0289ffda07bc41ffa889a3309237a2240c934bcdc7dd
//PMK = f2a14154b6c0e247d3c40730a40593ac3383a9fa443d65d3ea0b664c04b24d59
//PMKID = c1a8a1836d4399df674c9d3edc6692e5
}
+5 Zkušeností

Zobrazeno 13 zpráv z 13.