Annonce

Réduire
Aucune annonce.

Malware development/analysis : conversion de contenu répertoire en fichier ISO.

Réduire
X
 
  • Filtre
  • Heure
  • Afficher
Tout nettoyer
nouveaux messages

  • Tutoriel Malware development/analysis : conversion de contenu répertoire en fichier ISO.

    Ce code permet de convertir le répertoire désigné (et donc tout son contenu) en fichier image ISO compressé et directement utilisable en mounting.

    Les malwares les plus avancés (types engineers) utilisent ce processus pour la simple et bonne raison qu'il n'est nullement contrôlé, ni par le système d'exploitation ni par les systèmes de sécurité opérationnelle. Le fait de transférer (de la machine infectée au master server) un unique fichier compressé plutôt que plusieurs petits fichiers à la suite réduit le nombre de trames TCP émises et, in extenso, réduit l'activité du contrôle ICMP ; chose qui permet généralement de tromper la vigilance des IDS/IPS lorsque ceux-ci ne sont pas configurés en haute sensibilité.

    La rapidité de la conversion dépend de la taille du répertoire, mais ce code est optimisé (réduction des descripteurs de contrôle de validité), donc relativement rapide ; lors du transfert vers l'extérieur (stealing), l'encapsulation prend en contre-partie un certain temps afin que TCP vérifie l'intégrité des offset d'en-tête, mais une fois terminée, l'opération est relativement rapide.

    En extrapôlant, et afin d'optimiser le spreading du malware, ce-dernier pourrait se dupliquer dans le répertoire désigné, et ensuite lancer l'opération de conversion en ISO, il serait donc intégré à l'image disque et pourrait infecter n'importe quelle machine par l'intermédiaire du lecteur sur laquelle l'image serait ensuite montée ; les antivirus ne vérifiant pas la décompression et l'exécution des ISO, c'est extrêmement efficace.
    A titre d'exemple, ce module est embarqué par des malware type Flame ou Stuxnet dont le but, en plus de détourner les systèmes SCADA iraniens, était de voler tous les fichiers techniques concernant les installations nucléaires ciblées, répertoires faisant très souvent plusieurs gigaoctets et passant donc très bien en ISO.

    NB : j'ai essayé de commenter au maximum.


    -----------------------------------------------------------------------



    Code:
    void Folder2Iso(LPCTSTR lpszDir, LPCTSTR lpszIso, LPCTSTR lpVolumeName, LPCTSTR lpPublisher,
    const SYSTEMTIME* creationTime, BOOL bJoliet, BOOL* bStop,
    PPROGRESS_ROUTINE pProgressRoutine)
    {
    HANDLE hThread;
    BYTE OneSector[SECTOR_SIZE]; // création d'une dimension virtuelle
    DWORD d;
    list<Folder*>::const_iterator i;
    PROGRESS_STRUCT ps; // contrôleur de conversion
    
    ps.bFinished = FALSE;
    ps.progressRoutine = pProgressRoutine;
    
    HANDLE hIsoFile = CreateFile(lpszIso, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0); // création d'un objet 'file' destiné à recevoir l'ISO
    
    ZeroMemory(OneSector, sizeof OneSector); // attribution d'une zone mémoire liée à la dimension virtuelle
    
    int currentSector = bJoliet ? 20 : 19; // secteur désigné dans l'arbre itératif
    
    for(int j = 0; j < currentSector; j++)
    WriteFile(hIsoFile, OneSector, sizeof OneSector, &d, 0); // procédure d'écriture de l'ISO
    
    TCHAR szDir[MAX_PATH];
    LPTSTR lpEnd = bnstrcpy(szDir, lpszDir); // EOF
    LPTSTR lpIdent = lpEnd - 1;
    
    list<Folder*> dirList; // arbre contenant les différents secteurs
    
    Folder root(0, dirList, szDir, lpIdent, lpEnd, 0, bJoliet); // racine d'indexation
    root.SetNumber(1); // premier index selectionné
    
    if(*bStop)
    goto closeFile;
    
    root.SetExtent(&currentSector, bJoliet);
    
    int extent = 0;
    ps.bFinished = FALSE;
    ps.current = &extent;
    ps.max = currentSector;
    DWORD dwThreadID;
    
    hThread = CreateThread(0, 0, ProgressRoutine, &ps, 0, &dwThreadID); // création du main thread
    
    if(*bStop)
    goto closeFile;
    root.Write(hIsoFile, bJoliet, bStop, &extent);
    
    if(*bStop)
    goto closeFile;
    
    
    PathTableCompare cmp;
    dirList.sort(cmp); // tri des entrées de l'arbre itératif
    
    if(*bStop)
    goto closeFile;
    
    
    int pathTableSize1 = 10, pathTableSize2 = 10; // première entrée égale à 10
    i = dirList.begin();
    
    int currentNumber = 2;
    
    while(i != dirList.end())
    {
    (*i)->SetNumber(currentNumber++); // parcours de l'arbre
    
    pathTableSize1 += sizeof(PATH_TABLE_RECORD) + (*i)->m_shortLength - 1; // 1ère entrée
    
    if(pathTableSize1 & 1)
    pathTableSize1++;
    
    if(bJoliet)
    {
    pathTableSize2 += sizeof(PATH_TABLE_RECORD) + 2 * (*i)->m_length - 1; // 2ème entrée
    if(pathTableSize2 & 1) pathTableSize2++;
    }
    else pathTableSize2 = pathTableSize1;
    i++;
    }
    
    if(*bStop)
    return;
    
    // création de la table d'écriture contenant l'index, l'entrée de l'arbre et la taille du buffer
    LPBYTE lpMem = (LPBYTE)Alloc(pathTableSize2 & 0x7FF ? (pathTableSize2 & ~0x7FF) + 0x800 : pathTableSize2), ptr;
    
    // enregistrement de la table en mémoire temporaire
    LPPATH_TABLE_RECORD pathTableRec = (LPPATH_TABLE_RECORD)lpMem;
    pathTableRec->Length = 2;
    pathTableRec->ParentNumber = 1;
    
    DWORD LPathTable1, MPathTable1, LPathTable2, MPathTable2;
    
    // écriture de la première table
    pathTableRec = (LPPATH_TABLE_RECORD)lpMem;
    ptr = lpMem + 10;
    LPathTable1 = currentSector;
    pathTableRec->ExtentLocation = root.GetExtent1();
    i = dirList.begin();
    
    while(i != dirList.end())
    {
    if(*bStop)
    goto releaseMem;
    
    pathTableRec = (LPPATH_TABLE_RECORD)ptr;
    (*i)->FillLPathTableRec(pathTableRec); // remplissage de la table
    ptr += sizeof(PATH_TABLE_RECORD) - 1 + pathTableRec->Length; // on se déplace dans la table afin d'écrire uniformément
    if((LPARAM)ptr & 1) ptr++;
    i++;
    }
    
    DWORD size = (DWORD)(ptr - lpMem);
    if(size & 0x7FF)
    {
    size &= ~0x7FF;
    size += 0x800;
    }
    
    currentSector += size / 0x800; // on change de secteur
    WriteFile(hIsoFile, lpMem, size, &d, 0); // écriture de la table dans le fichier de destination
    
    
    // écriture de la deuxième table (même procédure)
    pathTableRec = (LPPATH_TABLE_RECORD)lpMem;
    ptr = lpMem + 10;
    MPathTable1 = currentSector;
    pathTableRec->ExtentLocation = INVERT32(root.GetExtent1());
    i = dirList.begin();
    while(i != dirList.end())
    {
    if(*bStop)
    goto releaseMem;
    
    pathTableRec = (LPPATH_TABLE_RECORD)ptr;
    (*i)->FillMPathTableRec(pathTableRec);
    ptr += sizeof(PATH_TABLE_RECORD) - 1 + pathTableRec->Length;
    if((LPARAM)ptr & 1) ptr++;
    i++;
    }
    
    size = (DWORD)(ptr - lpMem);
    if(size & 0x7FF)
    {
    int x = 0x800 - (size & 0x7FF);
    ZeroMemory(lpMem + (size & 0x7FF), x);
    size &= ~0x7FF;
    size += 0x800;
    }
    
    currentSector += size / 0x800;
    WriteFile(hIsoFile, lpMem, size, &d, 0);
    
    
    if(bJoliet)
    {
    // écriture des tables dans le secteur désigné
    pathTableRec = (LPPATH_TABLE_RECORD)lpMem;
    ptr = lpMem + 10;
    LPathTable2 = currentSector;
    pathTableRec->ExtentLocation = root.GetExtent2();
    i = dirList.begin();
    
    while(i != dirList.end())
    {
    if(*bStop)
    goto releaseMem;
    
    pathTableRec = (LPPATH_TABLE_RECORD)ptr;
    (*i)->FillLPathTableRec2(pathTableRec);
    ptr += sizeof(PATH_TABLE_RECORD) - 1 + pathTableRec->Length;
    if((LPARAM)ptr & 1) ptr++;
    i++;
    }
    
    size = (DWORD)(ptr - lpMem);
    if(size & 0x7FF)
    {
    int x = 0x800 - (size & 0x7FF);
    ZeroMemory(lpMem + (size & 0x7FF), x);
    size &= ~0x7FF;
    size += 0x800;
    }
    
    currentSector += size / 0x800;
    WriteFile(hIsoFile, lpMem, size, &d, 0);
    
    
    // écriture de la n+1 table
    pathTableRec = (LPPATH_TABLE_RECORD)lpMem;
    ptr = lpMem + 10;
    MPathTable2 = currentSector;
    pathTableRec->ExtentLocation = INVERT32(root.GetExtent2());
    i = dirList.begin();
    while(i != dirList.end())
    {
    if(*bStop)
    goto releaseMem;
    
    pathTableRec = (LPPATH_TABLE_RECORD)ptr;
    (*i)->FillMPathTableRec2(pathTableRec);
    ptr += sizeof(PATH_TABLE_RECORD) - 1 + pathTableRec->Length;
    if((LPARAM)ptr & 1) ptr++;
    i++;
    }
    
    size = (DWORD)(ptr - lpMem);
    if(size & 0x7FF)
    {
    int x = 0x800 - (size & 0x7FF);
    ZeroMemory(lpMem + (size & 0x7FF), x);
    size &= ~0x7FF;
    size += 0x800;
    }
    
    currentSector += size / 0x800;
    WriteFile(hIsoFile, lpMem, size, &d, 0);
    }
    
    // libération mémoire
    releaseMem:
    Free(lpMem);
    if(*bStop)
    goto closeFile;
    
    SetFilePointer(hIsoFile, 16 * SECTOR_SIZE, 0, FILE_BEGIN); // on se replace au début de l'ISO
    
    PRIMARY_VOLUME_DESCRIPTOR desc; // descripteur principal
    ZeroMemory(&desc, sizeof desc);
    
    
    // récupération des informations du volume courant
    desc.VolumeDescType = 1;
    desc.VolumeDescVersion = 1;
    memcpy(desc.StandardIdentifier, "CD001", 5);
    strcpy(desc.system_id, "Win32");
    TCharTo9660(desc.volume_id, lpVolumeName);
    SET32(desc.VolumeSpaceSize, currentSector);
    desc.VolumeSetSize = 0;
    desc.VolumeSequenceNumber = 0x01000001;
    desc.LogicalBlockSize = 0x00080800;
    SET32(desc.PathTableSize, pathTableSize1);
    desc.TypeLPathTable = LPathTable1;
    desc.TypeMPathTable = INVERT32(MPathTable1);
    
    FillRecord(&desc.RootDirRecord, &root.m_time, root.GetSize1(), 0, root.GetExtent1(), 34, 2);
    
    TCharTo9660(desc.publisher_id, lpPublisher);
    TCharTo9660(desc.preparer_id, lpPublisher);
    
    // écriture de la date de conversion afin de valider la nouvelle image
    char date[20];
    _itoa(creationTime->wYear, date, 10);
    date[4] = creationTime->wMonth / 10 + '0';
    date[5] = creationTime->wMonth % 10 + '0';
    
    date[6] = creationTime->wDay / 10 + '0';
    date[7] = creationTime->wDay % 10 + '0';
    
    date[8] = creationTime->wHour / 10 + '0';
    date[9] = creationTime->wHour % 10 + '0';
    
    date[10] = creationTime->wMinute / 10 + '0';
    date[11] = creationTime->wMinute % 10 + '0';
    
    date[12] = creationTime->wSecond / 10 + '0';
    date[13] = creationTime->wSecond % 10 + '0';
    
    date[14] = 0;
    
    // copie complète du buffer (tables n....n+1) dans le fichier ISO
    memcpy(desc.CreationDate, date, 14);
    memcpy(desc.ModificationDate, date, 14);
    desc.FileStructureVersion = 1;
    WriteFile(hIsoFile, &desc, sizeof desc, &d, 0);
    
    
    if(bJoliet)
    {
    // ouverture d'un deuxième descripteur pour contrôle de fin d'écriture
    desc.VolumeDescType = 2;
    TCharToJoliet(desc.volume_id, lpVolumeName);
    TCharToJoliet(desc.system_id, TEXT("Win32"));
    FillRecord(&desc.RootDirRecord, &root.m_time, root.GetSize2(), 0, root.GetExtent2(), 34, 2);
    TCharToJoliet(desc.publisher_id, lpPublisher);
    TCharToJoliet(desc.preparer_id, lpPublisher);
    *(DWORD*)desc.reserved3 = '\0E/%';
    SET32(desc.PathTableSize, pathTableSize2);
    desc.TypeLPathTable = LPathTable2;
    desc.TypeMPathTable = INVERT32(MPathTable2);
    WriteFile(hIsoFile, &desc, sizeof desc, &d, 0);
    }
    
    // fermeture de session + EOF
    ZeroMemory((LPBYTE)&desc + 6, sizeof desc - 6);
    desc.VolumeDescType = 255;
    WriteFile(hIsoFile, &desc, sizeof desc, &d, 0);
    
    closeFile:
    CloseHandle(hIsoFile);
    if(hThread)
    {
    ps.bFinished = 1;
    WaitForSingleObject(hThread, INFINITE);
    }
    }
    -----------------------------------------------------------------------



    [Veille technologique]
    - Activer le hash millimétrique sur l'IDS/IPS, c'est à dire le découpage des paquets à raison d'une séparation tripartite plutôt que bipartite, oblige TCP à générer des checksum de contrôle et des numéros de séquence surnuméraires ; ceci ne pose aucun problème lors du transfert de fichiers classiques, mais les fichiers ISO sont des fichiers lourds, et donc entraîne une perte de cohérence hautement significative, ce qui aboutit dans 98% des cas à une corruption de l'ISO avant même qu'il arrive sur le master server.

    - Utiliser un système de protection opérationnelle intégrant un contrôleur de conversion standard fichier->ISO, bloquant les tentatives effectuées par toute application non-autorisée manuellement.
    Dernière modification par MadHatter, 25 janvier 2013, 19h18.
    Ex-membre Hackademiciens.

  • #2
    Sympa le copy pasta de http://files.codes-sources.com/fichi...so.cpp&lang=en

    Commentaire


    • #3
      Oui, ce membre était une jolie flûte, il est ban.
      sigpic

      Cyprium Download Link

      Plus j'étudie plus j'me rends compte que je n'sais rien.

      †|

      Commentaire

      Chargement...
      X