github.com/saferwall/pe@v1.5.2/tls.go (about) 1 // Copyright 2018 Saferwall. All rights reserved. 2 // Use of this source code is governed by Apache v2 license 3 // license that can be found in the LICENSE file. 4 5 package pe 6 7 import ( 8 "encoding/binary" 9 ) 10 11 // TLSDirectoryCharacteristicsType represents the type of a TLS directory 12 // Characteristics. 13 type TLSDirectoryCharacteristicsType uint32 14 15 // TLSDirectory represents tls directory information with callback entries. 16 type TLSDirectory struct { 17 18 // of type *IMAGE_TLS_DIRECTORY32 or *IMAGE_TLS_DIRECTORY64 structure. 19 Struct interface{} `json:"struct"` 20 21 // of type []uint32 or []uint64. 22 Callbacks interface{} `json:"callbacks"` 23 } 24 25 // ImageTLSDirectory32 represents the IMAGE_TLS_DIRECTORY32 structure. 26 // It Points to the Thread Local Storage initialization section. 27 type ImageTLSDirectory32 struct { 28 29 // The starting address of the TLS template. The template is a block of data 30 // that is used to initialize TLS data. 31 StartAddressOfRawData uint32 `json:"start_address_of_raw_data"` 32 33 // The address of the last byte of the TLS, except for the zero fill. 34 // As with the Raw Data Start VA field, this is a VA, not an RVA. 35 EndAddressOfRawData uint32 `json:"end_address_of_raw_data"` 36 37 // The location to receive the TLS index, which the loader assigns. This 38 // location is in an ordinary data section, so it can be given a symbolic 39 // name that is accessible to the program. 40 AddressOfIndex uint32 `json:"address_of_index"` 41 42 // The pointer to an array of TLS callback functions. The array is 43 // null-terminated, so if no callback function is supported, this field 44 // points to 4 bytes set to zero. 45 AddressOfCallBacks uint32 `json:"address_of_callbacks"` 46 47 // The size in bytes of the template, beyond the initialized data delimited 48 // by the Raw Data Start VA and Raw Data End VA fields. The total template 49 // size should be the same as the total size of TLS data in the image file. 50 // The zero fill is the amount of data that comes after the initialized 51 // nonzero data. 52 SizeOfZeroFill uint32 `json:"size_of_zero_fill"` 53 54 // The four bits [23:20] describe alignment info. Possible values are those 55 // defined as IMAGE_SCN_ALIGN_*, which are also used to describe alignment 56 // of section in object files. The other 28 bits are reserved for future use. 57 Characteristics TLSDirectoryCharacteristicsType `json:"characteristics"` 58 } 59 60 // ImageTLSDirectory64 represents the IMAGE_TLS_DIRECTORY64 structure. 61 // It Points to the Thread Local Storage initialization section. 62 type ImageTLSDirectory64 struct { 63 // The starting address of the TLS template. The template is a block of data 64 // that is used to initialize TLS data. 65 StartAddressOfRawData uint64 `json:"start_address_of_raw_data"` 66 67 // The address of the last byte of the TLS, except for the zero fill. As 68 // with the Raw Data Start VA field, this is a VA, not an RVA. 69 EndAddressOfRawData uint64 `json:"end_address_of_raw_data"` 70 71 // The location to receive the TLS index, which the loader assigns. This 72 // location is in an ordinary data section, so it can be given a symbolic 73 // name that is accessible to the program. 74 AddressOfIndex uint64 `json:"address_of_index"` 75 76 // The pointer to an array of TLS callback functions. The array is 77 // null-terminated, so if no callback function is supported, this field 78 // points to 4 bytes set to zero. 79 AddressOfCallBacks uint64 `json:"address_of_callbacks"` 80 81 // The size in bytes of the template, beyond the initialized data delimited 82 // by the Raw Data Start VA and Raw Data End VA fields. The total template 83 // size should be the same as the total size of TLS data in the image file. 84 // The zero fill is the amount of data that comes after the initialized 85 // nonzero data. 86 SizeOfZeroFill uint32 `json:"size_of_zero_fill"` 87 88 // The four bits [23:20] describe alignment info. Possible values are those 89 // defined as IMAGE_SCN_ALIGN_*, which are also used to describe alignment 90 // of section in object files. The other 28 bits are reserved for future use. 91 Characteristics TLSDirectoryCharacteristicsType `json:"characteristics"` 92 } 93 94 // TLS provides direct PE and COFF support for static thread local storage (TLS). 95 // TLS is a special storage class that Windows supports in which a data object 96 // is not an automatic (stack) variable, yet is local to each individual thread 97 // that runs the code. Thus, each thread can maintain a different value for a 98 // variable declared by using TLS. 99 func (pe *File) parseTLSDirectory(rva, size uint32) error { 100 101 tls := TLSDirectory{} 102 103 if pe.Is64 { 104 tlsDir := ImageTLSDirectory64{} 105 tlsSize := uint32(binary.Size(tlsDir)) 106 fileOffset := pe.GetOffsetFromRva(rva) 107 err := pe.structUnpack(&tlsDir, fileOffset, tlsSize) 108 if err != nil { 109 return err 110 } 111 tls.Struct = tlsDir 112 113 if tlsDir.AddressOfCallBacks != 0 { 114 callbacks := make([]uint64, 0) 115 rvaAddressOfCallBacks := uint32(tlsDir.AddressOfCallBacks - 116 pe.NtHeader.OptionalHeader.(ImageOptionalHeader64).ImageBase) 117 offset := pe.GetOffsetFromRva(rvaAddressOfCallBacks) 118 for { 119 c, err := pe.ReadUint64(offset) 120 if err != nil || c == 0 { 121 break 122 } 123 callbacks = append(callbacks, c) 124 offset += 8 125 } 126 tls.Callbacks = callbacks 127 } 128 } else { 129 tlsDir := ImageTLSDirectory32{} 130 tlsSize := uint32(binary.Size(tlsDir)) 131 fileOffset := pe.GetOffsetFromRva(rva) 132 err := pe.structUnpack(&tlsDir, fileOffset, tlsSize) 133 if err != nil { 134 return err 135 } 136 tls.Struct = tlsDir 137 138 // 94a9dc17d47b03f6fb01cb639e25503b37761b452e7c07ec6b6c2280635f1df9 139 // Callbacks may be empty. 140 if tlsDir.AddressOfCallBacks != 0 { 141 callbacks := make([]uint32, 0) 142 rvaAddressOfCallBacks := tlsDir.AddressOfCallBacks - 143 pe.NtHeader.OptionalHeader.(ImageOptionalHeader32).ImageBase 144 offset := pe.GetOffsetFromRva(rvaAddressOfCallBacks) 145 for { 146 c, err := pe.ReadUint32(offset) 147 if err != nil || c == 0 { 148 break 149 } 150 callbacks = append(callbacks, c) 151 offset += 4 152 } 153 tls.Callbacks = callbacks 154 } 155 } 156 157 pe.TLS = tls 158 pe.HasTLS = true 159 return nil 160 } 161 162 // String returns the string representations of the `Characteristics` field of 163 // TLS directory. 164 func (characteristics TLSDirectoryCharacteristicsType) String() string { 165 166 m := map[TLSDirectoryCharacteristicsType]string{ 167 ImageSectionAlign1Bytes: "Align 1-Byte", 168 ImageSectionAlign2Bytes: "Align 2-Bytes", 169 ImageSectionAlign4Bytes: "Align 4-Bytes", 170 ImageSectionAlign8Bytes: "Align 8-Bytes", 171 ImageSectionAlign16Bytes: "Align 16-Bytes", 172 ImageSectionAlign32Bytes: "Align 32-Bytes", 173 ImageSectionAlign64Bytes: "Align 64-Bytes", 174 ImageSectionAlign128Bytes: "Align 128-Bytes", 175 ImageSectionAlign256Bytes: "Align 265-Bytes", 176 ImageSectionAlign512Bytes: "Align 512-Bytes", 177 ImageSectionAlign1024Bytes: "Align 1024-Bytes", 178 ImageSectionAlign2048Bytes: "Align 2048-Bytes", 179 ImageSectionAlign4096Bytes: "Align 4096-Bytes", 180 ImageSectionAlign8192Bytes: "Align 8192-Bytes", 181 } 182 183 v, ok := m[characteristics] 184 if ok { 185 return v 186 } 187 188 return "?" 189 }