Sujet n°10170
Posté par Sphinx le 12 Aoû - 16:59 (2011)
Titre : Module Marshal 2.1
Bonjour à tous. Certains parmi vous se souviendront peut être du Module Marshal Amélioré que j'ai développé quand Mk cherchait à transférer simplement une équipe d'un jeu à un autre Imbécile heureux

Depuis, ce système n'a pas bougé, jusque très récemment, d'où la création du
Module Marshal 2.1



L'objectif du Module Marshal 2.1 est le même que celui du Module Marshal Amélioré : permettre de transformer un objet Ruby (un pokémon par exemple) en une suite de caractères. Son intérêt réside donc surtout dans la forme des données transférées.


Ce module tient en un simple script :
Module Marshal 2.1
Code:
#======================================================================= 
# Module Marshal Amélioré 2.1 - Sphinx 
#   finalisé le 12/08/2011 
#   Correction de bugs le 08/12/2013 - Palbolsky
#   
# Crédits demandés 
#======================================================================= 
 
module Marshal 
  # MARSHALGROUP 
  MARSHALGROUP = 655 
   
  # STANDARDS regroupe les 3 masques statiques utilisés par le Module Marshal 2.0. 
  # Les 3 masques hexadécimaux doivent convenir chaque chiffre hexadécimal (0 -> 9 et A -> F) 
  # une et une seule fois. 
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
  STANDARDS = [ 
    # Masque statique hexadécimal 1 
    "51847e6a03bfc2d9", 
    # Masque statique hexadécimal 2 
    "79d32501b4c86fea", 
    # Masque statique hexadécimal 3 
    "cdfb5210ae768943" 
  ] 
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
   
  # Marshal.genMasks 
  #   génère de nouveaux masques valides pour remplacer les masques existants 
  def self.genMasks 
    keys = [] 
    loop do 
      keys = genKeys 
      break if validKeys(keys) 
    end 
    file = File.open("Masques.log", "w") 
    file.write("  STANDARDS = [\n    # Masque statique hexadécimal 1\n    \"#{keys[0]}\",\n    # Masque statique hexadécimal 2\n    \"#{keys[1]}\",\n    # Masque statique hexadécimal 3\n    \"#{keys[2]}\"\n  ]\n") 
    file.close 
  end 
  def self.genKeys 
    keys = [] 
    hexa = [ 
      ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"].sort {rand(3) - 1}, 
      ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"].sort {rand(3) - 1}, 
      ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"].sort {rand(3) - 1} 
    ] 
    for j in 0...3 
      keys[j] = "" 
      for i in 0...16 
        index = rand(hexa[j].size) 
        keys[j] += hexa[j][index] 
        hexa[j].delete_at(index) 
      end 
    end 
    return keys 
  end 
  def self.validKeys(keys) 
    for i in 0...keys[0].length 
      return false if keys[0][i] == keys[1][i] or keys[0][i] == keys[2][i] or keys[1][i] == keys[2][i] 
    end 
    return true 
  end 
   
  # Marshal.encrypt 
  #   encode l'objet obj 
  def self.encrypt(obj, filename = nil, *cles) 
    for cle in cles 
      unless cle.nil? or cle.empty? 
        cle = cle.unpack("C*") 
        obj = dump(obj).unpack("C*") 
        i = 0 
        for c in 0...obj.length 
          obj[c] += cle[c % cle.length] 
        end 
      end 
    end 
    key1 = "" 
    key2 = "" 
    key3 = "" 
    hexa1 = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"] 
    hexa2 = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"] 
    alphanum3 = [ 
      "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", 
      "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", 
      "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", 
      "u", "v", "w", "x", "y", "z", 
      "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", 
      "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", 
      "U", "V", "W", "X", "Y", "Z" 
    ] 
    for i in 0...16 
      index1 = rand(hexa1.size) 
      index2 = rand(hexa2.size) 
      index3 = rand(alphanum3.size) 
      key1 += hexa1[index1] 
      key2 += hexa2[index2] 
      key3 += alphanum3[index3] 
      hexa1.delete_at(index1) 
      hexa2.delete_at(index2) 
      alphanum3.delete_at(index3) 
    end 
 
    obj = dump(obj) 
    str = "" 
    for c in 0...obj.length 
      str += sprintf("%02x", obj[c]).tr(key1, key2) 
    end 
     
    write = key1.tr(STANDARDS[0], STANDARDS[1])     
    write += (sprintf("%04x", MARSHALGROUP)).tr(STANDARDS[1], key1)   
    write += key2.tr(STANDARDS[1], key1) 
    write += key3.tr(key1, key2) 
    write += str.tr(STANDARDS[2], key3) 
   
    if filename.is_a?(String) 
      file = File.open(filename, "w") 
      file.write(write) 
      file.close 
    else 
      return write 
    end 
  end 
   
  # Marshal.uncrypt 
  #   retourne l'objet encodé 
  def self.uncrypt(filename, isFile = false, *cles) 
    chunked = true
    a = filename
    if isFile 
      file = File.open(filename, "r") 
      a = file.read       
      file.close 
    end     

    # Localise les octets ajoutés si le serveur envoie du chunked
    i,j = 0
    loop do     
      if a[i..i] == "\n"
        i += 1
        break
      end
      if i > 12
        chunked = false       
        break
      end
      i += 1
    end       
   
    # Supprime les octets ajoutés si le serveur envoie du chunked
    if chunked
      b = filename   
      (b.size-i-1).times do |j|
        b[j..j] = a[j+i..j+i]
      end   
      a = b
      b = nil
    end
   
    key1 = a[0..15].tr(STANDARDS[1], STANDARDS[0])     
    marshalgroup = a[16..19].tr(key1, STANDARDS[1])     
   
    if MARSHALGROUP != 0 and MARSHALGROUP != marshalgroup.to_i(16) 
      print "Le MARSHALGROUP " + marshalgroup.to_i(16).to_s + " des données n'est pas compatible avec le\nMARSHALGROUP " + 
      MARSHALGROUP.to_s + " de cette partie. Les données n'ont pas été intégrées." 
      return 
    end
   
    key2 = a[20..35].tr(key1, STANDARDS[1]) 
    key3 = a[36..51].tr(key2, key1) 
    a = a.tr(key3, STANDARDS[2]) 
    str = "" 
    for i in 26...a.size / 2 
      str += (a[(i * 2)..(i * 2) + 1].tr(key2, key1)).to_i(16).chr 
    end 
    obj = load(str) 
    for cle in cles.reverse 
      unless cle.nil? or cle.empty? 
        cle = cle.unpack("C*") 
        i = 0 
        for c in 0...obj.length 
          obj[c] -= cle[c % cle.length] 
        end 
        obj = Marshal.load(obj.pack("C*")) 
      end 
    end 
    return obj 
  end 
