//------------------------------------------------------------------------------
void reg_read_enum_MRUWvalues(HKEY hk,char *chkey,char *key,char *exclu,char* description_id,unsigned int session_id, sqlite3 *db)
{
  HKEY CleTmp;
  if (RegOpenKey(hk,key,&CleTmp)!=ERROR_SUCCESS)return;

  DWORD nbValue,i;
  FILETIME last_update;
  if (RegQueryInfoKey (CleTmp,0,0,0,0,0,0,&nbValue,0,0,0,&last_update)!=ERROR_SUCCESS)
  {
    RegCloseKey(CleTmp);
    return;
  }

  //get date
  char parent_key_update[DATE_SIZE_MAX] = "";
  filetimeToString_GMT(last_update, parent_key_update, DATE_SIZE_MAX);

  //read USER + RID + SID
  char user[MAX_PATH], RID[MAX_PATH], sid[MAX_PATH];
  GetRegistryKeyOwner(CleTmp, user, RID, sid, MAX_PATH);

  //enum values
  char value[MAX_PATH], data[MAX_PATH], data_s[MAX_PATH];
  DWORD valueSize,dataSize,type;
  for (i=0;i<nbValue && start_scan;i++)
  {
    valueSize = MAX_PATH;
    dataSize  = MAX_PATH;
    value[0]  = 0;
    data[0]   = 0;
    type      = 0;
    if (RegEnumValue (CleTmp,i,(LPTSTR)value,(LPDWORD)&valueSize,0,(LPDWORD)&type,(LPBYTE)data,(LPDWORD)&dataSize)==ERROR_SUCCESS)
    {
      convertStringToSQL(value, MAX_PATH);
      snprintf(data_s,MAX_LINE_SIZE,"%S",data);
      convertStringToSQL(data_s, MAX_PATH);
      addRegistryMRUtoDB("",chkey,key,value,data_s,description_id,user,RID,sid,parent_key_update,session_id,db);
    }
  }
  RegCloseKey(CleTmp);
}
//------------------------------------------------------------------------------
unsigned int ReadRecord(char *buffer, DWORD size, STRING_TABLE *my_s_table, char *eventfile, sqlite3 *db, unsigned int session_id)
{
  #define EVENTLOG_H_EVTX_SIZE                    4+4+8+8+6
  typedef struct _EVENTLOG_H_EVTX {
    unsigned char MagicString[4];                 //4 ** + 0x00 + 0x00
    unsigned int RecordSize;                      //4
    unsigned long long int RecordNumber;          //8   //RecordNumber
    unsigned long long int TimeCreated;           //8
    unsigned char padding_star_xml[6];            //6 : 0f01 0100 0c01
  }EVENTLOG_H_EVTX;
  EVENTLOG_H_EVTX *h_dheader = (EVENTLOG_H_EVTX *)buffer;

  char indx[DEFAULT_TMP_SIZE]="", log_id[DEFAULT_TMP_SIZE]="",
  send_date[DATE_SIZE_MAX]="", write_date[DATE_SIZE_MAX]="",
  source[MAX_PATH]="", description[MAX_LINE_SIZE]="",
  user[DEFAULT_TMP_SIZE]="", rid[DEFAULT_TMP_SIZE]="", sid[DEFAULT_TMP_SIZE]="",
  state[DEFAULT_TMP_SIZE]="", critical[DEFAULT_TMP_SIZE]="";

  DWORD id=0;

  //test de validité
  if (h_dheader->RecordSize <= size
   && h_dheader->MagicString[0] == '*' && h_dheader->MagicString[1] == '*' && h_dheader->MagicString[2] == 0 && h_dheader->MagicString[3] == 0)
  {
    //lecture des informations du header
    //id
    snprintf(indx,DEFAULT_TMP_SIZE,"%08lu",(long unsigned int)(h_dheader->RecordNumber));

    //date : send_date
    FILETIME FileTime;
    FileTime.dwLowDateTime = (DWORD) h_dheader->TimeCreated;
    FileTime.dwHighDateTime = (DWORD)(h_dheader->TimeCreated >> 32);
    filetimeToString_GMT(FileTime, send_date, DATE_SIZE_MAX);

    //date : write_date = same
    strcpy(write_date,send_date);

    //afin de passer les enregistrelent avec header on passe tant qu'on à pas accès au header attendu ^^
    //permet de traiter les cas de données corrompues
    //0x00 0000 0100 0400 0100 0400
    char *c = buffer+EVENTLOG_H_EVTX_SIZE;
    DWORD pos=EVENTLOG_H_EVTX_SIZE;
    BOOL ok =FALSE;
    do
    {
      if (*c == 0x00 && *(c+1) == 0x00 && *(c+2) == 0x00 &&
      *(c+3) == 0x01 && *(c+4) == 0x00 && *(c+5) == 0x04 && *(c+6) == 0x00 &&
      *(c+7) == 0x01 && *(c+8) == 0x00 && *(c+9) == 0x04 &&*(c+10) == 0x00)
      {
        ok = TRUE;
        break;
      }

      c++;
      pos++;
    }while(pos<h_dheader->RecordSize-12);

    //traitement de la suite ^^
    if (ok)
    {
      //recherche de l'id ^^ dans une zone de moins de 100octets ^^
      //0x2100 0400 0000 XXXX = ID
      typedef struct _ID
      {
        unsigned short param;   // 0x0021
        unsigned char end;
        unsigned char type;     // level
        unsigned short padding; // 0x0000
        unsigned short id;
      }M_ID;
      M_ID * mid;

      while(pos<h_dheader->RecordSize-10)
      {
        if (*c == 0x21 && *(c+1) == 0x00)
        {
          //id identifié ^^
          mid = (M_ID *)c;
          snprintf(log_id,DEFAULT_TMP_SIZE,"%08lu",(DWORD) mid->id);
          id = mid->id;

          //Type
          switch(mid->type)
          {
            case 0x00 : strcpy(state,"INFORMATION"); break;
            case 0x01 : strcpy(state,"WARNING"); break;
            case 0x02 : strcpy(state,"ERROR"); break;
            case 0x04 : strcpy(state,"CRITICAL"); break;
            case 0x08 : strcpy(state,"AUDIT_SUCCESS"); break;
            case 0x10 : strcpy(state,"AUDIT_FAILURE"); break;
            default :snprintf(state,MAX_LINE_SIZE,"UNKNOW (%d)",mid->type);break;
          }
        }
        c++;pos++;
      }
      c+=8; //on passe l'id + 6 octets de padding

      //Source
      char *desc = c;
      source[0] = 0;
      while(pos+4<h_dheader->RecordSize-10)
      {//0x05- 0x12 = S-1-5-18, revoir la phase de détection pour prendre en compte le SID !!!!
        if (*c != 0x00 && *(c+1) == 0x00) //unicode
          if (*(c+2) != 0x00 && *(c+3)==0x00)
          //if (*c == 0x05)
          {
            snprintf(source,MAX_LINE_SIZE,"%S",c);
            break;
          }
        c++;
        pos++;
      }

      //si aucune source n'est définie on ajoute le nom du fichier sans evtx ^^
      if (source[0] == 0)
      {
        char *n = eventfile;
        while (*n)n++;
        while (*n != '\\')n--;
        n++;
        snprintf(source,MAX_PATH,"%s",n);
        source[strlen(source)-5]=0;

        //on vérifie que pas de % dans le nom sinon on met 0 à sa place ^^
        n = source;
        while (*n)
        {
          if (*n == '%'){*n=0; break;}
          n++;
        }
      }

      //traitement de la description !!
      TraiterDescription (desc,h_dheader->RecordSize/*-pos*/,description,MAX_LINE_SIZE);
    }

    //add
    convertStringToSQL(source, MAX_PATH);
    convertStringToSQL(description, MAX_LINE_SIZE);
    addLogtoDB(eventfile, indx, log_id,
           send_date, write_date, source, description,
           user, rid, sid, state, critical, session_id, db);
  }
//------------------------------------------------------------------------------
int callback_sqlite_registry_local(void *datas, int argc, char **argv, char **azColName)
{
  if (argv[0] == 0)return 0;

  FORMAT_CALBAK_TYPE *type = datas;
  unsigned int session_id = current_session_id;
  switch(type->type)
  {
    case SQLITE_REGISTRY_TYPE_SETTINGS:
    {
      HKEY hk = hkStringtohkey(argv[0]);
      switch(atoi(argv[3]))//value_type
      {
        case TYPE_VALUE_STRING:
        {
          char tmp[MAX_PATH]="";
          if (ReadValue(hk,argv[1],argv[2],tmp, MAX_PATH))
          {
            char parent_key_update[DATE_SIZE_MAX];
            ReadKeyUpdate(hk,argv[1], parent_key_update, DATE_SIZE_MAX);
            convertStringToSQL(tmp, MAX_PATH);
            addRegistrySettingstoDB("", argv[0], argv[1], argv[2], tmp, argv[4], argv[5], parent_key_update, session_id, db_scan);
          }
        }
        break;
        case TYPE_VALUE_DWORD:
        {
          char tmp[MAX_PATH]="";
          long int value= ReadDwordValue(hk,argv[1],argv[2]);
          if (value != -1)
          {
            snprintf(tmp,MAX_PATH,"0x%08X",(unsigned int)value);
            char parent_key_update[DATE_SIZE_MAX];
            ReadKeyUpdate(hk,argv[1], parent_key_update, DATE_SIZE_MAX);
            addRegistrySettingstoDB("", argv[0], argv[1], argv[2], tmp, argv[4], argv[5], parent_key_update, session_id, db_scan);
          }
        }
        break;
        case TYPE_VALUE_MULTI_STRING:
        {
          char tmp[MAX_PATH]="";
          long int i, tmp_size = ReadValue(hk,argv[1],argv[2],tmp, MAX_PATH);
          if (tmp_size>0)
          {
            char parent_key_update[DATE_SIZE_MAX];
            ReadKeyUpdate(hk,argv[1], parent_key_update, DATE_SIZE_MAX);
            for (i=0;i<tmp_size;i++)
            {
              if (tmp[i] == 0)tmp[i]=';';
            }
            convertStringToSQL(tmp, MAX_PATH);
            addRegistrySettingstoDB("", argv[0], argv[1], argv[2], tmp, argv[4], argv[5], parent_key_update, session_id, db_scan);
          }
        }
        break;
        case TYPE_VALUE_MULTI_WSTRING:
          {
            char tmp[REQUEST_MAX_SIZE]="",data_read[REQUEST_MAX_SIZE];
            DWORD pos=0, data_size_read = ReadValue(hk,argv[1],argv[2],tmp, REQUEST_MAX_SIZE);

            if (data_size_read)
            {
              char parent_key_update[DATE_SIZE_MAX];
              ReadKeyUpdate(hk,argv[1], parent_key_update, DATE_SIZE_MAX);

              while ((pos-1)*2<data_size_read)
              {
                snprintf(data_read+pos,REQUEST_MAX_SIZE,"%S;",tmp+(pos*2-1));
                pos = strlen(data_read);
              }

              convertStringToSQL(data_read, MAX_PATH);
              addRegistrySettingstoDB("", argv[0], argv[1], argv[2], data_read, argv[4], argv[5], parent_key_update, session_id, db_scan);
            }
          }
        break;
        case TYPE_VALUE_FILETIME:
        {
          char tmp[MAX_PATH]="";
          FILETIME ft;
          if (hk == 0 || argv[1][0]==0)break;
          ReadFILETIMEValue(hk,argv[1],argv[2],&ft);
          filetimeToString_GMT(ft, tmp, MAX_PATH);

          char parent_key_update[DATE_SIZE_MAX];
          ReadKeyUpdate(hk,argv[1], parent_key_update, DATE_SIZE_MAX);
          addRegistrySettingstoDB("", argv[0], argv[1], argv[2], tmp, argv[4], argv[5], parent_key_update, session_id, db_scan);
        }
        break;
        case TYPE_VALUE_WIN_SERIAL:
        {
          char tmp[MAX_PATH]="";
          if (GetWindowsCDKey_local(hk, argv[1], argv[2], tmp, MAX_PATH))
          {
            char parent_key_update[DATE_SIZE_MAX];
            ReadKeyUpdate(hk,argv[1], parent_key_update, DATE_SIZE_MAX);
            addRegistrySettingstoDB("", argv[0], argv[1], argv[2], tmp, argv[4], argv[5], parent_key_update, session_id, db_scan);
          }
        }
        break;
        case TYPE_ENUM_STRING_VALUE:
        {
          HKEY CleTmp=0;
          if (RegOpenKey(hk,argv[1],&CleTmp)!=ERROR_SUCCESS)return 0;

          FILETIME lastupdate;
          char parent_key_update[DATE_SIZE_MAX];

          DWORD NameSize, DataSize;
          char Name[MAX_PATH], Data[MAX_PATH], tmp[MAX_PATH];
          DWORD nbValue = 0, i,j, type2;
          if (RegQueryInfoKey (CleTmp,0,0,0,0,0,0,&nbValue,0,0,0,&lastupdate)==ERROR_SUCCESS)
          {
            filetimeToString_GMT(lastupdate, parent_key_update, DATE_SIZE_MAX);
            for (i=0;i<nbValue;i++)
            {
              NameSize = MAX_PATH;
              DataSize = MAX_PATH;
              Name[0]  = 0;
              Data[0]  = 0;
              type2     = 0;
              if (RegEnumValue (CleTmp,i,(LPTSTR)Name,(LPDWORD)&NameSize,0,(LPDWORD)&type2,(LPBYTE)Data,(LPDWORD)&DataSize)==ERROR_SUCCESS)
              {
                switch(type2)
                {
                  case REG_EXPAND_SZ:
                  case REG_SZ:addRegistrySettingstoDB("", argv[0], argv[1], Name, Data, argv[4], argv[5], parent_key_update, session_id, db_scan);break;
                  case REG_LINK:
                    snprintf(tmp,MAX_PATH,"%S",Data);
                    convertStringToSQL(tmp, MAX_PATH);
                    addRegistrySettingstoDB("", argv[0], argv[1], Name, tmp, argv[4], argv[5], parent_key_update, session_id, db_scan);
                  break;
                  case REG_MULTI_SZ:
                    for (j=0;j<DataSize;j++)
                    {
                      if (Data[j] == 0)Data[j]=';';
                    }
                    convertStringToSQL(Data, MAX_PATH);
                    addRegistrySettingstoDB("", argv[0], argv[1], Name, Data, argv[4], argv[5], parent_key_update, session_id, db_scan);
                  break;
                  case REG_DWORD:
                    snprintf(tmp,MAX_PATH,"0x%08X",&Data[0]);
                    addRegistrySettingstoDB("", argv[0], argv[1], Name, tmp, argv[4], argv[5], parent_key_update, session_id, db_scan);
                  break;
                  default : //binary/dword
                    strncpy(tmp,"0x",MAX_PATH);
                    NameSize = 0;
                    for (j=0;j<DataSize && NameSize<MAX_PATH;j++)
                    {
                      NameSize = strlen(tmp);
                      snprintf(tmp+NameSize,MAX_PATH-NameSize,"%02X",Data[j]&0xFF);
                    }
                    addRegistrySettingstoDB("", argv[0], argv[1], Name, tmp, argv[4], argv[5], parent_key_update, session_id, db_scan);
                  break;
                }
              }
            }
          }
        }
        break;
      }
    }
    break;
  }
  return 0;
}
//------------------------------------------------------------------------------
int callback_sqlite_registry_file(void *datas, int argc, char **argv, char **azColName)
{
  FORMAT_CALBAK_TYPE *type = datas;
  unsigned int session_id = current_session_id;
  char tmp[MAX_LINE_SIZE];
  switch(type->type)
  {
    case SQLITE_REGISTRY_TYPE_SETTINGS:
    {
      switch(atoi(argv[3]))//value_type
      {
        case TYPE_VALUE_STRING:
        case TYPE_VALUE_DWORD:
        case TYPE_VALUE_MULTI_STRING:
          if (Readnk_Value(local_hks.buffer,local_hks.taille_fic, (local_hks.pos_fhbin)+HBIN_HEADER_SIZE, local_hks.position,
                           argv[1], NULL, argv[2], tmp, MAX_LINE_SIZE))
          {
            //key update
            char parent_key_update[DATE_SIZE_MAX];
            Readnk_Infos(local_hks.buffer,local_hks.taille_fic, (local_hks.pos_fhbin), local_hks.position,
                         argv[1], NULL, parent_key_update, DATE_SIZE_MAX, NULL, 0,NULL, 0);

            //save
            convertStringToSQL(tmp, MAX_LINE_SIZE);
            addRegistrySettingstoDB(local_hks.file, "", argv[1], argv[2], tmp, argv[4], argv[5], parent_key_update, session_id, db_scan);
          }
        break;
        case TYPE_VALUE_MULTI_WSTRING:
        {
          char data_read[MAX_LINE_SIZE];
          DWORD pos=0, data_size_read = MAX_LINE_SIZE;
          if (ReadBinarynk_Value(local_hks.buffer,local_hks.taille_fic, (local_hks.pos_fhbin)+HBIN_HEADER_SIZE, local_hks.position,
                                 argv[1], NULL, argv[2], tmp, &data_size_read))
          {
            if (data_size_read)
            {
              //data_read
              while ((pos-1)*2<data_size_read)
              {
                snprintf(data_read+pos,MAX_LINE_SIZE,"%S;",tmp+(pos*2-1));
                pos = strlen(data_read);
              }

              //key update
              char parent_key_update[DATE_SIZE_MAX];
              Readnk_Infos(local_hks.buffer,local_hks.taille_fic, (local_hks.pos_fhbin), local_hks.position,
                           argv[1], NULL, parent_key_update, DATE_SIZE_MAX, NULL, 0,NULL, 0);

              //save
              convertStringToSQL(data_read, MAX_LINE_SIZE);
              addRegistrySettingstoDB(local_hks.file, "", argv[1], argv[2], data_read, argv[4], argv[5], parent_key_update, session_id, db_scan);
            }
          }
        }
        break;
        case TYPE_VALUE_FILETIME:
        {
          DWORD data_size = sizeof(FILETIME)+1;
          FILETIME f_date;
          if (ReadBinarynk_Value(local_hks.buffer,local_hks.taille_fic, (local_hks.pos_fhbin)+HBIN_HEADER_SIZE, local_hks.position,
                           argv[1], NULL, argv[2], (void*)&f_date, &data_size))
          {
            //key update
            char parent_key_update[DATE_SIZE_MAX];
            Readnk_Infos(local_hks.buffer,local_hks.taille_fic, (local_hks.pos_fhbin), local_hks.position,
                         argv[1], NULL, parent_key_update, DATE_SIZE_MAX, NULL, 0,NULL, 0);

            //convert date
            tmp[0] = 0;
            filetimeToString_GMT(f_date, tmp, DATE_SIZE_MAX);

            //save
            convertStringToSQL(tmp, MAX_LINE_SIZE);
            addRegistrySettingstoDB(local_hks.file, "", argv[1], argv[2], tmp, argv[4], argv[5], parent_key_update, session_id, db_scan);
          }
        }
        break;
        case TYPE_VALUE_WIN_SERIAL:
        {
          HBIN_CELL_NK_HEADER *nk_h = GetRegistryNK(local_hks.buffer,local_hks.taille_fic, (local_hks.pos_fhbin)+HBIN_HEADER_SIZE, local_hks.position,argv[1]);
          if (nk_h!=NULL)
          {
            //key update
            char parent_key_update[DATE_SIZE_MAX];
            Readnk_Infos(local_hks.buffer,local_hks.taille_fic, (local_hks.pos_fhbin), local_hks.position,
                         NULL, nk_h, parent_key_update, DATE_SIZE_MAX, NULL, 0,NULL, 0);



            //get value
            DWORD test_size = MAX_LINE_SIZE;
            DWORD serial_size;
            ReadBinarynk_Value(local_hks.buffer,local_hks.taille_fic, (local_hks.pos_fhbin)+HBIN_HEADER_SIZE, local_hks.position,
                                                         NULL, nk_h, argv[2], (void*)tmp, &test_size);
            if (test_size>65)
            {
              char result[MAX_PATH]="";

              char key[25] = "BCDFGHJKMPQRTVWXY2346789";
              BYTE enc[MAX_PATH];
              char lpszSerial[MAX_PATH];
              int i,c=0,nCur=0;

              for(i=52;i<=66;i++)enc[i-52] = tmp[i];
              for(i=24;i>=0;i--)
              {
                nCur = 0;
                for(c=14;c>-1;c--)
                {
                  nCur = nCur * 256;
                  nCur ^= enc[c];
                  enc[c] = nCur / 24;
                  nCur %= 24;
                }
                lpszSerial[i] = key[nCur];
              }

              serial_size = 0;
              for(i=0;lpszSerial[i] && (i+i/5) < 30 && MAX_PATH>serial_size;i++)
              {
                if(i % 5 == 0 && i>0)snprintf(result+serial_size,MAX_PATH-serial_size,"-%c",lpszSerial[i]);
                else snprintf(result+serial_size,MAX_PATH-serial_size,"%c",lpszSerial[i]);
                serial_size = strlen(result);
              }

              //save
              convertStringToSQL(result, MAX_LINE_SIZE);
              addRegistrySettingstoDB(local_hks.file, "", argv[1], argv[2], result, argv[4], argv[5], parent_key_update, session_id, db_scan);
            }
          }
        }
        break;
        case TYPE_ENUM_STRING_VALUE:
        {
          HBIN_CELL_NK_HEADER *nk_h = GetRegistryNK(local_hks.buffer,local_hks.taille_fic, (local_hks.pos_fhbin)+HBIN_HEADER_SIZE, local_hks.position,argv[1]);
          if (nk_h!=NULL)
          {
            //key update
            char parent_key_update[DATE_SIZE_MAX];
            Readnk_Infos(local_hks.buffer,local_hks.taille_fic, (local_hks.pos_fhbin), local_hks.position,
                         NULL, nk_h, parent_key_update, DATE_SIZE_MAX, NULL, 0,NULL, 0);

            //get values
            char value[MAX_PATH];
            DWORD i, nbSubValue = GetValueData(local_hks.buffer,local_hks.taille_fic, nk_h, (local_hks.pos_fhbin)+HBIN_HEADER_SIZE, 0, NULL, 0, NULL, 0);
            for (i=0;i<nbSubValue;i++)
            {
              if (GetValueData(local_hks.buffer,local_hks.taille_fic, nk_h, (local_hks.pos_fhbin)+HBIN_HEADER_SIZE, i,value,MAX_PATH,tmp,MAX_LINE_SIZE))
              {
                //save
                convertStringToSQL(value, MAX_PATH);
                convertStringToSQL(tmp, MAX_LINE_SIZE);
                addRegistrySettingstoDB(local_hks.file, "", argv[1], value, tmp, argv[4], argv[5], parent_key_update, session_id, db_scan);
              }
            }
          }
        }
        break;
      }
    }
  }
  return 0;
}
Example #5
0
//------------------------------------------------------------------------------
void PfCheck(unsigned int session_id, sqlite3 *db, char *file)
{
  //open file and read first datas
  HANDLE hfile = CreateFile(file,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,0);
  if (hfile != INVALID_HANDLE_VALUE)
  {
    DWORD sz_prefetch_file = GetFileSize(hfile,NULL);
    if ( sz_prefetch_file!= INVALID_FILE_SIZE && sz_prefetch_file > sizeof(HDR_PREFETCH))
    {
      char CreationTime[DATE_SIZE_MAX]="",LastWriteTime[DATE_SIZE_MAX]="",LastAccessTime[DATE_SIZE_MAX]="";
      DWORD count = 0, copiee;
      char exec_time[DATE_SIZE_MAX]="";
      char *depend;
      char *buffer;
      HDR_PREFETCH *pf;
      char *b, *e;

      char application_name[PREFETCH_APPLI_NAME_MAX_SIZE+1], path_application[MAX_PATH], path_depend[MAX_PATH];
      BOOL ok_path_application = FALSE;

      buffer = malloc(sizeof(char)*sz_prefetch_file+1);
      if (buffer!=NULL)
      {
        ReadFile(hfile, buffer, sz_prefetch_file,&copiee,0);
        pf = (HDR_PREFETCH*)buffer;

        if (pf->v_number > 0x11) //0x17 after winxp/2003 (+8octets)
        {
          count = pf->file_exec_counter2;
          filetimeToString_GMT(pf->last_file_exec2, exec_time, DATE_SIZE_MAX);
        }else
        {
          count = pf->file_exec_counter;
          filetimeToString_GMT(pf->last_file_exec, exec_time, DATE_SIZE_MAX);
        }

        //file times
        BY_HANDLE_FILE_INFORMATION hfi;
        if (GetFileInformationByHandle(hfile,&hfi))
        {
          filetimeToString_GMT(hfi.ftCreationTime, CreationTime, DATE_SIZE_MAX);
          filetimeToString_GMT(hfi.ftLastWriteTime, LastWriteTime, DATE_SIZE_MAX);
          filetimeToString_GMT(hfi.ftLastAccessTime, LastAccessTime, DATE_SIZE_MAX);
        }

        snprintf(application_name,PREFETCH_APPLI_NAME_MAX_SIZE,"%S",pf->filename);
        application_name[PREFETCH_APPLI_NAME_MAX_SIZE]=0;

        //search in path datas if name exist
        ok_path_application = FALSE;
        b = buffer+pf->secC_off;                  //start of datas
        e = buffer+pf->secC_off+pf->secC_size;    //end of datas
        DWORD size_depend = (e-b);
        if (size_depend <= sz_prefetch_file)
        {
          while (b<e)
          {
            snprintf(path_application,MAX_PATH,"%S",b);
            if (ContientNoCass(path_application,application_name))
            {
              ok_path_application = TRUE;
              break;
            }else
            {
              b = b + (strlen(path_application)+1)*2;
            }
          };

          if (!ok_path_application)path_application[0] = 0;

          //depend
          b = buffer+pf->secC_off;                  //start of datas
          e = buffer+pf->secC_off+pf->secC_size;    //end of datas
          depend = (char*)malloc(size_depend+2);
          if (depend != NULL)
          {
            depend[0] = 0;
            while (b<e)
            {
              snprintf(path_depend,MAX_PATH,"%S\r\n",b);
              snprintf(depend+strlen(depend),size_depend-strlen(depend),"%s",path_depend);
              //strncat(depend,path_depend,size_depend);
              b = b + (strlen(path_depend)-1)*2;
            };
            strncat(depend,"\0",size_depend);
            addPrefetchtoDB(file, CreationTime, LastWriteTime, LastAccessTime, count, exec_time, depend, path_application,session_id, db);
            free(depend);
          }else addPrefetchtoDB(file, CreationTime, LastWriteTime, LastAccessTime, count, exec_time, "", path_application,session_id, db);
          free(buffer);
        }
      }
    }
    CloseHandle(hfile);
  }
}
//------------------------------------------------------------------------------
void read_datas_lnk(unsigned char *buffer, DWORD taille_fic,
                    char *create_time, char *last_access_time, char *last_modification_time,
                    unsigned char *local_path, unsigned char *to)
{
  typedef struct
  {
    unsigned int header_size;         // default : 0x0000004C (76)
    unsigned char lnk_class_id[16];   // default : 00021401-0000-0000-00c0-000000000046
    unsigned int data_flag;
    unsigned int file_attribute_flag;
    FILETIME create_time;
    FILETIME last_access_time;
    FILETIME last_modification_time;
    unsigned int file_size;
    unsigned int icon_index;
    unsigned int show_window_value;
    unsigned short hot_key;
    unsigned char reserved[10];
    unsigned short item_list_size;
  }LNK_STRUCT, *PLNK_STRUCT;
  unsigned char tmp[MAX_PATH]="", *b;

  //header
  PLNK_STRUCT p = (PLNK_STRUCT)buffer;

  //get times
  filetimeToString_GMT(p->create_time, create_time, DATE_SIZE_MAX);
  filetimeToString_GMT(p->last_access_time, last_access_time, DATE_SIZE_MAX);
  filetimeToString_GMT(p->last_modification_time, last_modification_time, DATE_SIZE_MAX);

  //unicode or not
  BOOL unicode = FALSE;
  if ((p->data_flag & 0x80) == 0x80) unicode = TRUE;

  //if items list we pass
  if ((p->data_flag & 0x01) == 0x01)//hashlinktargetid
  {
    b = buffer + 2 + p->header_size + p->item_list_size;
  }else b = buffer + p->header_size;

  if (b-buffer < taille_fic)
  {
    typedef struct
    {
      unsigned short struct_size;
    }LNK_WORD_STRUCT, *PLNK_WORD_STRUCT;

    //link info
    if ((p->data_flag & 0x02) == 0x02)
    {
      typedef struct
      {
        DWORD struct_size;
        DWORD header_size;
        DWORD flags;
        DWORD vol_ID_offset;
        DWORD local_base_path_offset;
        DWORD Network_relative_path_offset;
        DWORD commun_path_offset;

        //infos
        DWORD CommonNetworkRelativeLinkSize;
        DWORD CommonNetworkRelativeLinkFlags;
        DWORD NetNameOffset;
        DWORD DeviceNameOffset;
        DWORD NetWorkProviderType;
      }LNK_INFO_STRUCT, *PLNK_INFO_STRUCT;
      PLNK_INFO_STRUCT pi = (PLNK_INFO_STRUCT)b;

      if ((pi->flags & 0x01) == 0x01 && (pi->flags & 0x02)  == 0x02)
      {
        if (pi->local_base_path_offset && pi->local_base_path_offset < pi->struct_size)snprintf(to,MAX_PATH,"%s",(char*)(b+pi->local_base_path_offset));

        if (pi->NetNameOffset && pi->NetNameOffset+pi->header_size < pi->struct_size)snprintf(local_path,MAX_PATH,"%s",(char*)(b+pi->NetNameOffset+pi->header_size));

        if (pi->DeviceNameOffset && pi->DeviceNameOffset+pi->header_size < pi->struct_size)snprintf(tmp,MAX_PATH,"%s\\",(char*)(b+pi->DeviceNameOffset+pi->header_size));

        if (pi->commun_path_offset && pi->commun_path_offset < pi->struct_size)snprintf(to,MAX_PATH,"%s%s",tmp,(char*)(b+pi->commun_path_offset));
      }else if ((pi->flags & 0x01) == 0x01) //local
      {
        if (pi->local_base_path_offset && pi->local_base_path_offset < pi->struct_size)snprintf(to,MAX_PATH,"%s",(char*)(b+pi->local_base_path_offset));
      }else if ((pi->flags & 0x02)  == 0x02) //network
      {
        //local path
        if (pi->NetNameOffset && pi->NetNameOffset+pi->header_size < pi->struct_size)snprintf(local_path,MAX_PATH,"%s",(char*)(b+pi->NetNameOffset+pi->header_size));

        if (pi->DeviceNameOffset && pi->DeviceNameOffset+pi->header_size < pi->struct_size)snprintf(tmp,MAX_PATH,"%s\\",(char*)(b+pi->DeviceNameOffset+pi->header_size));

        if (pi->commun_path_offset && pi->commun_path_offset < pi->struct_size)snprintf(to,MAX_PATH,"%s%s",tmp,(char*)(b+pi->commun_path_offset));
      }
      b = b + pi->struct_size;

    }else if ((p->data_flag & 0x04) == 0x04 || (p->data_flag & 0x08) == 0x08/* || (p->data_flag & 0x10) == 0x10*/)
    {
      //other
      if (!strlen(local_path) && !strlen(to) && b-buffer < taille_fic)
      {
        DWORD tmp_size;

      //pass datas no used

        //0x04 = have name/description first ?
        PLNK_WORD_STRUCT t = (PLNK_WORD_STRUCT)b;
        if ((p->data_flag & 0x04) == 0x04)
        {
          //0x08 = relative path
          if ((p->data_flag & 0x08) == 0x08)
          {
            if (unicode) b = b + t->struct_size*2 + 2;
            else b = b + t->struct_size + 2;
            t = b;

            if(b-buffer < taille_fic)
            {
              if (unicode) snprintf(to,MAX_PATH,"%S",b+2);
              else snprintf(to,MAX_PATH,"%s",(char*)(b+2));

              tmp_size = t->struct_size +b-buffer ;
              if (tmp_size < taille_fic && tmp_size < MAX_PATH) to[t->struct_size] = 0;

              if (unicode) b = b + t->struct_size*2 + 2;
              else b = b + t->struct_size + 2;
              t = b;

              //0x10 = workingdir
              if ((p->data_flag & 0x10) == 0x10 && b-buffer < taille_fic)
              {
                if (unicode) b = b + t->struct_size*2 + 2;
                else b = b + t->struct_size + 2;
                t = b;
              }

              //0x20 = arguments
              if ((p->data_flag & 0x20) == 0x20 && b-buffer < taille_fic)
              {
                if (unicode) snprintf(tmp,MAX_PATH," %S",b+2);
                else snprintf(tmp,MAX_PATH," %s",(char*)(b+2));

                tmp_size = t->struct_size +b-buffer;
                if (tmp_size < taille_fic && tmp_size+1 < MAX_PATH) tmp[t->struct_size+1] = 0;

                strncat(to,tmp,MAX_PATH);
                strncat(to,"\0",MAX_PATH);
              }
            }
          }else
          {
            if (unicode) snprintf(to,MAX_PATH,"%S",b+2);
            else snprintf(to,MAX_PATH,"%s",(char*)(b+2));

            tmp_size = t->struct_size +b-buffer ;
            if (tmp_size < taille_fic && tmp_size < MAX_PATH) to[t->struct_size] = 0;
          }
        }else
        {
          //0x08 = relative path
          if ((p->data_flag & 0x08) == 0x08 && b-buffer < taille_fic)
          {
            //if only we use it !!!
            if (unicode) snprintf(to,MAX_PATH,"%S",b+2);
            else snprintf(to,MAX_PATH,"%s",(char*)(b+2));

            tmp_size = t->struct_size +b-buffer ;
            if (tmp_size < taille_fic && tmp_size < MAX_PATH) to[t->struct_size] = 0;

            if (unicode) b = b + t->struct_size*2 + 2;
            else b = b + t->struct_size + 2;
            t = b;

            //0x10 = workingdir
            if ((p->data_flag & 0x10) == 0x10 && b-buffer < taille_fic)
            {
              if (unicode) b = b + t->struct_size*2 + 2;
              else b = b + t->struct_size + 2;
              t = b;
            }

            //0x20 = arguments
            if ((p->data_flag & 0x20) == 0x20 && b-buffer < taille_fic)
            {
              if (unicode) snprintf(tmp,MAX_PATH," %S",b+2);
              else snprintf(tmp,MAX_PATH," %s",(char*)(b+2));

              tmp_size = t->struct_size +b-buffer;
              if (tmp_size < taille_fic && tmp_size+1 < MAX_PATH) tmp[t->struct_size+1] = 0;

              strncat(to,tmp,MAX_PATH);
              strncat(to,"\0",MAX_PATH);
            }
          }else
          {
            //0x10 = workingdir
            if ((p->data_flag & 0x10) == 0x10 && b-buffer < taille_fic)
            {
              if (unicode) snprintf(to,MAX_PATH,"%S",b+2);
              else snprintf(to,MAX_PATH,"%s",(char*)(b+2));

              tmp_size = t->struct_size +b-buffer;
              if (tmp_size < taille_fic && tmp_size < MAX_PATH) to[t->struct_size] = 0;

              if (unicode) b = b + t->struct_size*2 + 2;
              else b = b + t->struct_size + 2;
              t = b;
            }

            //0x20 = arguments
            if ((p->data_flag & 0x20) == 0x20 && b-buffer < taille_fic)
            {
              if (unicode) snprintf(tmp,MAX_PATH," %S",b+2);
              else snprintf(tmp,MAX_PATH," %s",b+2);

              tmp_size = t->struct_size +b-buffer;
              if (tmp_size < taille_fic && tmp_size+1 < MAX_PATH) tmp[t->struct_size+1] = 0;

              strncat(to,tmp,MAX_PATH);
              strncat(to,"\0",MAX_PATH);
            }
          }
        }
      }
    }else if ((p->data_flag & 0x200) == 0x200 || p->data_flag == 0x80) // windows 8 format : ext_string
    {
      unsigned char *pos = b;
      PLNK_WORD_STRUCT t = (PLNK_WORD_STRUCT)b;

      if ((p->data_flag & 0x10) == 0x10)  //workingdir
      {
        if (unicode) pos = pos + t->struct_size*2 + 2;
        else pos = pos + t->struct_size + 2;
      }

      if (pos-buffer < taille_fic)
      {
        t = pos;
        if ((p->data_flag & 0x20) == 0x20)  //arguments
        {
          if (unicode) pos = pos + t->struct_size*2 + 2;
          else pos = pos + t->struct_size + 2;
        }

        if (pos-buffer < taille_fic)
        {
          t = pos;
          if ((p->data_flag & 0x40) == 0x40)  //iconlocation
          {
            if (unicode) pos = pos + t->struct_size*2 + 2;
            else pos = pos + t->struct_size + 2;
          }

          //pass first headers !!
          if (pos-buffer < taille_fic)
          {
            t = pos;
            if (pos-buffer+t->struct_size+8 < taille_fic)
            {
              snprintf(to,MAX_PATH,"%s",(char*)(pos+t->struct_size+8));
            }
          }
        }
      }
    }

    if (!strlen(local_path) && !strlen(to) && b-buffer < taille_fic)
    {
      if ((p->data_flag & 0x01) == 0x01)
      {
        //first struct
        unsigned char *pos = buffer + p->header_size + 2;
        if (pos-buffer < taille_fic)
        {
          PLNK_WORD_STRUCT t = pos;
          pos = pos + t->struct_size;

          //second struct
          if (pos-buffer+8 < taille_fic)
          {
            if (unicode)snprintf(to,MAX_PATH,"%S",pos+8);
            else snprintf(to,MAX_PATH,"%s",(char*)(pos+8));
          }
        }
      }
    }
  }
}
//------------------------------------------------------------------------------
//extraction des données de la valeur F du profil
DWORD TestUserDataFromSAM_F(USERS_INFOS *User_infos, char*buffer)
{
  User_infos->last_logon[0]            = 0;
  User_infos->last_password_change[0]  = 0;
  User_infos->nb_connexion             = 0;
  User_infos->state_id                 = 0;

  DWORD userRID = 0;

  if (strlen(buffer)>0x8F)
  {
    char tmp[MAX_PATH];

    //Offset 0008 : date de dernière connexion
    FILETIME FileTime;

    tmp[0] = buffer[0x16];
    tmp[1] = buffer[0x17];
    tmp[2] = buffer[0x14];
    tmp[3] = buffer[0x15];
    tmp[4] = buffer[0x12];
    tmp[5] = buffer[0x13];
    tmp[6] = buffer[0x10];
    tmp[7] = buffer[0x11];
    FileTime.dwLowDateTime = HTDF(tmp,8);

    tmp[0] = buffer[0x1E];
    tmp[1] = buffer[0x1F];
    tmp[2] = buffer[0x1C];
    tmp[3] = buffer[0x1D];
    tmp[4] = buffer[0x1A];
    tmp[5] = buffer[0x1B];
    tmp[6] = buffer[0x18];
    tmp[7] = buffer[0x19];
    FileTime.dwHighDateTime = HTDF(tmp,8);
    if ((FileTime.dwHighDateTime == 0) && (FileTime.dwLowDateTime == 0))strncpy(User_infos->last_logon,cps[TXT_MSG_NEVER].c,DATE_SIZE_MAX);
    else
    {
      filetimeToString_GMT(FileTime, User_infos->last_logon, DATE_SIZE_MAX);
      if (User_infos->last_logon[0] == 0)strncpy(User_infos->last_logon,cps[TXT_MSG_NEVER].c,DATE_SIZE_MAX);
    }

    //Last password change
    tmp[0] = buffer[0x36];
    tmp[1] = buffer[0x37];
    tmp[2] = buffer[0x34];
    tmp[3] = buffer[0x35];
    tmp[4] = buffer[0x32];
    tmp[5] = buffer[0x33];
    tmp[6] = buffer[0x30];
    tmp[7] = buffer[0x31];
    FileTime.dwLowDateTime = HTDF(tmp,8);

    tmp[0] = buffer[0x3E];
    tmp[1] = buffer[0x3F];
    tmp[2] = buffer[0x3C];
    tmp[3] = buffer[0x3D];
    tmp[4] = buffer[0x3A];
    tmp[5] = buffer[0x3B];
    tmp[6] = buffer[0x38];
    tmp[7] = buffer[0x39];
    FileTime.dwHighDateTime = HTDF(tmp,8);
    if ((FileTime.dwHighDateTime == 0) && (FileTime.dwLowDateTime == 0))strncpy(User_infos->last_password_change,cps[TXT_MSG_NEVER].c,DATE_SIZE_MAX);
    else
    {
      filetimeToString_GMT(FileTime, User_infos->last_password_change, DATE_SIZE_MAX);
      if (User_infos->last_password_change[0] == 0)strncpy(User_infos->last_password_change,cps[TXT_MSG_NEVER].c,DATE_SIZE_MAX);
    }

    //Offste 0038, second digit = State
    if (buffer[0x71]=='0')User_infos->state_id=301;
    else User_infos->state_id=300;

    //Password Expire
    if ((buffer[0x73]=='2')||(buffer[0x73]=='3')||(buffer[0x73]=='6')||(buffer[0x73]=='7')||(buffer[0x73]=='A')||(buffer[0x73]=='B')||(buffer[0x73]=='E')||(buffer[0x73]=='F'))
    {
      strncat(User_infos->last_password_change," (",MAX_PATH);
      strncat(User_infos->last_password_change,cps[TXT_MSG_MDP_NEVER_EXP].c,MAX_PATH);
      strncat(User_infos->last_password_change,")\0",MAX_PATH);
    }

    //nombre de connexion 0x42
    tmp[0] = buffer[0x86];
    tmp[1] = buffer[0x87];
    tmp[2] = buffer[0x84];
    tmp[3] = buffer[0x85];
    User_infos->nb_connexion = HTDF(tmp,4);

    //Offset 0030 : user RID
    tmp[0] = buffer[0x66];
    tmp[1] = buffer[0x67];
    tmp[2] = buffer[0x64];
    tmp[3] = buffer[0x65];
    tmp[4] = buffer[0x62];
    tmp[5] = buffer[0x63];
    tmp[6] = buffer[0x60];
    tmp[7] = buffer[0x61];
    userRID = HTDF(tmp,8);
  }

  return userRID;
}
//------------------------------------------------------------------------------
//local function part !!!
//------------------------------------------------------------------------------
void reg_read_enum_PathValues(HKEY hk,char *chkey,char *key,unsigned int session_id, sqlite3 *db)
{
  HKEY CleTmp;
  if (RegOpenKey(hk,key,&CleTmp)!=ERROR_SUCCESS)return;

  DWORD nbValue,i,j;
  FILETIME last_update;
  if (RegQueryInfoKey (CleTmp,0,0,0,0,0,0,&nbValue,0,0,0,&last_update)!=ERROR_SUCCESS)
  {
    RegCloseKey(CleTmp);
    return;
  }

  //get date
  char parent_key_update[DATE_SIZE_MAX] = "";
  filetimeToString_GMT(last_update, parent_key_update, DATE_SIZE_MAX);

  //read USER + RID + SID
  char user[MAX_PATH], RID[MAX_PATH], sid[MAX_PATH];
  GetRegistryKeyOwner(CleTmp, user, RID, sid, MAX_PATH);

  //enum values
  char value[MAX_PATH], data[MAX_PATH];
  DWORD valueSize,dataSize,type;
  for (i=0;i<nbValue && start_scan;i++)
  {
    valueSize = MAX_PATH;
    dataSize  = MAX_PATH;
    value[0]  = 0;
    type      = 0;
    if (RegEnumValue (CleTmp,i,(LPTSTR)value,(LPDWORD)&valueSize,0,(LPDWORD)&type,(LPBYTE)data,(LPDWORD)&dataSize)==ERROR_SUCCESS)
    {
      switch(type)
      {
        case REG_EXPAND_SZ:
        case REG_SZ:
          convertStringToSQL(value, MAX_PATH);
          convertStringToSQL(data, MAX_PATH);
          addRegistryPathtoDB("",chkey,key,value,data,user,RID,sid,parent_key_update,session_id,db);break;
        /*case REG_BINARY:
        case REG_LINK:
          {
            tmp[0] = 0;
            snprintf(tmp,MAX_PATH,"%S",data);
            convertStringToSQL(value, MAX_PATH);
            convertStringToSQL(tmp, MAX_PATH);
            addRegistryPathtoDB("",chkey,key,value,tmp,user,RID,sid,parent_key_update,session_id,db);
          }
        break;*/
        case REG_MULTI_SZ:
          for (j=0;j<dataSize;j++)
          {
            if (data[j] == 0)data[j]=';';
          }
          convertStringToSQL(value, MAX_PATH);
          convertStringToSQL(data, MAX_PATH);
          addRegistryPathtoDB("",chkey,key,value,data,user,RID,sid,parent_key_update,session_id,db);
        break;
      }
    }
  }
  RegCloseKey(CleTmp);
}
//------------------------------------------------------------------------------
void ReadDatas(unsigned int type, HKEY hk, char *chk, char *key_path, char *value, char*description_id, unsigned int session_id, sqlite3 *db)
{
  switch(type)//value_type
  {
    //list of all string in a directory and exclude "value"
    case TYPE_ENUM_STRING_VALUE:reg_read_enum_MRUvalues(hk, chk,key_path,value,description_id, session_id, db);break;
    case TYPE_ENUM_STRING_NVALUE:reg_read_enum_MRUNvalues(hk, chk,key_path,value,description_id, session_id, db);break;
    case TYPE_ENUM_STRING_WVALUE:reg_read_enum_MRUWvalues(hk, chk,key_path,value,description_id, session_id, db);break;

    case TYPE_ENUM_SUBNK_DATE:
    {
      //read all subkey
      HKEY CleTmp, CleTmp2;
      if (RegOpenKey(hk,key_path,&CleTmp)!=ERROR_SUCCESS)return;

      //enum keys
      DWORD nbSubKey=0,i;
      if (RegQueryInfoKey (CleTmp,NULL,NULL,NULL,&nbSubKey,NULL,NULL,NULL,NULL,NULL,NULL,NULL)!=ERROR_SUCCESS)
      {
        RegCloseKey(CleTmp);
        return;
      }

      char key[MAX_PATH], tmp_key[MAX_PATH], lastupdate[DATE_SIZE_MAX] ="";
      DWORD key_size;
      FILETIME LastWriteTime;
      char user[MAX_PATH], RID[MAX_PATH], sid[MAX_PATH];

      for (i=0;i<nbSubKey && start_scan;i++)
      {
        key[0]    = 0;
        key_size  = MAX_PATH;
        if (RegEnumKeyEx (CleTmp,i,key,(LPDWORD)&key_size,NULL,NULL,NULL,&LastWriteTime)==ERROR_SUCCESS)
        {
          snprintf(tmp_key,MAX_PATH,"%s\\%s",key_path,key);
          if (RegOpenKey(hk,tmp_key,&CleTmp2)==ERROR_SUCCESS)
          {
            user[0] = 0;
            RID[0]  = 0;
            sid[0]  = 0;
            GetRegistryKeyOwner(CleTmp2, user, RID, sid, MAX_PATH);

            filetimeToString_GMT(LastWriteTime, lastupdate, DATE_SIZE_MAX);
            addRegistryMRUtoDB("",chk,tmp_key,"","",description_id,user,RID,sid,lastupdate,session_id,db);
            RegCloseKey(CleTmp2);
          }
        }
      }
      RegCloseKey(CleTmp);
    }
    break;

    case TYPE_DBL_ENUM_VALUE:
    {
      //read all subkey
      HKEY CleTmp, CleTmp2, CleTmp3;
      if (RegOpenKey(hk,key_path,&CleTmp)!=ERROR_SUCCESS)return;

      //enum keys
      DWORD nbSubKey=0, nbSubKey2,i,j;
      if (RegQueryInfoKey (CleTmp,NULL,NULL,NULL,&nbSubKey,NULL,NULL,NULL,NULL,NULL,NULL,NULL)!=ERROR_SUCCESS)
      {
        RegCloseKey(CleTmp);
        return;
      }

      char key[MAX_PATH], key2[MAX_PATH], tmp_key[MAX_PATH], tmp_key2[MAX_PATH], lastupdate[DATE_SIZE_MAX] ="";
      DWORD key_size,key_size2;
      FILETIME LastWriteTime;
      char user[MAX_PATH], RID[MAX_PATH], sid[MAX_PATH], data[MAX_PATH];

      for (i=0;i<nbSubKey && start_scan;i++)
      {
        key[0]    = 0;
        key_size  = MAX_PATH;
        if (RegEnumKeyEx (CleTmp,i,key,(LPDWORD)&key_size,NULL,NULL,NULL,NULL)==ERROR_SUCCESS)
        {
          snprintf(tmp_key,MAX_PATH,"%s\\%s\\AVGeneral\\cRecentFiles",key_path,key);
          if (RegOpenKey(hk,tmp_key,&CleTmp2)==ERROR_SUCCESS)
          {
            nbSubKey2 = 0;
            if (RegQueryInfoKey (CleTmp2,NULL,NULL,NULL,&nbSubKey2,NULL,NULL,NULL,NULL,NULL,NULL,NULL)!=ERROR_SUCCESS)
            {
              RegCloseKey(CleTmp2);
              continue;
            }

            for (j=0;j<nbSubKey2 && start_scan;j++)
            {
              key2[0]    = 0;
              key_size2  = MAX_PATH;
              if (RegEnumKeyEx (CleTmp2,j,key2,(LPDWORD)&key_size2,NULL,NULL,NULL,&LastWriteTime)==ERROR_SUCCESS)
              {
                snprintf(tmp_key2,MAX_PATH,"%s\\%s",tmp_key,key2);
                if (RegOpenKey(hk,tmp_key2,&CleTmp3)==ERROR_SUCCESS)
                {
                  user[0] = 0;
                  RID[0]  = 0;
                  sid[0]  = 0;
                  data[0] = 0;
                  GetRegistryKeyOwner(CleTmp3, user, RID, sid, MAX_PATH);
                  filetimeToString_GMT(LastWriteTime, lastupdate, DATE_SIZE_MAX);

                  if(ReadValue(hk,tmp_key2,value,data, MAX_PATH))
                  {
                    convertStringToSQL(data, MAX_PATH);
                    addRegistryMRUtoDB("",chk,tmp_key2,value,data,description_id,user,RID,sid,lastupdate,session_id,db);
                  }
                  RegCloseKey(CleTmp3);
                }
              }
            }
            RegCloseKey(CleTmp2);
          }
        }
      }
      RegCloseKey(CleTmp);
    }
    break;

    //all string under one key
    case TYPE_ENUM_STRING_RVALUE:
    {
      //read all subkey
      HKEY CleTmp;
      if (RegOpenKey(hk,key_path,&CleTmp)!=ERROR_SUCCESS)return;

      DWORD nbSubKey=0,i;
      if (RegQueryInfoKey (CleTmp,NULL,NULL,NULL,&nbSubKey,NULL,NULL,NULL,NULL,NULL,NULL,NULL)!=ERROR_SUCCESS)
      {
        RegCloseKey(CleTmp);
        return;
      }

      char key[MAX_PATH], tmp_key[MAX_PATH];
      DWORD key_size;
      for (i=0;i<nbSubKey && start_scan;i++)
      {
        key[0]    = 0;
        key_size  = MAX_PATH;
        if (RegEnumKeyEx (CleTmp,i,key,(LPDWORD)&key_size,NULL,NULL,NULL,NULL)==ERROR_SUCCESS)
        {
          snprintf(tmp_key,MAX_PATH,"%s\\%s",key_path,key);
          reg_read_enum_MRUvalues(hk,chk,tmp_key,value,description_id, session_id, db_scan);
        }
      }
      RegCloseKey(CleTmp);

    }break;

    //all string under thow key + key
    case TYPE_ENUM_STRING_RRVALUE:
    {
      //read all subkey
      HKEY CleTmp,CleTmp2;
      if (RegOpenKey(hk,key_path,&CleTmp)!=ERROR_SUCCESS)return;

      DWORD nbSubKey=0,nbSubKey2,i,j;
      if (RegQueryInfoKey (CleTmp,NULL,NULL,NULL,&nbSubKey,NULL,NULL,NULL,NULL,NULL,NULL,NULL)!=ERROR_SUCCESS)
      {
        RegCloseKey(CleTmp);
        return;
      }

      char key[MAX_PATH], tmp_key[MAX_PATH],key2[MAX_PATH], tmp_key2[MAX_PATH];
      DWORD key_size,key_size2;
      for (i=0;i<nbSubKey && start_scan;i++)
      {
        key[0]    = 0;
        key_size  = MAX_PATH;
        if (RegEnumKeyEx (CleTmp,i,key,(LPDWORD)&key_size,NULL,NULL,NULL,NULL)==ERROR_SUCCESS)
        {
          snprintf(tmp_key,MAX_PATH,"%s\\%s",key_path,key);

          //second key !!!
          if (RegOpenKey(hk,tmp_key,&CleTmp2)!=ERROR_SUCCESS)continue;

          nbSubKey2 = 0;
          if (RegQueryInfoKey (CleTmp2,NULL,NULL,NULL,&nbSubKey2,NULL,NULL,NULL,NULL,NULL,NULL,NULL)!=ERROR_SUCCESS)
          {
            RegCloseKey(CleTmp2);
            continue;
          }

          for (j=0;j<nbSubKey2 && start_scan;j++)
          {
            key2[0]    = 0;
            key_size2  = MAX_PATH;
            if (RegEnumKeyEx (CleTmp2,j,key2,(LPDWORD)&key_size2,NULL,NULL,NULL,NULL)==ERROR_SUCCESS)
            {
              snprintf(tmp_key2,MAX_PATH,"%s\\%s\\%s",tmp_key,key2,value);
              reg_read_enum_MRUvalues(hk,chk,tmp_key2,"",description_id, session_id, db_scan);
            }
          }
          RegCloseKey(CleTmp2);
        }
      }
      RegCloseKey(CleTmp);

    }break;

    //all string under one key + key
    case TYPE_ENUM_STRING_R_VALUE:
    {
      //read all subkey
      HKEY CleTmp;
      if (RegOpenKey(hk,key_path,&CleTmp)!=ERROR_SUCCESS)return;

      DWORD nbSubKey=0,i;
      if (RegQueryInfoKey (CleTmp,NULL,NULL,NULL,&nbSubKey,NULL,NULL,NULL,NULL,NULL,NULL,NULL)!=ERROR_SUCCESS)
      {
        RegCloseKey(CleTmp);
        return;
      }

      char key[MAX_PATH], tmp_key[MAX_PATH];
      DWORD key_size;
      for (i=0;i<nbSubKey && start_scan;i++)
      {
        key[0]    = 0;
        key_size  = MAX_PATH;
        if (RegEnumKeyEx (CleTmp,i,key,(LPDWORD)&key_size,NULL,NULL,NULL,NULL)==ERROR_SUCCESS)
        {
          snprintf(tmp_key,MAX_PATH,"%s\\%s\\%s",key_path,key,value);
          reg_read_enum_MRUvalues(hk,chk,tmp_key,"",description_id, session_id, db_scan);
        }
      }
      RegCloseKey(CleTmp);
    }break;

    //only one value
    case TYPE_VALUE_STRING:
    {
      char data[MAX_PATH];
      if (ReadValue(hk,key_path,value,data, MAX_PATH))
      {
        HKEY CleTmp;
        if (RegOpenKey(hk,key_path,&CleTmp)==ERROR_SUCCESS)
        {
          char user[MAX_PATH]="", RID[MAX_PATH]="", SID[MAX_PATH]="";
          GetRegistryKeyOwner(CleTmp, user, RID, SID, MAX_PATH);
          RegCloseKey(CleTmp);

          char parent_key_update[DATE_SIZE_MAX]="";
          ReadKeyUpdate(hk,key_path, parent_key_update, DATE_SIZE_MAX);

          convertStringToSQL(data, MAX_PATH);
          addRegistryMRUtoDB("",chk,key_path,value,data,description_id,user,RID,SID,parent_key_update,session_id,db_scan);
        }
      }
    }break;
    //only one value
    case TYPE_VALUE_WSTRING:
    {
      char data[MAX_PATH],tmp[MAX_PATH];
      if (ReadValue(hk,key_path,value,tmp, MAX_PATH))
      {
        HKEY CleTmp;
        if (RegOpenKey(hk,key_path,&CleTmp)==ERROR_SUCCESS)
        {
          snprintf(data,MAX_PATH,"%S",tmp);

          char user[MAX_PATH]="", RID[MAX_PATH]="", SID[MAX_PATH]="";
          GetRegistryKeyOwner(CleTmp, user, RID, SID, MAX_PATH);
          RegCloseKey(CleTmp);

          char parent_key_update[DATE_SIZE_MAX]="";
          ReadKeyUpdate(hk,key_path, parent_key_update, DATE_SIZE_MAX);

          convertStringToSQL(data, MAX_PATH);
          addRegistryMRUtoDB("",chk,key_path,value,data,description_id,user,RID,SID,parent_key_update,session_id,db_scan);
        }
      }
    }break;
  }
}
Example #10
0
//------------------------------------------------------------------------------
DWORD WINAPI Scan_dns(LPVOID lParam)
{
  unsigned int local_id = (unsigned int)lParam;

  //check if local or not :)
  if (!LOCAL_SCAN || WINE_OS)
  {
    h_thread_test[local_id] = 0;
    check_treeview(htrv_test, H_tests[local_id], TRV_STATE_UNCHECK);//db_scan
    return 0;
  }

  //init
  if(!SQLITE_FULL_SPEED)sqlite3_exec(db_scan,"BEGIN TRANSACTION;", NULL, NULL, NULL);
  sqlite3 *db = (sqlite3 *)db_scan;
  unsigned int session_id = current_session_id;

  //make file directory
  char file[MAX_PATH]="";
  char ip[IPV6_SIZE_MAX],name[MAX_PATH];
  snprintf(file,MAX_PATH,"%s\\WINDOWS\\system32\\drivers\\etc\\hosts",getenv("SYSTEMDRIVE"));

  #ifdef CMD_LINE_ONLY_NO_DB
  printf("\"DNS\";\"file\";\"ip\";\"name\";\"last_file_update\";\"malware_check\";\"session_id\";\r\n");
  #endif // CMD_LINE_ONLY_NO_DB

  //open host file and read all hosts
  HANDLE Hfic = CreateFile(file,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,0);
  if (Hfic != INVALID_HANDLE_VALUE)
  {
    DWORD taille_fic = GetFileSize(Hfic,NULL);
    if (taille_fic != INVALID_FILE_SIZE)
    {
      char *buffer = (char *) HeapAlloc(GetProcessHeap(), 0, taille_fic+1);
      if (buffer != NULL)
      {
        //get last update
        char last_file_update[DATE_SIZE_MAX]="";
        FILETIME LastWriteTime;
        if(GetFileTime(Hfic,NULL,NULL,&LastWriteTime))filetimeToString_GMT(LastWriteTime, last_file_update, DATE_SIZE_MAX);

        //read data line by line
        DWORD copiee;
        char lines[MAX_PATH];
        if (ReadFile(Hfic, buffer, taille_fic,&copiee,0))
        {
          char *r = buffer;
          char *s,*c;
          while (*r)
          {
            //read line
            memset(lines,0,MAX_PATH);
            strncpy(lines,r,MAX_PATH);
            s = lines;
            while (*s && *s != '\r')s++;
            *s = 0;
            r = r+strlen(lines)+2;

            //comment or not :)
            if (lines[0]!='#' && strlen(lines) > 8)
            {
              //get IP
              strncpy(ip,lines,IPV6_SIZE_MAX);
              c = ip;

              while (*c && *c != ' ' && *c!= '\t' && (*c == '.' || *c == ':' || (*c<='9' && *c>='0')))c++;
              if (*c)
              {
                *c = 0;
                //get name
                c = lines+strlen(ip);
                while (*c && (*c == ' ' || *c == '\t'))c++;

                memset(name,0,MAX_PATH);
                strncpy(name,c,MAX_PATH);
                addHosttoDB(file, ip, name, last_file_update,session_id,db);
              }
            }
          }
        }
        HeapFree(GetProcessHeap(), 0, buffer);
      }
    }
    CloseHandle(Hfic);
  }

  //get cache
  HMODULE hDLL = LoadLibrary( "DNSAPI.DLL" );
  if (!hDLL) return 0;

  //function
  //typedef int(*DNS_GET_CACHE_DATA_TABLE)(PDNS_RECORD*);
  typedef int(WINAPI *DNS_GET_CACHE_DATA_TABLE)(PDNS_RECORD);
  DNS_GET_CACHE_DATA_TABLE DnsGetCacheDataTable = (DNS_GET_CACHE_DATA_TABLE)GetProcAddress(hDLL,"DnsGetCacheDataTable");

  if (DnsGetCacheDataTable != NULL)
  {
    PDNS_RECORD pcache = NULL;
    DNS_RECORD* dnsRecords = NULL, *dnsr;
    IN_ADDR ipAddress;
    char last_file_update[DATE_SIZE_MAX]="";

    if (DnsGetCacheDataTable(&pcache) == TRUE)
    {
      PDNS_RECORD cache = pcache;
      while (cache)
      {
        memset(name,0,MAX_PATH);
        snprintf(name,MAX_PATH,"%S",cache->pName);
        if (name[0] != 0)
        {
          //get IP + TTL
          if(DnsQuery(name,DNS_TYPE_A,0,NULL,&dnsRecords,NULL) == ERROR_SUCCESS)
          {
            dnsr = dnsRecords;
            while (dnsr != NULL)
            {
              ipAddress.S_un.S_addr = dnsr->Data.A.IpAddress;
              if (inet_ntoa(ipAddress) != NULL)
              {
                snprintf(ip,IP_SIZE_MAX,"%s",inet_ntoa(ipAddress));
                snprintf(last_file_update,DATE_SIZE_MAX,"%lu (s)",dnsr->dwTtl);
                addHosttoDB("", ip, name, last_file_update,session_id,db);
              }
              dnsr = dnsr->pNext;
            }
            //free
            DnsRecordListFree(dnsRecords,DnsFreeRecordList);
          }
        }
        cache = cache->pNext;
      }
    }
  }
  FreeLibrary(hDLL);

  if(!SQLITE_FULL_SPEED)sqlite3_exec(db_scan,"END TRANSACTION;", NULL, NULL, NULL);
  check_treeview(htrv_test, H_tests[local_id], TRV_STATE_UNCHECK);//db_scan
  h_thread_test[local_id] = 0;
  return 0;
}
//------------------------------------------------------------------------------
DWORD Traiter_RegBin_nk_deleted(char *fic, DWORD position, DWORD taille_fic, char *buffer, unsigned int session_id, sqlite3 *db, BOOL deleted)
{
  if (position + HBIN_CELL_NK_SIZE > taille_fic)return 1;
    HBIN_CELL_NK_HEADER *nk_h = (HBIN_CELL_NK_HEADER *)(buffer+position);
  //valide ?
  if (nk_h->key_name_size >0 && nk_h->key_name_size<taille_fic && nk_h->size>0 && (position-HBIN_CELL_NK_SIZE)&& nk_h->type == 0x6B6E)
  {
    if (nk_h->nb_values > 0 && nk_h->nb_values < 0xFFFFFFFF && nk_h->val_ls_offset < 0xFFFFFFFF && nk_h->val_ls_offset > 0)
    {
      if (!deleted) return HBIN_CELL_NK_SIZE;

      char path[MAX_LINE_SIZE]="";
      char value[MAX_LINE_SIZE];
      char data[MAX_LINE_SIZE];
      char type[MAX_LINE_SIZE];
      char parent_key_update[DATE_SIZE_MAX];
      char Owner_SID[MAX_PATH]="";

      //lecture du path complet + SID ^^
      ReadPath(buffer, taille_fic, position, path,MAX_LINE_SIZE,NULL,Owner_SID,MAX_PATH);

      //lecture des valeures ^^
      DWORD i, k;
      S_ITEM_LS *item_ls;
      HBIN_CELL_VK_HEADER *vk_h;
      char tmp[MAX_LINE_SIZE];
      char *c;

      //last update
      parent_key_update[0]=0;
      if (nk_h->last_write.dwHighDateTime != 0 || nk_h->last_write.dwLowDateTime != 0)
      {
        filetimeToString_GMT(nk_h->last_write, parent_key_update, DATE_SIZE_MAX);
        if (parent_key_update[0] != '2' && deleted) //bad date
          parent_key_update[0]=0;
      }

      BOOL val_ok;
      for (i=0;i< (nk_h->nb_values);i++)
      {
        value[0] = 0;
        type[0] = 0;
        if (nk_h->val_ls_offset+0x1000+i*HBIN_CELL_ITEM_LS+4 >= taille_fic)break;
        item_ls = (S_ITEM_LS *)&buffer[nk_h->val_ls_offset+0x1000+i*HBIN_CELL_ITEM_LS+4];
        //lecture de l'offset de la valeure :
        if (item_ls->val_of>0 && (item_ls->val_of+0x1000+HBIN_CELL_VK_SIZE)<taille_fic)
        {
          //traitement des valeures !!!
          val_ok = TRUE;
          vk_h = (HBIN_CELL_VK_HEADER *)&buffer[item_ls->val_of+0x1000];

          //récupération du nom de la valeur :
          strncpy(value,vk_h->value,MAX_LINE_SIZE);
          if (vk_h->name_size>=MAX_LINE_SIZE)value[MAX_LINE_SIZE-1]=0;
          else
          {
            value[vk_h->name_size]=0;
            if (strlen(value) != vk_h->name_size)val_ok = FALSE;
          }

          data[0] = 0;
          switch(vk_h->data_type)
          {
            //Chaines
            case 0x00000001 : //REG_SZ, chaine ASCII et Unicodes
              if (vk_h->data_size < 0xFFFFFFFF && vk_h->data_offset > 0 && vk_h->data_offset < taille_fic)
              {
                if (vk_h->data_size < 5)
                {
                  snprintf(data,MAX_LINE_SIZE,"%S",vk_h->cdata_offset);
                  data[vk_h->data_size/2]=0;
                }else snprintf(data,MAX_LINE_SIZE,"%S",(wchar_t *)&buffer[0x1000+vk_h->data_offset+HBIN_CELL_VK_DATA_PADDING_SIZE]);
              }
              strcpy(type,"REG_SZ\0");
            break;
            case 0x00000002 : //REG_EXPAND_SZ, chaine ASCII et Unicodes, contient des path type %path%
              data[0] = 0;
              if (vk_h->data_size < 0xFFFFFFFF && vk_h->data_offset > 0 && vk_h->data_offset < taille_fic)
              {
                if (vk_h->data_size < 5)
                {
                  strcpy(data,vk_h->cdata_offset);
                  data[4]=0;
                }else snprintf(data,MAX_LINE_SIZE,"%S",(wchar_t *)&buffer[0x1000+vk_h->data_offset+HBIN_CELL_VK_DATA_PADDING_SIZE]);
              }
              strcpy(type,"REG_EXPAND_SZ\0");
            break;
            case 0x00000006 : //REG_LINK, chaine ASCII et Unicodes, lien lien
              if (vk_h->data_size < 0xFFFFFFFF && vk_h->data_offset > 0 && vk_h->data_offset < taille_fic)
              {
                if (vk_h->data_size < 5)
                {
                  strcpy(data,vk_h->cdata_offset);
                  data[4]=0;
                }else snprintf(data,MAX_LINE_SIZE,"%S",(wchar_t *)&buffer[0x1000+vk_h->data_offset+HBIN_CELL_VK_DATA_PADDING_SIZE]);
              }
              strcpy(type,"REG_LINK\0");
            break;
            case 0x00000007 : //REG_MULTI_SZ, multiples chaine ASCII et Unicodes, lien
                if (vk_h->data_size < 0xFFFFFFFF && vk_h->data_offset > 0 && vk_h->data_offset < taille_fic)
                {
                  if (vk_h->data_size < 5)
                  {
                    strcpy(data,vk_h->cdata_offset);
                    data[4]=0;
                  }else
                  {
                    //traitement des chaines multiples :
                    do
                    {
                      snprintf(tmp,MAX_LINE_SIZE,"%S",(wchar_t *)&buffer[0x1000+vk_h->data_offset+HBIN_CELL_VK_DATA_PADDING_SIZE+2*strlen(data)]);
                      strncat (data,tmp,MAX_LINE_SIZE);
                      strncat (data," \0",MAX_LINE_SIZE);
                    }while (strlen(data)*2 < (vk_h->data_size));
                  }
                }
                strcpy(type,"REG_MULTI_SZ\0");
              break;
              case 0x00000003 : //REG_BINARY, données binaires
                if (vk_h->data_size < 0xFFFFFFFF && vk_h->data_offset > 0 && vk_h->data_offset < taille_fic)
                {
                  if (vk_h->data_size < 5)
                  {
                    for (k=0;k<vk_h->data_size && k/2<MAX_LINE_SIZE;k++)
                    {
                      snprintf(tmp,10,"%02X",vk_h->cdata_offset[k]&0xff);
                      strncat(data,tmp,MAX_LINE_SIZE);
                    }
                    strncat(data,"\0",MAX_LINE_SIZE);
                  }else
                  {
                    for (k=0;k<vk_h->data_size && k/2<MAX_LINE_SIZE;k++)
                    {
                      snprintf(tmp,10,"%02X",buffer[0x1000+vk_h->data_offset+HBIN_CELL_VK_DATA_PADDING_SIZE+k]&0xff);
                      strncat(data,tmp,MAX_LINE_SIZE);
                    }
                    strncat(data,"\0",MAX_LINE_SIZE);
                  }
                }
                strcpy(type,"REG_BINARY\0");
              break;
              case 0x0000000A : //REG_RESSOURCE_REQUIREMENT_LIST, données binaires
                if (vk_h->data_size < 0xFFFFFFFF && vk_h->data_offset > 0 && vk_h->data_offset < taille_fic)
                {
                  if (vk_h->data_size < 5)
                  {
                    for (k=0;k<vk_h->data_size && k/2<MAX_LINE_SIZE;k++)
                    {
                      snprintf(tmp,10,"%02X",vk_h->cdata_offset[k]&0xff);
                      strncat(data,tmp,MAX_LINE_SIZE);
                    }
                    strncat(data,"\0",MAX_LINE_SIZE);
                  }else
                  {
                    for (k=0;k<vk_h->data_size && k/2<MAX_LINE_SIZE;k++)
                    {
                      snprintf(tmp,10,"%02X",buffer[0x1000+vk_h->data_offset+HBIN_CELL_VK_DATA_PADDING_SIZE+k]&0xff);
                      strncat(data,tmp,MAX_LINE_SIZE);
                    }
                    strncat(data,"\0",MAX_LINE_SIZE);
                  }
                }
                strcpy(type,"REG_RESSOURCE_REQUIREMENT_LIST\0");
              break;
              case 0x00000004 : //REG_DWORD, données numériques 32bitschar
              case 0x00000005 : //REG_DWORD, données numériques 32bits signées
                if (vk_h->data_size > 0)
                {
                  snprintf(data,MAX_LINE_SIZE,"%08X",(unsigned int)(vk_h->data_offset&0xFFFFFFFF)); // en dword offset = valeur
                }
                strcpy(type,"REG_DWORD\0");
              break;
              case 0x0000000b : //REG_QWORD, données numériques 64bits signées
                if (vk_h->data_offset > 0 && vk_h->data_offset < taille_fic)
                {
                  c = &buffer[0x1000+vk_h->data_offset+HBIN_CELL_VK_DATA_PADDING_SIZE];
                  snprintf(data,MAX_LINE_SIZE,"0x%02X%02X%02X%02X%02X%02X%02X%02X",c[7]&0xff,c[6]&0xff,c[5]&0xff,c[4]&0xff,c[3]&0xff,c[2]&0xff,c[1]&0xff,c[0]&0xff);
                }
                strcpy(type,"REG_QWORD\0");
              break;
              default :
                if (deleted)val_ok = FALSE;
                //on ajoute pas au liste view les éléments inconnus non valides
                if (vk_h->data_size < 0xFFFFFFFF && vk_h->data_offset > 0 && vk_h->data_offset < taille_fic)
                {
                  /*for (k=0;k<vk_h->data_size && k/2<MAX_LINE_SIZE;k++)
                  {
                    snprintf(tmp,10,"%02X",buffer[0x1000+vk_h->data_offset+HBIN_CELL_VK_DATA_PADDING_SIZE+k]&0xff);
                    strncat(data,tmp,MAX_LINE_SIZE);
                  }
                  strncat(data,"\0",MAX_LINE_SIZE);*/

                  if (vk_h->data_type == 0x00000000)strcpy(type,"REG_NONE\0");
                  else val_ok = FALSE;
                }else
                {
                  if (vk_h->data_type == 0x00000000)strcpy(type,"REG_NONE\0");
                  else val_ok = FALSE;
                }
              break;
          }

          if (val_ok && strlen(value) || strlen(data))
          {
            //ajout de l'item
            addDeletedKey(fic, path, value, data, type,Owner_SID, parent_key_update,session_id, db);
          }
        }else break;
      }

      //no value : only directory
      if ((nk_h->nb_values < 1 || nk_h->nb_values == 0xFFFFFFFF) && (nk_h->nb_subkeys < 1 || nk_h->nb_subkeys == 0xFFFFFFFF))
      {
        addDeletedKey(fic, path, "", "", "", Owner_SID, parent_key_update,session_id, db);
      }
    }
    return HBIN_CELL_NK_SIZE;
  }
  return 1;
}
//------------------------------------------------------------------------------
//local function part !!!
//------------------------------------------------------------------------------
void Scan_registry_service_local(char *ckey, sqlite3 *db, unsigned int session_id)
{
  HKEY CleTmp;
  if (RegOpenKey(HKEY_LOCAL_MACHINE,ckey,&CleTmp)==ERROR_SUCCESS)
  {
    DWORD i,nbSubKey = 0;
    if (RegQueryInfoKey (CleTmp,0,0,0,&nbSubKey,0,0,0,0,0,0,0)==ERROR_SUCCESS)
    {
      FILETIME LastWriteTime;
      char key[MAX_PATH],key_path[MAX_PATH];
      DWORD key_size;
      DWORD state_id,type_id;
      char lastupdate[DATE_SIZE_MAX],
      name[MAX_PATH],path[MAX_PATH],description[MAX_PATH];

      for (i=0;i<nbSubKey && start_scan;i++)
      {
        key_size  = MAX_PATH;
        key[0]    = 0;
        if (RegEnumKeyEx (CleTmp,i,key,&key_size,0,0,0,&LastWriteTime)==ERROR_SUCCESS)
        {
          //path
          snprintf(key_path,MAX_PATH,"%s%s",ckey,key);

          //read values
          name[0]       = 0;
          path[0]       = 0;
          description[0]= 0;
          lastupdate[0] = 0;

          //name
          if (ReadValue(HKEY_LOCAL_MACHINE,key_path,"DisplayName",name, MAX_PATH) == 0)
          {
            if (ReadValue(HKEY_LOCAL_MACHINE,key_path,"Group",name, MAX_PATH) == 0)continue;

            strncpy(name,key,MAX_PATH);
          }

          //state id
          state_id = ReadDwordValue(HKEY_LOCAL_MACHINE,key_path,"Start");
          switch(state_id)
          {
            case 0: state_id=210;break;//Kernel module   : 210
            case 1: state_id=211;break;//Start by system : 211
            case 2: state_id=212;break;//Automatic start : 212
            case 3: state_id=213;break;//Manual start    : 213
            case 4: state_id=214;break;//Disable         : 214
            default:state_id=215;break;//Unknow          : 215
          }

          //path : ImagePath
          ReadValue(HKEY_LOCAL_MACHINE,key_path,"ImagePath",path, MAX_PATH);

          //description : Description
          if(ReadValue(HKEY_LOCAL_MACHINE,key_path,"Description",description, MAX_PATH) == 0)
            ReadValue(HKEY_LOCAL_MACHINE,key_path,"Group",description, MAX_PATH);

          //type_id
          type_id = ReadDwordValue(HKEY_LOCAL_MACHINE,key_path,"Type");
          if (type_id == 1)type_id = 200; //SERVICE : 200
          else type_id = 201;             //DRIVER  : 201

          //last update
          filetimeToString_GMT(LastWriteTime, lastupdate, DATE_SIZE_MAX);

          convertStringToSQL(path, MAX_PATH);
          convertStringToSQL(description, MAX_PATH);

          addRegistryServicetoDB("", "HKEY_LOCAL_MACHINE", key_path, name,
                                  state_id, path, description, type_id,
                                  lastupdate, session_id, db);
        }
      }
    }
    RegCloseKey(CleTmp);
  }
}