9
votes

Quelqu'un peut-il définir l'algorithme de checksum Windows PE?

Je voudrais mettre en œuvre cela en C #

J'ai regardé ici: http://www.codeproject.com/kb/cpp/pechecksum.aspx < P> et je suis conscient de la fonction ImageHLP.DLL MapFileandChecksum.

Cependant, pour diverses raisons, je voudrais mettre en œuvre cela moi-même.

Le meilleur que j'ai trouvé est ici: http://forum.sysinternals.com/optional-header-checksum-calculation_topic24214.html < / P>

Mais, je ne comprends pas l'explication. Peut-on clarifier la manière dont la somme de contrôle est calculée?

merci!

update

i de l'exemple de code, je ne comprends pas ce que cela signifie, et comment le traduire en C # xxx

update # 2

merci, est tombé sur un code Python qui fait semblable aussi ici xxx

Cependant, ce n'est toujours pas Travailler pour moi - voici ma conversion de ce code: xxx

peut-on me dire où je suis stupide?


2 commentaires

Qu'en est-il du code que vous ne comprenez pas? Exemple de code serait utile.


Désolé - éditer


7 Réponses :


6
votes

Le code dans le poste de forum n'est pas strictement identique à celui qui a été noté lors du démontage réel du code Windows PE. Le CodeProject Article Vous référence donne la "valeur pliide 32 bits en 16 bits" Comme: xxx

que vous pourriez traduire en c # comme: xxx


2 commentaires

Merci encore - avez heurté votre réponse, mais la mienne a marqué comme la réponse, comme je pense que cela représente l'algorithme complet.


@Mark: Certainement, je voulais simplement illustrer les parties pertinentes de l'article.



8
votes

