IdentifiantMot de passe
Loading...
Mot de passe oubli� ?Je m'inscris ! (gratuit)
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

C++ Discussion :

Calculer l'offset de fichier � partir d'une string


Sujet :

C++

  1. #1
    Membre � l'essai
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    4
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 4
    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 confirm�
    Homme Profil pro
    D�veloppeur informatique
    Inscrit en
    F�vrier 2005
    Messages
    5 513
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 53
    Localisation : France, Val de Marne (�le de France)

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

    Informations forums :
    Inscription : F�vrier 2005
    Messages : 5 513
    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
    Avatar de M�dinoc
    Homme Profil pro
    D�veloppeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 397
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 41
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 397
    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
    Membre � l'essai
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    4
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 4
    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. R�ponses: 6
    Dernier message: 20/06/2007, 22h32
  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, 11h16
  3. R�ponses: 4
    Dernier message: 01/12/2005, 01h01
  4. Copier un fichier � partir d'une URL ?
    Par oulahoup dans le forum ASP
    R�ponses: 2
    Dernier message: 18/08/2005, 21h52
  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, 12h21

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