Navigation

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

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    mai 2002
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mai 2002
    Messages : 4
    Points : 3
    Points
    3
    Par défaut Calculer l'offset de fichier à partir d'une string
    Bonjour, je voudrais trouver l'offset du fichier à partir de l'adresse d'une string ascii à l'intérieur de la dll.
    Je sais que je pourrais chercher à partir d'un pattern mais pour l'instant c'est la formule à partir d'une string qui m'intéresse.

    1. voici les lignes de la string que je peux trouver en parcourant le fichier avec ifstream:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    33e2390h : 64 65 66 61 75 6C 74 2D 62 61 63 6B 67 72 6E 64 |
    33e23a0h : 2D 63 6F 6C 72 00                               | "default-background-color"
    2. offset obtenu par le debuggeur:
    1180E33

    3. voici la ligne de l'offset du debuggeur dans un editeur hexadecimal:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1180E30h : 00 00 00 48 8D 15 56 17 26 02 48 89 F9 E8 5E 09 |


    Formule pour calculer le offset du fichier:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    offset_du_fichier = adresse_dans_le_code + adresse_de_la_ligne + longeur_de_la_commande - adresse_de_base
     
           ?          = 48 8D 15 56 17 26 02 +      0x1180E33      + 48 8D 15 56 17 26 02   -      0x400     
                        donc 0x02261756                              donc 0x7
    Résultat = 33E2190 ---- 512 bytes avant l'adresse de la string "default-background-color"

    Il me semble qu'il me manque une dernière donnée. Si je change de version de la dll et que je refais le calcul, le résultat change pour devenir 1024 et même 3072 bytes après l'adresse de la string.

    Je dépose ici un code trouvé sur un autre site qui pourrait peut-être aider:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    LPCSTR fileName="c:\\program files (x86)\\.......\\chome.dll"; //dll 64 bits
        HANDLE hFile; 
        HANDLE hFileMapping;
        LPVOID lpFileBase;
        PIMAGE_DOS_HEADER dosHeader;
        PIMAGE_NT_HEADERS peHeader;
        PIMAGE_SECTION_HEADER sectionHeader;
     
        hFile = CreateFileA(fileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
     
        if(hFile==INVALID_HANDLE_VALUE)
        {
            printf("\n CreateFile failed in read mode \n");
            return 1;
        }
     
        hFileMapping = CreateFileMapping(hFile,NULL,PAGE_READONLY,0,0,NULL);
     
        if(hFileMapping==0)
        {
            printf("\n CreateFileMapping failed \n");
            CloseHandle(hFile);
            return 1;
        }
     
        lpFileBase = MapViewOfFile(hFileMapping,FILE_MAP_READ,0,0,0); // Base pointer to file
     
        if(lpFileBase==0)
        {
            printf("\n MapViewOfFile failed \n");
            CloseHandle(hFileMapping);
            CloseHandle(hFile);
            return 1;
        }
     
        dosHeader = (PIMAGE_DOS_HEADER) lpFileBase;  //pointer to dos headers
     
        if(dosHeader->e_magic==IMAGE_DOS_SIGNATURE)
        {
            //if it is executable file print different fileds of structure
            //dosHeader->e_lfanew : RVA for PE Header
            printf("\n DOS Signature (MZ) Matched");
     
            //pointer to PE/NT header
            peHeader = (PIMAGE_NT_HEADERS) ((u_char*)dosHeader+dosHeader->e_lfanew);
     
            if(peHeader->Signature==IMAGE_NT_SIGNATURE)
            {
                printf("\n PE Signature (PE) Matched \n");
                // valid executable so we can proceed
     
                //address of entry point
                DWORD ptr = peHeader->OptionalHeader.AddressOfEntryPoint;
     
                //instead of AEP send any pointer to get actual disk offset of it
                printf("\n RVA : %x \n",ptr); // this is in memory address i.e. RVA
                //suppose any one wants to know actual disk offset of "address of entry point" (AEP)
     
                sectionHeader = IMAGE_FIRST_SECTION(peHeader); //first section address
                UINT nSectionCount = peHeader->FileHeader.NumberOfSections;
                UINT i=0;
                //check in which section the address belongs
                for( i=0; i<=nSectionCount; ++i, ++sectionHeader )
                {
                    if((sectionHeader->VirtualAddress) > ptr)
                    {
                        sectionHeader--;
                        break;
                    }
                }
     
                if(i>nSectionCount)
                {
                    sectionHeader = IMAGE_FIRST_SECTION(peHeader);
                    UINT nSectionCount = peHeader->FileHeader.NumberOfSections;
                    for(i=0; i<nSectionCount-1; ++i,++sectionHeader);
                }
     
                //once the correct section is found below formula gives the actual disk offset 
                DWORD retAddr = ptr - (sectionHeader->VirtualAddress) +
                        (sectionHeader->PointerToRawData);
                printf("\n Disk Offset : %x \n",retAddr+(PBYTE)lpFileBase);
                // retAddr+(PBYTE)lpFileBase contains the actual disk offset of address of entry point
     
            }
            UnmapViewOfFile(lpFileBase);
            CloseHandle(hFileMapping);
            CloseHandle(hFile);
            //getchar();
            return 0;
        }
        else
        {
            printf("\n DOS Signature (MZ) Not Matched \n");
            UnmapViewOfFile(lpFileBase);
            CloseHandle(hFileMapping);
            CloseHandle(hFile);
            return 1;
        }
    Le but pour l'instant c'est un exercice pour se localiser à l'intérieur d'un exécutable ou d'une dll à l'aide d'une string ascii.
    Merci à l'avance à tous ceux qui m'aideront à résoudre ce problème.

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    février 2005
    Messages
    4 738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Val de Marne (Île de France)

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

    Informations forums :
    Inscription : février 2005
    Messages : 4 738
    Points : 11 258
    Points
    11 258
    Par défaut
    C'est vraiment pas clair votre truc.
    Pour rappel, une Dll qui se charge dans un exécutable dispose de plusieurs segments et ils ne sont pas continus en mémoire.
    Une Dll en mémoire, c'est comme un puzzle et le fichier image de la Dll n'est qu'une boite contenant l'ensemble des bouts du puzzle de manière "désordonnée".

  3. #3
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    septembre 2005
    Messages
    27 088
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : septembre 2005
    Messages : 27 088
    Points : 40 420
    Points
    40 420
    Par défaut
    Par contre, Windows peut faire ça pour toi, vu que Windows sait à quelles plages mémoire les DLLs sont chargées.
    Voir la fonction GetModuleHandleEx(), notamment son flag GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS.

    Mais supposons que tu veuilles le faire manuellement: Au moment où tu lis la DLL pour calculer l'offset de la string voulue, tu dois en profiter pour lire également sa table des sections. En te servant de cette table, tu pourras convertir l'offset en RVA (Relative Virtual Address) qui est l'offset "en mémoire" que tu cherches.

    Perso j'ai un code en C# qui permet de faire la manœuvre inverse (calculer un offset à partir de la RVA), mais ça peut peut-être t'aider à faire le calcul qu'il te faut.
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    		/// <summary>
    		/// A single entry in the section table.
    		/// This is what allows to map a Relative Virtual Address (RVA) to a file offset.
    		/// </summary>
    		[StructLayout(LayoutKind.Sequential)]
    		struct IMAGE_SECTION_HEADER 
    		{
    			[MarshalAs(UnmanagedType.ByValArray, SizeConst=8)]
    			public byte[] Name;
     
    			/// <summary>Size of the section after loading.
    			/// It's the exact size, which means it can be smaller than <c>SizeOfRawData</c> because it does not include padding.
    			/// It can also be bigger, if the section contains "uninitialized data" that will occupy space in memory but not in the file.</summary>
    			public UInt32 VirtualSize;
    			/// <summary>RVA of the section's first byte.</summary>
    			public UInt32 VirtualAddress;
    			/// <summary>Size of the section within the PE file.</summary>
    			public UInt32 SizeOfRawData;
    			/// <summary>File offset of the section's first byte.</summary>
    			public UInt32 PointerToRawData;
     
    			public UInt32 PointerToRelocations;
    			public UInt32 PointerToLineNumbers;
    			public UInt16 NumberOfRelocations;
    			public UInt16 NumberOfLineNumbers;
    			public UInt32 Characteristics;
     
    			public string NameAsString { get { return Name==null ? null : Encoding.UTF8.GetString(Name).TrimEnd('\0'); } }
     
    			public void Dump(TextWriter output)
    			{
    				if(output==null) { throw new ArgumentNullException("output"); }
    				output.WriteLine("Name: {0}", NameAsString);
    				output.WriteLine("VirtualSize         : {0:X8}", VirtualSize);
    				output.WriteLine("VirtualAddress      : {0:X8}", VirtualAddress);
    				output.WriteLine("SizeOfRawData       : {0:X8}", SizeOfRawData);
    				output.WriteLine("PointerToRawData    : {0:X8}", PointerToRawData);
    				output.WriteLine("PointerToRelocations: {0:X8}", PointerToRelocations);
    				output.WriteLine("PointerToLineNumbers: {0:X8}", PointerToLineNumbers);
    				output.WriteLine("NumberOfRelocations :     {0:X4}", NumberOfRelocations);
    				output.WriteLine("NumberOfLineNumbers :     {0:X4}", NumberOfLineNumbers);
    				output.WriteLine("Characteristics     : {0:X8}", Characteristics);
    			}
     
    			public static int CompareVirtualAddresses(IMAGE_SECTION_HEADER x, IMAGE_SECTION_HEADER y)
    			{
    				int res = x.VirtualAddress.CompareTo(y.VirtualAddress);
    				if(res != 0) { return res; }
    				return 0;
    			}
    			public static int CompareVirtualAddressesAndOffsets(IMAGE_SECTION_HEADER x, IMAGE_SECTION_HEADER y)
    			{
    				int res = x.VirtualAddress.CompareTo(y.VirtualAddress);
    				if(res != 0) { return res; }
    				res = x.PointerToRawData.CompareTo(y.PointerToRawData);
    				if(res != 0) { return res; }
    				return 0;
    			}
     
    			public override string ToString()
    			{
    				return string.Format("{0} at RVA {1:X8}, file offset {2:X8}", NameAsString, VirtualAddress, PointerToRawData);
    			}
    		}
     
    		/// <summary>
    		/// Handles the PE file's section table after it's loaded.
    		/// This class is immutable.
    		/// </summary>
    		class SectionTable : IComparer<IMAGE_SECTION_HEADER>
    		{
    			readonly List<IMAGE_SECTION_HEADER> unsortedSections;
    			readonly List<IMAGE_SECTION_HEADER> sortedSections;
    			public readonly uint sectionTableOffset;
     
    			public SectionTable(IEnumerable<IMAGE_SECTION_HEADER> sections, uint sectionTableOffset)
    			{
    				this.unsortedSections = new List<IMAGE_SECTION_HEADER>(sections ?? new IMAGE_SECTION_HEADER[0]);
    				this.sortedSections = new List<IMAGE_SECTION_HEADER>(unsortedSections);
    				this.sortedSections.Sort(IMAGE_SECTION_HEADER.CompareVirtualAddressesAndOffsets);
    				this.sectionTableOffset = sectionTableOffset;
    			}
     
    			public bool MapRVAToSection(uint rva, out IMAGE_SECTION_HEADER foundSection, out uint offsetInSection)
    			{
    				if(sortedSections==null) { throw new ArgumentNullException("sortedSections"); }
    				int ixFoundForReal;
    				IMAGE_SECTION_HEADER dummy = new IMAGE_SECTION_HEADER();
    				dummy.VirtualAddress = rva;
    				int ixBinarySearch = sortedSections.BinarySearch(dummy, this);
    				if(ixBinarySearch >= 0)
    					ixFoundForReal = ixBinarySearch;
    				else
    				{
    					int ixNext = ~ixBinarySearch;
    					if(ixNext==0) { foundSection=new IMAGE_SECTION_HEADER(); offsetInSection=0; return false; } //Before the first section? I don't think it's a valid RVA.
    					ixFoundForReal = ixNext-1;
    				}
    				Debug.Assert(ixFoundForReal >= 0, "ixFoundForReal can't be negative at this point.");
    				Debug.Assert(ixFoundForReal < sortedSections.Count, "ixFoundForReal can't exceed section table length.");
    				Debug.Assert(sortedSections[ixFoundForReal].VirtualAddress <= rva, "RVA can't be below the found section.");
    				foundSection = sortedSections[ixFoundForReal];
    				offsetInSection = rva - foundSection.VirtualAddress;
    				if(offsetInSection >= foundSection.VirtualSize)
    					return false; //RVA is outside the section's virtual data
    				if(offsetInSection >= foundSection.SizeOfRawData)
    					return false; //RVA can't be mapped into the file because it's in the part of the section that's not in the file.
     
    				return true;
    			}
    			public bool MapRVAToFileOffset(uint rva, out uint fileOffset)
    			{
    				if(sortedSections==null) { throw new ArgumentNullException("sortedSections"); }
    				IMAGE_SECTION_HEADER foundSection;
    				uint offsetInSection;
    				if(!MapRVAToSection(rva, out foundSection, out offsetInSection))
    				{ fileOffset=0; return false; }
    				fileOffset = foundSection.PointerToRawData + offsetInSection;
    				return true;
    			}
     
    			int IComparer<IMAGE_SECTION_HEADER>.Compare(IMAGE_SECTION_HEADER x, IMAGE_SECTION_HEADER y)
    			{
    				return IMAGE_SECTION_HEADER.CompareVirtualAddresses(x, y);
    			}
     
    		}
    Il faut savoir que la plupart des adresses dans la DLL sont stockées sous forme de RVA (notamment, tout le Data Directory).
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  4. #4
    Candidat au Club
    Profil pro
    Inscrit en
    mai 2002
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mai 2002
    Messages : 4
    Points : 3
    Points
    3
    Par défaut Merci pour vos réponses
    Bonjour, merci beaucoup d'avoir pris le temps de me répondre et surtout à vous Médinoc pour votre bout de code.

    Je vais prendre le temps de le regarder ligne par ligne pour le comprendre.

    Merci.

    Manathan01

Discussions similaires

  1. compresser un fichier à partir d'une application
    Par Julian21 dans le forum C++
    Réponses: 6
    Dernier message: 20/06/2007, 23h32
  2. Sélectionner un fichier à partir d'une liste filtrée
    Par Lenaick dans le forum C++Builder
    Réponses: 7
    Dernier message: 14/03/2006, 12h16
  3. Réponses: 4
    Dernier message: 01/12/2005, 02h01
  4. Copier un fichier à partir d'une URL ?
    Par oulahoup dans le forum ASP
    Réponses: 2
    Dernier message: 18/08/2005, 22h52
  5. [SERVLET]Appel d'un fichier à partir d'une servlet
    Par fchafia dans le forum Servlets/JSP
    Réponses: 5
    Dernier message: 17/03/2005, 13h21

Partager

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