OK, j'ai finalement eu le travail ok ... mon problème était que j'utilisais des intens non utins !!! Ainsi, ce code fonctionne (en supposant que les données sont alignées sur 4 octets, sinon vous devrez le rembourrer un peu) - et Pechecksum est la position de la valeur de somme de contrôle dans la PE (qui n'est clairement pas utilisée lors du calcul de la somme de contrôle! !!!)

static uint CalcCheckSum(byte[] data, int PECheckSum)
{
    long checksum = 0;
    var top = Math.Pow(2, 32);

    for (var i = 0; i < data.Length / 4; i++)
    {
        if (i == PECheckSum / 4)
        {
            continue;
        }
        var dword = BitConverter.ToUInt32(data, i * 4);
        checksum = (checksum & 0xffffffff) + dword + (checksum >> 32);
        if (checksum > top)
        {
            checksum = (checksum & 0xffffffff) + (checksum >> 32);
        }
    }

    checksum = (checksum & 0xffff) + (checksum >> 16);
    checksum = (checksum) + (checksum >> 16);
    checksum = checksum & 0xffff;

    checksum += (uint)data.Length;
    return (uint)checksum;

}


1 commentaires

Ce n'est pas correct. Il ne correspond pas à la sortie ImageHLP.DLL MAPFILEANDCHECKSUM . Consultez la sortie à l'aide de l'exécutable PE Checksum fourni dans codeProject.com/articles/19326/...



0
votes

J'essayais de résoudre le même problème dans Java. Voici la solution de Mark's traduite en Java, à l'aide d'un ensemble aléatoireAccessfile au lieu d'un tableau d'octets comme entrée:

static long computeChecksum(RandomAccessFile data, long checksumOffset) throws IOException {
    long checksum = 0;
    long top = (long) Math.pow(2, 32);
    long length = data.length();

    for (long i = 0; i < length / 4; i++) {
        if (i == checksumOffset / 4) {
            data.skipBytes(4);
            continue;
        }

        long ch1 = data.read();
        long ch2 = data.read();
        long ch3 = data.read();
        long ch4 = data.read();

        long dword = ch1 + (ch2 << 8) + (ch3 << 16) + (ch4 << 24);

        checksum = (checksum & 0xffffffffL) + dword + (checksum >> 32);

        if (checksum > top) {
            checksum = (checksum & 0xffffffffL) + (checksum >> 32);
        }
    }

    checksum = (checksum & 0xffff) + (checksum >> 16);
    checksum = checksum + (checksum >> 16);
    checksum = checksum & 0xffff;
    checksum += length;

    return checksum;
}


0 commentaires

2
votes

Le code Java ci-dessous de Emmanuel peut ne pas fonctionner. Dans mon cas, il se bloque et ne complète pas. Je crois que cela est dû à l'utilisation intense de l'IO dans le code: en particulier les données.Lead ()'s. Cela peut être échangé avec un tableau comme solution. Où se trouve complètement ou progressivement le fichier dans une ou plusieurs matrices d'octets.

J'ai tenté cela, mais le calcul était trop lent en raison de la conditionnelle du décalage de la somme de contrôle pour sauter les octets d'en-tête de la somme de contrôle. J'imagine que la solution C # de l'OP aurait un problème similaire. P>

Le code ci-dessous le supprime également. P>

Public statique Long CompuTechecksum (RandomAccessFile Data, int CheckSumOffset) Jette IoException { P>

public static long computeChecksum2(FileChannel ch, int checksumOffset)
            throws IOException {

    ch.position(0);
    long sum = 0;
    long top = (long) Math.pow(2, 32);
    long length = ch.size();

    ByteBuffer buffer = ByteBuffer.wrap(new byte[(int) length]);
    buffer.order(ByteOrder.LITTLE_ENDIAN);

    ch.read(buffer);
    buffer.putInt(checksumOffset, 0x0000);

    buffer.position(0);
    while (buffer.hasRemaining()) {
        sum += buffer.getInt() & 0xffffffffL;
        if (sum > top) {
            sum = (sum & 0xffffffffL) + (sum >> 32);
        }
    }   
    sum = (sum & 0xffff) + (sum >> 16);
    sum = sum + (sum >> 16);
    sum = sum & 0xffff;
    sum += length;

    return sum;
}


0 commentaires

0
votes
private unsafe static int GetSetPEChecksum(byte[] Array) {
    var Value = 0;
    var Count = Array.Length;
    if(Count >= 64)
        fixed (byte* array = Array) {
            var Index = 0;
            var Coff = *(int*)(array + 60);
            if(Coff >= 64 && Count >= Coff + 92) {
                *(int*)(array + Coff + 88) = 0;
                var Bound = Count >> 1;
                if((Count & 1) != 0) Value = array[Count & ~1];
                var Short = (ushort*)array;
                while(Index < Bound) {
                    Value += Short[Index++];
                    Value = (Value & 0xffff) + (Value >> 16);
                    Value = (Value + (Value >> 16)) & 0xffff;
                }
                *(int*)(array + Coff + 88) = Value += Count;
            }
        }
    return Value;
}
If you need short unsafe... (Not need use Double and Long integers and not need Array aligning inside algorithm)

0 commentaires

0
votes

L'exemple Java n'est pas entièrement correct. Après la mise en œuvre de Java correspond au résultat de la mise en œuvre originale de Microsoft à partir de imagehlp.mapfileandkecksuma code>.

Il est important que les octets d'entrée sont masqués avec INPUTBYTE & 0XFF CODE> et le résultat " Code> long code> Masqué à nouveau lorsqu'il est utilisé dans le terme d'addition avec Mots courants et 0xffffffffl code> (Considérez le L): P>

    long checksum = 0;
    final long max = 4294967296L; // 2^32

    // verify the data is DWORD-aligned and add padding if needed
    final int remainder = data.length % 4;
    final byte[] paddedData = Arrays.copyOf(data, data.length
            + (remainder > 0 ? 4 - remainder : 0));

    for (int i = 0; i <= paddedData.length - 4; i += 4)
    {
        // skip the checksum field
        if (i == this.offsetToOriginalCheckSum)
            continue;

        // take DWORD into account for computation
        final long currentWord = (paddedData[i] & 0xff)
                               + ((paddedData[i + 1] & 0xff) << 8)
                               + ((paddedData[i + 2] & 0xff) << 16)
                               + ((paddedData[i + 3] & 0xff) << 24);

        checksum = (checksum & 0xffffffffL) + (currentWord & 0xffffffffL);

        if (checksum > max)
            checksum = (checksum & 0xffffffffL) + (checksum >> 32);
    }

    checksum = (checksum & 0xffff) + (checksum >> 16);
    checksum = checksum + (checksum >> 16);
    checksum = checksum & 0xffff;
    checksum += data.length; // must be original data length


0 commentaires

1
votes

Personne n'a vraiment répondu à la question originale de "Quelqu'un peut-il définir l'algorithme de checksum Windows PE?" Donc, je vais le définir comme le plus simplement possible. Un grand nombre d'exemples donnés jusqu'à présent optimisent des entiers non signés 32 bits (Aka Dwords), mais si vous voulez simplement comprendre l'algorithme lui-même à son plus fondamental, c'est simplement ceci:

  1. à l'aide d'un entier non signé 16 bits (alias un mot) pour stocker la somme de contrôle, additionnez tous les mots des données, à l'exception des 4 octets de la somme de contrôle en-tête PE facultatif. Si le fichier n'est pas aligné sur Word, le dernier octet est un 0x00.

  2. Convertissez la somme de contrôle d'un mot à un mot dword et ajoutez la taille du fichier.

    L'algorithme de contrôle PE ci-dessus est efficacement identique à l'algorithme d'origine MS-DOS Checksum. Les seules différences sont l'emplacement pour sauter et remplacer le XOR 0xFFFF à la fin et ajouter la taille du fichier.

    de mon Winpefile Classe pour PHP , l'algorithme ci-dessus ressemble à: xxx < / p>


0 commentaires