end

à copier au dessus de Main. Et voilà, c'est prêt à l'emploi Imbécile heureux


Tout d'abord, vous devez savoir que l'encodage s'appuie sur différents masques que vous trouverez en entête (entre les deux lignes de signe "=") :
Code:
#=======================================================================
  STANDARDS = [
    # Masque statique hexadécimal 1
    "51847e6a03bfc2d9",
    # Masque statique hexadécimal 2
    "79d32501b4c86fea",
    # Masque statique hexadécimal 3
    "cdfb5210ae768943"
  ]
#=======================================================================

Vous pouvez utiliser la commande :
Code:
Marshal.genMasks

dans un évent (dans une Insertion de script). Cette fonction crée un fichier "Masques.log" qui contient un bout de code Ruby (pour remplacer celui qui se trouve entre les lignes de signe "=")

Ensuite, vous pouvez modifier le MARSHALGROUP, en changeant le nombre qui se trouve après :
Code:
MARSHALGROUP =

Seul un code ayant un MARSHALGROUP identique à celui du module utilisé pourra être déchiffré.

Maintenant, passons en revue les méthodes pour encoder un objet, et pour décoder un code (chaque ligne de code contenue dans la même balise code donne le même résultat) :
Code:
Marshal.encrypt(objet)
Marshal.encrypt(objet, nil)

Retourne une chaine de caractères qui représente l'objet encodé.
Code:
Marshal.uncrypt("chaine_de_caracteres")
Marshal.uncrypt("chaine_de_caracteres", false)

Retourne l'objet contenu dans la chaine de caractères encodée "chaine_de_caracteres".

Code:
Marshal.encrypt(objet, "nom_de_fichier")

Enregistre une chaine de caractères qui représente l'objet encodé dans le fichier "nom_de_fichier".
Code:
Marshal.uncrypt("nom_de_fichier", true)

Retourne l'objet contenu dans le fichier "nom_de_fichier".

Vous pouvez ajouter des clefs d'encodage (autant que vous voulez) sachant que pour décoder, vous aurez besoin de donner ces mêmes clefs, en sens inverse.
Exemple d'objet encodé (puis décodé) par les clefs "clef1", "clef2" et "ABCDE" sans passer par un fichier :
Code:
chaine = Marshal.encrypt(objet, nil, "clef1", "clef2", "ABCDE")
objet = Marshal.uncrypt(chaine, false, "ABCDE", "clef2", "clef1")

Exemple d'objet encodé (puis décodé) par les clefs "DEFGH", "clef5" et "clef6" en passant par un fichier :
Code:
Marshal.encrypt(objet, "fichier", "DEFGH", "clef5", "clef6")
objet = Marshal.uncrypt("fichier", true, "clef6", "clef5", "DEFGH")


    IV) Nouveau mot de la fin

Ce script n'est pas utile pour le commun des mortels, en revanche il peut permettre aux développeurs d'autres systèmes d'échanger des informations entre les jeux d'une facon assez simple finalement Clin d'œil foireux

Posté par CollosalPokemon le 14 Aoû - 05:40 (2011)
cool, mais cela utilise de déchiffrer RGSSAD ? (Je vois qu'il ya décrypter la méthode)

Posté par Nuri Yuri le 14 Aoû - 10:49 (2011)
C'est pour décrypter le fichier créer avec ce Marshal pas pour décrypter l'archive RGSS.

Posté par Giratinaprimal le 7 Sep - 16:40 (2011)
J'ai SyntaxError à


Code:
break if validKeys(keys)






vers le début du script. Tant que j'ai ce bug, impossible de faire fonctionner le système d'échanges en ligne
de Sphinx...