IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Lecture de données temps réel


Sujet :

C++

  1. #1
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2016
    Messages
    103
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Bâtiment

    Informations forums :
    Inscription : Juin 2016
    Messages : 103
    Par défaut Lecture de données temps réel
    Bonjour à tous,

    je dois collecter des données à la volée afin d'optimiser le temps de calcul de mon application.

    Cependant, je ne vois pas par où commencer, chercher.

    Merci d'avance pour votre aide.

    KM.

  2. #2
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 446
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 446
    Par défaut
    Vous n'êtes vraiment pas précis.

    Donc réponse vague :
    1ère approche, reprendre depuis l'analyse du problème, parce que l'architecture d'une solution aurait dû prendre en compte la nature des données en entré et être en mesure de s'adapter aux contraintes de performance attendues (Monde des Bisounourses).
    2ème approches, utiliser des profilers et autres outils d'analyses de performances pour savoir où on peut un peu "gratter" du temps (sauf grosse boulette de conception ou changement dans le cahier des charge en cours de route, on va pas récupérer de milles et des cents).

  3. #3
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 146
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 146
    Billets dans le blog
    4
    Par défaut
    Faut sûrement appeler CollecterÀLaVolée(); quelquepart
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  4. #4
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2016
    Messages
    103
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Bâtiment

    Informations forums :
    Inscription : Juin 2016
    Messages : 103
    Par défaut
    Re bonjour et merci pour vos messages.

    Je dois lire un QRCode type JSON et récolter les données "à la volée" pour gagner en temps de calcul.

    Le tout en C++.

    J'ai vu qu'il existait des libs ; mais c'est pas très claire. Ou me tourner vers le multithreading.

    Car en //, je dois "parser" le JSON. Ca, c'est la partie facile.

    Merci à tous

  5. #5
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 446
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 446
    Par défaut
    Toujours aussi peu clair.

    Commencez par analyser la situation :
    - erreur de conception avec le mode d'utilisation "problématique"
    - détection des goulots d'étranglement
    - etc...


    >J'ai vu qu'il existait des libs ; mais c'est pas très claire. Ou me tourner vers le multithreading.
    Vous avez essayez le sang de poulet une nuit de pleine Lune ?

  6. #6
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Bonjour,

    Définissez précisément ce que veut dire "à la volée", "données", "collecte".
    Je me fiche des réponses, c'est la méthode que je décris.

    Que signifie "à la volée" par rapport à vos calculs?
    Quel est le rapport de taille entre les données calculées, traitées, et collectées?
    Quel est la quantité de données à traiter simultanément?

    La réponse n'est pas dans le langage, mais dans l'architecture, c'est à dire, dans l'analyse AVANT le code.

    Et le très très bon conseil est: on n'optimise que ce qu'un profileur nous dit.

    Un QR code contient le json, donc, à un moment, vous avez auto json_content = parse(qr_code);. Et vous ne pouvez rien faire avec votre QR code tant qu'il n'est pas completement parsé.

    On n'a pas du tout assez de contexte pour aider. Par exemple, le rapport entre les données à collecter, le calcul, et le json contenu dans le QR code.

  7. #7
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2016
    Messages
    103
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Bâtiment

    Informations forums :
    Inscription : Juin 2016
    Messages : 103
    Par défaut la suite...WIN 32 API
    Bonjour à tous et merci pour vos retours.

    Je tiens déjà à m'excuser si je n'ai pas été très clair dès le début.

    Je pars d'un code existant qui permet l'extraction d'une chaîne de caractères à la suite de frappes de touches virtuelles.

    La suite des touches reprennent le format d'un JSON stockée dans un 'simple' string.

    Je dois en extraire une valeur particulière. L'algo qui permet de faire ce travail, je l'ai déjà écrit. C'était la partie simple.

    Là où ça se corse, c'est, lorsque je lance la simulation, je dois simuler la saisie des minuscules et majuscules (j'ai trouvé sur stackoverflow une fonction qui fait le boulot : https://stackoverflow.com/questions/...rd-letters-c-c).

    Sinon, je ne crois pas que j'aurais réussi. Je n'avais jamais travaillé auparavant sur l'API de Windows ; et sur ce projet je suis seul en C++ (et j'ai la pression pour fournir des résultats )

    J'ai des difficultés à faire le lien entre les différentes structures (INPUT, SendInput, & KBDLLHOOKSTRUCT).

    Le fait est lorsque j'essaie de combiner la fonctionnalité d'extraction avec mon algo et la fonctionnalité de saisie de caractères, j'obtiens des aberrations :

    Par exemple, si je tape : "1000":"FR","4AA0":"errt"} => j'obtiens : "!)))":"FR"<"$AA)":"ERRT"@ : alors que je ne devrais obtenir uniquement "ERRT".

    Merci d'avance à tous d'avoir pris le temps de me lire ; et de m'apporter d'éventuelles solution.

    KM.

  8. #8
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2016
    Messages
    103
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Bâtiment

    Informations forums :
    Inscription : Juin 2016
    Messages : 103
    Par défaut finalement...
    j'ai pris trop de retard; on m'a v....

  9. #9
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 446
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 446
    Par défaut
    j'ai pris trop de retard; on m'a v....
    Si vous êtes aussi brouillon pour rapporter l'état du projet que vous l'êtes pour exprimer votre "problème" ici, ça m'étonne qu'à moitié.

    Et on est dans l'informatique, la peur du licenciement, comment dire ...


    Donc vous vous calmez, vous mettez les yeux en faces de trous.
    Vous mettez un peu d'ordre dans vos idées, cela permet souvent de trouver les raisons des problèmes.
    PUIS vous nous demandez ce que vous ne comprenez pas dans les comportements constatés (mais en nous expliquant avant la logique de la démarche, les résultats attendus et les résultats obtenus).

    Si je comprends, vous galérez à simuler des entrées claviers, mais qu'est-ce que vous en avez à foutre, bordel !?
    C'est pas votre problème les problématiques de performance de la simulation des touches.

    Des "harness" avec entré clavier, il y en a des dizaines, ça sert à rien de réinventer la roue.

    J'ai des difficultés à faire le lien entre les différentes structures (INPUT, SendInput, & KBDLLHOOKSTRUCT).
    Vous n'avez qu'à demander dans ce même forum.

    Par exemple, si je tape : "1000":"FR","4AA0":"errt"} => j'obtiens : "!)))":"FR"<"$AA)":"ERRT"@ : alors que je ne devrais obtenir uniquement "ERRT".
    Il semble que vous n'avez toujours pas compris la différence entre un caractère une touche du clavier.

    Merci d'avance à tous d'avoir pris le temps de me lire ; et de m'apporter d'éventuelles solution.
    Commencez par poser le problème SVP.

  10. #10
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2016
    Messages
    103
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Bâtiment

    Informations forums :
    Inscription : Juin 2016
    Messages : 103
    Par défaut split a 'virtual' string
    Merci pour le retour musclé !

    Je vais essayer d'être le plus clair possible (je suis parti d'un POC d'origine)

    Je dispose de 3 fonctions :

    - Une fonction qui gère l'émulation
    - Une fonction qui gère l'extraction
    - Une fonction CALLBACK pour la gestion du clavier.

    Lorsque je rentre en mode 'capture', je saisie les clés virtuelles. Ensuite, nous sortons du mode 'capture'.
    A la suite de ça, la fonction d'émulation renvoie la chaîne de caractère frappée (qui s'affiche automatique sur Nodepad++ par exemple).
    ET la fonction d'extraction qui doit extraire un champs particulier de ladite chaîne frappée.

    Or, mon but est non pas de renvoyer automatiquement sur le flux toute ma chaîne de caractères ; mais, comme vous l'avez compris uniquement la chaîne de caractères particulière.
    Mais de combiner les deux fonctions : d'envoi/de simulation & d'extraction. Et c'est là que ça bloque.

    C'est comme si je devais 'spliter' en amont ma chaîne de caractères virtuelle avant de l'afficher dans le bloc note.

    Je ne sais si j'ai été plus clair. J'ai fait vraiment au mieux je crois.

    Je vous mets ici le code en partie pour ne pas trop alourdir mon post :

    1 - La fonction d'émulation :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
     
     
    void sendEmulation(string text)
    {
        UINT ret;
        INPUT inputs[1];
     
        printf("Emulating output...");
        for (char c : text) {
     
     
            inputs[0].type = INPUT_KEYBOARD;
            inputs[0].ki.wScan = 0;
            inputs[0].ki.dwFlags = 0; 
            inputs[0].ki.time = 0;
            inputs[0].ki.dwExtraInfo = 0;
     
            // Get the virtual key corresponding to the character
            SHORT vk = VkKeyScanEx(c, currentKBL);
     
            // If we are sending digits in a french keyboard configuration, shift needs to be pressed
            bool is_shift_key = false;
     
            // Send the emulated char
            inputs[0].ki.wVk = vk;
            ret = SendInput(ARRAYSIZE(inputs), inputs, sizeof(INPUT));
     
            // Inter chars delay
            Sleep(intCharDelay);
     
        }
     
        Code = ""; 
    }
    2- La fonction d'extraction (algo basique) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
     
     
    string extractTkId(string payload) 
    {
        string ID;
     
     
    	std::regex re("[; ,]");
    	std::vector<std::string> v;
     
    	  std::copy(std::sregex_token_iterator(payload.begin(), payload.end(), re, -1),
                std::sregex_token_iterator(),
                std::back_inserter(v));
     
     //...//
     
      return ID;
    }
    3 - Et enfin, la callback :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
     
     
    LRESULT CALLBACK keyboardHook(int nCode, WPARAM wParam, LPARAM lParam)
    {
       //....//
     
      //On sort du mode 'capture'//
     
        else if (wParam == WM_KEYUP && p->vkCode == codeSuffix ) { // && shiftOn -> TODO le shift est on au key down mais pas au key up car relase avant, optimiser si au key down on se retrouve avec un ] en fin de tktId
                printf("Suffix detected, exit capturing mode and emulating output ID \n");
     
     
     
     
                captureMode = false; // deactivation of capture mode as the suffix has been found
                shiftOn = false;
     
                sendEmulation(qrCode);
     
                extractTkId(qrCode);
     
     
               return 1; // do not send the suffix char
     
         }
    Cependant, comme évoqué lors de mon post précédent, si je tape ma chaîne de caractères 'virtuellement' (en qwerty), par exemple :
    "tutu":"toto","titi":"tata","gege":"bibi" ; et que je veuiile récupérer "bibi", le code me renvoie et m'affiche toute la chaîne précédemment frappée (via SendInput() si j'ai bien compris).
    Et non pas uniquement "bibi".

    Merci à tous de votre temps et patience.

    KM

  11. #11
    Membre Expert

    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2013
    Messages
    1 582
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2013
    Messages : 1 582
    Par défaut
    Bonjour,

    Les codes partiels ne facilitent pas l'aide. Si au moins, il y avait un code complet pour chaque fonction extraite...

    Dans sendEmulation :
    • A quoi sert un tableau de 1 élément ? A part servir à la gymnastique des doigts à saisir [0] ?
    • ret n'est pas utilisé 'apparemment'.
    • La chaîne est transmise sans fin ? (0, nl, rc, nl/rc). Si oui, les envois vont se cumuler en une seule chaine apparente.


    Le Hook laisse passer les caractères qu'il voit ou en bloque certains ?
    La sortie du mode capture suppose le retrait du hook ou simplement sa passivation (ce qui semble le cas pour éviter la réentrance via sendEmulation) ?
    La capture n'est pas dépendante de l'application active ? C'est un key logger système ? Attention au respect de la loi.

    Salutations

  12. #12
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 446
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 446
    Par défaut
    @Kevin_Mylano, faudrait vraiment que vous compreniez un peu ce que vous faites, parce que là, c'est nimp.

    Commencez par comprendre comment fonctionne le hooking, puis comment sont générés les charactères dans l'application après réception d'un message d'envoi de touches à l'application.

    Il y a un monde entre une touche et un caractère et vous semblez complètement l'ignorer.

    Déjà, vous faites de très nombreuses approximations/erreurs de nommages, sans un peu de rigueur, vous allez tourner en rond :

    Lorsque je rentre en mode 'capture', je saisie les clés virtuelles.
    VIRTUAL KEY = c'est le key de keyboard, une TOUCHE, pas la key d'une key lock, on n'est pas dans un donjon d'AD&D.
    sendEmulation
    On émule quoi en faite ? Non en fait que des SendInput.
    etc...

    Cependant, comme évoqué lors de mon post précédent, si je tape ma chaîne de caractères 'virtuellement' (en qwerty), par exemple :
    J'espère que vous avez bien compris le commentaire ligne 21 de votre fonction "sendEmulation" pour comprendre pourquoi la différence de comportement.

    Au niveau du hook de clavier, vous ne voyez que des touches, pas de caractères et encore moins des chaines de caractères "complète".

    "tutu":"toto","titi":"tata","gege":"bibi" ; et que je veuiile récupérer "bibi", le code me renvoie et m'affiche toute la chaîne précédemment frappée (via SendInput() si j'ai bien compris).
    Vous la stockez où cette chaine de caractère, vu que le hook, lui, il ne voit qu'une touche (touche, pas caractère) monté ou descendre ?

    Vous avez un très très gros travail (et encore, vu le bordel "configuratoire" de Windows, c'est pas sûr de faire un machin "fiable") pour transformer une séquence d'évènement de touche en une chaine de caractères, et bon courage car chaque application a sa tambouille pour faire cette transformation.

    Mais bon, qui a besoin de fiabilité pour faire un keylogger pour piquer des numéros de CB.

    Si vous n'êtes pas un pirate du dimanche, vous avez vraisemblablement utilisé de mauvais outils pour pondre une "solution".

  13. #13
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2016
    Messages
    103
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Bâtiment

    Informations forums :
    Inscription : Juin 2016
    Messages : 103
    Par défaut Code du POC plus fourni
    Bonjour et merci pour le retour.

    Je pars d'un POC existant que j'ai repris. Je suis en QWERTY.

    Effectivement, lorsque je tape sur shift + ^ ('{')je rentre en mode capture ; j'entre dans le hook et je réalise ma saisie.

    Une fois ma saisie terminé, je sors du mode 'capture' et donc du hook via "}" ; et, c'est à ce moment là que je dois lancer la simulation et faire l'extraction et afficher l'ID.

    OR, en débuguant, j'ai remarqué que je passe jamais dans ma fonction d'extraction. Car elle devrait se produire "quasi en même temps" que ma sendEmulation qui renvoie ma chaîne de caractères

    virtuelle sur mon pad.

    Voici le code complet du POC plus en détails :

    Auparavant, une Remarque importante : pour l'extraction, je n'ai pas réussi à simuler les touches majuscules, donc j'ai 'splité' avec les caractères que j'obtenais en sortie (pour le moment, merci).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
     
     
    // Shift pressed indicator
    boolean shiftOn = false;
     
    // timestamp when capture mode has been switched to true
    uint64_t captureModeStartTime;
     
    HHOOK hook;
    string Code = ""; // Code reading buffer
    boolean captureMode = false; // if true, capture mode is on, if false, flow pass as is
     
    // Retrieve the keyboard layout
    const HKL currentKBL = GetKeyboardLayout(0);
     
    /*
    * Détermine le caractère en sortie en fonction de la langue et des combinaisons de touches.
    */
    char getChar(boolean shiftOn, int code) {
        /* 
        * EN
        */
        if (lang == "en") {
           TCHAR cVirtKey = (TCHAR)code;
     
           return cVirtKey;
        }
     
        return ' ';
    }
     
    /**
    * Get current timestamp in ms.
    */
    uint64_t timeSinceEpochMillisec() {
        using namespace std::chrono;
        return duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
    }
     
    /*
    * Determine if a character should be ignored (control, shift and prefix, suffix reserved ones).
    */
    boolean isExcludedKey(int keyCode) {
        return keyCode == codeCtrl || keyCode == codeShift || keyCode == codePrefix && shiftOn || keyCode == codeSuffix && shiftOn; // en
    }
     
    /*
    * Extract the ticketing Id from the pass payload 
    */
    string extractId(string payload) {
     
        string ticketID;
     
        std::regex re("[: ,]"); //{"1AA0":"FR", "0000" : "A1685713113503", "3AA0" : "SM92292417c3910016f7", "4AA0" : "SM92491027cf13201679"} : vrai format à extraire, plus tard//
        std::vector<std::string> v; //vextor<pair<string,string>> difficile à faire//
     
        std::copy(std::sregex_token_iterator(payload.begin(), payload.end(), re, -1),
            std::sregex_token_iterator(),
            std::back_inserter(v));
     
     
        for (int i = 0; i < v.size(); i++)
        {
            if (v[i] == "4AA0") //tickettickingID : 4AA0//
            {
                //cout << "ID : " << v[i + 1] << endl;
                ID = v[i + 1];
            }
        }
     
        return ID;  
    }
     
    /*
    * Generate the keyboard emulation output based on the language and the text to be typed.
    */
    void sendEmulation(string text) {
        UINT ret;
        INPUT inputs[1];
     
        int i = 0;
        printf("Emulating output...\n");
        for (char c : text) {
            printf("Char %c ", c);
     
            inputs[0].type = INPUT_KEYBOARD;
            inputs[0].ki.wScan = 0;
            inputs[0].ki.dwFlags = 0;
            inputs[0].ki.time = 0;
            inputs[0].ki.dwExtraInfo = 0;
     
            // Get the virtual key corresponding to the character
            SHORT vk = VkKeyScanEx(c, currentKBL);
     
            // If we are sending digits in a french keyboard configuration, shift needs to be pressed
            bool is_shift_key = false;
     
            // Send the emulated char
            inputs[0].ki.wVk = vk;
            ret = SendInput(ARRAYSIZE(inputs), inputs, sizeof(INPUT));
     
            // Inter chars delay
            Sleep(intCharDelay);
        }
     
        printf("\nEmulation done\n");
     
        Code = ""; // reinit qrCode buffer
    }
     
    LRESULT CALLBACK keyboardHook(int nCode, WPARAM wParam, LPARAM lParam)
    {
     
        // Check if capture mode timeout is expired to switch back in normal mode if capture mode is active
        if (captureMode == true && timeSinceEpochMillisec() - captureModeStartTime > captureModeTimeout) {
            printf("Deactivate capture mode as timeout of %d ms is reached since activation !", captureModeTimeout);
            captureMode = false;
        }
     
        // Init vars.
        KBDLLHOOKSTRUCT* p = (KBDLLHOOKSTRUCT*)lParam;
        DWORD newVkCode;
        INPUT inputs[1];
        UINT ret;
     
        /*
        * BEGIN - Debug print.
        */
     
        char wParamStr[16];
        char vkStr[16] = "";
     
        if (wParam == WM_KEYDOWN)
            strcpy_s(wParamStr, "KEYDOWN");
        else if (wParam == WM_KEYUP)
            strcpy_s(wParamStr, "KEYUP");
        else if (wParam == WM_SYSKEYDOWN)
            strcpy_s(wParamStr, "SYSKEYDOWN");
        else if (wParam == WM_SYSKEYUP)
            strcpy_s(wParamStr, "SYSKEYUP");
        else
            strcpy_s(wParamStr, "UNKNOWN");
     
        if (p->vkCode == 10)
            strcpy_s(vkStr, "<LF>");
        else if (p->vkCode == 13)
            strcpy_s(vkStr, "<CR>");
        else
            vkStr[0] = p->vkCode;
     
        //printf("%d - %s - %lu (%s) - %d - %lu\n", nCode, wParamStr, p->vkCode, vkStr, p->scanCode, p->time);
     
        /*
        * END - Debug print.
        */
     
        // Shift key action
        if (p->vkCode == codeShift) {
            if (wParam == WM_KEYDOWN) { // shift key is pressed, we activate the shift mode
                shiftOn = true;
            }
            else {// shift key is released, we deactivate the shift mode
                shiftOn = false;
            }
        }
     
        // Listen the appearance of prefix to determine whether we should start capture or let the flow go as is
        if (wParam == WM_KEYDOWN && p->vkCode == codePrefix && shiftOn && captureMode == false) { // en prefix detected, starting the capture
            printf("Prefix detected, entering capturing mode...\n");
            captureMode = true;
            captureModeStartTime = timeSinceEpochMillisec();
            //shiftOn = false;
     
            // Release the shift key in case the suffix char is a shifted one so the emulated output is not done with shift key down and not up
            inputs[0].type = INPUT_KEYBOARD;
            inputs[0].ki.wScan = 0;
            inputs[0].ki.time = 0;
            inputs[0].ki.dwExtraInfo = 0;
            inputs[0].ki.dwFlags = KEYEVENTF_KEYUP;
            inputs[0].ki.wVk = codeShift;
            ret = SendInput(ARRAYSIZE(inputs), inputs, sizeof(INPUT));
     
            return 1; // we do not interpret the prefix character
        }
     
        // If the prefix hasn't been detected yet then we are not in QRCode capture, the flow is transmitted without modification
        if ((!captureMode || (p->flags & LLKHF_INJECTED) != 0)) {
            return CallNextHookEx(hook, nCode, wParam, lParam);
        }
        else { 
            /*
            * Suffix mode
            */
            if (wParam == WM_KEYUP && p->vkCode == codeSuffix) { // && shiftOn -> TODO le shift est on au key down mais pas au key up
                printf("Suffix detected, exit capturing mode and emulating output ID \n");   
     
                // Extract the ticketingId from the payload.
                // TODO gérer l'error en cas de qrCode inférieur à la taille attendue
                string Id = extractId(qrCode);
     
                // Send the output emulation.
                sendEmulation(ticketingId);
     
                captureMode = false; // deactivation of capture mode as the suffix has been found
                shiftOn = false;
     
                return 1; // do not send the suffix char
     
            }
            else if ((p->flags & LLKHF_INJECTED) == 0 && wParam == WM_KEYDOWN && !isExcludedKey(p->vkCode)) { //ne pas traiter les caractères injectés et les touches de contrôle et majuscule
                char typed = getChar(shiftOn, p->vkCode);
                printf("Add char : %c - %d %d \n", typed, p->vkCode, p->scanCode);
                Code += typed;
            }
     
            return 1;
        }
    }
     
    int main()
    {
        // Hide the console.
        if (hideConsole) {
            ShowWindow(GetConsoleWindow(), SW_HIDE);
        }
     
        MSG messages;
     
        hook = SetWindowsHookEx(WH_KEYBOARD_LL, keyboardHook, NULL, 0);
        if (hook == NULL) {
            printf("Error %d\n", GetLastError());
            return 1;
        }
     
        printf("Proxy started, capturing keyboard events in lang [%s]...\n", lang);
     
        while (GetMessage(&messages, NULL, 0, 0))
        {
            TranslateMessage(&messages);
            DispatchMessage(&messages);
        }
        return 0;
    }

  14. #14
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2016
    Messages
    103
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Bâtiment

    Informations forums :
    Inscription : Juin 2016
    Messages : 103
    Par défaut divers
    Bonjour à tous.

    @bacelar, non je ne suis pas un hacker du dimanche lol.

    C'est mon N+1 qui a développé ce POC et me demande de faire l'extraction de l'ID (pour une boîte américaine d'où l'intérêt que je bascule mon clavier en qwerty).

    Je reconnais mes difficultés de compréhension. Et pourtant, j'essaie vraiment.

    En tout cas merci à tous de vos retour.

    ps : je ne suis plus sur le projet car j'ai été fired ; mais pour ma formation personnelle et que je puisse progresser il est important que je comprenne.

  15. #15
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 446
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 446
    Par défaut
    Vue la "qualité" très très moyenne du code, ne plus être dans cette boite, c'est une très très bonne nouvelle.

    La foire à la saucisse des globales (mention spéciale à la variable "lang" qui a réussi son jet de furtivité), utilisation d'API bas niveau pour faire des actions de "haut niveau d'abstraction", etc... c'est du travail de total cochon.
    Si c'est votre N+1 qui a écrit cette horreur, tu m'étonnes qu'il assume pas et qu'il fait porter le chapeau à celui d'après.

    Quite à utiliser "SetWindowsHookEx", pourquoi utiliser la version "du dimanche" avec "WH_KEYBOARD_LL" qui est beaucoup plus simple à utiliser mais beaucoup moins "puissante" en terme de performance et de discrétion ?

    Comme déjà indiqué, vous dites beaucoup d'imprécisions/erreurs, c'est peut-être votre N+1 qui à fait exprès de vous dire des conneries que vous avez gobé tout rond, ou lui aussi il est dans la sauce et qu'il ne comprend (plus) rien à ce qu'il a fait.
    Example :
    Effectivement, lorsque je tape sur shift + ^ ('{')je rentre en mode capture ; j'entre dans le hook
    Non, vous n'entrez pas dans le hook avec la séquence de touche.
    Le hook est appelé par le système (directement ou indirectement via le chainage des hooks) à chaque évènement clavier et cela dès qu'il s'est enregistré et tant qu'il ne se désenregistre pas (et que les autres hooks ne font pas de conneries, pas comme le vôtre, qui prend même pas la peine de se désenregistre (c'est pour les faibles ?) ).

    j'entre dans le hook et je réalise ma saisie.
    Non, vous êtes dans le hook depuis la ligne 111.
    Vous êtes dans le cas où vous passez la condition de la ligne 168, qui n'ouvre que la section permettant d'initier la partie "captureMode == true" du code ; et de faire croire à l'application victime (si elle est crédule) que le bouton shift a été lâché, pourquoi ? Selon les commentaires, des sombres bailles sur l'interprétation de la séquence suffixe. GG
    Oui, c'est du code spaghetti mais c'est le vôtre, ou de votre N+1.

    Une fois ma saisie terminé, je sors du mode 'capture' et donc du hook via "}" ;
    Non, vous ne sortez pas du hook. Il sera toujours appelé tant qu'il n'est pas désenregistré.

    Techniquement, vous entrez et sortez de la fonction de callback de hook à chaque évènement clavier.
    Mais avec votre collection toute moisie de variables globales, à chaque entrée/sortie dans la fonction de callback vous héritez d'un contexte de bidules foireux sauvegardés des appels précédents.

    Mention spéciale à la ligne 14 qui initialise une globale avec résultat d'une fonction, un bon petit "static initialization order fiasco". (les constexpr, c'est pas le genre de la maison Win32)

    La fonction "getChar" qui confond allégrement un code ASCII et un code de touche virtuelle (merci au clavier QWERTY).
    Si un code, c'est un int et pas un TCHAR, c'est pas juste pour faire jolie.
    Et le beau cast à la C pour clouer le bec au compilateur GG. Vous vous tirez une balle dans le pied avec "panache".
    (on ne rementionne pas le ghost "lang")

    La bonne petite fonction "extractId" qui a des valeurs magiques dedans, mais pas d'utilisation de MACRO type TEXT ou L, allez, sur un malentendu, ça passe. (bin non, on n'est pas chez mémé)
    Vous l'avez testé avec un débugueur dans des tests unitaires votre fonction avant de la plugger au reste du programme ?
    Moi, j'en doute, sinon vous aurez vu qu'elle est boguée de partout.
    (Je vous l'accorde, on lui envoie aussi de la merde de l'extérieur mais c'est toute la magie des TU, on sait d'où cela ne vient pas quand ils sont au vert.

    Non, mais c'est déjà pas très malin d'utiliser une variable globale de type chaine de caractère de nom "code" pour récupérer les caractères 'valides' entre l'entré du préfixe et du suffixe, en croyant qu'une liste ordonnées de touches c'est pareil qu'une liste ordonnées de caractère (même pas case-sensitive parce qu'on fait le zouave avec pour les séquences préfixe) mais en plus, c'est même pas utilisé en paramètre de "extractId" qui utilise une variable "qrCode" tout aussi fantomatique que "lang".
    Et "ticketingId" passé à la fonction "sendEmulation" et vient du même coin que "lang" et "qrCode" ?

    Un code qui fonctionne est plus simple à comprendre qu'un code tout pété.

  16. #16
    Membre Expert

    Homme Profil pro
    Directeur de projet
    Inscrit en
    Mai 2013
    Messages
    1 582
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Service public

    Informations forums :
    Inscription : Mai 2013
    Messages : 1 582
    Par défaut Key logger
    Bonjour,

    C'est vrai qu'avec tout le code il est plus facile de se faire un avis.

    Mais hormis ce qui a été légitimement dit, c'est quand même un peu navrant.

    La capture des caractères peut se faire sur les descentes de touche (il peut y avoir plusieurs descentes pour une remonté - autorepeat). Une chaîne de caractères peut être créée au fil de l'eau : on s'arrête quand un des caractères séparateurs (tabulation, enter ne sont pas dans la liste ?) est rencontré (nul besoin d'un regex ici). Alors une copie de la chaine peut être transmise pour usage puis la chaine du hook est vidée pour la détection suivante. Mais ce n'est pas si simple, il faut également gérer les del, ins, backspace et mouvements curseur, sinon on récupère n'importe quoi.

    Mais je vais arrêter là car le code suivant confirme le caractère frelaté de l'opération :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    // Hide the console.
        if (hideConsole) {
            ShowWindow(GetConsoleWindow(), SW_HIDE);
        }
    De même, il est tellement plus simple de placer le résultat dans le presse-papier. A moins de vouloir être très discret...

    Finalement, le point positif est que ce code malhonnête n'a aucune chance de marcher

    Salutations

  17. #17
    Membre confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2016
    Messages
    103
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Bâtiment

    Informations forums :
    Inscription : Juin 2016
    Messages : 103
    Par défaut divers
    Bonjour et merci pour vos retours (même si je n'ai pas tout compris..je viens de prendre connaissance assez tard).

    J'avais proposé dans un premier temps que l'on affiche les caractères saisies dans un fichier.

    Puis de traiter ledit fichier.

    On m'a répondu que non. Car le gain de temps est important.

    Je vous tiens au courant.

    Salutations,

    KM.

Discussions similaires

  1. Réponses: 1
    Dernier message: 16/11/2009, 11h29
  2. Acquisition et traitement données temps réel
    Par Munch dans le forum LabVIEW
    Réponses: 3
    Dernier message: 13/05/2009, 11h47
  3. Mise à jour de données temps réel avec Pentaho Data Integration
    Par jonathansauret dans le forum kettle/PDI
    Réponses: 0
    Dernier message: 29/10/2008, 15h55
  4. Acces et ajout de données temps réel
    Par byakuichi dans le forum Access
    Réponses: 1
    Dernier message: 07/05/2008, 22h51
  5. base de donnée temps réel SGBDTR
    Par ettaieb dans le forum Bases de données
    Réponses: 0
    Dernier message: 17/08/2007, 17h26

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo