github.com/saferwall/pe@v1.5.2/cmd/dump.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 main 6 7 import ( 8 "bytes" 9 "encoding/binary" 10 "encoding/hex" 11 "encoding/json" 12 "fmt" 13 "os" 14 "path/filepath" 15 "reflect" 16 "strings" 17 "sync" 18 "text/tabwriter" 19 "time" 20 "unicode" 21 "unsafe" 22 23 peparser "github.com/saferwall/pe" 24 "github.com/saferwall/pe/log" 25 ) 26 27 var ( 28 wg sync.WaitGroup 29 jobs chan string = make(chan string) 30 ) 31 32 func loopFilesWorker(cfg config) error { 33 for path := range jobs { 34 files, err := os.ReadDir(path) 35 if err != nil { 36 wg.Done() 37 return err 38 } 39 40 for _, file := range files { 41 if !file.IsDir() { 42 fullpath := filepath.Join(path, file.Name()) 43 parsePE(fullpath, cfg) 44 } 45 } 46 wg.Done() 47 } 48 return nil 49 } 50 51 func LoopDirsFiles(path string) error { 52 files, err := os.ReadDir(path) 53 if err != nil { 54 return err 55 } 56 57 go func() { 58 wg.Add(1) 59 jobs <- path 60 }() 61 for _, file := range files { 62 if file.IsDir() { 63 LoopDirsFiles(filepath.Join(path, file.Name())) 64 } 65 } 66 return nil 67 } 68 69 func prettyPrint(iface interface{}) string { 70 var prettyJSON bytes.Buffer 71 buff, _ := json.Marshal(iface) 72 err := json.Indent(&prettyJSON, buff, "", "\t") 73 if err != nil { 74 log.Errorf("JSON parse error: %v", err) 75 return string(buff) 76 } 77 78 return prettyJSON.String() 79 } 80 81 func humanizeTimestamp(ts uint32) string { 82 unixTimeUTC := time.Unix(int64(ts), 0) 83 return unixTimeUTC.String() 84 } 85 86 func hexDump(b []byte) { 87 var a [16]byte 88 n := (len(b) + 15) &^ 15 89 for i := 0; i < n; i++ { 90 if i%16 == 0 { 91 fmt.Printf("%4d", i) 92 } 93 if i%8 == 0 { 94 fmt.Print(" ") 95 } 96 if i < len(b) { 97 fmt.Printf(" %02X", b[i]) 98 } else { 99 fmt.Print(" ") 100 } 101 if i >= len(b) { 102 a[i%16] = ' ' 103 } else if b[i] < 32 || b[i] > 126 { 104 a[i%16] = '.' 105 } else { 106 a[i%16] = b[i] 107 } 108 if i%16 == 15 { 109 fmt.Printf(" %s\n", string(a[:])) 110 } 111 } 112 } 113 114 func hexDumpSize(b []byte, size int) { 115 var a [16]byte 116 117 // Append null bytes when length of the buffer 118 // is smaller than the requested size. 119 if len(b) < size { 120 temp := make([]byte, size) 121 copy(temp, b) 122 b = temp 123 } 124 125 n := (size + 15) &^ 15 126 for i := 0; i < n; i++ { 127 if i%16 == 0 { 128 fmt.Printf("%4d", i) 129 } 130 if i%8 == 0 { 131 fmt.Print(" ") 132 } 133 if i < len(b) { 134 fmt.Printf(" %02X", b[i]) 135 } else { 136 fmt.Print(" ") 137 } 138 if i >= len(b) { 139 a[i%16] = ' ' 140 } else if b[i] < 32 || b[i] > 126 { 141 a[i%16] = '.' 142 } else { 143 a[i%16] = b[i] 144 } 145 if i%16 == 15 { 146 fmt.Printf(" %s\n", string(a[:])) 147 } 148 } 149 } 150 151 func IntToByteArray(num uint64) []byte { 152 size := int(unsafe.Sizeof(num)) 153 arr := make([]byte, size) 154 for i := 0; i < size; i++ { 155 byt := *(*uint8)(unsafe.Pointer(uintptr(unsafe.Pointer(&num)) + uintptr(i))) 156 arr[i] = byt 157 } 158 return arr 159 } 160 161 func sentenceCase(s string) string { 162 newString := string(s[0]) 163 for i, r := range s[1:] { 164 if unicode.IsLower(r) && unicode.IsLetter(r) { 165 newString += string(r) 166 } else { 167 if i < len(s)-2 { 168 nextChar := rune(s[i+2]) 169 previousChar := rune(s[i]) 170 if unicode.IsLower(previousChar) && unicode.IsLetter(previousChar) { 171 newString += " " + string(r) 172 } else { 173 if unicode.IsLower(nextChar) && unicode.IsLetter(nextChar) { 174 newString += " " + string(r) 175 } else { 176 newString += string(r) 177 } 178 } 179 } 180 } 181 } 182 183 return newString 184 } 185 186 func isDirectory(path string) bool { 187 fileInfo, err := os.Stat(path) 188 if err != nil { 189 return false 190 } 191 return fileInfo.IsDir() 192 } 193 194 func parse(filePath string, cfg config) { 195 196 // filePath points to a file. 197 if !isDirectory(filePath) { 198 parsePE(filePath, cfg) 199 200 } else { 201 // filePath points to a directory, 202 // walk recursively through all files. 203 fileList := []string{} 204 filepath.Walk(filePath, func(path string, f os.FileInfo, err error) error { 205 if !isDirectory(path) { 206 fileList = append(fileList, path) 207 } 208 return nil 209 }) 210 211 for _, file := range fileList { 212 parsePE(file, cfg) 213 } 214 } 215 } 216 217 func parsePE(filename string, cfg config) { 218 219 logger := log.NewStdLogger(os.Stdout) 220 logger = log.NewFilter(logger, log.FilterLevel(log.LevelInfo)) 221 log := log.NewHelper(logger) 222 223 log.Infof("parsing filename %s", filename) 224 225 data, _ := os.ReadFile(filename) 226 pe, err := peparser.NewBytes(data, &peparser.Options{ 227 Logger: logger, 228 DisableCertValidation: false, 229 Fast: false, 230 }) 231 232 if err != nil { 233 log.Infof("Error while opening file: %s, reason: %s", filename, err) 234 return 235 } 236 defer pe.Close() 237 238 err = pe.Parse() 239 if err != nil { 240 if err != peparser.ErrDOSMagicNotFound { 241 log.Infof("Error while parsing file: %s, reason: %s", filename, err) 242 } 243 return 244 } 245 246 // Dump all results to disk in JSON format. 247 // f, err := os.Create("out.json") 248 // if err != nil { 249 // return 250 // } 251 // defer f.Close() 252 // f.WriteString(prettyPrint(pe)) 253 254 if cfg.wantDOSHeader { 255 DOSHeader := pe.DOSHeader 256 magic := string(IntToByteArray(uint64(DOSHeader.Magic))) 257 signature := string(IntToByteArray(uint64(pe.NtHeader.Signature))) 258 w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', tabwriter.AlignRight) 259 fmt.Print("\n\t------[ DOS Header ]------\n\n") 260 fmt.Fprintf(w, "Magic:\t 0x%x (%s)\n", DOSHeader.Magic, magic) 261 fmt.Fprintf(w, "Bytes On Last Page Of File:\t 0x%x\n", DOSHeader.BytesOnLastPageOfFile) 262 fmt.Fprintf(w, "Pages In File:\t 0x%x\n", DOSHeader.PagesInFile) 263 fmt.Fprintf(w, "Relocations:\t 0x%x\n", DOSHeader.Relocations) 264 fmt.Fprintf(w, "Size Of Header:\t 0x%x\n", DOSHeader.SizeOfHeader) 265 fmt.Fprintf(w, "Min Extra Paragraphs Needed:\t 0x%x\n", DOSHeader.MinExtraParagraphsNeeded) 266 fmt.Fprintf(w, "Max Extra Paragraphs Needed:\t 0x%x\n", DOSHeader.MaxExtraParagraphsNeeded) 267 fmt.Fprintf(w, "Initial SS:\t 0x%x\n", DOSHeader.InitialSS) 268 fmt.Fprintf(w, "Initial SP:\t 0x%x\n", DOSHeader.InitialSP) 269 fmt.Fprintf(w, "Checksum:\t 0x%x\n", DOSHeader.Checksum) 270 fmt.Fprintf(w, "Initial IP:\t 0x%x\n", DOSHeader.InitialIP) 271 fmt.Fprintf(w, "Initial CS:\t 0x%x\n", DOSHeader.InitialCS) 272 fmt.Fprintf(w, "Address Of Relocation Table:\t 0x%x\n", DOSHeader.AddressOfRelocationTable) 273 fmt.Fprintf(w, "Overlay Number:\t 0x%x\n", DOSHeader.OverlayNumber) 274 fmt.Fprintf(w, "OEM Identifier:\t 0x%x\n", DOSHeader.OEMIdentifier) 275 fmt.Fprintf(w, "OEM Information:\t 0x%x\n", DOSHeader.OEMInformation) 276 fmt.Fprintf(w, "Address Of New EXE Header:\t 0x%x (%s)\n", DOSHeader.AddressOfNewEXEHeader, signature) 277 w.Flush() 278 } 279 280 if cfg.wantRichHeader && pe.FileInfo.HasRichHdr { 281 richHeader := pe.RichHeader 282 fmt.Printf("\nRICH HEADER\n***********\n") 283 w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', tabwriter.AlignRight) 284 fmt.Fprintf(w, "\t0x%x\t XOR Key\n", richHeader.XORKey) 285 fmt.Fprintf(w, "\t0x%x\t DanS offset\n", richHeader.DansOffset) 286 fmt.Fprintf(w, "\t0x%x\t Checksum\n\n", pe.RichHeaderChecksum()) 287 fmt.Fprintln(w, "ProductID\tMinorCV\tCount\tUnmasked\tMeaning\tVSVersion\t") 288 for _, compID := range pe.RichHeader.CompIDs { 289 fmt.Fprintf(w, "0x%x\t0x%x\t0x%x\t0x%x\t%s\t%s\t\n", 290 compID.ProdID, compID.MinorCV, compID.Count, compID.Unmasked, 291 peparser.ProdIDtoStr(compID.ProdID), peparser.ProdIDtoVSversion(compID.ProdID)) 292 } 293 w.Flush() 294 fmt.Print("\n ---Raw header dump---\n") 295 hexDump(richHeader.Raw) 296 } 297 298 if cfg.wantNTHeader { 299 ntHeader := pe.NtHeader.FileHeader 300 w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', tabwriter.AlignRight) 301 characteristics := strings.Join(ntHeader.Characteristics.String(), " | ") 302 303 fmt.Print("\n\t------[ File Header ]------\n\n") 304 fmt.Fprintf(w, "Machine:\t 0x%x (%s)\n", int(ntHeader.Machine), ntHeader.Machine.String()) 305 fmt.Fprintf(w, "Number Of Sections:\t 0x%x\n", ntHeader.NumberOfSections) 306 fmt.Fprintf(w, "TimeDateStamp:\t 0x%x (%s)\n", ntHeader.TimeDateStamp, humanizeTimestamp(ntHeader.TimeDateStamp)) 307 fmt.Fprintf(w, "Pointer To Symbol Table:\t 0x%x\n", ntHeader.PointerToSymbolTable) 308 fmt.Fprintf(w, "Number Of Symbols:\t 0x%x\n", ntHeader.NumberOfSymbols) 309 fmt.Fprintf(w, "Number Of Symbols:\t 0x%x\n", ntHeader.NumberOfSymbols) 310 fmt.Fprintf(w, "Size Of Optional Header:\t 0x%x\n", ntHeader.SizeOfOptionalHeader) 311 fmt.Fprintf(w, "Characteristics:\t 0x%x (%s)\n", ntHeader.Characteristics, characteristics) 312 w.Flush() 313 314 fmt.Print("\n\t------[ Optional Header ]------\n\n") 315 if pe.Is64 { 316 oh := pe.NtHeader.OptionalHeader.(peparser.ImageOptionalHeader64) 317 dllCharacteristics := strings.Join(oh.DllCharacteristics.String(), " | ") 318 fmt.Fprintf(w, "Magic:\t 0x%x (%s)\n", oh.Magic, pe.PrettyOptionalHeaderMagic()) 319 fmt.Fprintf(w, "Major Linker Version:\t 0x%x\n", oh.MajorLinkerVersion) 320 fmt.Fprintf(w, "Minor Linker Version:\t 0x%x\n", oh.MinorLinkerVersion) 321 fmt.Fprintf(w, "Size Of Code:\t 0x%x (%s)\n", oh.SizeOfCode, BytesSize(float64(oh.SizeOfCode))) 322 fmt.Fprintf(w, "Size Of Initialized Data:\t 0x%x (%s)\n", oh.SizeOfInitializedData, 323 BytesSize(float64(oh.SizeOfInitializedData))) 324 fmt.Fprintf(w, "Size Of Uninitialized Data:\t 0x%x (%s)\n", oh.SizeOfUninitializedData, 325 BytesSize(float64(oh.SizeOfUninitializedData))) 326 fmt.Fprintf(w, "Address Of Entry Point:\t 0x%x\n", oh.AddressOfEntryPoint) 327 fmt.Fprintf(w, "Base Of Code:\t 0x%x\n", oh.BaseOfCode) 328 fmt.Fprintf(w, "Image Base:\t 0x%x\n", oh.ImageBase) 329 fmt.Fprintf(w, "Section Alignment:\t 0x%x (%s)\n", oh.SectionAlignment, 330 BytesSize(float64(oh.SectionAlignment))) 331 fmt.Fprintf(w, "File Alignment:\t 0x%x (%s)\n", oh.FileAlignment, 332 BytesSize(float64(oh.FileAlignment))) 333 fmt.Fprintf(w, "Major OS Version:\t 0x%x\n", oh.MajorOperatingSystemVersion) 334 fmt.Fprintf(w, "Minor OS Version:\t 0x%x\n", oh.MinorOperatingSystemVersion) 335 fmt.Fprintf(w, "Major Image Version:\t 0x%x\n", oh.MajorImageVersion) 336 fmt.Fprintf(w, "Minor Image Version:\t 0x%x\n", oh.MinorImageVersion) 337 fmt.Fprintf(w, "Major Subsystem Version:\t 0x%x\n", oh.MajorSubsystemVersion) 338 fmt.Fprintf(w, "Minor Subsystem Version:\t 0x%x\n", oh.MinorSubsystemVersion) 339 fmt.Fprintf(w, "Win32 Version Value:\t 0x%x\n", oh.Win32VersionValue) 340 fmt.Fprintf(w, "Size Of Image:\t 0x%x (%s)\n", oh.SizeOfImage, BytesSize(float64(oh.SizeOfImage))) 341 fmt.Fprintf(w, "Size Of Headers:\t 0x%x (%s)\n", oh.SizeOfHeaders, BytesSize(float64(oh.SizeOfHeaders))) 342 fmt.Fprintf(w, "Checksum:\t 0x%x\n", oh.CheckSum) 343 fmt.Fprintf(w, "Subsystem:\t 0x%x (%s)\n", uint16(oh.Subsystem), oh.Subsystem.String()) 344 fmt.Fprintf(w, "Dll Characteristics:\t 0x%x (%s)\n", uint16(oh.DllCharacteristics), dllCharacteristics) 345 fmt.Fprintf(w, "Size Of Stack Reserve:\t 0x%x (%s)\n", oh.SizeOfStackReserve, BytesSize(float64(oh.SizeOfStackReserve))) 346 fmt.Fprintf(w, "Size Of Stack Commit:\t 0x%x (%s)\n", oh.SizeOfStackCommit, BytesSize(float64(oh.SizeOfStackCommit))) 347 fmt.Fprintf(w, "Size Of Heap Reserve:\t 0x%x (%s)\n", oh.SizeOfHeapReserve, BytesSize(float64(oh.SizeOfHeapReserve))) 348 fmt.Fprintf(w, "Size Of Heap Commit:\t 0x%x (%s)\n", oh.SizeOfHeapCommit, BytesSize(float64(oh.SizeOfHeapCommit))) 349 fmt.Fprintf(w, "Loader Flags:\t 0x%x\n", oh.LoaderFlags) 350 fmt.Fprintf(w, "Number Of RVA And Sizes:\t 0x%x\n", oh.NumberOfRvaAndSizes) 351 fmt.Fprintf(w, "\n") 352 for entry := peparser.ImageDirectoryEntry(0); entry < peparser.ImageNumberOfDirectoryEntries; entry++ { 353 rva := oh.DataDirectory[entry].VirtualAddress 354 size := oh.DataDirectory[entry].Size 355 fmt.Fprintf(w, "%s Table:\t RVA: 0x%0.8x\t Size:0x%0.8x\t\n", entry.String(), rva, size) 356 } 357 } else { 358 oh := pe.NtHeader.OptionalHeader.(peparser.ImageOptionalHeader32) 359 dllCharacteristics := strings.Join(oh.DllCharacteristics.String(), " | ") 360 fmt.Fprintf(w, "Magic:\t 0x%x (%s)\n", oh.Magic, pe.PrettyOptionalHeaderMagic()) 361 fmt.Fprintf(w, "Major Linker Version:\t 0x%x\n", oh.MajorLinkerVersion) 362 fmt.Fprintf(w, "Minor Linker Version:\t 0x%x\n", oh.MinorLinkerVersion) 363 fmt.Fprintf(w, "Size Of Code:\t 0x%x (%s)\n", oh.SizeOfCode, BytesSize(float64(oh.SizeOfCode))) 364 fmt.Fprintf(w, "Size Of Initialized Data:\t 0x%x (%s)\n", oh.SizeOfInitializedData, 365 BytesSize(float64(oh.SizeOfInitializedData))) 366 fmt.Fprintf(w, "Size Of Uninitialized Data:\t 0x%x (%s)\n", oh.SizeOfUninitializedData, 367 BytesSize(float64(oh.SizeOfUninitializedData))) 368 fmt.Fprintf(w, "Address Of Entry Point:\t 0x%x\n", oh.AddressOfEntryPoint) 369 fmt.Fprintf(w, "Base Of Code:\t 0x%x\n", oh.BaseOfCode) 370 fmt.Fprintf(w, "Image Base:\t 0x%x\n", oh.ImageBase) 371 fmt.Fprintf(w, "Section Alignment:\t 0x%x (%s)\n", oh.SectionAlignment, 372 BytesSize(float64(oh.SectionAlignment))) 373 fmt.Fprintf(w, "File Alignment:\t 0x%x (%s)\n", oh.FileAlignment, 374 BytesSize(float64(oh.FileAlignment))) 375 fmt.Fprintf(w, "Major OS Version:\t 0x%x\n", oh.MajorOperatingSystemVersion) 376 fmt.Fprintf(w, "Minor OS Version:\t 0x%x\n", oh.MinorOperatingSystemVersion) 377 fmt.Fprintf(w, "Major Image Version:\t 0x%x\n", oh.MajorImageVersion) 378 fmt.Fprintf(w, "Minor Image Version:\t 0x%x\n", oh.MinorImageVersion) 379 fmt.Fprintf(w, "Major Subsystem Version:\t 0x%x\n", oh.MajorSubsystemVersion) 380 fmt.Fprintf(w, "Minor Subsystem Version:\t 0x%x\n", oh.MinorSubsystemVersion) 381 fmt.Fprintf(w, "Win32 Version Value:\t 0x%x\n", oh.Win32VersionValue) 382 fmt.Fprintf(w, "Size Of Image:\t 0x%x (%s)\n", oh.SizeOfImage, BytesSize(float64(oh.SizeOfImage))) 383 fmt.Fprintf(w, "Size Of Headers:\t 0x%x (%s)\n", oh.SizeOfHeaders, BytesSize(float64(oh.SizeOfHeaders))) 384 fmt.Fprintf(w, "Checksum:\t 0x%x\n", oh.CheckSum) 385 fmt.Fprintf(w, "Subsystem:\t 0x%x (%s)\n", uint16(oh.Subsystem), oh.Subsystem.String()) 386 fmt.Fprintf(w, "Dll Characteristics:\t 0x%x (%s)\n", uint16(oh.DllCharacteristics), dllCharacteristics) 387 fmt.Fprintf(w, "Size Of Stack Reserve:\t 0x%x (%s)\n", oh.SizeOfStackReserve, BytesSize(float64(oh.SizeOfStackReserve))) 388 fmt.Fprintf(w, "Size Of Stack Commit:\t 0x%x (%s)\n", oh.SizeOfStackCommit, BytesSize(float64(oh.SizeOfStackCommit))) 389 fmt.Fprintf(w, "Size Of Heap Reserve:\t 0x%x (%s)\n", oh.SizeOfHeapReserve, BytesSize(float64(oh.SizeOfHeapReserve))) 390 fmt.Fprintf(w, "Size Of Heap Commit:\t 0x%x (%s)\n", oh.SizeOfHeapCommit, BytesSize(float64(oh.SizeOfHeapCommit))) 391 fmt.Fprintf(w, "Loader Flags:\t 0x%x\n", oh.LoaderFlags) 392 fmt.Fprintf(w, "Number Of RVA And Sizes:\t 0x%x\n", oh.NumberOfRvaAndSizes) 393 fmt.Fprintf(w, "\n") 394 for entry := peparser.ImageDirectoryEntry(0); entry < peparser.ImageNumberOfDirectoryEntries; entry++ { 395 rva := oh.DataDirectory[entry].VirtualAddress 396 size := oh.DataDirectory[entry].Size 397 fmt.Fprintf(w, "%s Table:\t RVA: 0x%0.8x\t Size:0x%0.8x\t\n", entry.String(), rva, size) 398 } 399 } 400 w.Flush() 401 } 402 403 if cfg.wantCOFF && pe.FileInfo.HasCOFF { 404 fmt.Printf("\nCOFF\n****\n") 405 w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', tabwriter.AlignRight) 406 fmt.Fprintln(w, "Name\tValue\tSectionNumber\tType\tStorageClass\tNumberOfAuxSymbols\t") 407 for _, sym := range pe.COFF.SymbolTable { 408 symName, _ := sym.String(pe) 409 fmt.Fprintf(w, "%s\t0x%x\t0x%x\t0x%x\t0x%x\t0x%x\t\n", 410 symName, sym.Value, sym.SectionNumber, 411 sym.Type, sym.StorageClass, sym.NumberOfAuxSymbols) 412 } 413 w.Flush() 414 } 415 416 if cfg.wantSections && pe.FileInfo.HasSections { 417 w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', tabwriter.AlignRight) 418 for i, sec := range pe.Sections { 419 hdr := sec.Header 420 fmt.Printf("\n\t------[ Section Header #%d ]------\n\n", i) 421 fmt.Fprintf(w, "Name:\t %v (%s)\n", hdr.Name, sec.String()) 422 fmt.Fprintf(w, "Virtual Size:\t 0x%x (%s)\n", hdr.VirtualSize, 423 BytesSize(float64(hdr.VirtualSize))) 424 fmt.Fprintf(w, "Virtual Address:\t 0x%x\n", hdr.VirtualAddress) 425 fmt.Fprintf(w, "Size Of Raw Data Size:\t 0x%x (%s)\n", hdr.SizeOfRawData, 426 BytesSize(float64(hdr.SizeOfRawData))) 427 fmt.Fprintf(w, "Pointer To Raw Data:\t 0x%x\n", hdr.PointerToRawData) 428 fmt.Fprintf(w, "Pointer To Relocations:\t 0x%x\n", hdr.PointerToRelocations) 429 fmt.Fprintf(w, "Pointer To Line Numbers:\t 0x%x\n", hdr.PointerToLineNumbers) 430 fmt.Fprintf(w, "Number Of Relocations:\t 0x%x\n", hdr.NumberOfRelocations) 431 fmt.Fprintf(w, "Number Of Line Numbers:\t 0x%x\n", hdr.NumberOfLineNumbers) 432 fmt.Fprintf(w, "Characteristics:\t 0x%x (%s)\n", hdr.Characteristics, 433 strings.Join(sec.PrettySectionFlags(), " | ")) 434 fmt.Fprintf(w, "Entropy:\t %f\n", sec.CalculateEntropy(pe)) 435 w.Flush() 436 437 fmt.Fprintf(w, "\n") 438 hexDumpSize(sec.Data(0, hdr.PointerToRawData, pe), 128) 439 } 440 } 441 442 if cfg.wantImport && pe.FileInfo.HasImport { 443 fmt.Printf("\nIMPORTS\n********\n") 444 w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', tabwriter.AlignRight) 445 for _, imp := range pe.Imports { 446 desc := imp.Descriptor 447 fmt.Printf("\n\t------[ %s ]------\n\n", imp.Name) 448 fmt.Fprintf(w, "Name:\t 0x%x\n", desc.Name) 449 fmt.Fprintf(w, "Original First Thunk:\t 0x%x\n", desc.OriginalFirstThunk) 450 fmt.Fprintf(w, "First Thunk:\t 0x%x\n", desc.FirstThunk) 451 fmt.Fprintf(w, "TimeDateStamp:\t 0x%x (%s\n", desc.TimeDateStamp, 452 humanizeTimestamp(desc.TimeDateStamp)) 453 fmt.Fprintf(w, "Forwarder Chain:\t 0x%x\n", desc.ForwarderChain) 454 fmt.Fprintf(w, "\n") 455 fmt.Fprintln(w, "Name\tThunkRVA\tThunkValue\tOriginalThunkRVA\tOriginalThunkValue\tHint\t") 456 for _, impFunc := range imp.Functions { 457 fmt.Fprintf(w, "%s\t0x%x\t0x%x\t0x%x\t0x%x\t0x%x\t\n", 458 impFunc.Name, impFunc.ThunkRVA, impFunc.ThunkValue, 459 impFunc.OriginalThunkRVA, impFunc.OriginalThunkValue, impFunc.Hint) 460 } 461 w.Flush() 462 463 } 464 } 465 466 if cfg.wantResource && pe.FileInfo.HasResource { 467 var printRsrcDir func(rsrcDir peparser.ResourceDirectory) 468 padding := 0 469 470 printRsrcDataEntry := func(entry peparser.ResourceDataEntry) { 471 padding++ 472 w := tabwriter.NewWriter(os.Stdout, 1, 1, padding, ' ', 0) 473 imgRsrcDataEntry := entry.Struct 474 fmt.Fprintf(w, "\n\t\u27A1 Resource Data Entry\n\t") 475 fmt.Fprintf(w, "|- Offset To Data: 0x%x\n\t", imgRsrcDataEntry.OffsetToData) 476 fmt.Fprintf(w, "|- Size: 0x%x\n\t", imgRsrcDataEntry.Size) 477 fmt.Fprintf(w, "|- Code Page: 0x%x\n\t", imgRsrcDataEntry.CodePage) 478 fmt.Fprintf(w, "|- Reserved: 0x%x\n\t", imgRsrcDataEntry.Reserved) 479 fmt.Fprintf(w, "|- Language: %d (%s)\n\t", entry.Lang, entry.Lang.String()) 480 fmt.Fprintf(w, "|- Sub-language: %s\n\t", peparser.PrettyResourceLang(entry.Lang, int(entry.SubLang))) 481 w.Flush() 482 padding-- 483 } 484 485 printRsrcDir = func(rsrcDir peparser.ResourceDirectory) { 486 padding++ 487 w := tabwriter.NewWriter(os.Stdout, 1, 1, padding, ' ', 0) 488 imgRsrcDir := rsrcDir.Struct 489 fmt.Fprintf(w, "\n\t\u27A1 Resource Directory\n\t") 490 fmt.Fprintf(w, "|- Characteristics: 0x%x\n\t", imgRsrcDir.Characteristics) 491 fmt.Fprintf(w, "|- TimeDateStamp: 0x%x\n\t", imgRsrcDir.TimeDateStamp) 492 fmt.Fprintf(w, "|- Major Version: 0x%x\n\t", imgRsrcDir.MajorVersion) 493 fmt.Fprintf(w, "|- Minor Version: 0x%x\n\t", imgRsrcDir.MinorVersion) 494 fmt.Fprintf(w, "|- Number Of Named Entries: 0x%x\n\t", imgRsrcDir.NumberOfNamedEntries) 495 fmt.Fprintf(w, "|- Number Of ID Entries: 0x%x\n\t", imgRsrcDir.NumberOfIDEntries) 496 fmt.Fprintf(w, "|----------------------------------\n\t") 497 padding++ 498 w.Flush() 499 w = tabwriter.NewWriter(os.Stdout, 1, 1, padding, ' ', 0) 500 for i, entry := range rsrcDir.Entries { 501 fmt.Fprintf(w, "\t|- \u27A1 Resource Directory Entry %d, ID: %d", i+1, entry.ID) 502 503 // Print the interpretation of a resource ID only in root node. 504 if padding == 2 { 505 if entry.ID <= peparser.RTManifest { 506 fmt.Fprintf(w, " (%s)", peparser.ResourceType(entry.ID).String()) 507 } 508 } 509 fmt.Fprintf(w, "\n\t|- Name: 0x%x\n\t", entry.Struct.Name) 510 if entry.Name != "" { 511 fmt.Fprintf(w, " (%s)", entry.Name) 512 } 513 fmt.Fprintf(w, "|- Offset To Data: 0x%x\t", entry.Struct.OffsetToData) 514 fmt.Fprintf(w, "\n\t|----------------------------------\t") 515 w.Flush() 516 if entry.IsResourceDir { 517 printRsrcDir(entry.Directory) 518 } else { 519 printRsrcDataEntry(entry.Data) 520 } 521 522 } 523 padding -= 2 524 525 } 526 527 fmt.Printf("\nRESOURCES\n**********\n") 528 printRsrcDir(pe.Resources) 529 530 versionInfo, err := pe.ParseVersionResources() 531 if err != nil { 532 log.Errorf("failed to parse version resources: %v", err) 533 } else { 534 fmt.Printf("\nVersion Info: %v", prettyPrint(versionInfo)) 535 } 536 } 537 538 if cfg.wantException && pe.FileInfo.HasException { 539 fmt.Printf("\nEXCEPTIONS\n***********\n") 540 for _, exception := range pe.Exceptions { 541 entry := exception.RuntimeFunction 542 fmt.Printf("\n\u27A1 BeginAddress: 0x%x EndAddress:0x%x UnwindInfoAddress:0x%x\t\n", 543 entry.BeginAddress, entry.EndAddress, entry.UnwindInfoAddress) 544 545 ui := exception.UnwindInfo 546 handlerFlags := peparser.PrettyUnwindInfoHandlerFlags(ui.Flags) 547 prettyFlags := strings.Join(handlerFlags, ",") 548 fmt.Printf("|- Version: 0x%x\n", ui.Version) 549 fmt.Printf("|- Flags: 0x%x", ui.Flags) 550 if ui.Flags == 0 { 551 fmt.Print(" (None)\n") 552 } else { 553 fmt.Printf(" (%s)\n", prettyFlags) 554 } 555 556 fmt.Printf("|- Size Of Prolog: 0x%x\n", ui.SizeOfProlog) 557 fmt.Printf("|- Count Of Codes: 0x%x\n", ui.CountOfCodes) 558 fmt.Printf("|- Exception Handler: 0x%x\n", ui.ExceptionHandler) 559 fmt.Print("|- Unwind codes:\n") 560 for _, uc := range ui.UnwindCodes { 561 fmt.Printf("|- * %.2x: %s, %s\n", uc.CodeOffset, 562 uc.UnwindOp.String(), uc.Operand) 563 } 564 } 565 } 566 567 if cfg.wantCertificate && pe.FileInfo.HasCertificate { 568 fmt.Printf("\nSECURITY\n*********\n") 569 570 cert := pe.Certificates 571 w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', tabwriter.AlignRight) 572 fmt.Fprintln(w, "Length\tRevision\tCertificateType\t") 573 fmt.Fprintf(w, "0x%x\t0x%x\t0x%x\t\n", cert.Header.Length, cert.Header.Revision, 574 cert.Header.CertificateType) 575 w.Flush() 576 fmt.Print("\n ---Raw Certificate dump---\n") 577 hexDump(cert.Raw) 578 fmt.Print("\n---Certificate ---\n\n") 579 fmt.Fprintf(w, "Issuer Name:\t %s\n", cert.Info.Issuer) 580 fmt.Fprintf(w, "Subject Name:\t %s\n", cert.Info.Subject) 581 fmt.Fprintf(w, "Serial Number:\t %x\n", cert.Info.SerialNumber) 582 fmt.Fprintf(w, "Validity From:\t %s to %s\n", cert.Info.NotBefore.String(), cert.Info.NotAfter.String()) 583 fmt.Fprintf(w, "Signature Algorithm:\t %s\n", cert.Info.SignatureAlgorithm.String()) 584 fmt.Fprintf(w, "PublicKey Algorithm:\t %s\n", cert.Info.PublicKeyAlgorithm.String()) 585 w.Flush() 586 587 // Calculate the PE authentihash. 588 pe.Authentihash() 589 } 590 591 if cfg.wantReloc && pe.FileInfo.HasReloc { 592 fmt.Printf("\nRELOCATIONS\n***********\n") 593 for _, reloc := range pe.Relocations { 594 fmt.Printf("\n\u27A1 Virtual Address: 0x%x | Size Of Block:0x%x | Entries Count:0x%x\t\n", 595 reloc.Data.VirtualAddress, reloc.Data.SizeOfBlock, len(reloc.Entries)) 596 fmt.Print("|- Entries:\n") 597 for _, relocEntry := range reloc.Entries { 598 fmt.Printf("|- Data: 0x%x | Offset: 0x%x | Type:0x%x (%s)\n", relocEntry.Data, 599 relocEntry.Offset, relocEntry.Type, relocEntry.Type.String(pe)) 600 } 601 } 602 } 603 604 if cfg.wantDebug && pe.FileInfo.HasDebug { 605 fmt.Printf("\nDEBUGS\n*******\n") 606 w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', tabwriter.AlignRight) 607 for _, debug := range pe.Debugs { 608 imgDbgDir := debug.Struct 609 fmt.Fprintf(w, "\n\t------[ %s ]------\n", debug.Type) 610 fmt.Fprintf(w, "Characteristics:\t 0x%x\n", imgDbgDir.Characteristics) 611 fmt.Fprintf(w, "TimeDateStamp:\t 0x%x (%s)\n", imgDbgDir.TimeDateStamp, 612 humanizeTimestamp(imgDbgDir.TimeDateStamp)) 613 fmt.Fprintf(w, "Major Version:\t 0x%x\n", imgDbgDir.MajorVersion) 614 fmt.Fprintf(w, "Minor Version:\t 0x%x\n", imgDbgDir.MinorVersion) 615 fmt.Fprintf(w, "Type:\t 0x%x\n", imgDbgDir.Type) 616 fmt.Fprintf(w, "Size Of Data:\t 0x%x (%s)\n", imgDbgDir.SizeOfData, 617 BytesSize(float64(imgDbgDir.SizeOfData))) 618 fmt.Fprintf(w, "Address Of Raw Data:\t 0x%x\n", imgDbgDir.AddressOfRawData) 619 fmt.Fprintf(w, "Pointer To Raw Data:\t 0x%x\n", imgDbgDir.PointerToRawData) 620 fmt.Fprintf(w, "\n") 621 switch imgDbgDir.Type { 622 case peparser.ImageDebugTypeCodeView: 623 debugSignature, err := pe.ReadUint32(imgDbgDir.PointerToRawData) 624 if err != nil { 625 continue 626 } 627 if debugSignature == peparser.CVSignatureRSDS { 628 pdb := debug.Info.(peparser.CVInfoPDB70) 629 fmt.Fprintf(w, "CV Signature:\t 0x%x (%s)\n", pdb.CVSignature, 630 pdb.CVSignature.String()) 631 fmt.Fprintf(w, "Signature:\t %s\n", pdb.Signature.String()) 632 fmt.Fprintf(w, "Age:\t 0x%x\n", pdb.Age) 633 fmt.Fprintf(w, "PDB FileName:\t %s\n", pdb.PDBFileName) 634 } else if debugSignature == peparser.CVSignatureNB10 { 635 pdb := debug.Info.(peparser.CVInfoPDB20) 636 fmt.Fprintf(w, "CV Header Signature:\t 0x%x (%s)\n", 637 pdb.CVHeader.Signature, pdb.CVHeader.Signature.String()) 638 fmt.Fprintf(w, "CV Header Offset:\t 0x%x\n", pdb.CVHeader.Offset) 639 fmt.Fprintf(w, "Signature:\t 0x%x (%s)\n", pdb.Signature, 640 humanizeTimestamp(pdb.Signature)) 641 fmt.Fprintf(w, "Age:\t 0x%x\n", pdb.Age) 642 fmt.Fprintf(w, "PDBFileName:\t %s\n", pdb.PDBFileName) 643 644 } 645 case peparser.ImageDebugTypePOGO: 646 pogo := debug.Info.(peparser.POGO) 647 if len(pogo.Entries) > 0 { 648 fmt.Fprintf(w, "Signature:\t 0x%x (%s)\n\n", pogo.Signature, 649 pogo.Signature.String()) 650 fmt.Fprintln(w, "RVA\tSize\tName\tDescription\t") 651 fmt.Fprintln(w, "---\t----\t----\t-----------\t") 652 for _, pogoEntry := range pogo.Entries { 653 fmt.Fprintf(w, "0x%x\t0x%x\t%s\t%s\t\n", pogoEntry.RVA, 654 pogoEntry.Size, pogoEntry.Name, 655 peparser.SectionAttributeDescription(pogoEntry.Name)) 656 } 657 } 658 case peparser.ImageDebugTypeRepro: 659 repro := debug.Info.(peparser.REPRO) 660 fmt.Fprintf(w, "Hash:\t %x\n", repro.Hash) 661 fmt.Fprintf(w, "Size:\t 0x%x (%s)\n", repro.Size, BytesSize(float64(repro.Size))) 662 case peparser.ImageDebugTypeExDllCharacteristics: 663 exDllCharacteristics := debug.Info.(peparser.DllCharacteristicsExType) 664 fmt.Fprintf(w, "Value:\t %d (%s)\n", exDllCharacteristics, 665 exDllCharacteristics.String()) 666 case peparser.ImageDebugTypeVCFeature: 667 VCFeature := debug.Info.(peparser.VCFeature) 668 fmt.Fprintf(w, "Pre VC11:\t 0x%x\n", VCFeature.PreVC11) 669 fmt.Fprintf(w, "C/C++:\t 0x%x\n", VCFeature.CCpp) 670 fmt.Fprintf(w, "/GS:\t 0x%x\n", VCFeature.Gs) 671 fmt.Fprintf(w, "/sdl:\t 0x%x\n", VCFeature.Sdl) 672 fmt.Fprintf(w, "GuardN:\t 0x%x\n", VCFeature.GuardN) 673 case peparser.ImageDebugTypeFPO: 674 fpo := debug.Info.([]peparser.FPOData) 675 if len(fpo) > 0 { 676 fmt.Fprintln(w, "OffsetStart\tProcSize\tNumLocals\tParamsSize\tPrologLength\tSavedRegsCount\tHasSEH\tUseBP\tReserved\tFrameType\t") 677 fmt.Fprintln(w, "------\t------\t------\t------\t------\t------\t------\t------\t------\t------\t") 678 for _, fpoData := range fpo { 679 fmt.Fprintf(w, "0x%x\t0x%x\t0x%x\t0x%x\t0x%x\t0x%x\t0x%x\t0x%x\t0x%x\t%d (%s)\t\n", 680 fpoData.OffsetStart, fpoData.ProcSize, fpoData.NumLocals, 681 fpoData.ParamsSize, fpoData.PrologLength, 682 fpoData.SavedRegsCount, fpoData.HasSEH, fpoData.UseBP, 683 fpoData.Reserved, fpoData.FrameType, fpoData.FrameType.String()) 684 } 685 } 686 } 687 } 688 689 w.Flush() 690 } 691 692 if cfg.wantBoundImp && pe.FileInfo.HasBoundImp { 693 fmt.Printf("\nBOUND IMPORTS\n************\n") 694 695 w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', tabwriter.AlignRight) 696 for _, bndImp := range pe.BoundImports { 697 fmt.Printf("\n\t------[ %s ]------\n\n", bndImp.Name) 698 fmt.Fprintf(w, "TimeDateStamp:\t 0x%x (%s)\n", bndImp.Struct.TimeDateStamp, 699 humanizeTimestamp(bndImp.Struct.TimeDateStamp)) 700 fmt.Fprintf(w, "Offset Module Name:\t 0x%x\n", bndImp.Struct.OffsetModuleName) 701 fmt.Fprintf(w, "# Module Forwarder Refs:\t 0x%x\n", bndImp.Struct.NumberOfModuleForwarderRefs) 702 fmt.Fprintf(w, "\n") 703 if len(bndImp.ForwardedRefs) > 0 { 704 fmt.Fprintln(w, "Name\tTimeDateStamp\tOffsetModuleName\tReserved\t") 705 for _, fr := range bndImp.ForwardedRefs { 706 fmt.Fprintf(w, "%s\t0x%x\t0x%x\t0x%x\t\n", fr.Name, 707 fr.Struct.TimeDateStamp, fr.Struct.OffsetModuleName, 708 fr.Struct.Reserved) 709 } 710 } 711 w.Flush() 712 } 713 } 714 715 if cfg.wantTLS && pe.FileInfo.HasTLS { 716 fmt.Printf("\nTLS\n*****\n\n") 717 718 tls := pe.TLS 719 w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', tabwriter.AlignRight) 720 if pe.Is64 { 721 imgTLSDirectory64 := tls.Struct.(peparser.ImageTLSDirectory64) 722 fmt.Fprintf(w, "Start Address Of Raw Data:\t 0x%x\n", imgTLSDirectory64.StartAddressOfRawData) 723 fmt.Fprintf(w, "End Address Of Raw Data:\t 0x%x\n", imgTLSDirectory64.EndAddressOfRawData) 724 fmt.Fprintf(w, "Address Of Index:\t %x\n", imgTLSDirectory64.AddressOfIndex) 725 fmt.Fprintf(w, "Address Of CallBacks:\t 0x%x\n", imgTLSDirectory64.AddressOfCallBacks) 726 fmt.Fprintf(w, "Size Of Zero Fill:\t 0x%x\n", imgTLSDirectory64.SizeOfZeroFill) 727 fmt.Fprintf(w, "Characteristics:\t 0x%x (%s)\n", imgTLSDirectory64.Characteristics, 728 imgTLSDirectory64.Characteristics.String()) 729 fmt.Fprintf(w, "Callbacks:\n") 730 if len(tls.Callbacks.([]uint64)) > 0 { 731 for _, callback := range tls.Callbacks.([]uint64) { 732 fmt.Fprintf(w, "0x%x\t\n", callback) 733 } 734 } 735 } else { 736 imgTLSDirectory32 := tls.Struct.(peparser.ImageTLSDirectory32) 737 fmt.Fprintf(w, "Start Address Of Raw Data:\t 0x%x\n", imgTLSDirectory32.StartAddressOfRawData) 738 fmt.Fprintf(w, "End Address Of Raw Data:\t 0x%x\n", imgTLSDirectory32.EndAddressOfRawData) 739 fmt.Fprintf(w, "Address Of Index:\t %x\n", imgTLSDirectory32.AddressOfIndex) 740 fmt.Fprintf(w, "Address Of CallBacks:\t 0x%x\n", imgTLSDirectory32.AddressOfCallBacks) 741 fmt.Fprintf(w, "Size Of Zero Fill:\t 0x%x\n", imgTLSDirectory32.SizeOfZeroFill) 742 fmt.Fprintf(w, "Characteristics:\t 0x%x (%s)\n", imgTLSDirectory32.Characteristics, 743 imgTLSDirectory32.Characteristics.String()) 744 fmt.Fprintf(w, "Callbacks:\n") 745 if len(tls.Callbacks.([]uint32)) > 0 { 746 for _, callback := range tls.Callbacks.([]uint32) { 747 fmt.Fprintf(w, "0x%x\t\n", callback) 748 } 749 } 750 } 751 752 w.Flush() 753 } 754 755 if cfg.wantLoadCfg && pe.FileInfo.HasLoadCFG { 756 fmt.Printf("\nLOAD CONFIG\n************\n\n") 757 758 loadConfig := pe.LoadConfig 759 w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', tabwriter.TabIndent) 760 v := reflect.ValueOf(loadConfig.Struct) 761 typeOfS := v.Type() 762 imgLoadConfigDirectorySize := v.Field(0).Interface().(uint32) 763 tmp := uint32(0) 764 for i := 0; i < v.NumField(); i++ { 765 // Do not print the fields of the image load config directory structure 766 // that does not belong to it. 767 tmp += uint32(binary.Size((v.Field(i).Interface()))) 768 if tmp > imgLoadConfigDirectorySize { 769 break 770 } 771 fmt.Fprintf(w, " %s\t : 0x%v\n", sentenceCase(typeOfS.Field(i).Name), 772 v.Field(i).Interface()) 773 } 774 w.Flush() 775 } 776 777 if cfg.wantCLR && pe.FileInfo.HasCLR { 778 fmt.Printf("\nCLR\n****\n") 779 780 fmt.Print("\n\t------[ CLR Header ]------\n\n") 781 clr := pe.CLR 782 w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', tabwriter.AlignRight) 783 784 clrHdr := clr.CLRHeader 785 flags := strings.Join(clrHdr.Flags.String(), " | ") 786 fmt.Fprintf(w, "Size Of Header:\t 0x%x\n", clrHdr.Cb) 787 fmt.Fprintf(w, "Major Runtime Version:\t 0x%x\n", clrHdr.MajorRuntimeVersion) 788 fmt.Fprintf(w, "Minor Runtime Version:\t 0x%x\n", clrHdr.MinorRuntimeVersion) 789 fmt.Fprintf(w, "MetaData RVA:\t 0x%x\n", clrHdr.MetaData.VirtualAddress) 790 fmt.Fprintf(w, "MetaData Size:\t 0x%x\n", clrHdr.MetaData.Size) 791 fmt.Fprintf(w, "Flags:\t 0x%x (%v)\n", clrHdr.Flags, flags) 792 fmt.Fprintf(w, "EntryPoint RVA or Token:\t 0x%x\n", clrHdr.EntryPointRVAorToken) 793 fmt.Fprintf(w, "Resources RVA:\t 0x%x\n", clrHdr.Resources.VirtualAddress) 794 fmt.Fprintf(w, "Resources Size:\t 0x%x (%s)\n", clrHdr.Resources.Size, BytesSize(float64(clrHdr.Resources.Size))) 795 fmt.Fprintf(w, "Strong Name Signature RVA:\t 0x%x\n", clrHdr.StrongNameSignature.VirtualAddress) 796 fmt.Fprintf(w, "Strong Name Signature Size:\t 0x%x (%s)\n", clrHdr.StrongNameSignature.Size, BytesSize(float64(clrHdr.StrongNameSignature.Size))) 797 fmt.Fprintf(w, "Code Manager Table RVA:\t 0x%x\n", clrHdr.CodeManagerTable.VirtualAddress) 798 fmt.Fprintf(w, "Code Manager Table Size:\t 0x%x (%s)\n", clrHdr.CodeManagerTable.Size, BytesSize(float64(clrHdr.CodeManagerTable.Size))) 799 fmt.Fprintf(w, "VTable Fixups RVA:\t 0x%x\n", clrHdr.VTableFixups.VirtualAddress) 800 fmt.Fprintf(w, "VTable Fixups Size:\t 0x%x (%s)\n", clrHdr.VTableFixups.Size, BytesSize(float64(clrHdr.VTableFixups.Size))) 801 fmt.Fprintf(w, "Export Address Table Jumps RVA:\t 0x%x\n", clrHdr.ExportAddressTableJumps.VirtualAddress) 802 fmt.Fprintf(w, "Export Address Table Jumps Size:\t 0x%x (%s)\n", clrHdr.ExportAddressTableJumps.Size, BytesSize(float64(clrHdr.ExportAddressTableJumps.Size))) 803 fmt.Fprintf(w, "Managed Native Header RVA:\t 0x%x\n", clrHdr.ManagedNativeHeader.VirtualAddress) 804 fmt.Fprintf(w, "Managed Native Header Size:\t 0x%x (%s)\n", clrHdr.ManagedNativeHeader.Size, BytesSize(float64(clrHdr.ManagedNativeHeader.Size))) 805 w.Flush() 806 807 fmt.Print("\n\t------[ MetaData Header ]------\n\n") 808 mdHdr := clr.MetadataHeader 809 fmt.Fprintf(w, "Signature:\t 0x%x (%s)\n", mdHdr.Signature, 810 string(IntToByteArray(uint64(mdHdr.Signature)))) 811 fmt.Fprintf(w, "Major Version:\t 0x%x\n", mdHdr.MajorVersion) 812 fmt.Fprintf(w, "Minor Version:\t 0x%x\n", mdHdr.MinorVersion) 813 fmt.Fprintf(w, "Extra Data:\t 0x%x\n", mdHdr.ExtraData) 814 fmt.Fprintf(w, "Version String Length:\t 0x%x\n", mdHdr.VersionString) 815 fmt.Fprintf(w, "Version String:\t %s\n", mdHdr.Version) 816 fmt.Fprintf(w, "Flags:\t 0x%x\n", mdHdr.Flags) 817 fmt.Fprintf(w, "Streams Count:\t 0x%x\n", mdHdr.Streams) 818 w.Flush() 819 820 fmt.Print("\n\t------[ MetaData Streams ]------\n\n") 821 for _, sh := range clr.MetadataStreamHeaders { 822 fmt.Fprintf(w, "Stream Name:\t %s\n", sh.Name) 823 fmt.Fprintf(w, "Offset:\t 0x%x\n", sh.Offset) 824 fmt.Fprintf(w, "Size:\t 0x%x (%s)\n", sh.Size, BytesSize(float64(sh.Size))) 825 w.Flush() 826 fmt.Print("\n ---Stream Content---\n") 827 hexDumpSize(clr.MetadataStreams[sh.Name], 128) 828 fmt.Print("\n") 829 } 830 831 fmt.Print("\n\t------[ MetaData Tables Stream Header ]------\n\n") 832 mdTablesStreamHdr := clr.MetadataTablesStreamHeader 833 fmt.Fprintf(w, "Reserved:\t 0x%x\n", mdTablesStreamHdr.Reserved) 834 fmt.Fprintf(w, "Major Version:\t 0x%x\n", mdTablesStreamHdr.MajorVersion) 835 fmt.Fprintf(w, "Minor Version:\t 0x%x\n", mdTablesStreamHdr.MinorVersion) 836 fmt.Fprintf(w, "Heaps:\t 0x%x\n", mdTablesStreamHdr.Heaps) 837 fmt.Fprintf(w, "RID:\t 0x%x\n", mdTablesStreamHdr.RID) 838 fmt.Fprintf(w, "MaskValid:\t 0x%x\n", mdTablesStreamHdr.MaskValid) 839 fmt.Fprintf(w, "Sorted:\t 0x%x\n", mdTablesStreamHdr.Sorted) 840 w.Flush() 841 842 fmt.Print("\n\t------[ MetaData Tables ]------\n\n") 843 mdTables := clr.MetadataTables 844 for _, mdTable := range mdTables { 845 fmt.Fprintf(w, "Name:\t %s | Items Count:\t 0x%x\n", mdTable.Name, mdTable.CountCols) 846 } 847 w.Flush() 848 849 for table, modTable := range pe.CLR.MetadataTables { 850 switch table { 851 case peparser.Module: 852 fmt.Print("\n\t[Modules]\n\t---------\n") 853 modTableRow := modTable.Content.(peparser.ModuleTableRow) 854 modName := pe.GetStringFromData(modTableRow.Name, pe.CLR.MetadataStreams["#Strings"]) 855 Mvid := pe.GetStringFromData(modTableRow.Mvid, pe.CLR.MetadataStreams["#GUID"]) 856 MvidStr := hex.EncodeToString(Mvid) 857 fmt.Fprintf(w, "Generation:\t 0x%x\n", modTableRow.Generation) 858 fmt.Fprintf(w, "Name:\t 0x%x (%s)\n", modTableRow.Name, string(modName)) 859 fmt.Fprintf(w, "Mvid:\t 0x%x (%s)\n", modTableRow.Mvid, MvidStr) 860 fmt.Fprintf(w, "EncID:\t 0x%x\n", modTableRow.EncID) 861 fmt.Fprintf(w, "EncBaseID:\t 0x%x\n", modTableRow.EncBaseID) 862 w.Flush() 863 864 } 865 } 866 } 867 868 // Get file type. 869 if pe.IsEXE() { 870 log.Debug("File is Exe") 871 } 872 if pe.IsDLL() { 873 log.Debug("File is DLL") 874 } 875 if pe.IsDriver() { 876 log.Debug("File is Driver") 877 } 878 879 // Calculate the PE checksum. 880 pe.Checksum() 881 882 fmt.Print("\n") 883 }