IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

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.

Aktivity
Avatar
Caster
Člen
Avatar
Caster:14.10.2022 16:09

const char* VarA = { "Ahoj", 0x354d12ba8e36, 0x7c5d253b7425 };

Zkusil jsem: const char* VarA[16] = { "Ahoj", 0x354d12ba8e36, 0x7c5d253b7425 };

Chci docílit: Přiřadit proměnné Var hodnotu

 
Odpovědět
14.10.2022 16:09
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Caster
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"
};
Nahoru Odpovědět
14.10.2022 17:07
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Caster
Člen
Avatar
Odpovídá na DarkCoder
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.

 
Nahoru Odpovědět
14.10.2022 17:18
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Caster
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}
};
Nahoru Odpovědět
14.10.2022 17:47
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Caster
Člen
Avatar
Odpovídá na DarkCoder
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"

 
Nahoru Odpovědět
14.10.2022 18:49
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Caster
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];
}
Nahoru Odpovědět
14.10.2022 19:12
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Caster
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 };
Nahoru Odpovědět
14.10.2022 19:30
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Caster
Člen
Avatar
Odpovídá na DarkCoder
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]);
    }
}
 
Nahoru Odpovědět
14.10.2022 19:51
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Caster
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.

Nahoru Odpovědět
14.10.2022 20:36
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Caster
Člen
Avatar
Odpovídá na DarkCoder
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
 
Nahoru Odpovědět
14.10.2022 23:40
Avatar
DarkCoder
Člen
Avatar
Odpovídá na Caster
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";
Nahoru Odpovědět
15.10.2022 0:44
"I ta nejlepší poučka postrádá na významu, není-li patřičně předána." - DarkCoder
Avatar
Caster
Člen
Avatar
Caster:15.10.2022 18:19

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.

 
Nahoru Odpovědět
15.10.2022 18:19
Avatar
Caster
Člen
Avatar
Caster:15.10.2022 23:39

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
}
Akceptované řešení
+5 Zkušeností
Řešení problému
 
Nahoru Odpovědět
15.10.2022 23:39
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 13 zpráv z 13.